📄 drivers_net_arm_ep93xx_eth_c_diff.htm
字号:
+ if (NULL != pSkb) {
+ skb_reserve(pSkb, 2); /*odd 16 bit alignment to make protocal stack happy */
+ pSkb->dev = pD;
+ pDest = skb_put(pSkb, len);
+
+ memcpy(pDest,
+ pP->s.
+ pRxBufDesc[pQRxSts->f.
+ bi].vaddr,
+ len);
+ pSkb->protocol =
+ eth_type_trans(pSkb, pD);
+ netif_rx(pSkb); /*pass Rx packet to system */
+ pD->last_rx = jiffies;
+ pP->d.stats.rx_packets++; /*inc Rx stat counter */
+ if (3 == pQRxSts->f.am)
+ pP->d.stats.multicast++; /*multicast */
+ } else {
+ _PRTK_SYSFAIL(("eth_isrRx(): Low Memory, Rx dropped\n"));
+ pP->d.stats.rx_dropped++;
+ } /*else */
+ } else { /*errored Rx */
+ _PRTK_INFO_ISR(("eth_isrRx(): errored Rx, QueRxSts[%d]:0x%x/0x%x\n", idxSts, (unsigned int)pP->s.pQueRxSts[idxSts].w.e0, (unsigned int)pP->s.pQueRxSts[idxSts].w.e1));
+ pP->d.stats.rx_errors++;
+ if (pQRxSts->f.oe)
+ pP->d.stats.rx_fifo_errors++; /*overrun */
+ if (pQRxSts->f.fe)
+ pP->d.stats.rx_frame_errors++; /*frame error */
+ if (pQRxSts->f.runt || pQRxSts->f.edata)
+ pP->d.stats.rx_length_errors++; /*inv length */
+ if (pQRxSts->f.crce)
+ pP->d.stats.rx_crc_errors++; /*crc error */
+ } /*else */
+ } else {
+ _PRTK_HWFAIL(("eth_isrRx(): unmatching QueRxSts[%d].BI:0x%x; idxQueRxDesc:0x%x\n", idxSts, pQRxSts->f.bi, pP->d.idxQueRxDesc));
+ } /*else */
+ }
+ /*if */
+ cntStsProcessed++;
+ } /*while */
+
+ /*enqueue */
+ _PRTK_INFO_ISR(("eth_isrRx(): enqueue QueRxSts:%d QueRxDesc:%d\n",
+ cntStsProcessed, cntDescProcessed));
+ RegWr32(REG_RxSEQ, cntStsProcessed);
+ RegWr32(REG_RxDEQ, cntDescProcessed);
+
+ return 0;
+} /*eth_isrRx() */
+
+/*****************************************************************************
+* eth_isrTx()
+*****************************************************************************/
+static int eth_isrTx(struct net_device *pD)
+{
+ _PRTK_ENTRY_ISR(("eth_isrTx(pD:0x%x)\n", (unsigned int)pD));
+
+ eth_cleanUpTx(pD);
+ eth_chkTxLvl(pD); /*resume Tx if it was stopped */
+ return 0;
+} /*eth_isrTx() */
+
+/*****************************************************************************
+* ep93xxEth_isr()
+*****************************************************************************/
+static irqreturn_t ep93xxEth_isr(int irq, void *pDev, struct pt_regs *pRegs)
+{
+ struct net_device *pD = pDev;
+ int lpCnt;
+ u32 intS;
+
+ _PRTK_ENTRY_ISR(("ep93xxEth_isr(irq:%d,pDev:0x%x,pRegs:0x%x)\n",
+ irq, (unsigned int)pDev, (unsigned int)pRegs));
+
+ lpCnt = 0;
+ do {
+ intS = RegRd32(REG_IntStsC); /*get INT status and then clear */
+
+ /*
+ intE=RegRd32(REG_IntEn); //get INT Source Enable
+ intS&=(intE&~0x07)|(IntSts_AHBE|IntSts_OTHER|IntSts_SWI)|
+ ((intE&0x07)?IntSts_RxSQ:0x00);
+ _PRTK_INFO_ISR(("ep93xxEth_isr(): intS:0x%x intE:0x%x\n",intS,intE));
+ */
+
+ if (!intS)
+ break; /*no INT */
+ if (IntSts_RxSQ & intS)
+ eth_isrRx(pD); /*Rx INT */
+ if (IntSts_TxSQ & intS)
+ eth_isrTx(pD); /*Tx INT */
+ } while (lpCnt++ < 64); /*limit loop to serve other interrupts too */
+ return IRQ_HANDLED;
+} /*ep93xxEth_isr() */
+
+/*=========================================================
+ * Exposed Driver Routines to the Outside World
+ *=======================================================*/
+
+/*****************************************************************************
+* ep93xxEth_getStats()
+*****************************************************************************/
+static struct net_device_stats *ep93xxEth_getStats(struct net_device *pD)
+{
+ _PRTK_ENTRY(("ep93xxEth_getStats(pD:0x%x)\n", (unsigned int)pD));
+
+#ifdef _PRTK_DUMP /*@ for debug */
+ {
+ static int tog = 0;
+ tog = tog ? 0 : 1;
+ if (tog) {
+ _dbg_ep9312Eth_dumpQueues(pD);
+ /*_dbg_phy_dumpReg(pD);*/
+ _dbg_ep9312eth_dumpReg(pD);
+ } /*if */
+ }
+#endif /*ifdef _PRTK_DUMP */
+
+ return &((struct ep93xxEth_info *)netdev_priv(pD))->d.stats;
+} /*ep93xxEth_getStats() */
+
+/*****************************************************************************
+* ep93xxEth_setMulticastList()
+*****************************************************************************/
+static void ep93xxEth_setMulticastList(struct net_device *pD)
+{
+ u8 tblMulti[8 + 1];
+
+ _PRTK_ENTRY(("ep93xxEth_setMulticastList(pD:0x%x)\n",
+ (unsigned int)pD));
+
+ if (IFF_PROMISC & pD->flags) { /*set promiscuous mode */
+ _PRTK_INFO(("ep93xxEth_setMulticastList(): set Promiscuous mode\n"));
+ RegWr32(REG_RxCTL, RxCTL_PA | RegRd32(REG_RxCTL));
+
+ } else if (IFF_ALLMULTI & pD->flags) { /*set to receive all multicast addr */
+ _PRTK_INFO(("ep93xxEth_setMulticastList(): set All-Multicast mode\n"));
+ RegWr32(REG_RxCTL, RxCTL_MA | (~RxCTL_PA & RegRd32(REG_RxCTL)));
+ eth_indAddrWr(pD, AFP_AFP_HASH,
+ "\xff\xff\xff\xff\xff\xff\xff\xff");
+
+ } else if (pD->mc_count) { /*set H/W multicasting filter */
+ _PRTK_INFO(("ep93xxEth_setMulticastList(): set Multicast mode\n"));
+ RegWr32(REG_RxCTL, RxCTL_MA | (~RxCTL_PA & RegRd32(REG_RxCTL)));
+ eth_setMulticastTbl(pD, &tblMulti[0]);
+ eth_indAddrWr(pD, AFP_AFP_HASH, &tblMulti[0]);
+
+ } else { /*no multicasting */
+ _PRTK_INFO(("ep93xxEth_setMulticastList(): no Promiscuous/Multicast\n"));
+ RegWr32(REG_RxCTL, ~(RxCTL_PA | RxCTL_MA) & RegRd32(REG_RxCTL));
+ } /*else */
+} /*ep93xxEth_setMulticastList() */
+
+/*****************************************************************************
+* ep93xxEth_txTimeout()
+*****************************************************************************/
+static void ep93xxEth_txTimeout(struct net_device *pD)
+{
+ int status;
+
+ _PRTK_ENTRY(("ep93xxEth_txTimeout(pD:0x%p)\n", pD));
+
+ /* If we get here, some higher level has decided we are broken.
+ There should really be a "kick me" function call instead. */
+ _PRTK_WARN(("ep93xxEth_txTimeout(): transmit timed out\n"));
+
+ /* Check if PHY Auto negotiation has done?
+ * If not, we need to check the Link status.
+ * If no network cable is present, just print a error message
+ */
+ if (gPhyAutoNegoDone == 0) {
+ status = phy_init(pD);
+ if (status != 0) {
+ printk(KERN_WARNING "%s: No network cable detected!\n",
+ pD->name);
+ return;
+ }
+ }
+
+ /*kick Tx engine */
+ eth_restartTx(pD);
+
+ /*ask the Network Stack to resume Tx */
+ pD->trans_start = jiffies;
+ netif_wake_queue(pD);
+} /*ep93xxEth_txTimeout() */
+
+/*****************************************************************************
+* ep93xxEth_hardStartXmit()
+*****************************************************************************/
+static int ep93xxEth_hardStartXmit(struct sk_buff *pSkb, struct net_device *pD)
+{
+
+/*@swk to check H/W defect of Tx Underrun Error caused by certain frame length*/
+
+ struct ep93xxEth_info *pP = netdev_priv(pD);
+ union transmitDescriptor *pQTxDesc;
+ int idxQTxDescHd;
+ int filled;
+ int status;
+
+ _PRTK_ENTRY(("ep93xxEth_hardStartXmit(pSkb:0x%x,pD:0x%x)\n",
+ (unsigned int)pSkb, (unsigned int)pD));
+
+ _PRTK_INFO(("ep93xxEth_hardStartXmit(): pSkb->len:0x%x\n", pSkb->len));
+
+ /* Check if PHY Auto negotiation has done?
+ * If not, we need to check the Link status
+ * and have PHY do auto-negotiation.
+ * If no network cable is present, just drop the packet.
+ */
+ if (gPhyAutoNegoDone == 0) {
+ status = phy_init(pD);
+ if (status != 0) {
+ return 1;
+ }
+ }
+
+ idxQTxDescHd = pP->d.idxQueTxDescHead;
+ pQTxDesc = &pP->s.pQueTxDesc[idxQTxDescHd];
+
+ /*check Tx Descriptor Queue fill-up level */
+ filled = idxQTxDescHd - pP->d.idxQueTxDescTail;
+ if (filled < 0)
+ filled += LEN_QueTxDesc;
+ filled += 1;
+
+ if ( /*!pP->d.txStopped&& */ LVL_TxStop <= filled) { /*check Queue level */
+ netif_stop_queue(pD); /*no more Tx allowed */
+ pP->d.txStopped = 1;
+ _PRTK_INFO(("ep93xxEth_hardStartXmit(): Tx STOP requested, filled:%d\n", filled));
+ if (LVL_TxStop < filled) {
+ /*this situation can not be happen */
+ _PRTK_SYSFAIL(("ep93xxEth_hardStartXmit(): a Tx Request while stop\n"));
+ return 1;
+ } /*if */
+ }
+
+ /*if */
+ /*fill up Tx Descriptor Queue entry */
+ if (pSkb->len < 60) {
+ pQTxDesc->f.bl = 60;
+ memset(pP->s.pTxBufDesc[idxQTxDescHd].vaddr, 0, 60);
+ } else {
+ pQTxDesc->f.bl = pSkb->len;
+ }
+ pQTxDesc->f.ba = virt_to_bus(pP->s.pTxBufDesc[idxQTxDescHd].vaddr);
+ pQTxDesc->f.bi = idxQTxDescHd;
+ pQTxDesc->f.af = 0;
+ pQTxDesc->f.eof = 1;
+ _PRTK_INFO(("ep93xxEth_hardStartXmit(): Tx buf:x%08x len:%d QTxD[%d]:x%08x x%08x\n", (unsigned int)pSkb->data, pSkb->len, (unsigned int)idxQTxDescHd, (unsigned int)pQTxDesc->w.e0, (unsigned int)pQTxDesc->w.e1));
+
+ /* copy data to Tx buffer */
+ memcpy(pP->s.pTxBufDesc[idxQTxDescHd].vaddr, pSkb->data, pSkb->len);
+ pP->s.pTxBufDesc[idxQTxDescHd].pFreeRtn = NULL;
+
+ /* Don't need this. Flush Tx buffer into memory */
+ /* dma_cache_wback(pP->s.pTxBufDesc[idxQTxDescHd].vaddr, pQTxDesc->f.bl); */
+
+ /* Free the data buffer passed by upper layer */
+ free_skb(pSkb);
+
+ pP->d.idxQueTxDescHead = IdxNext(pP->d.idxQueTxDescHead, LEN_QueTxDesc); /*ahead Tx Desc Queue */
+ RegWr32(REG_TxDEQ, 1); /* Enqueue a Tx Descriptor to the device */
+
+ return 0;
+} /*ep93xxEth_hardStartXmit() */
+
+/*****************************************************************************
+ . ep93xxEth_close()
+ .
+ . this makes the board clean up everything that it can
+ . and not talk to the outside world. Caused by
+ . an 'ifconfig ethX down'
+ *
+*****************************************************************************/
+
+static int ep93xxEth_close(struct net_device *pD)
+{
+
+ _PRTK_ENTRY(("ep93xxEth_close(pD:0x%x)\n", (unsigned int)pD));
+
+ disable_irq(pD->irq); /*request system to disable INT */
+
+ netif_stop_queue(pD);
+ eth_shutDown(pD); /*shut device down */
+
+ return 0;
+} /*ep93xxEth_close() */
+
+/*******************************************************
+ * ep93xxEth_open()
+ *
+ * Open and Initialize the board
+ *
+ * Set up everything, reset the card, etc ..
+ *
+ ******************************************************/
+static int ep93xxEth_open(struct net_device *pD)
+{
+ int status;
+ struct ep93xxEth_info *pP = netdev_priv(pD);
+
+ _PRTK_ENTRY(("ep93xxEth_open(pD:0x%x)\n", (unsigned int)pD));
+
+ memcpy(pD->dev_addr, default_mac, 6);
+ GET_MAC_ADDR(pD,&pD->dev_addr[0]);
+
+ /*clear dynamic device info */
+ memset(&pP->d, 0, sizeof(pP->d));
+
+ /*reset/init device */
+ status = eth_init(pD);
+ if (status != 0) {
+ return -EAGAIN;
+ }
+
+ /*turn on INT, turn on Rx */
+ eth_enable(pD);
+
+#if 0 /*@ */
+ _dbg_phy_dumpReg(pD);
+ _dbg_ep9312eth_dumpReg(pD);
+ _dbg_ep9312Eth_dumpQueues(pD);
+#endif
+
+ /*link to upper layer */
+ netif_start_queue(pD);
+
+ return 0;
+} /*ep9213Eth_open() */
+
+/*
+ * Linux-2.6 style probe function, stolen from eepro.c
+ */
+struct net_device *__init ep93xx_probe(int unit)
+{
+ struct net_device *dev = alloc_etherdev(sizeof(struct ep93xxEth_info));
+ int err;
+
+ if (!dev)
+ return ERR_PTR(-ENODEV);
+
+ SET_MODULE_OWNER(dev);
+
+ sprintf(dev->name, "eth%d", unit);
+
+ err = do_ep93xx_probe(dev);
+ if (err)
+ goto out;
+
+ err = register_netdev(dev);
+ if (err)
+ goto out1;
+ return dev;
+ out1:
+ release_region(dev->base_addr, DEV_REG_SPACE);
+
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -