📄 if_eitp.c
字号:
unit = pDrvCtrl->idr.ac_if.if_unit; do { pDrvCtrl->txCleaning = TRUE; if (pDrvCtrl->tfdQueue.head == NULL) /* tfd queue empty */ needTxStart = TRUE; /* set flag */ else needTxStart = FALSE; /* process transmitted frames */ while (1) { /* Get TFD. No ints allowed while manipulating this queue. */ /* Disable system interrupts (NOTE #1) */ intLevel = intLock (); pTfd = (TFD*) eiQGet ((EI_LIST *)&pDrvCtrl->cleanQueue); /* Re-enable system interrupts */ intUnlock (intLevel); if (pTfd == NULL) break; pDrvCtrl->idr.ac_if.if_collisions += /* add any colls */ (pTfd->status & CFD_S_RETRY) ? 16 : /* excessive colls */ (pTfd->status & CFD_S_COLL_MASK); /* some colls */ if (!(pTfd->status & CFD_S_OK)) /* packet not sent */ { pDrvCtrl->idr.ac_if.if_oerrors++; /* incr err count */ pDrvCtrl->idr.ac_if.if_opackets--; /* decr sent count */ } /* return to tfdQ */ eiQPut (unit,(EI_LIST *)&pDrvCtrl->tfdQueue, (EI_NODE*)pTfd); } if (needTxStart) /* check flag */#ifdef BSD43_DRIVER eiTxStartup (unit);#else eiTxStartup (pDrvCtrl);#endif pDrvCtrl->txCleaning = FALSE; } while (pDrvCtrl->cleanQueue.head != NULL); /* check again */ }/********************************************************************************* eiHandleRecvInt - task level interrupt service for input packets** This routine is called at task level indirectly by the interrupt* service routine to do any message received processing.*/static void eiHandleRecvInt ( DRV_CTRL *pDrvCtrl ) { RFD *pRfd; do { pDrvCtrl->rcvHandling = TRUE; /* interlock with eiInt() */ while ((pRfd = eiRxQGet (pDrvCtrl)) != NULL) if (eiReceive (pDrvCtrl, pRfd) == OK) eiRxQPut (pDrvCtrl, pRfd); pDrvCtrl->rcvHandling = FALSE; /* interlock with eiInt() */ } while (eiRxQFull (pDrvCtrl)); /* make sure rx q still empty */ }/********************************************************************************* eiReceive - pass a received frame to the next layer up** Strips the Ethernet header and passes the packet to the appropriate* protocol. The return value indicates if buffer loaning was used to hold* the data. A return value of OK means that loaning was not done, and it* is therefore 'ok' to return the RFD to the Rx queue. A return value of ERROR* means that buffer loaning was employed, and so the RFD is still in use and* should not be returned to the Rx queue. In this latter case, the RFD will* eventually be returned by the protocol, via a call to our eiLoanFree().*/static STATUS eiReceive ( DRV_CTRL *pDrvCtrl, RFD *pRfd ) { ETH_HDR *pEh; u_char *pData; int len;#ifdef BSD43_DRIVER UINT16 etherType;#endif MBUF *m = NULL; BOOL rfdLoaned = FALSE; /* Check packet for errors. This should be completely unnecessary, * but since Intel does not seem capable of explaining the exact * functioning of the 'save bad frames' config bit, we will look for * errors. */ if ( ( pRfd->status & ( RFD_S_OK | RFD_S_COMPLETE ) ) != ( RFD_S_OK | RFD_S_COMPLETE ) ) { ++pDrvCtrl->idr.ac_if.if_ierrors; /* bump error counter */ eiRxQPut (pDrvCtrl, pRfd); /* free the RFD */ return (ERROR); } /* Bump input packet counter. */ ++pDrvCtrl->idr.ac_if.if_ipackets; len = pRfd->actualCnt & ~0xc000; /* get frame length */ pEh = (ETH_HDR *)pRfd->enetHdr; /* get ptr to ethernet header */ /* Service input hook */ if ( (etherInputHookRtn != NULL) ) { if ( (* etherInputHookRtn) (&pDrvCtrl->idr, (char *)pEh, len) ) { eiRxQPut (pDrvCtrl, pRfd); /* free the RFD */ return (OK); } } len -= EH_SIZE; pData = (u_char *) pRfd->enetData;#ifdef BSD43_DRIVER etherType = ntohs (pEh->ether_type);#endif /* we can loan out receive frames from 82596 receive queue if: * * 1) the threshold of loanable frames has not been exceeded * 2) size of the input ethernet frame is large enough to be used with * clustering. */ if ((pDrvCtrl->nLoanRfds > 0) && (USE_CLUSTER (len)) && ((m = build_cluster (pData, len, &pDrvCtrl->idr, MC_EI, &pRfd->refCnt, eiLoanFree, (int) pDrvCtrl, (int) pRfd, NULL)) != NULL)) { pDrvCtrl->nLoanRfds --; /* one less to loan */ rfdLoaned = TRUE; /* we loaned a frame */ } else m = copy_to_mbufs (pData, len, 0, &pDrvCtrl->idr); if (m != NULL)#ifdef BSD43_DRIVER do_protocol_with_type (etherType, m, &pDrvCtrl->idr, len);#else do_protocol (pEh, m, &pDrvCtrl->idr, len);#endif else pDrvCtrl->idr.ac_if.if_ierrors++; /* bump error counter */ return ((rfdLoaned) ? ERROR : OK); }/********************************************************************************* eiLoanFree - return a loaned receive frame descriptor** This routine is called by the protocol code when it has completed use of* an RFD that we loaned to it.*/static void eiLoanFree ( DRV_CTRL *pDrvCtrl, RFD *pRfd ) { eiRxQPut (pDrvCtrl, pRfd); pDrvCtrl->nLoanRfds ++; }/********************************************************************************* eiDeviceStart - reset and start the device** This routine assumes interrupts from the device have been disabled, and* that the driver control structure has been initialized.*/static STATUS eiDeviceStart ( int unit /* physical unit number */ ) { void *pTemp; DRV_CTRL *pDrvCtrl; SCP *pScp; /* system config ptr */ ISCP *pIscp; /* intermediate system config ptr */ SCB *pScb; /* system control block ptr */ unsigned long loopy; /* Get pointers */ pDrvCtrl = & drvCtrl [unit]; pScp = pDrvCtrl->pScp; pIscp = pDrvCtrl->pIscp; pScb = pDrvCtrl->pScb; /* Issue the reset operation to the device */ sys596Port (unit, PORT_RESET, NULL); /* Initialize the SCP */ pScp->scpRsv1 = pScp->scpRsv2 = pScp->scpRsv3 = 0; pScp->scpSysbus = pDrvCtrl->sysbus; pTemp = CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, pIscp); LINK_WR (&pScp->pIscp, pTemp); /* point SCP to ISCP */ /* Initialize the ISCP */ pIscp->iscpBusy = 1; pIscp->iscpRsv1 = 0; pTemp = CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, pScb); LINK_WR (&pIscp->pScb, pTemp); /* point ISCP to SCB */ /* Initialize the SCB */ bzero ((char *)pScb, sizeof (SCB)); /* Tell the device where the SCP is located */ pTemp = CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, pScp); sys596Port (unit, PORT_NEWSCP, (UINT32) pTemp); sys596ChanAtn (unit); /* * The device will now read our SCP and ISCP. It will clear the busy * flag in the ISCP. */ /* Delay here for ample time. Can not use taskDelay() because all * interrupts have been enabled, and thus no clock ticks. */ for ( loopy = 0x00100000; loopy--; ) ; if ( pIscp->iscpBusy == 1 ) return (ERROR); return (OK); }/********************************************************************************* eiDiag - format and issue a diagnostic command*/static STATUS eiDiag ( int unit ) { DRV_CTRL *pDrvCtrl; pDrvCtrl = & drvCtrl [unit]; bzero ((char *)pDrvCtrl->pCfd, sizeof (CFD)); /* zero command frame */ eiAction (unit, CFD_C_DIAG); /* run diagnostics */ if (!(pDrvCtrl->pCfd->cfdStatus & CFD_S_OK)) return (ERROR); return (OK); }/********************************************************************************* eiConfig - format and issue a config command*/static void eiConfig ( int unit ) { DRV_CTRL *pDrvCtrl; pDrvCtrl = & drvCtrl [unit]; bzero ((char *)pDrvCtrl->pCfd, sizeof (CFD)); /* zero command frame */ /* Recommeded i82596 User's Manual configuration values. Note that * the original manual, #296443-001, was full of errors. Errors in the * description of the config bytes that I am aware of are noted below. * It is possible there are further errors. Intel has replaced the * manual with #296853-001, which does correct some errors, but not all. */ pDrvCtrl->pCfd->cfdConfig.ccByte8 = 0x8e; pDrvCtrl->pCfd->cfdConfig.ccByte9 = 0xc8; /* The manual is wrong about bit 7 in byte 10. * A '0' allows reception of bad packets. * A '1' causes rejection of bad packets. */ pDrvCtrl->pCfd->cfdConfig.ccByte10 = 0xc0; pDrvCtrl->pCfd->cfdConfig.ccByte11 = 0x2e; /* loopback, NSAI */ pDrvCtrl->pCfd->cfdConfig.ccByte12 = 0x00; pDrvCtrl->pCfd->cfdConfig.ccByte13 = 0x60; pDrvCtrl->pCfd->cfdConfig.ccByte14 = 0x00; pDrvCtrl->pCfd->cfdConfig.ccByte15 = 0xf2; pDrvCtrl->pCfd->cfdConfig.ccByte16 = 0x00; /* promiscuous off */ pDrvCtrl->pCfd->cfdConfig.ccByte17 = 0x00; pDrvCtrl->pCfd->cfdConfig.ccByte18 = 0x40; /* The manual is wrong about 2 bits in byte 19. * Bit 5, multicast, a '1' disables. * Bit 2, include CRC, a '1' disables. */ pDrvCtrl->pCfd->cfdConfig.ccByte19 = 0xff; pDrvCtrl->pCfd->cfdConfig.ccByte20 = 0x00; pDrvCtrl->pCfd->cfdConfig.ccByte21 = 0x3f; eiAction (unit, CFD_C_CONFIG); /* configure the chip */ }/********************************************************************************* eiIASetup - format and issue an interface address command*/static void eiIASetup ( int unit ) { DRV_CTRL *pDrvCtrl; pDrvCtrl = & drvCtrl [unit]; bzero ((char *)pDrvCtrl->pCfd, sizeof (CFD)); /* zero command frame */ bcopy ( (char *)pDrvCtrl->idr.ac_enaddr, (char *)pDrvCtrl->pCfd->cfdIASetup.ciAddress, 6 ); eiAction (unit, CFD_C_IASETUP); /* setup the address */ }/********************************************************************************* eiRxStartup - start up the Receive Unit** Starts up the Receive Unit. Assumes that the receive structures are set up.*/static void eiRxStartup ( DRV_CTRL *pDrvCtrl ) { SCB *pScb = pDrvCtrl->pScb; void * pTemp; int intLevel; if (pScb->scbStatus & SCB_S_RUREADY) /* already running */ return; pTemp = CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, pDrvCtrl->pFreeRfd); LINK_WR (&pScb->pRF, pTemp); /* point to free Rfd */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -