📄 nicevbend.c
字号:
** nicReadReg - read from a NIC register** RETURNS: the register value.*/LOCAL UINT8 nicEvbReadReg ( NIC_DEVICE * pNic, volatile UINT8 * pReg, char page ) { volatile UINT8 * nicDma = (volatile UINT8 *) NIC_DMA; UINT8 cr; int level = intLock (); do { cr = pNic->Cr; } while (!((*nicDma) & ACC_MASK)); if ((cr & PBMASK) != page) do { pNic->Cr = (cr & 0x3f) | page; } while (!((*nicDma) & ACC_MASK)); do { cr = *pReg; } while (!((*nicDma) & ACC_MASK)); intUnlock (level); return (cr); }/********************************************************************************* nicEvbReadPort - read from the DMA port** RETURNS: the DMA port value.*/LOCAL UINT8 nicEvbReadPort (void) { UINT8 value;#ifndef NIC_FASTER int level = intLock ();#endif do { value = *(volatile UINT8 *) NIC_PORT; } while (!((*(volatile UINT8 *) NIC_DMA) & ACC_MASK));#ifndef NIC_FASTER intUnlock (level);#endif return (value); }/********************************************************************************* nicEvbReceive - receive data from the NIC network interface** This routine transfers data from the NIC device ring buffers via the* remote DMA.** RETURNS: OK, always.*/LOCAL STATUS nicEvbReceive ( NICEVB_END_DEVICE* pDrvCtrl, UINT32 nicBufAddr, char* pData, int len ) { NIC_DEVICE * pNic = pDrvCtrl->pNic; int residual; int dmaCnt; int ix;#ifdef NIC_FASTER nicEvbWriteReg(pNic, &pNic->Imr, 0, RPAGE0); /* disable all interrupts */#endif DRV_LOG (DRV_DEBUG_RX, "nicReceive: nicBufAddr:%u pData:%p len:%d\n", nicBufAddr, pData, len, 0, 0, 0); if ((nicBufAddr + len) < (PSTOP * PACKET_SIZE)) { nicEvbWriteReg (pNic, &pNic->Rbcr0, (len & 0xff), RPAGE0); nicEvbWriteReg (pNic, &pNic->Rbcr1, ((len & 0xff00) >> 8), RPAGE0); nicEvbWriteReg (pNic, &pNic->Rsar0, (nicBufAddr & 0xff), RPAGE0); nicEvbWriteReg (pNic, &pNic->Rsar1, (((nicBufAddr & 0xff00)>> 8)), RPAGE0); nicEvbWriteCr (pNic, RREAD); for (ix = 0; ix < len; ix ++) *pData++ = nicEvbReadPort (); } else { residual = (nicBufAddr + len) - (PSTOP * PACKET_SIZE); dmaCnt = len - residual; nicEvbWriteReg (pNic, &pNic->Rbcr0, (dmaCnt & 0xff), RPAGE0); nicEvbWriteReg (pNic, &pNic->Rbcr1, ((dmaCnt & 0xff00) >> 8), RPAGE0); nicEvbWriteReg (pNic, &pNic->Rsar0, (nicBufAddr & 0xff), RPAGE0); nicEvbWriteReg (pNic, &pNic->Rsar1, (((nicBufAddr & 0xff00)>> 8)), RPAGE0); nicEvbWriteCr (pNic, RREAD); for (ix = 0; ix < dmaCnt; ix++) *pData++ = nicEvbReadPort (); nicEvbWriteReg (pNic, &pNic->Rbcr0, (residual & 0xff), RPAGE0); nicEvbWriteReg (pNic, &pNic->Rbcr1, ((residual & 0xff00) >> 8), RPAGE0); nicEvbWriteReg (pNic, &pNic->Rsar0, 0x00, RPAGE0); nicEvbWriteReg (pNic, &pNic->Rsar1, PSTART, RPAGE0); nicEvbWriteCr (pNic, RREAD); for (ix = 0; ix < residual; ix++) *pData++ = nicEvbReadPort (); }#ifdef NIC_FASTER nicEvbWriteReg(pNic, &pNic->Imr, PRXE | OVWE, RPAGE0); /* re-enable intr. */#endif return (OK); } /********************************************************************************* nicEvbPktBufRead - read data from the NIC receive ring buffer** This routine gets exclusive access to the remote DMA, and calls* nicReceive() to get data from the NIC's receive ring buffer.** RETURNS: OK, or ERROR if obtaining the requested bytes encountered an error.*/LOCAL STATUS nicEvbPktBufRead ( NICEVB_END_DEVICE* pDrvCtrl, UINT32 nicBufAddr, UINT32 len, char* pData ) { STATUS status = OK; /* avoid starting DMA if device is down to to fatal error */ if ((END_FLAGS_GET(&pDrvCtrl->end) & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) { DRV_LOG (DRV_DEBUG_RX, "nicPktBufRead: NOT UP and RUNNING\n", 0, 0, 0, 0, 0, 0); return (ERROR); } if (!NIC_IS_IN_POLL_MODE()) { if (semTake (pDrvCtrl->dmaSem, 100) == ERROR) /* get DMA */ { DRV_LOG (DRV_DEBUG_LOAD, "nicPktBufRead: can't obtain dmaSem\n", 0, 0, 0, 0, 0, 0); semTake (pDrvCtrl->dmaSem, WAIT_FOREVER); } } status = nicEvbReceive (pDrvCtrl, nicBufAddr, pData, len); if (!NIC_IS_IN_POLL_MODE()) semGive(pDrvCtrl->dmaSem); return (status); }/********************************************************************************* nicEvbPagePtrUpdate - updates receive buffer/page pointers** This routine updates the receive buffer/page pointer and the receive* boundary register (BNRY). The chip is re-initialized if the receive next * packet pointer recorded in the current packet header is out of range.** RETURNS: TRUE, or FALSE if next packet pointer is out of range.*/ LOCAL BOOL nicEvbPagePtrUpdate ( NICEVB_END_DEVICE* pDrvCtrl, NIC_CLUSTER pRxCluster ) { NIC_RX_FRAME* pRx = (NIC_RX_FRAME*)pRxCluster; NIC_DEVICE* pNic = pDrvCtrl->pNic; /* update ring buffer/page pointers */ if ((pRx->rxHdr.nextRxPage < PSTART)||(pRx->rxHdr.nextRxPage >= PSTOP)) { DRV_LOG (DRV_DEBUG_LOAD, "nicPagePtrUpdate: statusHeader=0x%x nextRxPage=%d IntNb=%d\n", pRx->rxHdr.status, pRx->rxHdr.nextRxPage, nicIntNb, 0, 0, 0);#ifdef NIC_INSTRUMENT nicInitNb++;#endif /* TODO MID increament error count */ /* pDrvCtrl->idr.ac_if.if_ierrors++; */ /* restart the chip - we should never end up here - */ /* nicEvbConfig (0); HELP was index 0 */ nicEvbConfig (pDrvCtrl); pDrvCtrl->nextPkt = CURR; /* mark the interface -- up */ END_FLAGS_SET (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING | IFF_MULTICAST | IFF_BROADCAST)); return (FALSE); } /* updates the Boundary pointer register (BNRY) */ if ((pDrvCtrl->nextPkt = pRx->rxHdr.nextRxPage) == PSTART) nicEvbWriteReg (pNic, &pNic->Bnry, PSTOP - 1, RPAGE0); else nicEvbWriteReg (pNic, &pNic->Bnry, pDrvCtrl->nextPkt - 1, RPAGE0); return (TRUE); }/********************************************************************************* nicEvToStack - passes received data to stack** This routine grabs a MBuf from the pool, assigns data pointer to pointes the * receive data and passes the MBuf to stack.** RETURNS: OK, or ERROR in case of any error.*/LOCAL STATUS nicEvbToStack ( NICEVB_END_DEVICE* pDrvCtrl, /* the device */ NIC_CLUSTER pCluster ) { NIC_RX_FRAME* pRx = (NIC_RX_FRAME*)pCluster; CL_BLK_ID pClBlk; M_BLK_ID pMblk; UINT32 len; STATUS nRetValue = ERROR; len = pRx->rxHdr.cntL + (pRx->rxHdr.cntH << 8) - NIC_ETH_CRC_LEN; if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL) { DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!\n", 1, 2, 3, 4, 5, 6); netClFree (pDrvCtrl->end.pNetPool, pCluster); END_ERR_ADD (&pDrvCtrl->end, 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->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL) { netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk); netClFree (pDrvCtrl->end.pNetPool, pCluster); DRV_LOG (DRV_DEBUG_MB, "Out of M Blocks!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); goto cleanRXD; } END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); /* Join the cluster to the MBlock */ netClBlkJoin (pClBlk, (char*)pCluster, len, NULL, 0, 0, 0); netMblkClJoin (pMblk, pClBlk); /* make the packet data coherent */ /* LN_CACHE_INVALIDATE (pMblk->mBlkHdr.mData, len); */ /* pMblk->mBlkHdr.mData += pDrvCtrl->offset; */ NIC_FRAME_DATA_ADDR_GET(pCluster); pMblk->mBlkHdr.mLen = len; pMblk->mBlkHdr.mData = pCluster; pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkPktHdr.len = len; /* Call the upper layer's receive routine. */ END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk); return nRetValue;cleanRXD: return OK; }/********************************************************************************* nicEvbRead - read a packet off the interface ring buffer** nicRead copies packets from local memory into an mbuf and hands it to* the next higher layer (IP).** RETURNS: TRUE, or FALSE if the packet reception encountered errors.*/LOCAL BOOL nicEvbRead ( NICEVB_END_DEVICE* pDrvCtrl ) { NIC_CLUSTER pRxCluster; DRV_LOG (DRV_DEBUG_POLL, "Start Read!\n", 1, 2, 3, 4, 5, 6); pRxCluster = (NIC_CLUSTER)nicEvbReadFrame (pDrvCtrl); /* Pass the data up to the stack */ if (pRxCluster == NULL) return FALSE; nicEvbToStack (pDrvCtrl, pRxCluster); return (TRUE); }/********************************************************************************* nicEvbReadFrame - 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 NIC_CLUSTER nicEvbReadFrame ( NICEVB_END_DEVICE* pDrvCtrl ) { NIC_RX_FRAME* pRx; UINT32 len; /* len of Rx pkt */ int cur; NIC_CLUSTER pRetCluster = NULL; NIC_DEVICE* pNic = pDrvCtrl->pNic; /* NIC registers */ if (!(END_FLAGS_GET(&pDrvCtrl->end) & (IFF_UP | IFF_RUNNING)) || (pDrvCtrl->nextPkt == (cur = nicEvbReadReg (pNic, &pNic->Curr, RPAGE1)))) return (pRetCluster); /* * OK, 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 = (NIC_RX_FRAME*)netClusterGet(pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId)) == NULL) { DRV_LOG (DRV_DEBUG_RX, "Cannot loan!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); return (pRetCluster); } /* read header in cluster*/ DRV_LOG (DRV_DEBUG_RX, "nicPktBufRead : Reading Header\n", 1, 2, 3, 4, 5, 6); if (nicEvbPktBufRead (pDrvCtrl, pDrvCtrl->nextPkt << 8, (NIC_RX_HDR_SZ), (char *) &pRx->rxHdr) == ERROR) { DRV_LOG (DRV_DEBUG_RX, "nicRead could not read packet header\n", 0, 0, 0, 0, 0, 0); return (pRetCluster); } /* TODO */ len = pRx->rxHdr.cntL + (pRx->rxHdr.cntH << 8) - NIC_ETH_CRC_LEN; /* valid frame checks */ /* * NOTE: 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. */#ifdef NIC_INSTRUMENT nicLen = len; nicHdrStat = pRx->rxHdr.status; nicNextPage = pRx->rxHdr.nextRxPage; nicCurrentPage = cur;#endif if ((len < 60) || (len > 1514) || ((pRx->rxHdr.status & ~PHY) != PRX)) { /* TODO increament error count */ /* pDrvCtrl->idr.ac_if.if_ierrors++; */ DRV_LOG (DRV_DEBUG_LOAD, "nicRead receive error: statusHeader=0x%x nextRxPage=%d \ currentPage=%d len=%d IntNb=%d\n", pRx->rxHdr.status, pRx->rxHdr.nextRxPage, cur,len,nicIntNb, 0); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); nicEvbPagePtrUpdate (pDrvCtrl, (NIC_CLUSTER)pRx); return (pRetCluster); } /* copy Ethernet packet section of the frame */ DRV_LOG (DRV_DEBUG_RX, "nicPktBufRead : Reading Frame\n", 1, 2, 3, 4, 5, 6); if (nicEvbPktBufRead (pDrvCtrl, (pDrvCtrl->nextPkt << 8) + NIC_RX_HDR_SZ, len, (char *) &pRx->enetHdr) == ERROR) { DRV_LOG (DRV_DEBUG_LOAD, "nicRead: Could not read packet data\n", 0, 0, 0, 0, 0, 0); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); nicEvbPagePtrUpdate(pDrvCtrl, (NIC_CLUSTER)pRx); return (pRetCluster); } /* update ring buffer/page pointers */ if (!nicEvbPagePtrUpdate (pDrvCtrl, (NIC_CLUSTER)pRx)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -