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

📄 ae531xlnx.c

📁 atheros ar531x ethernet driver
💻 C
📖 第 1 页 / 共 3 页
字号:
    }    /* Check if we can transport this packet */    length = max((u32)60, length);  /* total length */        mtu = dev->mtu;    max_buf_size = mtu + ETH_HLEN;    if (length > max_buf_size) {        AE531X_PRINT(AE531X_DEBUG_ERROR,                  ("eth%d Tx: length %d too long.  mtu=%d, trailer=%d\n",                   dev_sw_state->enetUnit, length, mtu, PHY_TRAILER_SIZE));        MAC_state->stats.tx_errors++;        MAC_state->stats.tx_aborted_errors++;        goto dropFrame;    }    #ifdef CONFIG_VLAN_ROUTER#ifdef HEADER_MODE	skb_push(skb,PHY_HEADER_SIZE);	length += PHY_HEADER_SIZE;#else	length += PHY_TRAILER_SIZE;#endif 	phySetDestinationPort(skb->data, length, MACInfo->unit);	MACInfo  = &per_MAC_info[0].MACInfo;#endif	/* Reap any old, completed Tx descriptors */	ae531x_TxReap(MAC_state, skb->len);    txDesc = MACInfo->txQueue.curDescAddr;    if (txDesc == MACInfo->txQueue.reapDescAddr) {        int i;        AE531X_PRINT(AE531X_DEBUG_ERROR,                  ("eth%d Tx: cannot get txDesc\n",                   dev_sw_state->enetUnit));        MAC_state->stats.tx_dropped++;        MAC_state->stats.tx_fifo_errors++;        /*         * Stop transmit queues for any ethernet devices         * associated with this MAC.         */#if 0 /* XXX: no way to recover from queue stop until ae531x_MAC_tx_timeout()	   *      is rewritten to avoid calls to shedule().	   */        for (i=0; i<AE531X_DEV_PER_MAC; i++) {            if (MAC_state->dev_sw_state[i]->dev)                netif_stop_queue(MAC_state->dev_sw_state[i]->dev);        }#endif        goto dropFrame;    }    /* We won't fail now; so consume this descriptor */    AE531X_CONSUME_DESC((&MACInfo->txQueue));    	#if TX_TWO_BUF == 1    if (!buf2) {        /* break tx dma into two blocks, the second being sdram burst aligned */        lenb1 = 0x10 - ((UINT32)skb->data & 0x0f);        buf2 = (char *)skb->data + lenb1;    }    buf2 = virt_to_bus(skb->data + lenb1);#endif 	      /* Update the descriptor */    buf = virt_to_bus(skb->data);	        AE531X_DESC_BUFPTR_SET(txDesc, buf);    AE531X_DESC_SWPTR_SET(txDesc, skb);    ctrlen = AE531X_DESC_CTRLEN_GET(txDesc);    ctrlen = (ctrlen & (DescEndOfRing)) |                            DescTxFirst |                             DescTxLast |                        DescTxIntEnable;    if (buf2) {        AE531X_DESC_LNKBUF_SET(txDesc, (UINT32)buf2);        ctrlen |= ((lenb1 << DescSize1Shift) & DescSize1Mask)                | (((length - lenb1) << DescSize2Shift) & DescSize2Mask);    } else {    ctrlen |= ((length << DescSize1Shift) & DescSize1Mask);    }    AE531X_DESC_CTRLEN_SET(txDesc, ctrlen);    AE531X_DESC_STATUS_SET(txDesc, DescOwnByDma);    /* Alert DMA engine to resume Tx */    ae531x_WriteDmaReg(MACInfo, DmaTxPollDemand, 0);    sysWbFlush();    AE531X_PRINT(AE531X_DEBUG_TX,              ("eth%d Tx: Desc=0x%8.8x, L=0x%8.8x, D=0x%8.8x, d=0x%8.8x, length=0x%8.8x\n",               dev_sw_state->enetUnit,               (UINT32)txDesc,               AE531X_DESC_CTRLEN_GET(txDesc),               buf,               AE531X_DESC_LNKBUF_GET(txDesc),               length));    /* Tell upper layers to keep it coming */        dev->trans_start = jiffies;    LEAVE();    MAC_state->stats.tx_bytes += skb->len;//AE531X_DESC_STATUS_RX_SIZE(cmdsts);    MAC_state->stats.tx_packets++;	    return 0;dropFrame:    kfree_skb(skb);    LEAVE();    return 0;}/******************************************************************************** ae531x_MAC_tx_timeout handles transmit timeouts*/static voidae531x_MAC_tx_timeout(struct net_device *dev){    ae531x_dev_sw_state_t *dev_sw_state;    ae531x_MAC_state_t *MAC_state;    ae531x_MAC_t *MACInfo;    ARRIVE();    dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;    MAC_state = dev_sw_state->MAC_state;    MACInfo = &MAC_state->MACInfo;    AE531X_PRINT(AE531X_DEBUG_ERROR,             ("enet%d: Tx timeout\n", dev_sw_state->enetUnit));    ae531x_restart(MACInfo);    LEAVE();}/******************************************************************************** ae531x_MAC_do_ioctl is a placeholder for future ioctls.*/#define SIOCDEVPRIVATEGETPORTSPEED    (SIOCDEVPRIVATE + 0)#define SIOCDEVPRIVATESETPORTSPEEDANDDUPLEX    (SIOCDEVPRIVATE + 1)#define SIOCDEVPRIVATEGETPORTDUPLEX   (SIOCDEVPRIVATE + 2)#define SIOCDEVPRIVATEGETPORTLINKED   (SIOCDEVPRIVATE + 3)#define SIOCDEVPRIVATELOCKPORTMAC       (SIOCDEVPRIVATE + 4)#define SIOCDEVPRIVATELOCKPORTDB       (SIOCDEVPRIVATE + 5)#define SIOCDEVPRIVATETESTSWITCH      (SIOCDEVPRIVATE + 6)#define SIOCDEVPRIVATENETSTATS      (SIOCDEVPRIVATE + 7)static intae531x_MAC_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){        int rv = 1;        ae531x_MAC_t *MACInfo;        struct parse_t	{	int port;   //port number	int svalue; //set value	int gvalue; //get value	unsigned char mac[6];	};        ae531x_dev_sw_state_t *dev_sw_state;        ae531x_MAC_state_t *MAC_state;        struct parse_t *parse;        ARRIVE();        dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;        MAC_state = dev_sw_state->MAC_state;        MACInfo = &MAC_state->MACInfo;        parse = (struct parse_t*)(ifr->ifr_data);        switch( cmd ) {	case SIOCDEVPRIVATEGETPORTSPEED:		parse->gvalue = phyIsSpeed100(parse->port);	      break;	case SIOCDEVPRIVATEGETPORTDUPLEX:		parse->gvalue = phyIsFullDuplex_ext(parse->port);	      break;	case SIOCDEVPRIVATESETPORTSPEEDANDDUPLEX:		phySet(parse->port, MV_PHY_CONTROL, (parse->svalue << 8));	      break;	case SIOCDEVPRIVATEGETPORTLINKED: 		parse->gvalue = phyIsLinkAlive(parse->port);	      break;      	case SIOCDEVPRIVATENETSTATS: 		memcpy(ifr->ifr_data, dev->get_stats(dev), sizeof(struct net_device_stats));		      break;    	            		        default:            AE531X_PRINT(AE531X_DEBUG_ERROR,                     ("Unsupported ioctl: 0x%x\n", cmd));            rv = -EOPNOTSUPP;        }        LEAVE();        return rv;}static voidae531x_MAC_setup_fntable(struct net_device *dev){    ARRIVE();    dev->get_stats       = ae531x_MAC_get_stats;    dev->open            = ae531x_MAC_open;    dev->stop            = ae531x_MAC_stop;    dev->hard_start_xmit = ae531x_MAC_start_xmit;    dev->do_ioctl        = ae531x_MAC_do_ioctl;    dev->poll            = ae531x_MAC_poll;    dev->weight          = 128;    dev->mtu 		 = dev->mtu;     #if 0 /* XXX: currently, ae531x_MAC_tx_timeout() will call functions	   *      that in turn call schedule(). this is BAD, since the	   *      timeout call runs at interrupt time. until ae531x_MAC_tx_timeout	   *      is rewritten to avoid schedule() calls, we do not use it.	   */    dev->tx_timeout      = ae531x_MAC_tx_timeout;#else    dev->tx_timeout      = NULL;#endif    dev->features        = NETIF_F_HW_CSUM |\                           NETIF_F_HIGHDMA;    LEAVE();}static voidar5312EepromRead(char *EepromAddr, u_int16_t id, unsigned int off, 		 unsigned int nbytes, char *data){	int i;		for (i=0; i<nbytes; i++, off++) {		data[i] = EepromAddr[off];	}}intae531x_get_numMACs(void){    int devid;    u16 radioMask;    /* Probe to find out the silicon revision and enable the       correct number of macs */    devid = ((u_int16_t) ((sysRegRead(AR531X_REV) >>8) & 			  (AR531X_REV_MAJ | AR531X_REV_MIN)));    switch (devid) {    case AR5212_AR5312_REV2:    case AR5212_AR5312_REV7:        /* Need to determine if we have a 5312 or a 2312 since they           have the same Silicon Rev ID*/        ar5312EepromRead(radioConfig,0,2*AR531X_RADIO_MASK_OFF,2,			 (char *) &radioMask);        if ((radioMask & AR531X_RADIO0_MASK) != 0) {            return 2;        }        return 1;    case AR5212_AR2313_REV8:        return 1;    }#ifdef CONFIG_VLAN_ROUTER    return 2;#else          /* default to 1 */    return 1;#endif     }BOOLae531x_twisted_enet(void){    int wisoc_revision;    wisoc_revision = (sysRegRead(AR531X_REV) & AR531X_REV_MAJ) >> AR531X_REV_MAJ_S;    if ( (wisoc_revision == AR531X_REV_MAJ_AR2313) ||         /* next clause is used to determine AR2312, based on number of MACs.           * must do this since revision is same for 5312 and 2312.          */         (wisoc_revision == AR531X_REV_MAJ_AR5312 && ae531x_get_numMACs() == 1) ) {        return TRUE;    } else {        return FALSE;    }}#define BOARD_DATA_CONFIG 0xa87ff000//#define BOARD_DATA_CONFIG 0xbffff000intae531x_get_board_config(void){    int dataFound;    char *bd_config;    /*     * Find start of Board Configuration data, using heuristics:     * Search back from the (aliased) end of flash by 0x1000 bytes     * at a time until we find the string "5311", which marks the     * start of Board Configuration.  Give up if we've searched     * more than 500KB.     */    dataFound = 0;    for (bd_config = (char *)BOARD_DATA_CONFIG;         bd_config > (char *)(BOARD_DATA_CONFIG - 0x30000);         bd_config -= 0x1000)    {        if ( *(int *)bd_config == AR531X_BD_MAGIC) {            dataFound = 1;            break;        }    }    if (!dataFound) {        printk("Could not find Board Configuration Data\n");		bd_config = NULL;    }	    ar531x_boardConfig = (struct ar531x_boarddata *) bd_config;	    return(dataFound);}intae531x_get_radio_config(void){    int dataFound;    char *radio_config;    /*      * Now find the start of Radio Configuration data, using heuristics:     * Search forward from Board Configuration data by 0x1000 bytes     * at a time until we find non-0xffffffff.     */    dataFound = 0;    for (radio_config = ((char *) ar531x_boardConfig) + 0x1000;         radio_config < (char *)0xbffff000;         radio_config += 0x1000)    {        if (*(int *)radio_config != 0xffffffff) {            dataFound = 1;            break;        }    }    if (!dataFound) { /* AR2316 relocates radio config to new location */	dataFound = 0;	for (radio_config = ((char *) ar531x_boardConfig) + 0xf8;	     radio_config < (char *)0xbffff0f8;	     radio_config += 0x1000)	{	    if (*(int *)radio_config != 0xffffffff) {		dataFound = 1;		break;	    }	}    }    if (!dataFound) {        printk("Could not find Radio Configuration data\n");	radio_config = NULL;    }    radioConfig = radio_config;    return(dataFound);}static int __initae531x_MAC_setup(void){    int next_dev, i;    struct net_device *dev;    ae531x_dev_sw_state_t *dev_sw_state;    ae531x_MAC_state_t *MAC_state;    ae531x_MAC_t *MACInfo;    char *addr;    ARRIVE();    MOD_INC_USE_COUNT;    for (i=0;i<AR531X_NUM_ENET_MAC * AE531X_DEV_PER_MAC; i++) {	ae531x_MAC_dev[i] = NULL;    }        if (!ae531x_get_board_config()) {	LEAVE();	return -1;    }    if (!ae531x_get_radio_config()) {	LEAVE();	return(-1);    }#ifdef CONFIG_VLAN_ROUTER        for(i=0, next_dev = 0; i<ae531x_get_numMACs() && next_dev < AR531X_NUM_ENET_MAC;         i++, next_dev++){#else    for(i=0, next_dev = AR531X_NUM_ENET_MAC-1;         i<ae531x_get_numMACs() && next_dev>=0;         i++, next_dev--){#endif 		        /* if MAC is bogus in config data, skip */        addr = ae531x_enet_mac_address_get(next_dev);        if((*(u32 *)addr == 0xffffffff) && (*(u16 *)(addr+4)==0xffff)){            /* bogus MAC config data */            continue;        }	        dev = ae531x_MAC_dev[next_dev] =            init_etherdev(NULL, sizeof(ae531x_dev_sw_state_t));	        if (dev == NULL) {            LEAVE();            return -1;        }	        ae531x_MAC_setup_fntable(dev);        dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;        dev_sw_state->enetUnit = next_dev;        dev_sw_state->unit_on_MAC = 0;        MAC_state = &per_MAC_info[next_dev];        dev_sw_state->MAC_state = MAC_state;        MAC_state->dev_sw_state[AE531X_LAN_PORT] = dev_sw_state;        MAC_state->primary_dev = -1;        /* Initialize per-MAC information */        MACInfo = &MAC_state->MACInfo;        MACInfo->unit = next_dev;	if (MACInfo->unit == 0) {    		 			            MACInfo->macBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_MAC_OFFSET);            MACInfo->dmaBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_DMA_OFFSET);            MACInfo->phyBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);            MAC_state->irq = AR531X_IRQ_ENET0_INTRS;        } else {#ifndef CONFIG_AR531X_COBRA            MACInfo->macBase = (u32) (PHYS_TO_K1(AR531X_ENET1)+AE531X_MAC_OFFSET);            MACInfo->dmaBase = (u32) (PHYS_TO_K1(AR531X_ENET1)+AE531X_DMA_OFFSET);            if (ae531x_twisted_enet()) {                MACInfo->phyBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);            } else {                MACInfo->phyBase = (u32)(PHYS_TO_K1(AR531X_ENET1)+AE531X_PHY_OFFSET);            }            MAC_state->irq = AR531X_IRQ_ENET1_INTRS;#endif#ifdef CONFIG_VLAN_ROUTER            MACInfo->macBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_MAC_OFFSET);            MACInfo->dmaBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_DMA_OFFSET);            MACInfo->phyBase = (u32)(PHYS_TO_K1(AR531X_ENET0)+AE531X_PHY_OFFSET);            MAC_state->irq = AR531X_IRQ_ENET1_INTRS;#endif         }        MACInfo->OSinfo = (void *)MAC_state;    }    LEAVE();    return 0;}module_init(ae531x_MAC_setup);/******************************************************************************** ae531x_MAC_unload is the module unload function*/static void __exitae531x_MAC_unload(void){    int i;    for (i=0;i<AR531X_NUM_ENET_MAC * AE531X_DEV_PER_MAC; i++) {        if (ae531x_MAC_dev[i] != NULL) {            if( (((ae531x_dev_sw_state_t *)ae531x_MAC_dev[i]->priv)->dev) != NULL)                  ae531x_MAC_stop(ae531x_MAC_dev[i]);		unregister_netdev(ae531x_MAC_dev[i]);		ae531x_MAC_dev[i] = NULL;        }    }   MOD_DEC_USE_COUNT;}MODULE_AUTHOR("Atheros Communications, Inc.");MODULE_DESCRIPTION("Support for Atheros WiSoC Ethernet device");#ifdef MODULE_LICENSEMODULE_LICENSE("Atheros");#endifmodule_exit(ae531x_MAC_unload);

⌨️ 快捷键说明

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