📄 if_dc.c
字号:
if (tmd->tDesc0 & PCISWAP(TDESC0_OWN)) break; /* now bump the tmd disposal index pointer around the ring */ pDrvCtrl->txDiIndex = (pDrvCtrl->txDiIndex + 1) % pDrvCtrl->dcNumTds; pDrvCtrl->txCount--;#ifdef DC_DEBUG { UINT tdesc0 = PCISWAP(tmd->tDesc0); DC_STATS * pErrStats = &pDrvCtrl->errStats; if (tdesc0 & TDESC0_TO) pErrStats->txJbrTmo++; if (tdesc0 & TDESC0_LO) pErrStats->txLostCarrier++; if (tdesc0 & TDESC0_NC) pErrStats->txNoCarrier++; if (tdesc0 & TDESC0_LC) pErrStats->txLateCollision++; if (tdesc0 & TDESC0_HF) pErrStats->txHeartBeatFail++; if (tdesc0 & TDESC0_LF) pErrStats->txLinkFail++; if (tdesc0 & TDESC0_UF) pErrStats->txUnderflow++; if (tdesc0 & TDESC0_DE) pErrStats->txDeferred++; }#endif /* DC_DEBUG */ /* * TDESC0_ES is an "OR" of LC, NC, UF, EC. * here for error conditions. */ if (tmd->tDesc0 & PCISWAP(TDESC0_ES)) { /* check for no carrier */#if 0 /* HELP */ if ((tmd->tDesc0 & PCISWAP(TDESC0_NC | TDESC0_LO | TDESC0_LF)) && (pDrvCtrl->dcMediaBlocks.DontSwitch == 0)) { dcSelectMedia (pDrvCtrl); return; } pDrvCtrl->dcMediaBlocks.DontSwitch = 1;#endif pDrvCtrl->idr.ac_if.if_oerrors++; /* output error */ pDrvCtrl->idr.ac_if.if_opackets--; /* * If error was due to excess collisions, bump the collision * counter. */ if (tmd->tDesc0 & PCISWAP(TDESC0_EC)) pDrvCtrl->idr.ac_if.if_collisions += 16; /* bump the collision counter if late collision */ if (tmd->tDesc0 & PCISWAP(TDESC0_LC)) pDrvCtrl->idr.ac_if.if_collisions++; /* check for no carrier */#if 0 /* HELP */ if (tmd->tDesc0 & PCISWAP(TDESC0_NC | TDESC0_LO | TDESC0_LF)) { logMsg ("dc%d: no carrier\n", pDrvCtrl->idr.ac_if.if_unit, 0,0,0,0,0); dcSelectMedia (pDrvCtrl); }#endif /* * Restart chip on fatal errors. * The following code handles the situation where the transmitter * shuts down due to an underflow error. This is a situation that * will occur if the DMA cannot keep up with the transmitter. * It will occur if the device is being held off from DMA access * for too long or due to significant memory latency. DRAM * refresh or slow memory could influence this. Many * implementation use a dedicated device buffer. This can be * static RAM to eliminate refresh conflicts; or dual-port RAM * so that the device can have free run of this memory during its * DMA transfers. */ if (tmd->tDesc0 & PCISWAP(TDESC0_UF)) { pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING); netJobAdd ((FUNCPTR)dcRestart, pDrvCtrl->idr.ac_if.if_unit, 0,0,0,0 ); return; } } tmd->tDesc0 = 0; /* clear all error & stat stuff */ } /* Flush the write pipe */ CACHE_PIPE_FLUSH (); }/********************************************************************************* dcGetFullRMD - get next received message RMD** Returns ptr to next Rx desc to process, or NULL if none ready.*/LOCAL DC_RDE * dcGetFullRMD ( DRV_CTRL * pDrvCtrl /* pointer to device control struct */ ) { DC_RDE * rmd; /* pointer to Rx ring descriptor */ /* Refuse to do anything if flags are down */ if ( (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING) ) != (IFF_UP | IFF_RUNNING) ) return ((DC_RDE *) NULL); rmd = pDrvCtrl->rxRing + pDrvCtrl->rxIndex; /* form ptr to Rx desc */ DC_CACHE_INVALIDATE (rmd, RMD_SIZ); if ((rmd->rDesc0 & PCISWAP(RDESC0_OWN)) == 0) return (rmd); else return ((DC_RDE *) NULL); }/********************************************************************************* dcRecv - process the next incoming packet**/LOCAL STATUS dcRecv ( DRV_CTRL * pDrvCtrl, /* pointer to device control struct */ DC_RDE * rmd /* pointer to Rx ring descriptor */ ) { ENET_HDR * pEnetHdr; /* pointer to ethernet header */ MBUF * pMbuf = NULL; /* pointer to mbuf */ u_long pPhys; UCHAR * pData; /* pointer to data */ int len; /* length */ USHORT ether_type; /* ether packet type */#ifdef DC_DEBUG UINT32 rdesc0; /* desc0 status word */#endif /* DC_DEBUG */#ifdef DC_DEBUG rdesc0 = rmd->rDesc0; if (rdesc0 & PCISWAP(0x40000000)) pDrvCtrl->errStats.rxFiltrErr++; if (rdesc0 & PCISWAP(0x00004000)) pDrvCtrl->errStats.rxDescErr++; if (rdesc0 & PCISWAP(RDESC0_RF)) pDrvCtrl->errStats.rxRuntFrm++; if (rdesc0 & PCISWAP(RDESC0_TL)) pDrvCtrl->errStats.rxTooLong++; if (rdesc0 & PCISWAP(RDESC0_CS)) pDrvCtrl->errStats.rxCollision++; if (rdesc0 & PCISWAP(0x00000008)) pDrvCtrl->errStats.rxMiiErr++; if (rdesc0 & PCISWAP(RDESC0_DB)) pDrvCtrl->errStats.rxDribbleBit++; if (rdesc0 & PCISWAP(RDESC0_CE)) pDrvCtrl->errStats.rxCrcErr++;#endif /* DC_DEBUG */ /* Discard if we have errors */ if (rmd->rDesc0 & PCISWAP(RDESC0_ES)) { ++pDrvCtrl->idr.ac_if.if_ierrors; /* bump error stat */ goto cleanRXD; } /* Process clean packets */ ++pDrvCtrl->idr.ac_if.if_ipackets; /* bump statistic */ len = RDESC0_FL_GET(PCISWAP(rmd->rDesc0)); /* frame length */ len -= 4; /* Frame length includes CRC in it so subtract it */ /* Get pointer to packet */ pEnetHdr = DC_CACHE_PHYS_TO_VIRT(PCI_TO_MEM_PHYS(PCISWAP(rmd->rDesc2))); DC_CACHE_INVALIDATE (pEnetHdr, len); /* make the packet data coherent */ /* call input hook if any */ if ((etherInputHookRtn == NULL) || ((*etherInputHookRtn) (& pDrvCtrl->idr.ac_if, (char *) pEnetHdr, len)) == 0) { /* Adjust length to size of data only */ len -= SIZEOF_ETHERHEADER; /* Get pointer to packet data */ pData = ((u_char *) pEnetHdr) + SIZEOF_ETHERHEADER; ether_type = ntohs ( pEnetHdr->type ); /* OK to loan out buffer ? -> build an mbuf cluster */ if ((pDrvCtrl->nLoanRx > 0) && (USE_CLUSTER (len)) && (pMbuf = BUILD_CLUSTER (pDrvCtrl, pEnetHdr, pData, len))) { pPhys = (u_long) DC_CACHE_VIRT_TO_PHYS(MEM_TO_PCI_PHYS( (pDrvCtrl->lPool[--pDrvCtrl->nLoanRx]))); rmd->rDesc2 = PCISWAP(pPhys); } else { if ((pMbuf = bcopy_to_mbufs (pData, len, 0, & pDrvCtrl->idr.ac_if, pDrvCtrl->memWidth)) == NULL) { ++pDrvCtrl->idr.ac_if.if_ierrors; /* bump error stat */ goto cleanRXD; } } /* send on up... */ do_protocol_with_type (ether_type, pMbuf, &pDrvCtrl->idr, len); } /* Done with descriptor, clean up and give it to the device. */cleanRXD: /* clear status bits and give ownership to device */ rmd->rDesc0 = PCISWAP(RDESC0_OWN); /* Flush the write pipe */ CACHE_PIPE_FLUSH (); /* Advance our management index */ pDrvCtrl->rxIndex = (pDrvCtrl->rxIndex + 1) % pDrvCtrl->dcNumRds; return (OK); }#ifdef BSD43_DRIVER/********************************************************************************* dcOutput - driver output routine** This routine is called by the stack to transmit an mbuf.* This routine is called by the stack to transmit an mbuf.*/LOCAL int dcOutput ( IDR * pIDR, /* pointer to interface data record */ MBUF * pMbuf, /* pointer to mbuf */ SOCK * pDest /* pointer to destination sock */ ) { int unit = ((IFNET *)pIDR)->if_unit; DRV_CTRL * pDrvCtrl = &drvCtrl[unit]; int errorVal; errorVal = ether_output ((IFNET *)pIDR, pMbuf, pDest, (FUNCPTR) dcStartOutput, pIDR); if ((errorVal == ENOBUFS) && !pDrvCtrl->txFlushScheduled) {#ifdef DC_DEBUG pDrvCtrl->errStats.txDropped++;#endif /* DC_DEBUG */ dcTxFlush (pDrvCtrl); } return (errorVal); }#endif /* BSD43_DRIVER *//********************************************************************************* dcTxFlush - flush enqueued transmit buffers**/LOCAL void dcTxFlush ( DRV_CTRL * pDrvCtrl ) { int retry; int delayCount;#ifdef DC_DEBUG pDrvCtrl->errStats.txFlushCalled++; if (pDrvCtrl->idr.ac_if.if_snd.ifq_len) pDrvCtrl->errStats.txFlushNeeded++;#endif /* DC_DEBUG */ retry = DC_FLUSH_RETRIES; while (pDrvCtrl->idr.ac_if.if_snd.ifq_len && retry) { dcTxRingClean (pDrvCtrl); if (DC_TD_INDEX_NEXT(pDrvCtrl) != pDrvCtrl->txDiIndex) DC_START_OUTPUT (pDrvCtrl); else { for (delayCount=1000; delayCount--;) ; retry--; } }#ifdef DC_DEBUG if (pDrvCtrl->idr.ac_if.if_snd.ifq_len == 0) pDrvCtrl->errStats.txFlushDone++;#endif /* DC_DEBUG */ pDrvCtrl->txFlushScheduled = FALSE; } /********************************************************************************* dcStartOutput - send transmit buffers**/LOCAL void dcStartOutput (# ifdef BSD43_DRIVER int unit# else DRV_CTRL * pDrvCtrl# endif /* BSD43_DRIVER */ ) {# ifdef BSD43_DRIVER DRV_CTRL * pDrvCtrl = &drvCtrl[unit];# endif /* BSD43_DRIVER */ DC_TDE * pTxD; MBUF * pMbuf; char * pTxdBuf; int bufLen; int retries;#ifdef DC_DEBUG pDrvCtrl->errStats.txQsizeCur=pDrvCtrl->idr.ac_if.if_snd.ifq_len;#endif /* DC_DEBUG */ retries = MAX_TX_RETRIES; while (pDrvCtrl->idr.ac_if.if_snd.ifq_len && retries) { pTxD = pDrvCtrl->txRing + pDrvCtrl->txIndex; if (((pTxD->tDesc0 & PCISWAP(TDESC0_OWN)) != 0) || (DC_TD_INDEX_NEXT (pDrvCtrl) == pDrvCtrl->txDiIndex)) { dcTxRingClean (pDrvCtrl);#ifdef DC_DEBUG pDrvCtrl->errStats.txRetries++;#endif /* DC_DEBUG */ retries--; continue; } retries = MAX_TX_RETRIES; /* Get pointer to transmit buffer */ pTxdBuf = (char *)DC_CACHE_PHYS_TO_VIRT(PCI_TO_MEM_PHYS( PCISWAP(pTxD->tDesc2))); IF_DEQUEUE (&pDrvCtrl->idr.ac_if.if_snd, pMbuf); /* copy stuff */ bcopy_from_mbufs (pTxdBuf, pMbuf, bufLen, pDrvCtrl->memWidth); pTxD->tDesc0 = 0; /* clear buffer error status */ pTxD->tDesc1 &= PCISWAP (~TDESC1_TBS1_MSK); pTxD->tDesc1 |= PCISWAP (TDESC1_TBS1_PUT(max (ETHERSMALL, bufLen))); pTxD->tDesc0 = PCISWAP (TDESC0_OWN); /* give ownership to device */ CACHE_PIPE_FLUSH (); /* Flush the write pipe */ /* Advance our management index */ pDrvCtrl->txIndex = DC_TD_INDEX_NEXT (pDrvCtrl);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -