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

📄 ins_eth_ocm.old

📁 sopc builder 中网络的eth_ocm核
💻 OLD
📖 第 1 页 / 共 2 页
字号:
#include "ins_eth_ocm.h"
/**
 * Function for obtaining MAC address.
 * @param name Name of this MAC
 * @param net  NET interface (Interniche typedef)
 * @param mac_addr Character array into which MAC address should be written.
 *
 * @return zero on success, nonzero otherwise.
 */ 
extern int get_mac_addr(char name[], NET net, unsigned char mac_addr[6]);

/**
 * Determine whether PHY is full duplex or not.
 * This is fully vendor specific depending on the PHY you are using.
 * For this reason, this function is declared as external (so you can
 * write your own).
 * 
 * @param  pmac MAC register map.
 * @return 0x11 if Gigabit link is established and full duplex,
 *         0x01 if not Gigabit link is established and full duplex, 
 *         0x00 if not Gigabit link is established and half duplex, * If the link speed cannot be determined, it is fall back to 10/100.
 */
extern int getPHYSpeed(eth_ocm_dev *dev);


static void eth_ocm_rx_isr(void *context, alt_u32 id);
static int eth_ocm_read_init(eth_ocm_dev *dev);
static int eth_ocm_rcv(eth_ocm_dev *dev);

/**
 * Prepare ethernet MAC.
 *
 * @param ins_dev   Pointer to associated alt_iniche_dev struct
 * @return
 */
error_t eth_ocm_prep(alt_iniche_dev *ins_dev){
    NET ifp;
    int index;
    eth_ocm_dev *dev;

    index = ins_dev->if_num;
    dev = (eth_ocm_dev *)ins_dev;

    //Status message
    dprintf("eth_ocm_prep\n");

    //create eth_ocm_info struct
    dev->info = (eth_ocm_info *)malloc(sizeof(eth_ocm_info));
    dev->info->sem = 0; //initialize semaphore

    ifp = nets[index];
    ifp->n_mib->ifAdminStatus = ETH_OCM_STATUS_DOWN;    
    ifp->n_mib->ifOperStatus =  ETH_OCM_STATUS_DOWN;
    ifp->n_mib->ifLastChange =  cticks * (100/TPS);     //timestamp
    ifp->n_mib->ifPhysAddress = (u_char*)dev->info->mac_addr;
    ifp->n_mib->ifDescr =       (u_char*)"Opencores 10/100 ethernet MAC";
    ifp->n_lnh =                ETHHDR_SIZE;            /* ethernet header size. */
    ifp->n_hal =                ETH_OCM_MAC_ADDR_LEN;   /* MAC address length */
    ifp->n_mib->ifType =        ETHERNET;               /* device type */
    ifp->n_mtu =                ETH_OCM_MAX_MTU;        /* max frame size */

    /* install our hardware driver routines */
    ifp->n_init =       eth_ocm_init;
    ifp->pkt_send =     NULL;
    ifp->raw_send =     eth_ocm_raw_send;
    ifp->n_close =      eth_ocm_close;
    ifp->n_stats =      eth_ocm_stats;

#ifdef IP_V6
      ifp->n_flags |= (NF_NBPROT | NF_IPV6);
#else
      ifp->n_flags |= NF_NBPROT;
#endif

    /* get the MAC address. */
    get_mac_addr(dev->name, ifp, dev->info->mac_addr);

    /* set cross-pointers between iface and eth_ocm structs */
    dev->info->netp = ifp;
    ifp->n_local = (void*)(dev);

    index++;
    return index;
}
//End of function eth_ocm_prep

/**
 * Initializes the Opencores ethernet MAC. Called by InterNiche stack
 *
 * @param 
 */
int eth_ocm_init(int iface){
    int status = SUCCESS;
    int duplex;
    int temp;
    NET ifp;
    eth_ocm_dev *dev;
    eth_ocm_info *info;

    dprintf("[eth_ocm_init]\n");
    //get the ifp first
    ifp = nets[iface];
    //now get the info pointer
    dev = (eth_ocm_dev *)ifp->n_local;
    info = dev->info;

    // reset the mac (this is self clearing)
    IOWR_ETH_OCM_SW_RESET(dev->base);

    //Reset Descriptors (supposedly this can be done while in reset)
    for(temp=ETH_OCM_DESC_START;temp<ETH_OCM_DESC_END;temp++)
        IOWR(dev->base, temp, 0);

    //Let's disable the MAC until everything else is set up
    IOWR_ETH_OCM_MODER(dev->base,0);     
    //Set number of TX descriptors (RX descriptors is 128 minus this number)
    IOWR_ETH_OCM_TX_BD_NUM(dev->base, 64);

    /* perform any necessary PHY setup */
    //Let's set the MDIO interface up to run at 4MHz.
    temp = (ALT_CPU_FREQ / 1000000);
    temp += 2;
    temp &= 0xFFFFFFFE;   //only even numbers allowed)
    IOWR_ETH_OCM_MIIMODER(dev->base, temp);
    IOWR_ETH_OCM_MIICOMMAND(dev->base, 0);
    //Find out if we should run in duplex or not
    duplex = getPHYSpeed(dev);

    if(duplex)
        duplex = ETH_OCM_MODER_FULLD_MSK;

    // Configure MAC options
    // Interrupt sources
    IOWR_ETH_OCM_INT_MASK(dev->base, 
            ETH_OCM_DEFAULT_INTERRUPT_MASK);//Interrupt on receive
    // Clear any existing interrupts
    IOWR_ETH_OCM_INT_SOURCE(dev->base, 0xFFFFFFFF);

    // Inter-packet gap 
    if(duplex)
        IOWR_ETH_OCM_IPGT(dev->base, ETH_OCM_FULL_DUPLEX_IPGT); 
    else
        IOWR_ETH_OCM_IPGT(dev->base, ETH_OCM_HALF_DUPLEX_IPGT);

    //Let's set the defaults just because they've bitten us before
    IOWR_ETH_OCM_IPGR1(dev->base, 0x0000000C);
    IOWR_ETH_OCM_IPGR2(dev->base, 0x00000012);
    IOWR_ETH_OCM_PACKETLEN(dev->base, 0x00400600);  //Min and Max frame sizes
    IOWR_ETH_OCM_COLLCONF(dev->base, 0x000F003F);
    IOWR_ETH_OCM_CTRLMODER(dev->base, 0x00000000);

    dprintf("[eth_ocm_init] Configuring MAC address "
            "%02x:%02x:%02x:%02x:%02x:%02x\n",
            info->mac_addr[0],info->mac_addr[1],info->mac_addr[2],
            info->mac_addr[3],info->mac_addr[4],info->mac_addr[5]);
    //Configure the MAC address
    IOWR_ETH_OCM_MAC_ADDR0(dev->base,
            ( ((int)info->mac_addr[5])         |
             (((int)info->mac_addr[4]) << 8)   |
             (((int)info->mac_addr[3]) << 16)  |
             (((int)info->mac_addr[2]) << 24)  )
            );

    IOWR_ETH_OCM_MAC_ADDR1(dev->base,
            ( ((int)((unsigned char)info->mac_addr[1]))         |
             (((int)((unsigned char)info->mac_addr[0])) << 8)   )
            );


    //Enable MAC
    IOWR_ETH_OCM_MODER(dev->base,
           ETH_OCM_MODER_PAD_MSK    |   //Enable padding of small packets
           ETH_OCM_MODER_CRCEN_MSK  |   //Append CRC to TX packets
           ETH_OCM_MODER_RXEN_MSK   |   //Enable receive
           ETH_OCM_MODER_TXEN_MSK   |   //Enable transmit
           duplex                       //Discovered duplex
           );

    dprintf("\nOpencores MAC post-init: MODER = 0x%08x\n",
            IORD_ETH_OCM_MODER(dev->base));


   /* status = UP */
   nets[iface]->n_mib->ifAdminStatus = ETH_OCM_STATUS_UP;
   nets[iface]->n_mib->ifOperStatus = ETH_OCM_STATUS_UP;

   //register ISR interrupt handler
   temp = alt_irq_register(dev->irq, dev, eth_ocm_rx_isr);
   if(temp)
       dprintf("[eth_ocm_init] Failed to register RX ISR\n");
   //Setup the first read transfer
   eth_ocm_read_init(dev);

   return status;   //MAC is ready to rock and roll
}
//End of eth_ocm_init function


/**
 *  Raw send function to initiate a transfer to the mac 
 *
 * @param  net  - NET structure associated with the Opencores MAC instance
 * @param  data - pointer to the data payload
 G
 * @return SUCCESS if success, else a negative value
 */
int eth_ocm_raw_send(NET net, char * data, unsigned data_bytes){
    int result;
    int i;
    unsigned len;
    eth_ocm_dev *dev;
    eth_ocm_info *info;
    alt_u8 *buf;

    OS_ENTER_CRITICAL(); //disable interrupts

    dev = (eth_ocm_dev *)net->n_local;
    info = dev->info;
    len = data_bytes;
    result = 0;

    //Check to see if someone is nesting send calls (BAD!)
    if(info->sem){
       dprintf("Nested eth_ocm_raw_send\n");
       OS_EXIT_CRITICAL();
       return ENP_RESOURCE;
    }

    //Grab the semaphore
    info->sem = 1;
    // clear bit-31 before passing it to SGDMA Driver
    buf = (alt_u8 *)alt_remap_cached( (volatile void *)data, 4);
    //advance the pointer beyond the header bias
    buf = (alt_u8 *)((unsigned int)buf + ETHHDR_BIAS);

    //Some error checks first
    if(len < ETH_OCM_MIN_MTU)
        result = -1;        //packet too small
    if(len > ETH_OCM_MAX_MTU)
        result = -EFBIG;    //packet too big
    if((IORD_ETH_OCM_DESC_CTRL(dev->base, ETH_OCM_FIRST_TX_DESC) & ETH_OCM_TXDESC_READY_MSK))
        result = -EBUSY;    //DMA not available

    if(!result){
        //Write pointer to descriptor
        IOWR_ETH_OCM_DESC_PTR(dev->base, ETH_OCM_FIRST_TX_DESC, (unsigned int)buf);
        //Write length and setup transfer
        IOWR_ETH_OCM_DESC_CTRL(dev->base, ETH_OCM_FIRST_TX_DESC,
                ((len << ETH_OCM_TXDESC_LEN_OFST)    |
                 ETH_OCM_TXDESC_READY_MSK            |
                 ETH_OCM_TXDESC_WRAP_MSK             |
                 ETH_OCM_TXDESC_PAD_MSK              |
                 ETH_OCM_TXDESC_CRC_MSK)

⌨️ 快捷键说明

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