📄 ns83902end.c
字号:
NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_ABORT | CR_STA, CR_RPAGE0); NS83902_REG_SET (pDrvCtrl, NS83902_TCR, TCR_MODE0, CR_RPAGE0); }/********************************************************************************* ns83902EnetAddrGet - get the Ethernet address.** Get ethernet address from the BSP.** RETURNS: N/A.*/LOCAL void ns83902EnetAddrGet ( NS83902_END_DEVICE* pDrvCtrl, char* addr ) {#if _BYTE_ORDER == _BIG_ENDIAN /* For big endian we need to swap byte order */ int i; char bytes[6]; SYS_ENET_ADDR_GET (pDrvCtrl, bytes); for (i=0; i<6; i++) *addr++ = bytes[5-i];#else /* _BYTE_ORDER == _LITTLE_ENDIAN */ /* Little endian is in correct order */ SYS_ENET_ADDR_GET (pDrvCtrl, addr);#endif /* _BYTE_ORDER == _BIG_ENDIAN */ }/********************************************************************************* ns83902WritePort - write to the DMA port** RETURNS: N/A.*/LOCAL void ns83902WritePort ( NS83902_END_DEVICE* pDrvCtrl, char * pBuf, int len ) { int ix; UINT16 * pWide; if (pDrvCtrl->wide == TRUE) { len = (++len) >> 1; pWide = (UINT16 *) pBuf; for (ix = 0 ; ix < len; ix++) { SYS_OUT_SHORT (pDrvCtrl, pDrvCtrl->ioPort, *pWide++); SYS_NS83902_DELAY(); } } else { for (ix = 0 ; ix < len; ix++) { SYS_OUT_BYTE (pDrvCtrl, pDrvCtrl->ioPort, *pBuf++); SYS_NS83902_DELAY(); } } } /********************************************************************************* ns83902ReadPort - read the DMA port** RETURNS: N/A.*/LOCAL void ns83902ReadPort ( NS83902_END_DEVICE* pDrvCtrl, char * pBuf, int len ) { int ix; UINT16 * pWide; if (pDrvCtrl->wide == TRUE) { len = (++len) >> 1; pWide = (UINT16 *) pBuf; for (ix = 0 ; ix < len; ix++) { SYS_IN_SHORT (pDrvCtrl, pDrvCtrl->ioPort, *pWide++); } } else { for (ix = 0 ; ix < len; ix++) { SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->ioPort, *pBuf++); } } } /********************************************************************************* ns83902PktBufRead - read data from the NIC receive ring buffer** This routine gets exclusive access to the remote DMA, and gets data from * the NIC's receive ring buffer.** RETURNS: OK, or ERROR if obtaining the requested bytes encountered an error.*/LOCAL STATUS ns83902PktBufRead ( NS83902_END_DEVICE* pDrvCtrl, UINT32 ns83902BufAddr, UINT32 len, char* pData ) { /* Exclusive DMA access */ if (!NS83902_IS_IN_POLL_MODE()) NS83902_SEM_TAKE (pDrvCtrl, WAIT_FOREVER); DRV_LOG (NS83902_DEBUG_RX, "ns83902Receive: ns83902BufAddr:%u pData:%p len:%d\n", ns83902BufAddr, (int)pData, len, 4, 5, 6); /* Set up remote read DMA transfer */ NS83902_REG_SET (pDrvCtrl, NS83902_RBCR0, LSB(len), CR_RPAGE0); NS83902_REG_SET (pDrvCtrl, NS83902_RBCR1, MSB(len), CR_RPAGE0); NS83902_REG_SET (pDrvCtrl, NS83902_RSAR0, LSB(ns83902BufAddr), CR_RPAGE0); NS83902_REG_SET (pDrvCtrl, NS83902_RSAR1, MSB(ns83902BufAddr), CR_RPAGE0); NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_RREAD, CR_RPAGE0); /* Get data through DMA port */ ns83902ReadPort (pDrvCtrl, pData, len); if (!NS83902_IS_IN_POLL_MODE()) NS83902_SEM_GIVE (pDrvCtrl); return (OK); }/********************************************************************************* ns83902ReadFrame - read a packet off the interface ring buffer into a cluster** Allocates a new cluster from the cluster pool, and reads the frame from the* device into the cluster.** RETURNS: a cluster or NULL if any error*/LOCAL NS83902_CLUSTER ns83902ReadFrame ( NS83902_END_DEVICE* pDrvCtrl ) { NS83902_RX_FRAME* pRx; NS83902_CLUSTER pRetCluster = NULL; UINT32 frameAddress; UINT16 len; /* len of Rx pkt */ UINT8 bnry; UINT8 rsr; UINT8 cur; /* Check receive status */ NS83902_REG_GET (pDrvCtrl, NS83902_RSR, rsr, CR_RPAGE0); if ((rsr & RSR_PRX) != RSR_PRX) return (pRetCluster); NS83902_REG_GET (pDrvCtrl, NS83902_CURR, cur, CR_RPAGE1); if (!(END_FLAGS_GET(&pDrvCtrl->endObj) & (IFF_UP | IFF_RUNNING)) || (pDrvCtrl->nextPage == cur)) return (pRetCluster); DRV_LOG (NS83902_DEBUG_RX, "Start Read!\n", 1, 2, 3, 4, 5, 6); /* * There is work to be done. * First we copy the NIC receive status header from the NIC buffer * into our local area. This is done so that we can obtain the length * of the packet before copying out the rest of it. Note that the length * field in the NIC header includes the Ethernet header, the data, and * the 4 byte FCS field. */ /* Get a cluster */ if ((pRx = (NS83902_RX_FRAME*) netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPoolId)) == NULL) { pDrvCtrl->lastError.errCode = END_ERR_NO_BUF; muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError); DRV_LOG (NS83902_DEBUG_RX, "Cannot loan!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); return (pRetCluster); } /* read header */ DRV_LOG (NS83902_DEBUG_RX, "ns83902PktBufRead : Reading Header\n", 1, 2, 3, 4, 5, 6); if (ns83902PktBufRead (pDrvCtrl, pDrvCtrl->nextPage << 8, (NS83902_RX_HDR_SZ), (char *) &pRx->rxHdr) == ERROR) { DRV_LOG (NS83902_DEBUG_RX, "ns83902PktBufRead could not read packet header\n", 0, 0, 0, 0, 0, 0); netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pRx); return (pRetCluster); } /* Calculate real length */ len = pRx->rxHdr.count;#if (_BYTE_ORDER == _BIG_ENDIAN) len = ((len >> 8) & 0x00ff) + ((len << 8) & 0xff00) - NS83902_ETH_CRC_LEN;#else len = len - NS83902_ETH_CRC_LEN;#endif /* write back value to rxHdr */ pRx->rxHdr.count = len; /* Current frame address and next page */ frameAddress = (pDrvCtrl->nextPage << 8) + NS83902_RX_HDR_SZ; pDrvCtrl->nextPage = pRx->rxHdr.nextRxPage; /* valid frame checks */#ifdef NS83902_INSTRUMENT ns83902Len = len; ns83902HdrStat = pRx->rxHdr.status; ns83902NextPage = pRx->rxHdr.nextRxPage; ns83902CurrentPage = cur;#endif /* check for critical error; should never happen */ if (pDrvCtrl->nextPage < pDrvCtrl->rxStartPage || pDrvCtrl->nextPage >= pDrvCtrl->rxStopPage ) { /* Can't recover, restart */#ifdef NS83902_INSTRUMENT ns83902InitNb++;#endif ns83902Config (pDrvCtrl); pDrvCtrl->nextPage = pDrvCtrl->rxStartPage; /* mark the interface up */ END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING | IFF_MULTICAST | IFF_BROADCAST)); netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pRx); return (pRetCluster); } /* * If the packet's receive status byte indicates an error the packet is * discarded and the receive page pointers are updated to point to the * next packet. */ if ((len < 60) || (len > 1514) || ((pRx->rxHdr.status & ~RSR_PHY) != RSR_PRX)) { DRV_LOG (NS83902_DEBUG_RX, "ns83902Rcv receive error: statusHeader=0x%x nextRxPage=%d \ currentPage=%d len=%d IntNb=%d\n", pRx->rxHdr.status, pRx->rxHdr.nextRxPage, cur, len, ns83902IntNb, 0); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); /* update boundary pointer */ if (pDrvCtrl->nextPage == pDrvCtrl->rxStartPage) bnry = pDrvCtrl->rxStopPage; else bnry = pDrvCtrl->nextPage - 1; NS83902_REG_SET (pDrvCtrl, NS83902_BNRY, bnry, CR_RPAGE0); netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pRx); return (pRetCluster); } /* copy Ethernet packet section of the frame */ DRV_LOG (NS83902_DEBUG_RX, "ns83902PktBufRead : Reading Frame\n", 1, 2, 3, 4, 5, 6); if (ns83902PktBufRead (pDrvCtrl, frameAddress, len, (char *) &pRx->enetHdr) == ERROR) { DRV_LOG (NS83902_DEBUG_RX, "ns83902Recv: Could not read packet data\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pRx); } else { /* Successfully got a frame */ pRetCluster = (NS83902_CLUSTER) pRx; END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1); } /* update boundary pointer */ if (pDrvCtrl->nextPage == pDrvCtrl->rxStartPage) bnry = pDrvCtrl->rxStopPage; else bnry = pDrvCtrl->nextPage - 1; NS83902_REG_SET (pDrvCtrl, NS83902_BNRY, bnry, CR_RPAGE0); DRV_LOG (NS83902_DEBUG_RX, "End Read!\n", 1, 2, 3, 4, 5, 6); return (pRetCluster); }/********************************************************************************* ns83902Recv - read a packet off the interface ring buffer** ns83902Recv copies packets from local memory into an mbuf and hands it to* the next higher layer (IP or etherInputHook).** RETURNS: TRUE, or FALSE if the packet reception encountered errors.*/LOCAL void ns83902Recv ( NS83902_END_DEVICE* pDrvCtrl, NS83902_CLUSTER pCluster ) { NS83902_RX_FRAME* pRx = (NS83902_RX_FRAME*) pCluster; CL_BLK_ID pClBlk; M_BLK_ID pMblk; UINT32 len = pRx->rxHdr.count; /* Process frame received */ if ((pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)) == NULL) { pDrvCtrl->lastError.errCode = END_ERR_NO_BUF; muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError); DRV_LOG (NS83902_DEBUG_RX, "Out of Cluster Blocks!\n", 1, 2, 3, 4, 5, 6); netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pCluster); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); goto cleanRXD; } /* * OK we've got a spare, let's get an M_BLK_ID and marry it to the * one in the ring. */ if ((pMblk = mBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT, MT_DATA)) == NULL) { netClBlkFree (pDrvCtrl->endObj.pNetPool, pClBlk); netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *)pCluster); DRV_LOG (NS83902_DEBUG_MB, "Out of M Blocks!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); goto cleanRXD; } END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1); /* Join the cluster to the MBlock */ netClBlkJoin (pClBlk, (char*)pCluster, len, NULL, 0, 0, 0); netMblkClJoin (pMblk, pClBlk); pMblk->mBlkHdr.mData = (char *)&pRx->enetHdr; pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* set the packet header */ pMblk->mBlkHdr.mLen = len; /* set the data len */ pMblk->mBlkPktHdr.len = len; /* set the total len */ /* Call the upper layer's receive routine. */ END_RCV_RTN_CALL (&pDrvCtrl->endObj, pMblk);cleanRXD: return; }/********************************************************************************* ns83902Restart - restart chip after receive ring buffer overflow** This routine is called from an isr handler that deals with a receive DMA* overflow condition. It gets access to the remote DMA, cleans up NIC* registers and defers work to task context to empty the receive ring buffers.** RETURNS: N/A.*/LOCAL void ns83902Restart ( NS83902_END_DEVICE* pDrvCtrl, UINT8 cr ) { UINT8 isr;#ifdef NS83902_INSTRUMENT ns83902RestartNb++;#endif /* Buffer ring overflow algorithm */ NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STP | CR_ABORT, CR_RPAGE0); /* wait at least 1.6 mSec */ SYS_MS_DELAY (2); /* Remove packets from buffer */ NS83902_REG_SET (pDrvCtrl, NS83902_RBCR0, 0, CR_RPAGE0); NS83902_REG_SET (pDrvCtrl, NS83902_RBCR1, 0, CR_RPAGE0); NS83902_REG_GET (pDrvCtrl, NS83902_ISR, isr, CR_RPAGE0); if ((cr & CR_TXP) && (!(isr & (ISR_TXE | ISR_PTX)))) pDrvCtrl->txResend = TRUE; NS83902_REG_SET (pDrvCtrl, NS83902_TCR, TCR_MODE1, CR_RPAGE0); NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_ABORT | CR_STA, CR_RPAGE0); END_FLAGS_SET (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING | IFF_NOTRAILERS); pDrvCtrl->rxOvw = TRUE; if (pDrvCtrl->rxHandling == FALSE) { pDrvCtrl->rxHandling = TRUE; netJobAdd ((FUNCPTR) ns83902HandleInt, (int) pDrvCtrl, 0, 0, 0, 0); } }/********************************************************************************* ns83902HandleInt - 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.* It resends any packet that was in the midst of transmission when the overflow* hit.* Actual processing of the packet is done by calling ns83902Recv().
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -