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

📄 ae531xlnx.c

📁 atheros ar531x ethernet driver
💻 C
📖 第 1 页 / 共 3 页
字号:
  }  return NULL;}    #endif/******************************************************************************** ae531x_phy_poll periodically checks for changes in phy status* (e.g. dropped link).*/static intae531x_phy_poll(void *data){    ae531x_dev_sw_state_t *dev_sw_state = (ae531x_dev_sw_state_t *)data;    ae531x_MAC_t *MACInfo = &dev_sw_state->MAC_state->MACInfo;    int unit = dev_sw_state->enetUnit;#if 0    while(dev_sw_state->dev!=NULL) {        if (MACInfo->port_is_up) {            phyCheckStatusChange(unit);        }        set_current_state(TASK_UNINTERRUPTIBLE);        schedule_timeout(AE531X_PHY_POLL_SECONDS * HZ);    }#else    if(dev_sw_state->dev!=NULL) {        if (MACInfo->port_is_up) {            phyCheckStatusChange(unit);                    } 	dev_sw_state->timer.expires = TIMER_WUT; 	add_timer(&dev_sw_state->timer);    }#endif     return 0;}static char invalid_enet_MAC_addr[] = {0, 0, 0, 0, 0, 0};/* * Fetch a pointer to an ethernet's MAC address * in the Board Configuration data (in flash). */char *ae531x_enet_mac_address_get(int MACUnit){	/* XXX: Hack for poorly configured boards.	 *      Cannot setup bridging properly (brctl) when both enet	 *      interfaces share the same MAC address.	 * 	 */#ifdef CONFIG_ASK_MULT_MAC_HACK    static u8  enet0Mac[6] = {0x00, 0x0d, 0x0b, 0x13, 0x6b, 0x16};    static u8  enet1Mac[6] = {0x00, 0x0d, 0x0b, 0x13, 0x6b, 0x17};#endif    static u8  enet0Mac[6] = {0x00, 0x0d, 0x0b, 0x13, 0x6b, 0x16};    static u8  enet1Mac[6] = {0x00, 0x0d, 0x0b, 0x13, 0x6b, 0x17};    if (!ar531x_boardConfig)        return invalid_enet_MAC_addr;    if (MACUnit == 0) {#ifndef CONFIG_ASK_MULT_MAC_HACK        return enet0Mac;//ar531x_boardConfig->enet0Mac;#else		return enet0Mac;#endif    }    if (MACUnit == 1) {#ifndef CONFIG_ASK_MULT_MAC_HACK        return enet1Mac;//ar531x_boardConfig->enet1Mac;#else		return enet1Mac;#endif    }    printk("Invalid ethernet MAC unit number (%d)!\n", MACUnit);    return invalid_enet_MAC_addr;}/******************************************************************************** ae531x_MAC_open is the standard Linux open function.  It puts* hardware into a known good state, allocates queues, starts* the phy polling task, and arranges for interrupts to be handled.*/static int ae531x_MAC_open(struct net_device *dev){    ae531x_dev_sw_state_t *dev_sw_state;    ae531x_MAC_state_t *MAC_state;    ae531x_MAC_t *MACInfo;    u8 *MACAddr;    int rv;    struct tq_struct *restart_task;    pid_t phy_poll_pid;    ARRIVE();    dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;    dev_sw_state->dev = dev;    MAC_state = dev_sw_state->MAC_state;    MACInfo = &MAC_state->MACInfo;        restart_task = &MAC_state->restart_task;    restart_task->routine = ae531x_restart;    restart_task->data = (void *)MACInfo;    AE531X_PRINT(AE531X_DEBUG_RESET,              ("ae531x_MAC_open eth%d ethmac%d macBase=0x%x dmaBase=0x%x irq=0x%x\n",               dev_sw_state->enetUnit,               MACInfo->unit,               MACInfo->macBase,               MACInfo->dmaBase,               MAC_state->irq));    /* Default MAC address */    MACAddr = ae531x_enet_mac_address_get(MACInfo->unit);    if((dev->dev_addr[0] == 0x00) && (dev->dev_addr[1] == 0x00) && (dev->dev_addr[2] == 0x00) &&        (dev->dev_addr[3] == 0x00) && (dev->dev_addr[4] == 0x00) && (dev->dev_addr[5] == 0x00))               memcpy(dev->dev_addr, MACAddr, dev->addr_len );    if (!MACInfo->port_is_up ) {        /* Bring MAC and PHY out of reset */          #ifdef CONFIG_VLAN_ROUTER        	      if(!hwInit && MACInfo->unit == 0)	      {  #endif       		        ae531x_reset(MACInfo);	        /* Attach interrupt handler */       	        rv = request_irq(MAC_state->irq, ae531x_MAC_intr, SA_INTERRUPT,	                    "ae531x_MAC_intr", (void *)MACInfo);	                    	        if (rv < 0) {	            AE531X_PRINT(AE531X_DEBUG_ERROR,	                         ("request_irq(0x%x) failed (%d)\n",	                          MAC_state->irq, rv));	            goto open_failure;	        }	        	        /* Initialize PHY */			AE531X_PRINT(AE531X_DEBUG_RESET, ("\n --- phyBase: %08x\n", MACInfo->phyBase));			        phySetup(MACInfo->unit, MACInfo->phyBase);        	#if 0    	        /* Start thread to poll for phy link status changes */	        phy_poll_pid = kernel_thread(ae531x_phy_poll, dev_sw_state, 0);	        if (phy_poll_pid < 0) {	            AE531X_PRINT(AE531X_DEBUG_ERROR,	                     ("ethmac%d unable to start Phy Poll thread\n",	                     MACInfo->unit));	        }	#else	        		/* set and active a timer process */		init_timer(&dev_sw_state->timer);		dev_sw_state->timer.expires = TIMER_WUT;		dev_sw_state->timer.data = (unsigned long)dev_sw_state;		dev_sw_state->timer.function = &ae531x_phy_poll;		add_timer(&dev_sw_state->timer);        	#endif 	        /* Allocate RX/TX Queues */ 	        if (ae531x_AllocateQueues(MACInfo) < 0) {	            AE531X_PRINT(AE531X_DEBUG_RESET, ("Queue allocation failed"));	            free_irq(MAC_state->irq, (void *)MACInfo);	            goto open_failure;	        }	        /* Initialize DMA and descriptors */	        ae531x_DmaReset(MACInfo);	        /* Initialize MAC */	        ae531x_MACReset(MACInfo);	        /* Enable Receive/Transmit */	        ae531x_EnableComm(MACInfo);#ifdef CONFIG_VLAN_ROUTER	        		        hwInit = TRUE;     	      }      #endif             MAC_state->primary_dev = dev_sw_state->unit_on_MAC;              MACInfo->port_is_up = TRUE;    }#ifdef CONFIG_VLAN_ROUTER#ifndef HEADER_MODE    if(MACInfo->unit == 1)    {    	mv_setATUDB(CPU_PORT, dev->dev_addr, 0);    	mv_setATUDB(CPU_PORT, dev->dev_addr, 1);    	//mv_showATUDB(CPU_PORT); for debug    }	#endif#endif    	    dev->trans_start = jiffies;    SET_MODULE_OWNER(dev);    LEAVE();      return 0;open_failure:    LEAVE();    return -1;}/* * Shut down MAC hardware. */static voidae531x_MAC_shutdown(ae531x_MAC_state_t *MAC_state){    ae531x_MAC_t *MACInfo;    MACInfo = &MAC_state->MACInfo;    MACInfo->port_is_up = FALSE;    /* Disable Receive/Transmit */    ae531x_DisableComm(MACInfo);    /* Disable Interrupts */    ae531x_DmaIntDisable(MACInfo);    sysWbFlush();    free_irq(MAC_state->irq, (void *)MACInfo);#ifdef CONFIG_VLAN_ROUTER        hwInit = FALSE;#endif         /* Free Transmit & Receive skb's/descriptors */    ae531x_TxReap(MAC_state, 0); /* one last time */    ae531x_FreeQueues(MACInfo);}/******************************************************************************** ae531x_MAC_stop is the standard Linux stop function.  It undoes* everything set up by ae531x_MAC_open.*/static intae531x_MAC_stop(struct net_device *dev){    ae531x_dev_sw_state_t *dev_sw_state;    ae531x_MAC_state_t *MAC_state;    ae531x_MAC_t *MACInfo;    int i;    ARRIVE();    dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;    MAC_state = dev_sw_state->MAC_state;    MACInfo = &MAC_state->MACInfo;#ifdef CONFIG_VLAN_ROUTER    if(MACInfo->unit == 0)   #endif      del_timer(&dev_sw_state->timer);         for (i=0; i<AE531X_DEV_PER_MAC; i++) {        if ((MAC_state->dev_sw_state[i]->dev) &&            (MAC_state->dev_sw_state[i]->dev != dev_sw_state->dev)) {            break;        }    }    if (i < AE531X_DEV_PER_MAC) {        /* Physical MAC is still in use */        if (MAC_state->primary_dev == dev_sw_state->unit_on_MAC) {            /*             * If the primary_dev is being stopped             * then we need to assign a new one.             */            MAC_state->primary_dev = i;        }    } else {#ifdef CONFIG_VLAN_ROUTER    		if(MACInfo->unit == 0)   #endif   	        /* Physical MAC is no longer in use */        ae531x_MAC_shutdown(MAC_state);    }    dev_sw_state->dev = NULL;    LEAVE();    return 0;}/******************************************************************************** ae531x_rxbuf_alloc - Allocate an skb to be associated with an RX descriptor.** RETURNS: A pointer to the skb.  Also returns a pointer to the underlying* buffer and the size of that buffer. */void *ae531x_rxbuf_alloc(ae531x_MAC_t *MACInfo, char **rxBuffp, int *rxBuffSizep){    int buf_size;    struct sk_buff *skb;    char *rxBuff;    int rxBuffSize;    buf_size = AE531X_RX_BUF_SIZE;    skb = dev_alloc_skb(buf_size);    if (skb) {        /* skb->dev = dev; */        skb_reserve(skb, RXBUFF_RESERVE);        rxBuffSize = skb_tailroom(skb);        rxBuff = skb->tail;        *rxBuffp = rxBuff;        *rxBuffSizep = rxBuffSize;    }    return skb;}/******************************************************************************** ae531x_swptr_free - Free the skb, if any, associated with a descriptor.*/voidae531x_swptr_free(VIRT_ADDR desc){    struct sk_buff *skb;    skb = (struct sk_buff *)AE531X_DESC_SWPTR_GET(desc);    if (skb) {        AE531X_DESC_SWPTR_SET(desc, NULL);        kfree_skb(skb);    }}/********************************************************************************* ae531x_TxReap - the driver Tx completion routine.** This routine reaps sk_buffs which have already been transmitted.**/static voidae531x_TxReap(ae531x_MAC_state_t *MAC_state, int length){    AE531X_QUEUE      *txq;    VIRT_ADDR         txDesc;    UINT32            cmdsts;    struct            sk_buff *skb;    int               reaped;    ae531x_MAC_t      *MACInfo;    static int        aeUselessReap = 0;#ifdef DEBUG    static int        aeMaxReap = 0;#endif    ARRIVE();    #ifdef CONFIG_VLAN_ROUTER    MACInfo = &per_MAC_info[0].MACInfo;    txq  = &per_MAC_info[0].MACInfo.txQueue;#else        MACInfo = &MAC_state->MACInfo;    txq = &MACInfo->txQueue;#endif         reaped = 0;    while (1) {        txDesc = AE531X_QUEUE_ELE_NEXT_GET(txq, txq->reapDescAddr);        if (txDesc == txq->curDescAddr) {            break;        }        cmdsts = AE531X_DESC_STATUS_GET(KSEG1ADDR(txDesc));        if (cmdsts & DescOwnByDma) {            break;        }        /* Release sk_buff associated with completed transmit */        skb = (struct sk_buff *)AE531X_DESC_SWPTR_GET(txDesc);        if (skb) {          	            kfree_skb(skb);            AE531X_DESC_SWPTR_SET(txDesc, NULL);        }#if 0          /* Update statistics according to completed transmit desc */        if (cmdsts & DescTxErrors) {            AE531X_PRINT(AE531X_DEBUG_ERROR,                    ("enetmac%d Tx prior error: 0x%8.8x <0x%8.8x> 0x%8.8x\n",                    MACInfo->unit,                    cmdsts,                    DescTxErrors,                    (int)txDesc));#ifdef DEBUG			//my_mvPhyShow(MACInfo->unit);	    printk ("ae531xMacControl: 0x%08x\tMacFlowControl: 0x%08x\n",		    ae531x_ReadMacReg(MACInfo, MacControl),		    ae531x_ReadMacReg(MACInfo, MacFlowControl));#endif            MAC_state->stats.tx_errors++;            if (cmdsts & (DescTxLateCollision | DescTxExcCollisions)) {                MAC_state->stats.tx_aborted_errors++;            }            if (cmdsts & (DescTxLostCarrier | DescTxNoCarrier)) {                MAC_state->stats.tx_carrier_errors++;            }        } else {           // MAC_state->stats.tx_bytes += length;//AE531X_DESC_STATUS_RX_SIZE(cmdsts);           // MAC_state->stats.tx_packets++;        }#endif        MAC_state->stats.collisions +=            ((cmdsts & DescTxCollMask) >> DescTxCollShift);        txq->reapDescAddr = txDesc;        reaped++;    }    if (reaped > 0) {        int i;#ifdef DEBUG		if (reaped > aeMaxReap) {			aeMaxReap = reaped;			printk("max reaped = %d\n", reaped);		}#endif        AE531X_PRINT(AE531X_DEBUG_TX_REAP,             ("reaped %d\n", reaped));        /*         * Re-start transmit queues for all ethernet devices         * associated with this MAC.         */            for (i=0; i<AE531X_DEV_PER_MAC; i++) {            if (MAC_state->dev_sw_state[i]->dev)                netif_start_queue(MAC_state->dev_sw_state[i]->dev);        }          } else {        aeUselessReap++;    }    LEAVE();}/******************************************************************************** ae531x_MAC_start_xmit sends a packet.*/static intae531x_MAC_start_xmit(struct sk_buff *skb, struct net_device *dev){    ae531x_dev_sw_state_t *dev_sw_state;    ae531x_MAC_state_t *MAC_state;    ae531x_MAC_t *MACInfo;    u32 buf;    u32 ctrlen;    u32 length, lenb1 = 0;    char *buf2 = NULL;    int mtu;    int max_buf_size;    VIRT_ADDR txDesc;    int iface;    unsigned long flags;    ARRIVE();    dev_sw_state = (ae531x_dev_sw_state_t *)dev->priv;    MAC_state = dev_sw_state->MAC_state;        MACInfo = &MAC_state->MACInfo;        iface = MACInfo->unit;    length = skb->len;    /* Check if this port is up, else toss packet */    if (!MACInfo->port_is_up) {        buf = virt_to_bus(skb->data);        AE531X_PRINT(AE531X_DEBUG_ERROR,                  ("eth%d Tx Down, dropping buf=0x%8.8x, length=0x%8.8x, skb=%p\n",                   dev_sw_state->enetUnit, buf, length, (void *)skb));        MAC_state->stats.tx_dropped++;        MAC_state->stats.tx_carrier_errors++;        goto dropFrame;    }    if (ae531x_IsInResetMode(MACInfo)) {        AE531X_PRINT(AE531X_DEBUG_ERROR,                  ("eth%d Tx: In Chip reset - drop frame\n",                   dev_sw_state->enetUnit));        MAC_state->stats.tx_dropped++;        MAC_state->stats.tx_aborted_errors++;        goto dropFrame;

⌨️ 快捷键说明

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