📄 nicevbend.c
字号:
return (pRetCluster); } END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); DRV_LOG (DRV_DEBUG_POLL, "End Read!\n", 1, 2, 3, 4, 5, 6); return (NIC_CLUSTER)pRx; }/********************************************************************************* nicEvbRestart - restart chip after receive ring buffer overflow** This routine is the task-level handler that deals with a receive DMA* overflow condition. It gets access to the remote DMA, cleans up NIC* registers, empties the receive ring buffers, and then resends any* packet that was in the midst of transmission when the overflow hit.** RETURNS: N/A.*/LOCAL void nicEvbRestart ( NICEVB_END_DEVICE* pDrvCtrl, UINT8 cr ) { NIC_DEVICE * pNic = pDrvCtrl->pNic; /* NIC registers */ BOOL resend = FALSE;#ifdef NIC_INSTRUMENT nicRestartNb++;#endif nicEvbWriteCr (pNic, STP); nicEvbResetDelay (); /* wait at least 1.6 mSec */ if(!NIC_IS_IN_POLL_MODE()) { if (semTake(pDrvCtrl->dmaSem, 100) == ERROR) { DRV_LOG (DRV_DEBUG_LOAD, "nicRestart: can't obtain dmaSem\n", 0, 0, 0, 0, 0,0); semTake (pDrvCtrl->dmaSem, WAIT_FOREVER); } } nicEvbWriteReg (pNic, &pNic->Rbcr0, 0, RPAGE0); nicEvbWriteReg (pNic, &pNic->Rbcr1, 0, RPAGE0); if ((cr & TXP) && (!(nicEvbReadReg (pNic, &pNic->Isr, RPAGE0) & (TXE | PTX)))) resend = TRUE; nicEvbWriteReg (pNic, &pNic->Tcr, MODE1, RPAGE0); nicEvbWriteCr (pNic, RPAGE0 | ABORT | STA); /* back to page 0 */ END_FLAGS_SET (&pDrvCtrl->end, IFF_UP | IFF_RUNNING | IFF_NOTRAILERS); while (nicEvbRead (pDrvCtrl)) ; nicEvbWriteReg(pNic, &pNic->Isr, OVW, RPAGE0); nicEvbWriteReg (pNic, &pNic->Tcr, MODE0, RPAGE0); if (resend) nicEvbWriteCr (pNic, RPAGE0 | STA | TXP | ABORT); if(!NIC_IS_IN_POLL_MODE()) semGive(pDrvCtrl->dmaSem); nicEvbWriteReg (pNic, &pNic->Imr, PRXE | OVWE, RPAGE0); }/********************************************************************************* nicEvbHandleInt - deferred receive interrupt handler** This function handles the received frames from the device. It runs in the* context of the netTask, which was triggered by a received packet interrupt.* Actual processing of the packet is done by calling nicEvbRead().** RETURNS: N/A.*/LOCAL void nicEvbHandleInt ( NICEVB_END_DEVICE* pDrvCtrl ) { /* empties the receive ring buffer of its packets */ while (nicEvbRead (pDrvCtrl)); }/********************************************************************************* nicIntr - The driver's interrupt handler** This function clears the cause of the device interrupt(s) and then acts* on the individual possible causes. The primary goal of this routine is to* minimize the time spent in it. This is accomplished by deferring processing* to the netTask via the netJobAdd() function.** Note that in case the receiver overruns, we promptly mark the interface as* "down" and leave error handling to task-level. This is in case netTask* is in the midst of DMA activity, we must allow it to complete. The receive* handler will give up when it discovers the interface is down, which will* then allow netTask to run our OVW handler. This provides a nice orderly* error recovery.** RETURNS: N/A.*/LOCAL void nicEvbInt ( NICEVB_END_DEVICE* pDrvCtrl ) { NIC_DEVICE * pNic = pDrvCtrl->pNic; /* NIC registers */ UINT8 isr; /* copy of ISR */ UINT8 cr; /* copy of CR */#ifdef DRV_DEBUG nicIntNb++;#endif DRV_LOG (DRV_DEBUG_INT, "Inside INT\n", 1, 2, 3, 4, 5, 6); isr = nicEvbReadReg(pNic, &pNic->Isr, RPAGE0); nicEvbWriteReg(pNic, &pNic->Isr, isr, RPAGE0); /* handle receiver overrun */ if ((isr & OVW) && (END_FLAGS_GET(&pDrvCtrl->end) & (IFF_UP | IFF_RUNNING))) { cr = nicEvbReadReg (pNic, &pNic->Cr, RPAGE0); nicEvbWriteReg(pNic, &pNic->Imr, 0, RPAGE0); /* disable all interrupts */ /* mark the interface -- down */ END_FLAGS_CLR (&pDrvCtrl->end, IFF_UP | IFF_RUNNING); netJobAdd ((FUNCPTR) nicEvbRestart, (int) pDrvCtrl, cr, 0, 0, 0); return; } /* handle packet received */ if ((isr & PRX) && (END_FLAGS_GET(&pDrvCtrl->end) & (IFF_UP | IFF_RUNNING))) netJobAdd ((FUNCPTR) nicEvbHandleInt, (int) pDrvCtrl, 0, 0, 0, 0); }/********************************************************************************* nicEvbSend - the driver's actual output routine** This routine accepts outgoing packets from the snd queue, and then * gains exclusive access to the DMA (through a mutex semaphore),* then calls nicEvbTransmit() to send the packet out onto the interface.** RETURNS: OK, or ERROR if the packet could not be transmitted.*/LOCAL STATUS nicEvbSend ( NICEVB_END_DEVICE* pDrvCtrl, M_BLK* pMblk ) { int status = OK; DRV_LOG(DRV_DEBUG_TX, "Begin nicEvbSend pDrvCtrl %p pMblk %p\n", pDrvCtrl, pMblk, 0, 0, 0, 0); if ((END_FLAGS_GET(&pDrvCtrl->end) & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) { DRV_LOG(DRV_DEBUG_TX, "Device is NOT UP and RUNNING\n", 0, 0, 0, 0, 0, 0); if(!NIC_IS_IN_POLL_MODE()) netMblkClChainFree (pMblk); /* free the given mBlk chain */ errno = EINVAL; return (ERROR); } if(!NIC_IS_IN_POLL_MODE()) { if (semTake (pDrvCtrl->dmaSem, 100) == ERROR) /* get DMA access */ { DRV_LOG(DRV_DEBUG_TX, "nicTxStartup: can't obtain dmaSem\n", 0, 0, 0, 0, 0, 0); semTake (pDrvCtrl->dmaSem, WAIT_FOREVER); } } /* update statistics */ END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);#ifdef NIC_INSTRUMENT nicTxNb++;#endif /* send packet out over interface */ if ((status = nicEvbTransmit (pDrvCtrl, pMblk, TRUE)) == ERROR) { DRV_LOG(DRV_DEBUG_TX, "FAILED nicEvbTransmit\n", 0, 0, 0, 0, 0, 0); /* update statistics */ END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1); /* TODO update error count */ } if(!NIC_IS_IN_POLL_MODE()) { semGive (pDrvCtrl->dmaSem); /* free the Mblk chain */ netMblkClChainFree (pMblk); } DRV_LOG(DRV_DEBUG_TX, "End nicEvbSend \n", 0, 0, 0, 0, 0, 0); return status; }/********************************************************************************* nicEvbTransmit - send data over the NIC network interface** This routine transfers data to the NIC device via the remote DMA, and* then signal for a transmission.** RETURNS: OK, or ERROR if the transmitter signalled an error.*/LOCAL STATUS nicEvbTransmit ( NICEVB_END_DEVICE* pDrvCtrl, M_BLK* pMblk, BOOL waitFlag ) { NIC_DEVICE * pNic = pDrvCtrl->pNic; UINT8 cr; UINT8 isr; UINT8* pBuf; int status = OK; int count; int ix; int len; int tranxLen; /* find the length of the packet */ len = nicEvbMblkDataLenGet (pMblk); /* find the length of the packet */ tranxLen = max (len, MINPKTSIZE); #ifdef NIC_FASTER nicWriteReg(pNic, &pNic->Imr, 0, RPAGE0); /* disable all interrupts */#endif nicEvbWriteReg (pNic, &pNic->Rbcr0, 0x10, RPAGE0); nicEvbWriteCr (pNic, RREAD); nicEvbWriteReg (pNic, &pNic->Rbcr0, (tranxLen & 0x00ff), RPAGE0); nicEvbWriteReg (pNic, &pNic->Rbcr1, (tranxLen & 0xff00) >> 8, RPAGE0); nicEvbWriteReg (pNic, &pNic->Rsar0, 0x00, RPAGE0); nicEvbWriteReg (pNic, &pNic->Rsar1, 0x00, RPAGE0); nicEvbWriteCr (pNic, RWRITE); count = 0; while (pMblk != NULL) { pBuf = (char *)pMblk->mBlkHdr.mData; len = pMblk->mBlkHdr.mLen; for (ix = 0 ; ix < len; ix++) { count++; nicEvbWritePort (*pBuf++); } pMblk = pMblk->mBlkHdr.mNext; } for (; count < tranxLen; count ++) /* pad out if too short */ nicEvbWritePort (0); nicEvbWriteReg (pNic, &pNic->Tpsr, 0x00, RPAGE0); nicEvbWriteReg (pNic, &pNic->Tbcr0, (tranxLen & 0x000000ff), RPAGE0); nicEvbWriteReg (pNic, &pNic->Tbcr1, ((tranxLen & 0x0000ff00) >> 8), RPAGE0); cr = nicEvbReadReg (pNic, &pNic->Cr, RPAGE0); nicEvbWriteReg(pNic, &pNic->Isr, (PTX | TXE), RPAGE0); nicEvbWriteCr (pNic, TXP | (cr & (RWRITE | RREAD))); /* start Tx */ count = 0; if (waitFlag) /* wait for Tx to end ? */ { while (count++ < NIC_TRANS_TIMEOUT) /* only poll a few times */ { isr = nicEvbReadReg (pNic, &pNic->Isr, RPAGE0); if (isr & TXE) /* error encountered */ { DRV_LOG(DRV_DEBUG_TX, "ERROR in Transmition\n", 0, 0, 0, 0, 0, 0); status = ERROR; break; } if (isr & PTX) /* Tx done */ { DRV_LOG(DRV_DEBUG_TX, "Transmit Done\n", 0, 0, 0, 0, 0, 0); break; } } if (count >= NIC_TRANS_TIMEOUT) /* error ? */ { status = ERROR;#ifdef NIC_INSTRUMENT nicTxTimeout++;#endif DRV_LOG(DRV_DEBUG_LOAD, "nicTransmit TRANS_TIMEOUT %d\n", nicTxTimeout,0,0,0,0,0); } }#ifdef NIC_FASTER nicEvbWriteReg(pNic, &pNic->Imr, PRXE | OVWE, RPAGE0); /* re-enable intr. */#endif return (status); }/********************************************************************************* nicEvbMblkDataLenGet - gets the total len of the given Mblk chain packet** RETURNS: length of the packet.**/LOCAL int nicEvbMblkDataLenGet ( M_BLK* pMblk ) { int nPktChainLen = 0; while (pMblk != NULL) { nPktChainLen += pMblk->mBlkHdr.mLen; pMblk = pMblk->mBlkHdr.mNext; } return (nPktChainLen); }/********************************************************************************* nicEnetAddrGet - get the Ethernet address.** Get ethernet address from the BSP.** RETURNS: N/A.*/LOCAL void nicEvbEnetAddrGet ( NICEVB_END_DEVICE* pDrvCtrl, char* pAddress ) { UINT8 enetAdrs[6]; UINT8 count; if (sysEnetAddrGet (pDrvCtrl->unit, enetAdrs) != ERROR ) { for (count=0; count<6; count++) pAddress[count] = enetAdrs[5-count]; } }/********************************************************************************* nicEvbWritePort - write to the DMA port** RETURNS: N/A.*/LOCAL void nicEvbWritePort ( UINT8 value ) {#ifndef NIC_FASTER int level = intLock ();#endif do { *(volatile char *) NIC_PORT = value; } while (!((*(volatile UINT8 *) NIC_DMA) & ACC_MASK));#ifndef NIC_FASTER intUnlock (level);#endif } /********************************************************************************* nicIoctl - the driver's I/O control routine** Perform device-specific commands.** RETURNS: 0, or EINVAL if the command 'cmd' is not supported.*/LOCAL int nicEvbIoctl ( NICEVB_END_DEVICE* pDrvCtrl, int cmd, caddr_t data ) { int error = 0; DRV_LOG (DRV_DEBUG_LOAD, "nicEvbIoctl Command %d\n", cmd, 2, 3, 4, 5, 6); switch (cmd) { case EIOCSADDR: if (data == NULL) return (EINVAL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -