📄 if_eex.c
字号:
if (intConnect ( (VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec), eexInt, (int)pDrvCtrl) == ERROR) return (ERROR); /* Start the device */ if ( eexDeviceStart (unit) == ERROR ) return (ERROR); eexDiag (unit); /* run diagnostics */ eexConfig (unit); /* configure chip */ eexIASetup (unit); /* set up address */ /* Carve up the shared memory region into the specific sections */ pDrvCtrl->rfdBase = (TFD_OFFSET + (sizeof (TFRAME) * pDrvCtrl->nTFDs)); /* create the free tfd queue; nTFDs is non-zero */ for (ix = 0, currentFd = TFD_OFFSET; ix < pDrvCtrl->nTFDs; ix ++, pDrvCtrl->lastFd = currentFd, currentFd += sizeof (TFRAME)) { /* Initialize the TFD to link to next TFD, point to adjacent TBD */ sysOutWord (port + WRPTR, currentFd); sysOutWord (port + DXREG, 0); /* status */ sysOutWord (port + DXREG, CFD_C_XMIT); /* command */ sysOutWord (port + DXREG, currentFd + sizeof (TFRAME)); /* TFD link */#ifdef EEX_AL_LOC sysOutWord (port + DXREG, currentFd + sizeof (TFD)); /* TBD ptr */#else sysOutWord (port + DXREG, currentFd + sizeof (TFD) + FRAME_SIZE); /* TBD ptr */ sysOutWord (port + WRPTR, currentFd + sizeof (TFD) + FRAME_SIZE); /* point to TBD */#endif /* EEX_AL_LOC */ /* Initialize the TBD following the above TFD */ sysOutWord (port + DXREG, 0); /* status */ sysOutWord (port + DXREG, 0xffff); /* next TBD */#ifdef EEX_AL_LOC sysOutWord (port + DXREG, /* buffer address */ currentFd + sizeof (TFD) + sizeof (TBD));#else sysOutWord (port + DXREG, /* buffer address */ currentFd + sizeof (TFD) + EH_SIZE);#endif /* EEX_AL_LOC */ sysOutWord (port + DXREG, 0); /* buffer add. hi */ } /* Fix the link field of the last TFD to point to the first */ sysOutWord (port + WRPTR, pDrvCtrl->lastFd + TF_LINK); sysOutWord (port + DXREG, TFD_OFFSET); pDrvCtrl->tfdQueue.head = TFD_OFFSET; /* Initialize queues */ pDrvCtrl->tfdQueue.tail = pDrvCtrl->lastFd; eexQInit ( (EEX_LIST *)&pDrvCtrl->txQueue); /* to be sent queue */ eexQInit ( (EEX_LIST *)&pDrvCtrl->cblQueue); /* actively sending queue */ eexQInit ( (EEX_LIST *)&pDrvCtrl->cleanQueue); /* queue of TFDs to clean */ /* create all the receive frame descriptors */ for (ix = 0, currentFd = pDrvCtrl->rfdBase; ix < pDrvCtrl->nRFDs; ix ++, pDrvCtrl->lastFd = currentFd, currentFd += sizeof (RFRAME)) { /* Initialize the RFD to link to next RFD, point to following RBD */ sysOutWord (port + WRPTR, currentFd); sysOutWord (port + DXREG, 0); /* status */ sysOutWord (port + DXREG, 0); /* command */ sysOutWord (port + DXREG, currentFd + sizeof (RFRAME)); /* RFD link */#ifdef EEX_AL_LOC sysOutWord (port + DXREG, currentFd + sizeof (RFD)); /* RBD ptr */#else sysOutWord (port + DXREG, currentFd + sizeof (RFD) + FRAME_SIZE); /* RBD ptr */ sysOutWord (port + WRPTR, currentFd + sizeof (RFD) + FRAME_SIZE); /* point to RBD */#endif /* EEX_AL_LOC */ /* Initialize the RBD following the above RFD */ sysOutWord (port + DXREG, 0); /* act. count */ sysOutWord (port + DXREG, 0xffff); /* next RBD */#ifdef EEX_AL_LOC sysOutWord (port + DXREG, /* buffer address */ currentFd + sizeof (RFD) + sizeof (RBD));#else sysOutWord (port + DXREG, /* buffer address */ currentFd + sizeof (RFD) + EH_SIZE);#endif /* EEX_AL_LOC */ sysOutWord (port + DXREG, 0); /* buffer add. hi */ sysOutWord (port + DXREG, RBD_M_EL + FRAME_SIZE); /* buffer size */ } /* Fix the link field of the last RFD to point to the first */ sysOutWord (port + WRPTR, pDrvCtrl->lastFd + RF_LINK); sysOutWord (port + DXREG, pDrvCtrl->rfdBase); pDrvCtrl->rxQueue.head = pDrvCtrl->rfdBase; /* Initialize queue */ pDrvCtrl->rxQueue.tail = pDrvCtrl->lastFd; pDrvCtrl->freeRfd = pDrvCtrl->rxQueue.head; eex586IntAck (unit); /* clear any pended dev ints */ eex586IntEnable (unit); /* enable interrupts at system */ eexRxStartup (pDrvCtrl); /* start receive unit */ return (OK); }/********************************************************************************* eexEnetAddrGet - get OEM Ethernet address from EtherExpress on-board EEPROM** The "OEM" (i.e. not necessarily assigned by Intel) Ethernet address for the* board is contained in words 2, 3, and 4 of the on-board EEPROM. Note that* EEPROM addresses are WORD not byte addresses!* The byte swapping arises from the address being stored in big-endian byte* order, apparently in approximation of the transmitted order (but the bits* would have to be reversed for true transmitted bit order).*/static STATUS eexEnetAddrGet ( DRV_CTRL *pDrvCtrl, char addr[] ) { UINT16 eepromAddress; char *dest = addr; UINT16 t; for (eepromAddress = EEX_EEPROM_EA_HIGH; eepromAddress >= EEX_EEPROM_EA_LOW; eepromAddress--) { t = eexReadEEPROM (pDrvCtrl, eepromAddress); *dest++ = t >> 8; *dest++ = t & 0xff; } return (OK); }/********************************************************************************* eex586IntAck - acknowledge EtherExpress 16 interrupt** The board hardware conatains an interrupt latch which is cleared by clearing* the interrupt enable bit. We presume we want the interrupts enabled so we* re-enable the interrupt.*/static void eex586IntAck ( int unit ) { eex586IntDisable (unit); eex586IntEnable (unit); }/********************************************************************************* eex586IntDisable - disable EtherExpress 16 interrupt** Prevent the board's 82586 from interrupting the system.* As noted in IntAck above, the board has an interrupt latch which is cleared* "with the disable-enable interrupt bit". We will assume that after the* moment of disabling, pending interrupts will be latched and honored when* the interrupt is re-enabled. There is no evidence to support this* assumption, and it should be tested some day.*/static void eex586IntDisable ( int unit ) { DRV_CTRL *pDrvCtrl; pDrvCtrl = & drvCtrl [unit]; sysOutByte (pDrvCtrl->port + SEL_IRQ, pDrvCtrl->irqCode); }/********************************************************************************* eex586IntEnable - enable EtherExpress 16 interrupt** Allow the board's 82586 to interrupt the system.*/static void eex586IntEnable ( int unit ) { DRV_CTRL *pDrvCtrl; pDrvCtrl = & drvCtrl [unit]; sysOutByte (pDrvCtrl->port + SEL_IRQ, pDrvCtrl->irqCode | IRQ_ENB); }/********************************************************************************* eex586SetReset - reset the EtherExpress 16's 82586 chip** Set chip into reset state (and hold it there until released elsewhere).*/static void eex586SetReset ( int unit ) { DRV_CTRL *pDrvCtrl; pDrvCtrl = & drvCtrl [unit]; sysOutByte (pDrvCtrl->port + EE_CTRL, RESET_82586); }/********************************************************************************* eex586ClearReset - remove the EtherExpress 16's 82586 chip from reset state** Clear the bit holding the chip's reset line enabled, allowing the chip* to follow its power-on initialization sequence.*/static void eex586ClearReset ( int unit ) { DRV_CTRL *pDrvCtrl; pDrvCtrl = & drvCtrl [unit]; /* All other bits in this register should be zero when chip runs */ sysOutByte (pDrvCtrl->port + EE_CTRL, 0); }/********************************************************************************* eex586ChanAtn - assert Channel Attention to the EtherExpress 16's 82586 chip** Channel Attention tells the 82586 to examine its System Control Block* for commands and acknowledgements.* This could really be a macro.*/static void eex586ChanAtn ( DRV_CTRL *pDrvCtrl ) { /* The act of writing to the port does the job; data is irrelevant */ sysOutByte (pDrvCtrl->port + CA_CTRL, 0); }/********************************************************************************* eexReadEEPROM - read one word from the on-board EEPROM** Note that a necessary side effect of accessing the EEPROM is to set the* RESET_82586 bit, because the 82586's bus signals must be disabled.* Note that EEPROM addresses are WORD not byte addresses!*/static UINT16 eexReadEEPROM ( DRV_CTRL *pDrvCtrl, UINT16 address ) { int port; UCHAR eeCtrl; /* maintains current port contents */ UINT16 value; port = pDrvCtrl->port + EE_CTRL; eeCtrl = sysInByte (port) & (EEPROM_CHIPSEL | RESET_82586); sysOutByte (port, eeCtrl | EEPROM_CHIPSEL); eexOutBitsEEPROM (port, 3, EEPROM_OP_READ); eexOutBitsEEPROM (port, 6, address); value = eexInBitsEEPROM (port, 16); eeCtrl &= EEPROM_CHIPSEL; /* be certain chip select is clear */ sysOutByte (port, eeCtrl); /* also the data port */ eexDelayEEPROM(); /* data setup time */ sysOutByte (port, eeCtrl | EEPROM_CLOCK); /* clock with CS low? */ eexDelayEEPROM(); sysOutByte (port, eeCtrl); eexDelayEEPROM(); return (value); }/********************************************************************************* eexOutBitsEEPROM - send a bit string to the on-board EEPROM** Shifts the righmost 'count' bits out, LEFTMOST first.*/static void eexOutBitsEEPROM ( int port, int count, UINT16 bits ) { UCHAR eeCtrl; /* maintains current port contents */ bits <<= 16 - count; /* left-justify the bit string */ eeCtrl = sysInByte (port) & (EEPROM_CHIPSEL | RESET_82586); while (count--) { if (bits & 0x8000) eeCtrl |= EEPROM_OUTPUT; else eeCtrl &= ~EEPROM_OUTPUT; sysOutByte (port, eeCtrl); eexDelayEEPROM(); /* data setup time */ sysOutByte (port, eeCtrl | EEPROM_CLOCK); eexDelayEEPROM(); sysOutByte (port, eeCtrl); eexDelayEEPROM(); bits <<= 1; } sysOutByte (port, eeCtrl & ~EEPROM_OUTPUT); /* clear output bit */ }/********************************************************************************* eexInBitsEEPROM - receive a bit string from the on-board EEPROM**/static UINT16 eexInBitsEEPROM ( int port, int count ) { UCHAR eeCtrl; /* maintains current port contents */ UINT16 value; /* build result a bit at a time */ eeCtrl = sysInByte (port) & (EEPROM_CHIPSEL | RESET_82586); value = 0; while (count--) { value <<= 1; sysOutByte (port, eeCtrl | EEPROM_CLOCK); eexDelayEEPROM(); if (sysInByte (port) & EEPROM_INPUT) value |= 1; sysOutByte (port, eeCtrl); eexDelayEEPROM(); } return (value); }/********************************************************************************* eexDelayEEPROM - delay for EEPROM to recognize clock change** Supposedly 4.0 microseconds for the Hyundai EEPROM.*/static void eexDelayEEPROM ( ) { taskDelay (1); /* gross overkill! */ }/******************************************************************************//* END OF FILE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -