📄 ei82596end.c
字号:
/********************************************************************************* ei82596PollReceive - receive a packet in polled mode** RETURNS:*/LOCAL STATUS ei82596PollReceive ( END_CTRL *pDrvCtrl, M_BLK_ID pMblk ) { RFD *pRfd; int len; while ((pRfd = ei82596RxQGet (pDrvCtrl)) != NULL) { len = (pRfd->count & ~0xc000); if (((pRfd->status & (RFD_S_OK | RFD_S_COMPLETE)) != (RFD_S_OK | RFD_S_COMPLETE)) || (pMblk->mBlkHdr.mLen < len) || (!(pMblk->mBlkHdr.mFlags & M_EXT))) { END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); ei82596RxQPut (pDrvCtrl, pRfd); continue; } END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1); pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkHdr.mLen = len; pMblk->mBlkPktHdr.len = pMblk->mBlkHdr.mLen; bcopy ((char *)pRfd->enetHdr, (char *)pMblk->mBlkHdr.mData, len); ei82596RxQPut (pDrvCtrl, pRfd); DRV_LOG (DRV_DEBUG_POLL_RX, "R+ ", 0, 1, 2, 3, 4, 5); return (OK); } return (EAGAIN); }/********************************************************************************* ei82596DeviceStart - reset and start the device** This routine assumes interrupts from the device have been disabled, and* that the driver control structure has been initialized.*/LOCAL STATUS ei82596DeviceStart ( END_CTRL *pDrvCtrl ) { void *pTemp; SCP *pScp; /* system config ptr */ ISCP *pIscp; /* intermediate system config ptr */ SCB *pScb; /* system control block ptr */ int unit=pDrvCtrl->unit; pDrvCtrl->txBlocked = FALSE; /* Get pointers */ pScp = pDrvCtrl->pScp; pIscp = pDrvCtrl->pIscp; pScb = pDrvCtrl->pScb; /* perform board specific initializations */ sys596Init (pDrvCtrl->unit); /* Issue the reset operation to the device */ sys596Port (unit, PORT_RESET, 0); /* 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%d: device did not initialize\n", pDrvCtrl->unit); return (ERROR); } return (OK); }/********************************************************************************* ei82596Diag - format and issue a diagnostic command** Assumes that device interrupts are disabled.*/LOCAL STATUS ei82596Diag ( END_CTRL *pDrvCtrl ) { bzero ((char *)pDrvCtrl->pCfd, sizeof (CFD)); /* zero command frame */ ei82596Action (pDrvCtrl, CFD_C_DIAG); /* run diagnostics */ if (!(pDrvCtrl->pCfd->cfdStatus & CFD_S_OK)) { printErr ("eiDiag: i82596 diagnostics failed. cfdStatus=0x%x\n", pDrvCtrl->pCfd->cfdStatus); return (ERROR); } return (OK); }/********************************************************************************* ei82596Config - format and issue a config command*/LOCAL void ei82596Config ( END_CTRL *pDrvCtrl ) { 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 = DRV_FLAGS_ISSET (EI_PROMISC) ? 0x01 : 0x00; 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 = DRV_FLAGS_ISSET (EI_MCAST) ? 0xdf : 0xff; pDrvCtrl->pCfd->cfdConfig.ccByte20 = 0x00; pDrvCtrl->pCfd->cfdConfig.ccByte21 = 0x3f; ei82596Action (pDrvCtrl, CFD_C_CONFIG); /* configure the chip */ }/********************************************************************************* eiIASetup - format and issue an interface address command*/LOCAL void ei82596IASetup ( END_CTRL * pDrvCtrl ) { bzero ((char *)pDrvCtrl->pCfd, sizeof (CFD)); /* zero command frame */ bcopy ( (char *)END_HADDR(&pDrvCtrl->endObj), (char *)pDrvCtrl->pCfd->cfdIASetup.ciAddress, EADDR_LEN ); ei82596Action (pDrvCtrl, CFD_C_IASETUP); /* setup the address */ }/********************************************************************************* ei82596RxStartup - start up the Receive Unit** Starts up the Receive Unit. Assumes that the receive structures are set up.*/LOCAL void ei82596RxStartup ( END_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 */ if (! DRV_FLAGS_ISSET (EI_POLLING)) SYS_INT_DISABLE( pDrvCtrl ); if ((pScb->scbStatus & SCB_S_RUMASK) != SCB_S_RUIDLE) ei82596Command (pDrvCtrl, SCB_C_RUABORT); /* abort if not idle */ ei82596Command (pDrvCtrl, SCB_C_RUSTART); /* start receive unit */ if (! DRV_FLAGS_ISSET (EI_POLLING)) SYS_INT_ENABLE( pDrvCtrl ); }/********************************************************************************* ei82596Action - execute the specified action with the CFD** 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.*/LOCAL void ei82596Action ( END_CTRL *pDrvCtrl, UINT16 action ) { void *pTemp; CFD *pCfd; SCB *pScb; int unit=pDrvCtrl->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); LINK_WR (&pScb->pCB, pTemp); /* point chip at CFD */ sys596ChanAtn (unit); /* notify device of new command */ } while (1) /* wait for command acceptance and interrupt */ { if ((pScb->scbCommand == 0) && (pScb->scbStatus & SCB_S_CNA)) break; } /* Acknowledge the event to the device */ pScb->scbCommand = (SCB_S_CX | SCB_S_CNA); sys596ChanAtn (unit); while (1) /* wait for acknowledge acceptance */ { if (pScb->scbCommand == 0) break; } }/********************************************************************************* ei82596Command - deliver a command to the 82596 via SCB** This function causes the device to execute a command. It should be called* with interrupts from the device disabled. An error status is returned if* the command field does not return to zero, from a previous command, in a* reasonable amount of time.*/LOCAL STATUS ei82596Command ( END_CTRL *pDrvCtrl, UINT16 cmd ) { int loopy; SCB * pScb; pScb = pDrvCtrl->pScb; for (loopy = 0x8000; loopy--;) { if (pScb->scbCommand == 0) /* wait for cmd zero */ break; } if (loopy > 0) { pScb->scbCommand = cmd; /* fill in command */ sys596ChanAtn (pDrvCtrl->unit); /* channel attention */ return (OK); } else { logMsg("ei driver: command field frozen\n", 0, 0, 0, 0, 0, 0); return (ERROR); } }/********************************************************************************* ei82596DeviceRestart - reset the chip and reinitialize the tx and rx queues**/LOCAL void ei82596DeviceRestart ( END_CTRL * pDrvCtrl ) { EI_LIST tmpQueue; EI_NODE *pNode; BOOL doMuxTxRestart; /* Do we need to restart the mux? */ /* mark the interface -- down */ END_FLAGS_CLR (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING)); /* disable interrupts */ SYS_INT_DISABLE( pDrvCtrl ); doMuxTxRestart = pDrvCtrl->txBlocked; /* reset the device */ if (ei82596DeviceStart (pDrvCtrl) == ERROR) return; /* discard the current cbl list, thread it to clean list */ END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER); ei82596QCat (&pDrvCtrl->cleanQueue, &pDrvCtrl->cblQueue); ei82596QInit (&pDrvCtrl->cblQueue); END_TX_SEM_GIVE (&pDrvCtrl->endObj); /* reset watchdog timer counts */ pDrvCtrl->wdTxTimeout = 0; pDrvCtrl->wdRxTimeout = 0; /* stop the receiver, and command units */ ei82596Command (pDrvCtrl, SCB_C_RUABORT); ei82596Command (pDrvCtrl, SCB_C_CUABORT); if (ei82596Diag (pDrvCtrl) == ERROR) return; ei82596Config (pDrvCtrl); ei82596IASetup (pDrvCtrl); /* If we are not cleaning now, schedule one */ if (! pDrvCtrl->txCleaning) { pDrvCtrl->txCleaning = TRUE; netJobAdd ((FUNCPTR) ei82596TxCleanQ, (int) pDrvCtrl, 0, 0, 0, 0); } if (pDrvCtrl->txQueue.head != NULL) /* anything to flush? */ ei82596TxQFlush (pDrvCtrl); /* flush the tx q */ else pDrvCtrl->txI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -