⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ins_eth_ocm.old

📁 sopc builder 中网络的eth_ocm核
💻 OLD
📖 第 1 页 / 共 2 页
字号:
                 );
        //Wait for transfer to complete
        i=0;
        do{
            result = IORD_ETH_OCM_DESC_CTRL(dev->base, ETH_OCM_FIRST_TX_DESC);
            i++;
        }while((result & ETH_OCM_TXDESC_READY_MSK) && i<ETH_OCM_TRANSMIT_TIMEOUT);
        //Make sure no timeout occurred
        if(i<ETH_OCM_TRANSMIT_TIMEOUT){
            //TODO Add case for retry
            if(result &
                    (ETH_OCM_TXDESC_UR_MSK      |
                    ETH_OCM_TXDESC_RL_MSK       |
                    ETH_OCM_TXDESC_LC_MSK       |
                    ETH_OCM_TXDESC_CS_MSK)){

                dprintf("[eth_ocm_raw_send] Transmit error 0x%x\n", result);
                result = -EIO;  //Some error occured
            } 
            else
                result = 0;
        } 
        else{   //Timeout
            result = -ETIMEDOUT;
        }
    }   //End of if(!result) Transmit branch

    //Check final result
    if(!result){    //Successfull transfer
       net->n_mib->ifOutOctets += data_bytes;   //Increment TX data counter
       // we dont know whether it was unicast or not, we count both in <ifOutUcastPkts>
       net->n_mib->ifOutUcastPkts++;
       result = SUCCESS;
    }
    else{   //Failed transfer
        dprintf("[eth_ocm_raw_send] Transmit failed, "
                "ret=%d, len=%d\n",
                result,
                len);

       net->n_mib->ifOutDiscards++; //increment TX discard counter
       result = SEND_DROPPED;   // ENP_RESOURCE and SEND_DROPPED have the same value! 
    }
    
    info->sem = 0;              //release semaphore
    OS_EXIT_CRITICAL();         //reenable interrupts
    return result;              //success 
}
//End of function eth_ocm_raw_send


/**
 * Receive ISR (interrupt service routine)
 *
 * @param  context  - context of the Opencores MAC instance
 * @param  id       - IRQ number 
 */
void eth_ocm_rx_isr(void *context, alt_u32 id){
    eth_ocm_dev *dev;
    int result;
    dev = (eth_ocm_dev *)context;

    //Check to see whether the interrupt was a successfull transfer or not
    result = IORD_ETH_OCM_INT_SOURCE(dev->base);
    IOWR_ETH_OCM_INT_SOURCE(dev->base, 0x7F);  //clear interrupts
    //Call the receive function. This will set up a new transfer
    eth_ocm_rcv(dev);

    //Check to see if there is something in the stack's received queue
    if ((rcvdq.q_len) > 0){
        SignalPktDemux();        
    }
}


/**
 *  Set up the first receive transfer
 */
static int eth_ocm_read_init(eth_ocm_dev *dev){
    eth_ocm_info *info;
    alt_u8 *uncached_packet_payload;
    PACKET *pkt_array;
    int result;
    int i;

    info = dev->info;
    pkt_array = info->pkt_array;
    pkt_array[0] = pk_alloc(ETH_OCM_BUF_ALLOC_SIZE);
    result = 0;

    if (!pkt_array[0]){  // couldn't get a free buffer for rx 
      dprintf("[eth_ocm_read_init] Fatal error: No free packet buffers for RX\n");
      return ENP_NOBUFFER;
    }

    // ensure bit-31 of pkt_array[i]->nb_buff is clear before passing
    uncached_packet_payload = (alt_u8*)alt_remap_cached ((volatile void*) pkt_array[0]->nb_buff, 4);
    uncached_packet_payload = (alt_u8*)(((unsigned int)uncached_packet_payload) + ETHHDR_BIAS);

    if(!(IORD_ETH_OCM_DESC_CTRL(dev->base, ETH_OCM_FIRST_RX_DESC) & ETH_OCM_RXDESC_EMPTY_MSK)){
        //Write pointer
        IOWR_ETH_OCM_DESC_PTR(dev->base, 
                ETH_OCM_FIRST_RX_DESC,
                uncached_packet_payload); 
        //Write the control register to start the transfer
        IOWR_ETH_OCM_DESC_CTRL(dev->base, ETH_OCM_FIRST_RX_DESC,
               (ETH_OCM_RXDESC_EMPTY_MSK |
                ETH_OCM_RXDESC_IRQ_MSK   |
                ETH_OCM_RXDESC_WRAP_MSK)
               ); 
    }
    else
        result = -EBUSY;

    if(!result)
        result = SUCCESS;
    else
        dprintf("[eth_ocm_read_init] Fatal error: Unable to set up initial RX\n");

    return result;
}
//End of function eth_ocm_read_init


/**
 * Receive operation. Checks the status of the received frame.
 * Attempt to obtain a new buffer from the InterNiche stack.
 * Schedules another RX transfer
 *
 * @return SUCCESS on success
 */
static int eth_ocm_rcv(eth_ocm_dev *dev)
{
    eth_ocm_info *info;
    struct ethhdr *eth;
    int pklen;
    int stat;
    int i;

    PACKET pkt;
    PACKET *pkt_array;
    alt_u8 *uncached_packet_payload;

    info = dev->info;
    pkt_array = info->pkt_array;
    stat = IORD_ETH_OCM_DESC_CTRL(dev->base, ETH_OCM_FIRST_RX_DESC);
    pklen = stat & ETH_OCM_RXDESC_LEN_MSK;
    pklen = pklen >> ETH_OCM_RXDESC_LEN_OFST;

    //Increment received byte count
    info->netp->n_mib->ifInOctets += (u_long)pklen;

    pkt_array[0]->nb_prot = pkt_array[0]->nb_buff + ETHHDR_SIZE;
    pkt_array[0]->nb_plen = pklen - (14 + 4); //Packet length minus (header + CRC)
    //TODO See if MAC appends CRC
    pkt_array[0]->nb_tstamp = cticks;
    pkt_array[0]->net = info->netp;

    
    // set packet type for demux routine
    eth = (struct ethhdr *)(pkt_array[0]->nb_buff + ETHHDR_BIAS);
    pkt_array[0]->type = eth->e_type;

    if (!(stat & ETH_OCM_RXDESC_ERROR_MSK)){
        pkt = pk_alloc(ETH_OCM_BUF_ALLOC_SIZE);
        if (!pkt){  // couldn't get a free buffer for rx 
          dprintf("No free buffers for rx\n");
          info->netp->n_mib->ifInDiscards++;
        }
        else{
          putq(&rcvdq, pkt_array[0]);
          pkt_array[0] = pkt;
        }
    }
    else{
        dprintf("[eth_ocm_rcv] Frame discarded due to errors!\n");
        info->netp->n_mib->ifInDiscards++;
    }

    // ensure bit-31 of pkt_array[]->nb_buff is clear before passing
    // to DMA Driver
    uncached_packet_payload = (alt_u8*)alt_remap_cached ((volatile void*) pkt_array[0]->nb_buff, 4);
    uncached_packet_payload = (alt_u8*)((unsigned int)uncached_packet_payload + ETHHDR_BIAS);

    if(!(IORD_ETH_OCM_DESC_CTRL(dev->base, ETH_OCM_FIRST_RX_DESC) & ETH_OCM_RXDESC_EMPTY_MSK)){
        //Write pointer
        IOWR_ETH_OCM_DESC_PTR(dev->base, 
                ETH_OCM_FIRST_RX_DESC,
                (unsigned int)uncached_packet_payload); 
        //Write the control register to start the transfer
        IOWR_ETH_OCM_DESC_CTRL(dev->base, ETH_OCM_FIRST_RX_DESC,
               (ETH_OCM_RXDESC_EMPTY_MSK |
                ETH_OCM_RXDESC_IRQ_MSK   |
                ETH_OCM_RXDESC_WRAP_MSK)
               ); 
    }
    else
        stat = -EBUSY;
            
    return SUCCESS;
}



void eth_ocm_stats(void *pio, int iface) {
    NET ifp;
    eth_ocm_dev *dev;

    //get the ifp first
    ifp = nets[iface];
    dev = (eth_ocm_dev *)ifp->n_local;
    ns_printf(pio, "eth_ocm_stats(), stats will be added later!\n");
}

/**
 * Closes the opencores mac interface
 *
 * @param  iface    index of the NET interface associated with the Opencores MAC.
 * @return SUCCESS
 */

int eth_ocm_close(int iface)
{
  int err;
  NET ifp;
  eth_ocm_dev *dev;

  /* status = down */
  ifp = nets[iface];
  dev = (eth_ocm_dev *)ifp->n_local;

  ifp->n_mib->ifAdminStatus = ETH_OCM_STATUS_DOWN;

  /* disable the interrupt in the OS*/
  err = alt_irq_register (dev->irq, 0, NULL);
  if (err){
    dprintf("[eth_ocm_close]Could not unregister interrupt, error = %d\n",err);
    return err;
  }

  // Shut down the MAC
  IOWR_ETH_OCM_MODER(dev->base, 0);

  /* status = down */
  ifp->n_mib->ifOperStatus = ETH_OCM_STATUS_DOWN;
  //deallocate memory for the eth_ocm_info struct allocated in eth_ocm_prep
  free(dev->info);

  return SUCCESS;
}

//End of file ins_eth_ocm.h

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -