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

📄 drivers_net_arm_ep93xx_eth_c_diff.htm

📁 linux2.6.11.6drivers_net_arm_ep93xx_eth_c
💻 HTM
📖 第 1 页 / 共 5 页
字号:
+			pP->d.stats.tx_errors++;
+			if (pQTxSts->f.lcrs)
+				pP->d.stats.tx_carrier_errors++;	/*loss of CRS */
+			if (pQTxSts->f.txu)
+				pP->d.stats.tx_fifo_errors++;	/*underrun */
+			if (pQTxSts->f.ecoll)
+				pP->d.stats.collisions++;	/*excessive collision */
+		}		/*else */
+
+		/*ahead Tx Descriptor Queue tail index */
+		pP->d.idxQueTxDescTail =
+		    IdxNext(pP->d.idxQueTxDescTail, LEN_QueTxDesc);
+	}			/*while */
+
+	return 0;
+}				/*eth_cleanUpTx() */
+
+/*****************************************************************************
+* eth_restartTx()
+*****************************************************************************/
+static int eth_restartTx(struct net_device *pD)
+{
+	struct ep93xxEth_info *pP = netdev_priv(pD);
+	int i;
+
+	_PRTK_ENTRY(("eth_restartTx(pD:0x%p)\n", pD));
+
+	/*disable int */
+	RegWr32(REG_GIntMsk, RegRd32(REG_GIntMsk) & ~GIntMsk_IntEn);	/*turn off master INT control */
+
+	/*stop Tx and Tx DMA */
+	RegWr32(REG_TxCTL, RegRd32(REG_TxCTL) & ~TxCTL_STxON);	/*Tx off */
+	RegWr32(REG_BMCtl, RegRd32(REG_BMCtl) | BMCtl_TxDis);	/*disable Tx DMA */
+
+	/*reset Tx DMA */
+	RegWr32(REG_BMCtl, BMCtl_TxChR | RegRd32(REG_BMCtl));	/*reset Tx DMA */
+
+	/*release Tx buffers */
+	for (i = 0; i < LEN_QueTxDesc; i++) {
+		if (pP->s.pTxBufDesc[i].pFreeRtn) {
+			pP->s.pTxBufDesc[i].pFreeRtn(pP->s.pTxBufDesc[i].vaddr);
+			pP->s.pTxBufDesc[i].pFreeRtn = NULL;
+		}		/*if */
+		pP->d.stats.tx_dropped++;
+	}			/*for */
+
+	/*init Tx Queues and flush cache */
+	memset(pP->s.pQueTxSts, 0, sizeof(pP->s.pQueTxSts[0]) * LEN_QueTxSts);	/*clear FP flag */
+
+	/*init variables */
+	pP->d.txStopped = 0;
+	pP->d.idxQueTxSts = pP->d.idxQueTxDescHead = pP->d.idxQueTxDescTail = 0;
+
+	/*init registers */
+	waitOnReg32(pD, REG_BMSts, BMCtl_TxChR, ~BMCtl_TxChR, 1);	/*wait to finish Tx DMA reset */
+	RegWr32(REG_TxSBA, pP->s.phyQueTxSts);	/*base addr of Tx Status Queue */
+	RegWr32(REG_TxSCA, pP->s.phyQueTxSts);	/*current addr */
+	RegWr16(REG_TxSBL, sizeof(pP->s.pQueTxSts[0]) * LEN_QueTxSts);	/*base len */
+	RegWr16(REG_TxSCL, sizeof(pP->s.pQueTxSts[0]) * LEN_QueTxSts);	/*current len */
+	RegWr32(REG_TxDBA, pP->s.phyQueTxDesc);	/*base addr of Tx Descriptor Queue */
+	RegWr32(REG_TxDCA, pP->s.phyQueTxDesc);	/*current addr */
+	RegWr16(REG_TxDBL, sizeof(pP->s.pQueTxDesc[0]) * LEN_QueTxDesc);	/*base len */
+	RegWr16(REG_TxDCL, sizeof(pP->s.pQueTxDesc[0]) * LEN_QueTxDesc);	/*current len */
+
+	/*start Tx and Tx DMA */
+	RegWr32(REG_TxCTL, RegRd32(REG_TxCTL) | TxCTL_STxON);	/*Tx on */
+	RegWr32(REG_BMCtl, RegRd32(REG_BMCtl) | BMCtl_TxEn);	/*enable Tx DMA */
+
+	/*enable int again */
+	RegWr32(REG_GIntMsk, RegRd32(REG_GIntMsk) | GIntMsk_IntEn);	/*turn on master INT control */
+
+	return 0;
+}				/*eth_restartTx() */
+
+/*****************************************************************************
+* eth_reset()
+*****************************************************************************/
+static int eth_reset(struct net_device *pD)
+{
+	int err;
+
+	_PRTK_ENTRY(("eth_reset(pD:0x%p)\n", pD));
+
+	RegWr8(REG_SelfCTL, SelfCTL_RESET);	/*soft reset command */
+	err = waitOnReg32(pD, REG_SelfCTL, SelfCTL_RESET, ~SelfCTL_RESET, 1);
+	if (err)
+		_PRTK_WARN(("eth_reset(): Soft Reset does not self-clear\n"));
+
+	/*if */
+	/*reset PHY */
+	/*phy_reset(pD); */
+
+	return 0;
+}				/*eth_reset() */
+
+/*****************************************************************************
+ . Function: eth_shutDown()
+ . Purpose:  closes down the Ethernet module
+ . Make sure to:
+ .	1. disable all interrupt mask
+ .	2. disable Rx
+ .	3. disable Tx
+ .
+ . TODO:
+ .   (1) maybe utilize power down mode.
+ .	Why not yet?  Because while the chip will go into power down mode,
+ .	the manual says that it will wake up in response to any I/O requests
+ .	in the register space.   Empirical results do not show this working.
+* 
+*****************************************************************************/
+static int eth_shutDown(struct net_device *pD)
+{
+
+	_PRTK_ENTRY(("eth_shutDown(pD:0x%p)\n", pD));
+
+	eth_reset(pD);
+	/*@ power down the Ethernet module */
+
+	return 0;
+}				/*eth_shutDown() */
+
+/*****************************************************************************
+*  eth_enable()
+ 
+  Purpose:
+        Turn on device interrupt for interrupt driven operation.
+        Also turn on Rx but no Tx.
+* 
+*****************************************************************************/
+static int eth_enable(struct net_device *pD)
+{
+
+	_PRTK_ENTRY(("eth_enable(pD:0x%p)\n", pD));
+
+	RegWr32(REG_IntEn, Default_IntSrc);	/*setup Interrupt sources */
+	RegWr32(REG_GIntMsk, GIntMsk_IntEn);	/*turn on INT */
+	eth_rxCtl(pD, 1);	/*turn on Rx */
+
+	return 0;
+}				/*eth_enable() */
+
+/*****************************************************************************
+*  eth_init()
+ 
+  Purpose:
+        Reset and initialize the device.
+        Device should be initialized enough to function in polling mode.
+        Tx and Rx must be disabled and no INT generation.
+* 
+*****************************************************************************/
+static int eth_init(struct net_device *pD)
+{
+	int status;
+
+	_PRTK_ENTRY(("eth_init(pD:0x%p)\n", pD));
+
+	/*reset device */
+	eth_reset(pD);
+
+	/*init PHY */
+	gPhyAutoNegoDone = 0;
+	status = phy_init(pD);
+	if (status != 0) {
+		printk(KERN_WARNING "%s: No network cable detected!\n",
+		       pD->name);
+	}
+
+	/*init MAC */
+	RegWr32(REG_SelfCTL, 0x0f00);	/*Set MDC clock to be divided by 8
+					   and enable PreambleSuppress bit */
+	RegWr32(REG_GIntMsk, 0x00);	/*mask Interrupt */
+	RegWr32(REG_RxCTL, RxCTL_BA | RxCTL_IA0);	/*no Rx on at this point */
+	RegWr32(REG_TxCTL, 0x00);
+	RegWr32(REG_GT, 0x00);
+	RegWr32(REG_BMCtl, 0x00);
+	RegWr32(REG_RxBTH, (0x80 << 16) | (0x40 << 0));	/*Buffer Threshold */
+	RegWr32(REG_TxBTH, (0x80 << 16) | (0x40 << 0));
+	RegWr32(REG_RxSTH, (4 << 16) | (2 << 0));	/*Status Threshold */
+	RegWr32(REG_TxSTH, (4 << 16) | (2 << 0));
+	RegWr32(REG_RxDTH, (4 << 16) | (2 << 0));	/*Descriptor Threshold */
+	RegWr32(REG_TxDTH, (4 << 16) | (2 << 0));
+	RegWr32(REG_MaxFL, ((1518 + 1) << 16) | (944 << 0));	/*Max Frame Length & Tx Start Threshold */
+
+	RegRd32(REG_TxCollCnt);	/*clear Tx Collision Counter */
+	RegRd32(REG_RxMissCnt);	/*clear Rx Miss Counter */
+	RegRd32(REG_RxRntCnt);	/*clear Rx Runt Counter */
+
+	RegRd32(REG_IntStsC);	/*clear Pending INT */
+
+	RegWr32(REG_TxCTL, TxCTL_STxON | RegRd32(REG_TxCTL));	/*Tx on */
+
+	/*Set MAC address */
+	eth_indAddrWr(pD, AFP_AFP_IA0, &pD->dev_addr[0]);
+
+	/*init queue */
+	devQue_start(pD);
+
+	return 0;
+}				/*eth_init() */
+
+/*****************************************************************************
+*  driver_init()
+*
+*  Purpose:
+*        Logical driver initialization for an individual device
+*        Minimum device H/W access at this point
+*
+*  Task:
+*        Initialize the structure if needed
+*        print out my vanity message if not done so already
+*        print out what type of hardware is detected
+*        print out the ethernet address
+*        find the IRQ
+*        set up my private data
+*        configure the dev structure with my subroutines
+*        actually GRAB the irq.
+*        GRAB the region
+* 
+*****************************************************************************/
+static int __init driver_init(struct net_device *pD, u32 baseA, int irq)
+{
+	struct ep93xxEth_info *pP;
+	int err = 0;
+	int i;
+	struct resource *res;
+
+	_PRTK_ENTRY(("driver_init(pD:0x%p,baseA:0x%x,irq:%d)\n", pD,
+		     (unsigned int)baseA, irq));
+
+	/*print out driver version */
+	if (0 == numOfInstance)
+		printk("ep93xx_eth() version: %s", version);
+
+	/*allocate the private structure */
+	if (0 == pD->priv) {
+		pD->priv = kmalloc(sizeof(struct ep93xxEth_info), GFP_KERNEL);
+		if (0 == pD->priv) {
+			_PRTK_SYSFAIL((cardname
+				       " initDriver(): fail to allocate pD->priv\n"));
+			return -ENOMEM;
+		}		/*if */
+	}			/*if */
+	memset(pD->priv, 0x00, sizeof(struct ep93xxEth_info));	/*init to 0 */
+
+	/*privite info */
+	pP = netdev_priv(pD);
+	pP->s.id = numOfInstance;	/*device instance ID */
+	pP->s.miiIdPhy = 1;	/*MII Bus ID of PHY device */
+
+	/*device access info */
+	pD->base_addr = baseA;	/*base address */
+	pD->irq = irq;		/*IRQ number */
+
+	/*Grab the region so that no one else tries to probe this device */
+	res = request_region(baseA, DEV_REG_SPACE, cardname);
+	if (res == NULL) {
+		_PRTK_SYSFAIL((cardname
+			       " initDriver(): unable to get region 0x%x-0x%x\n",
+			       (int)baseA, (int)(baseA + DEV_REG_SPACE - 1)));
+		return -EAGAIN;
+	}
+
+	/*if */
+	/*Grab the IRQ (support no auto-probing) */
+	_PRTK_INFO(("initDriver(): grabbing IRQ %d\n", pD->irq));
+	err = request_irq(pD->irq, &ep93xxEth_isr, 0, cardname, pD);
+	if (err) {
+		_PRTK_SYSFAIL((cardname
+			       " initDriver(): unable to get IRQ %d (err=%d)\n",
+			       pD->irq, err));
+		return -EAGAIN;
+	}
+
+	/*if */
+	/*init device handler functions */
+	pD->open = &ep93xxEth_open;
+	pD->stop = &ep93xxEth_close;
+	pD->hard_start_xmit = &ep93xxEth_hardStartXmit;
+	pD->tx_timeout = &ep93xxEth_txTimeout;
+	pD->watchdog_timeo = /*@ HZ/2 */ HZ * 5;
+	pD->get_stats = &ep93xxEth_getStats;
+	pD->set_multicast_list = &ep93xxEth_setMulticastList;
+
+	/*Fill in the fields of the device structure with ethernet values */
+	ether_setup(pD);
+
+	/*init device descriptor/status queues */
+	devQue_init(pD);
+	/*reset the device, and put it into a known state */
+	eth_reset(pD);
+
+	/*print out the device info */
+	PRINTK((cardname " #%d at 0x%x IRQ:%d MAC", pP->s.id,
+		(int)pD->base_addr, pD->irq));
+	for (i = 0; i < 6; i++)
+		PRINTK((":%02x", pD->dev_addr[i]));
+	PRINTK(("\n"));
+
+	numOfInstance++;	/*inc Number Of Instance under this device driver */
+
+	return 0;
+}				/*driver_init() */
+
+/*****************************************************************************
+* eth_isrRx()
+*
+*  Interrupt Service Routines
+* 
+*****************************************************************************/
+static int eth_isrRx(struct net_device *pD)
+{
+	struct ep93xxEth_info *pP = netdev_priv(pD);
+	union receiveStatus *pQRxSts;
+	int idxQRxStsHead;	/*index of Rx Status Queue Head from device (next put point) */
+	int idxSts;
+	int cntStsProcessed, cntDescProcessed;
+	char *pDest;
+	struct sk_buff *pSkb;
+	int len;
+	unsigned int dt;
+
+	_PRTK_ENTRY_ISR(("eth_isrRx(pD:0x%x)\n", (unsigned int)pD));
+
+	/*get Current Rx Status Queue pointer */
+	dt = RegRd32(REG_RxSCA);
+	idxQRxStsHead = (dt - pP->s.phyQueRxSts) / sizeof(pP->s.pQueRxSts[0]);	/*convert to array index */
+	_PRTK_INFO_ISR(("eth_isrRx(): RxSCA:0x%x -> idx:%d\n", dt,
+			idxQRxStsHead));
+	if (!(0 <= idxQRxStsHead && idxQRxStsHead < LEN_QueRxSts)) {
+		_PRTK_HWFAIL(("eth_isrRx(): invalid REG_RxSCA:0x%x idx:%d (phyQueRxSts:0x%x Len:%x)\n", dt, idxQRxStsHead, (int)pP->s.phyQueRxSts, LEN_QueRxSts));
+		/*@ do recover */
+		return -1;
+	}
+
+	/*if */
+	/*process Rx (limit to idxQRxStsHead due to cache) */
+	cntStsProcessed = cntDescProcessed = 0;
+	while (idxQRxStsHead != pP->d.idxQueRxSts) {
+		idxSts = pP->d.idxQueRxSts;
+		pP->d.idxQueRxSts = IdxNext(pP->d.idxQueRxSts, LEN_QueRxSts);
+		pQRxSts = &pP->s.pQueRxSts[idxSts];
+		_PRTK_INFO_ISR(("eth_isrRx(): QRxSts[%d]:0x%x 0x%x\n", idxSts,
+				(unsigned int)pQRxSts->w.e0,
+				(unsigned int)pQRxSts->w.e1));
+		if (!pQRxSts->f.rfp) {	/*empty? */
+			_PRTK_HWFAIL(("eth_isrRx(): QueRxSts[%d] is empty; Hd:%d\n", idxSts, idxQRxStsHead));
+			/*@ do recover */
+			return -1;
+		}		/*if */
+		pQRxSts->f.rfp = 0;	/*mark processed */
+
+		if (pQRxSts->f.eob) {	/*buffer has data */
+			if (pQRxSts->f.bi == pP->d.idxQueRxDesc) {	/*check BI */
+				pP->d.idxQueRxDesc = IdxNext(pP->d.idxQueRxDesc, LEN_QueRxDesc);	/*inc Desc index */
+				cntDescProcessed++;
+				if (pQRxSts->f.eof && pQRxSts->f.rwe) {	/*received a frame without error */
+					len = pQRxSts->f.fl;
+					_PRTK_INFO_ISR(("eth_isrRx(): Rx Len:%d\n", len));
+					pSkb = dev_alloc_skb(len + 5);	/*alloc buffer for protocal stack */

⌨️ 快捷键说明

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