📄 if_eex.c
字号:
** This routine is called at task level indirectly by the interrupt* service routine to do any message received processing.*/static void eexHandleRecvInt ( DRV_CTRL *pDrvCtrl ) { EEX_SHORTLINK rfdOffset; do { pDrvCtrl->rcvHandling = TRUE; /* interlock with eexInt() */ while ( (rfdOffset = eexRxQGet (pDrvCtrl)) != NULL) (void) eexReceive (pDrvCtrl, rfdOffset); pDrvCtrl->rcvHandling = FALSE; /* interlock with eexInt() */ } while (eexRxQFull (pDrvCtrl)); /* make sure rx q still empty */ }/********************************************************************************* eexReceive - pass a received frame to the next layer up** Strips the Ethernet header and passes the packet to the appropriate* protocol.* Is responsible for proper disposition of frame buffer in all cases.*/static STATUS eexReceive ( DRV_CTRL *pDrvCtrl, EEX_SHORTLINK rfdOffset ) { struct ether_header * pEh; u_char * pData; int len;#ifdef BSD43_DRIVER UINT16 etherType;#endif MBUF * m = NULL; UINT16 status; /* 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. */ sysOutWord (pDrvCtrl->port + RDPTR, rfdOffset); status = sysInWord (pDrvCtrl->port + DXREG); if ( ( status & ( RFD_S_OK | RFD_S_COMPLETE ) ) != ( RFD_S_OK | RFD_S_COMPLETE ) ) { ++pDrvCtrl->idr.ac_if.if_ierrors; /* bump error counter */#ifdef EEX_DEBUG1 /* dhe 10/20/94 */ logMsg ("case 1: status=%x,offset=%x\n", status, rfdOffset, 0, 0, 0, 0);#endif eexRxQPut (pDrvCtrl, rfdOffset); /* free the RFD */ return (ERROR); } /* get frame length */ sysOutWord (pDrvCtrl->port + RDPTR, rfdOffset + RF_ACT_COUNT); len = sysInWord (pDrvCtrl->port + DXREG) & ACT_COUNT_MASK;#ifndef EEX_AL_LOC len += EH_SIZE;#endif /* EEX_AL_LOC */ sysOutWord (pDrvCtrl->port + RDPTR, rfdOffset + RF_BUFFER); sysInWordString (pDrvCtrl->port + DXREG, (short *) buffer, (len + 1) / 2); pEh = (struct ether_header *)buffer; /* get ptr to ethernet header */ /* Bump input packet counter. */ ++pDrvCtrl->idr.ac_if.if_ipackets; /* Service input hook */ if ( (etherInputHookRtn != NULL) ) { if ( (* etherInputHookRtn) (&pDrvCtrl->idr, (char *)pEh, len) ) {#ifdef EEX_DEBUG1 /* dhe 10/20/94 */ logMsg ("case 2: status=%x, offset=%x\n", status, rfdOffset, 0, 0, 0, 0);#endif eexRxQPut (pDrvCtrl, rfdOffset); /* free the RFD */ return (OK); } } len -= EH_SIZE; pData = (u_char *) buffer + EH_SIZE;#ifdef BSD43_DRIVER etherType = ntohs (pEh->ether_type);#endif 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 statistic */#ifdef EEX_DEBUG1 /* dhe 10/20/94 */ logMsg ("case 3: status=%x, offset=%x\n", status, rfdOffset, 0, 0, 0, 0);#endif eexRxQPut (pDrvCtrl, rfdOffset); /* free the RFD */ return (OK); }/********************************************************************************* eexDeviceStart - 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 eexDeviceStart ( int unit /* physical unit number */ ) { DRV_CTRL *pDrvCtrl; /* Get pointers */ pDrvCtrl = & drvCtrl [unit]; /* Ensure the 82586 is in its reset state */ eex586SetReset (unit); /* Initialize the SCP */ sysOutWord (pDrvCtrl->port + WRPTR, SCP_OFFSET); sysOutWord (pDrvCtrl->port + DXREG, 0); /* sysbus is 16-bit */ sysOutWord (pDrvCtrl->port + DXREG, 0); sysOutWord (pDrvCtrl->port + DXREG, 0); sysOutWord (pDrvCtrl->port + DXREG, ISCP_OFFSET); sysOutWord (pDrvCtrl->port + DXREG, 0); /* Initialize the ISCP */ sysOutWord (pDrvCtrl->port + WRPTR, ISCP_OFFSET); sysOutWord (pDrvCtrl->port + DXREG, 1); /* Set ISCP busy bit */ sysOutWord (pDrvCtrl->port + DXREG, SCB_OFFSET); sysOutWord (pDrvCtrl->port + DXREG, 0); /* SCB is zero-based */ sysOutWord (pDrvCtrl->port + DXREG, 0); /* Initialize the SCB */ /* WRPTR is at the SCB following ISCP initialization */ sysOutWord (pDrvCtrl->port + DXREG, 0); sysOutWord (pDrvCtrl->port + DXREG, 0); sysOutWord (pDrvCtrl->port + DXREG, 0); sysOutWord (pDrvCtrl->port + DXREG, 0); sysOutWord (pDrvCtrl->port + DXREG, 0); sysOutWord (pDrvCtrl->port + DXREG, 0); sysOutWord (pDrvCtrl->port + DXREG, 0); sysOutWord (pDrvCtrl->port + DXREG, 0); /* Tell the device to read the SCP */ eex586ClearReset (unit); eex586ChanAtn (pDrvCtrl); /* * The device will now read our SCP and ISCP. It will clear the busy * flag in the ISCP. */ taskDelay (50); sysOutWord (pDrvCtrl->port + RDPTR, ISCP_OFFSET); if ( sysInByte (pDrvCtrl->port + DXREG) == 1 ) { printf ("\neex: device did not initialize\n"); return (ERROR); } return (OK); }/********************************************************************************* eexDiag - format and issue a diagnostic command*/static void eexDiag ( int unit ) { DRV_CTRL *pDrvCtrl; pDrvCtrl = & drvCtrl [unit]; bzero ( (char *)pDrvCtrl->pCfd, sizeof (CFD)); /* zero command frame */ eexAction (unit, CFD_C_DIAG); /* run diagnostics */ if (!(pDrvCtrl->pCfd->cfdStatus & CFD_S_OK)) printErr ("eexDiag: i82586 diagnostics failed.\n"); }/********************************************************************************* eexConfig - format and issue a config command*/static void eexConfig ( int unit ) { DRV_CTRL *pDrvCtrl; pDrvCtrl = & drvCtrl [unit]; bzero ( (char *)pDrvCtrl->pCfd, sizeof (CFD)); /* zero command frame */ /* Recommended i82586 User's Manual configuration values. */ pDrvCtrl->pCfd->cfdConfig.byteCount = 12; pDrvCtrl->pCfd->cfdConfig.fifoLimit = 0x08; pDrvCtrl->pCfd->cfdConfig.srdy_saveBad = 0x40;#ifdef EEX_AL_LOC pDrvCtrl->pCfd->cfdConfig.addrLen_loopback = 0x2e;#else pDrvCtrl->pCfd->cfdConfig.addrLen_loopback = 0x26;#endif /* EEX_AL_LOC */ pDrvCtrl->pCfd->cfdConfig.backoff = 0x00; pDrvCtrl->pCfd->cfdConfig.interframe = 0x60; pDrvCtrl->pCfd->cfdConfig.slotTimeLow = 0x00; pDrvCtrl->pCfd->cfdConfig.slotTimeHi_retry = 0xf2; pDrvCtrl->pCfd->cfdConfig.promiscuous = 0x00; /* promiscuous off */ pDrvCtrl->pCfd->cfdConfig.carrier_collision = 0x00; pDrvCtrl->pCfd->cfdConfig.minFrame = 0x40; eexAction (unit, CFD_C_CONFIG); /* configure the chip */ }/********************************************************************************* eexIASetup - format and issue an interface address command*/static void eexIASetup ( 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 ); eexAction (unit, CFD_C_IASETUP); /* set up the address */ }/********************************************************************************* eexRxStartup - start up the Receive Unit** Starts up the Receive Unit. Assumes that the receive structures are set up.*/static void eexRxStartup ( DRV_CTRL *pDrvCtrl ) { if (sysInWord (pDrvCtrl->port + SCB_STATUS) & SCB_S_RUREADY) /* already running */ return; /* zero the status and EL bit of the current queue tail dhe 10/26/94 */ sysOutWord(pDrvCtrl->port + WRPTR, pDrvCtrl->rxQueue.tail); sysOutWord(pDrvCtrl->port + DXREG, 0); sysOutWord(pDrvCtrl->port + DXREG, 0); /* set up head and tail to point to original list dhe 10/26/94 */ pDrvCtrl->rxQueue.head = pDrvCtrl->rfdBase; pDrvCtrl->rxQueue.tail = pDrvCtrl->lastFd; /* Point receive area to list of free frames */ sysOutWord (pDrvCtrl->port + SCB_RFA, pDrvCtrl->freeRfd); /* * need to rebuild the rfd list here--copy code from initialization * routine. set queue.head and queue.tail. */ eex586IntDisable (pDrvCtrl->idr.ac_if.if_unit); if ( (sysInWord (pDrvCtrl->port + SCB_STATUS) & SCB_S_RUMASK) != SCB_S_RUIDLE) eexCommand (pDrvCtrl, SCB_C_RUABORT); /* abort if not idle */ eexCommand (pDrvCtrl, SCB_C_RUSTART); /* start receive unit */ eex586IntEnable (pDrvCtrl->idr.ac_if.if_unit); }/********************************************************************************* eexAction - 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 eexAction ( int unit, UINT16 action ) { CFD *pCfd; DRV_CTRL *pDrvCtrl; pDrvCtrl = & drvCtrl [unit]; pCfd = pDrvCtrl->pCfd; /* Building command in scratch area */ while (1) /* wait for idle command unit */ { if ( (sysInWord (pDrvCtrl->port + SCB_STATUS) & 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 */ /* and the SCB */ sysOutWord (pDrvCtrl->port + SCB_COMMAND, SCB_S_CX | /* ack any events */ SCB_S_FR | SCB_S_CNA | SCB_S_RNR | SCB_C_CUSTART); /* start command unit */ /* Point SCB to command area in board memory */ sysOutWord (pDrvCtrl->port + SCB_CBL, CFD_OFFSET); /* Copy CFD to board memory */ sysOutWord (pDrvCtrl->port + WRPTR, CFD_OFFSET); sysOutWordString (pDrvCtrl->port + DXREG, (short *) pCfd, sizeof (CFD) / 2); eex586ChanAtn (pDrvCtrl); /* notify device of new command */ } while (1) /* wait for command acceptance and interrupt */ { if ( (sysInWord (pDrvCtrl->port + SCB_COMMAND) == 0) && (sysInWord (pDrvCtrl->port + SCB_STATUS) & SCB_S_CNA)) break; } /* Copy updated CFD back to system memory */ sysOutWord (pDrvCtrl->port + RDPTR, CFD_OFFSET); sysInWordString (pDrvCtrl->port + DXREG, (short *) pCfd, sizeof (CFD) / 2); /* Acknowledge the event to the device */ sysOutWord(pDrvCtrl->port + SCB_COMMAND, SCB_S_CX | SCB_S_CNA); eex586ChanAtn (pDrvCtrl); while (1) /* wait for acknowledge acceptance */ { if (sysInWord (pDrvCtrl->port + SCB_COMMAND) == 0) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -