📄 if_eihk.c
字号:
* 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) + (pRfd->rbd.actualCnt & ~0xc000)); pEh = (ETH_HDR *)pRfd->enetHdr; /* ptr to ethernet header */ /* Service input hook */ if ( (etherInputHookRtn != NULL) ) { /* pull enetHdr down 2 bytes to be contiguous with enetData */ bcopyBytes((char *)pEh, ((char*)pEh+2), EH_SIZE); if ( (* etherInputHookRtn) (&pDrvCtrl->idr, ((char *)pEh+2), 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 */ /* 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. */ taskDelay (50); if ( pIscp->iscpBusy == 1 ) { printf ("\nei: device did not initialize\n"); return (ERROR); } return (OK); }/********************************************************************************* eiDiag - format and issue a diagnostic command*/static void 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)) printErr ("eiDiag: i82596 diagnostics failed.\n"); }/********************************************************************************* 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; 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 */ sys596IntDisable (pDrvCtrl->idr.ac_if.if_unit); if ((pScb->scbStatus & SCB_S_RUMASK) != SCB_S_RUIDLE) eiCommand (pDrvCtrl, SCB_C_RUABORT); /* abort if not idle */ eiCommand (pDrvCtrl, SCB_C_RUSTART); /* start receive unit */ sys596IntEnable (pDrvCtrl->idr.ac_if.if_unit); }/********************************************************************************* eiAction - execute the specified action with the CFD pointed to in pDrvCtrl** Do the command contained in the CFD synchronously, so that we know* it's complete upon return. This routine assumes that interrupts from the* device have been disabled.*/static void eiAction ( int unit, UINT16 action ) { void *pTemp; CFD *pCfd; SCB *pScb; DRV_CTRL *pDrvCtrl; pDrvCtrl = & drvCtrl [unit]; pCfd = pDrvCtrl->pCfd; pScb = pDrvCtrl->pScb; while (1) /* wait for idle command unit */ { if ((pScb->scbStatus & SCB_S_CUMASK) == SCB_S_CUIDLE) break; } { /* Prepare and issue the command to the device */ /* fill in CFD */ pCfd->cfdStatus = 0; /* clear status */ pCfd->cfdCommand = CFD_C_EL | action; /* fill in action */ LINK_WR (&pCfd->link, NULL); /* terminate link */ /* and the SCB */ pScb->scbCommand = SCB_S_CX | /* ack any events */ SCB_S_FR | SCB_S_CNA | SCB_S_RNR | SCB_C_CUSTART; /* start command unit */ pTemp = CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, pCfd);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -