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

📄 drivers_net_arm_ep93xx_eth_c_diff.htm

📁 linux2.6.11.6drivers_net_arm_ep93xx_eth_c
💻 HTM
📖 第 1 页 / 共 5 页
字号:
+					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 + -