📄 if_elt.c
字号:
static void eltRxFree ( ELT_CTRL * pDrvCtrl, ELT_FRAME * pFrame ) { pFrame->lNext = NULL; pFrame->count = 0; pFrame->nextByte = pFrame->header; pFrame->length = 0; eltIntDisable (pDrvCtrl); if (pDrvCtrl->pRxHead == NULL) pDrvCtrl->pRxHead = pFrame; else pDrvCtrl->pRxTail->lNext = pFrame; pDrvCtrl->pRxTail = pFrame; if (pDrvCtrl->pRxCurrent == NULL) { pDrvCtrl->pRxCurrent = pFrame; eltIntMaskSet (pDrvCtrl, RX_COMPLETE | RX_EARLY); } eltIntEnable (pDrvCtrl); }/********************************************************************************* eltStatFlush - flush the board's statistics registers to statistics block** Called when the board reports that its statistics registers are getting* full, or when someone wants to see the current statistics (to fully update* the statistics block).** Note that reading a statistics register zeroes it in the hardware.* Note also that zeroing all the registers is necessary and sufficient* to clear the interrupt condition.** Must be called with board or system interrupts disabled.*/static void eltStatFlush ( ELT_CTRL * pDrvCtrl ) { int port; port = pDrvCtrl->port; sysOutWord (port + ELT_COMMAND, SELECT_WINDOW | WIN_STATISTICS); sysOutWord (port + ELT_COMMAND, STATS_DISABLE); pDrvCtrl->eltStat.nocarriers += sysInByte (port + CARRIER_LOSTS) & 0x0f; pDrvCtrl->eltStat.heartbeats += sysInByte (port + SQE_FAILURES) & 0x0f; pDrvCtrl->eltStat.multcollisions += sysInByte (port + MULT_COLLISIONS) & 0x3f; pDrvCtrl->eltStat.collisions += sysInByte (port + ONE_COLLISIONS) & 0x3f; pDrvCtrl->eltStat.latecollisions += sysInByte (port + LATE_COLLISIONS); pDrvCtrl->eltStat.rxoverruns += sysInByte (port + RECV_OVERRUNS); pDrvCtrl->eltStat.txnoerror += sysInByte (port + GOOD_TRANSMITS); pDrvCtrl->eltStat.rxnoerror += sysInByte (port + GOOD_RECEIVES); pDrvCtrl->eltStat.deferring += sysInByte (port + TX_DEFERRALS); /* Must read all the registers to be sure to clear the interrupt */ (void) sysInWord (port + BYTES_RECEIVED); (void) sysInWord (port + BYTES_TRANSMITTED); sysOutWord (port + ELT_COMMAND, STATS_ENABLE); sysOutWord (port + ELT_COMMAND, SELECT_WINDOW | WIN_OPERATING); }/********************************************************************************* eltIntMaskSet - enable specific status conditions to cause interrupts** Sets bit(s) in the intMask field of the device control structure and in* the board's "read zero mask" where a one bit enables the corresponding* status condition to be read and to cause an interrupt.*/static void eltIntMaskSet ( ELT_CTRL * pDrvCtrl, int maskBits ) { eltIntDisable (pDrvCtrl); pDrvCtrl->intMask |= maskBits; sysOutWord (pDrvCtrl->port + ELT_COMMAND, MASK_STATUS | pDrvCtrl->intMask); eltIntEnable (pDrvCtrl); }/********************************************************************************* eltIntEnable - enable board to cause interrupts** Because the board has maskable status, this routine can simply set the* mask to all ones. We set all the bits symbolically; the effect is the* same. Note that the interrupt latch is not maskable; if none of the other* mask bits are set, no interrupts will occur at all. Only those interrupts* whose status bits are enabled will actually occur. Note that the "intMask"* field in the device control structure is really the status mask.*/static void eltIntEnable ( ELT_CTRL * pDrvCtrl ) { UINT16 status; status = sysInByte (pDrvCtrl->port + ELT_STATUS) & 0x00ff; sysOutWord (pDrvCtrl->port + ELT_COMMAND, ACK_INTERRUPT | status); sysOutWord (pDrvCtrl->port + ELT_COMMAND, MASK_INTERRUPT | ADAPTER_FAILURE | TX_COMPLETE | TX_AVAILABLE | RX_COMPLETE | RX_EARLY | INTERRUPT_REQ | UPDATE_STATS); }/********************************************************************************* eltIntDisable - prevent board from causing interrupts** This routine simply sets all the interrupt mask bits to zero.* It is intended for guarding board-critical sections.*/static void eltIntDisable ( ELT_CTRL * pDrvCtrl ) { UINT16 status; sysOutWord (pDrvCtrl->port + ELT_COMMAND, MASK_INTERRUPT | 0); status = sysInByte (pDrvCtrl->port + ELT_STATUS) & 0x00ff; sysOutWord (pDrvCtrl->port + ELT_COMMAND, ACK_INTERRUPT | status); }/********************************************************************************* eltTxStart - turn on board's transmit function*/static void eltTxStart ( ELT_CTRL * pDrvCtrl ) { sysOutWord (pDrvCtrl->port + ELT_COMMAND, TX_ENABLE); }/********************************************************************************* eltRxStart - enable board to start receiving*/static void eltRxStart ( ELT_CTRL * pDrvCtrl ) { sysOutWord (pDrvCtrl->port + ELT_COMMAND, SET_RX_FILTER | pDrvCtrl->rxFilter); sysOutWord (pDrvCtrl->port + ELT_COMMAND, RX_ENABLE); }/********************************************************************************* eltActivate - attempt to find and activate the adapter with given address** The 3Com 3C509 ISA adapter does not enable itself at power-on. This is* left to the driver, which presumably knows which board it wants. This* we do know, from the port field in the driver control structure.** As a helpful side effect, this routine stores the OEM Ethernet address* of the selected adapter into the driver control structure.** Note that this procedure will activate only one board of the given I/O* address; this is presumably designed in by 3Com as a helpful feature.*/static STATUS eltActivate ( ELT_CTRL * pDrvCtrl ) { int adapterPort; /* I/O address of adapter we're to look for */ int selectedPort; /* I/O address of adapter we've found */ int addressConfig; /* adapter's address configuration register */ int resourceConfig; /* adapter's resource configuration register */ char nodeAddress [EA_SIZE]; STATUS status = OK; /* presume OK, change if there's a problem */ adapterPort = pDrvCtrl->port; eltIdCommand (ID_PORT); /* wake up all adapters */ sysOutByte (ID_PORT, ID_SET_TAG); /* clear all tags */ /* first see if there's a 3Com 3C5xx board out there at all */ if (eltIdEepromRead (EE_A_MANUFACTURER) != MANUFACTURER_ID) return (ERROR); /* Identify adapters one by one until we find the right one; * as we eliminate adapters, we tag them so they don't participate * in the next round of contention eliminations. Along the way, * as part of the adapter contention process, we read out the * station address and resource configuration. */ do { eltIdCommand (ID_PORT); /* prepare for contention */ /* Now read all untagged adapters' addresses from EEPROM * a bit at a time. Tagged adapters ignore the reads therefore * won't be found; we find the next untagged adapter. */ * (UINT16 *) &nodeAddress [0] = eltIdEepromRead (EE_A_OEM_NODE_0); * (UINT16 *) &nodeAddress [2] = eltIdEepromRead (EE_A_OEM_NODE_1); * (UINT16 *) &nodeAddress [4] = eltIdEepromRead (EE_A_OEM_NODE_2); resourceConfig = eltIdEepromRead (EE_A_RESOURCE); addressConfig = eltIdEepromRead (EE_A_ADDRESS); if ( (addressConfig & AC_IO_BASE_MASK) == AC_IO_BASE_EISA) { /* the EISA base address is the last possible one; if we hit * this value without finding the adapter we want, we're done. */ status = ERROR; break; } selectedPort = (addressConfig & AC_IO_BASE_MASK) * AC_IO_BASE_FACTOR + AC_IO_BASE_ZERO;#ifdef ELT_DEBUG printf ("elt: activate: adapter at 0x%04x\n", selectedPort);#endif /* ELT_DEBUG */ /* tag this adapter so if we don't want it it won't contend again */ sysOutByte (ID_PORT, ID_SET_TAG + 1); } while (selectedPort != adapterPort); if (status != ERROR) { sysOutByte (ID_PORT, ID_ACTIVATE); uswab (nodeAddress, (char *)pDrvCtrl->idr.ac_enaddr, EA_SIZE); } return (status); }/********************************************************************************* eltIdCommand - put all adapters into ID command state** This procedure synchronizes the ID state machines of all installed 3Com* adapters in preparation for contending among them.*/static void eltIdCommand ( int idPort /* I/O address to use as ID port (1x0 hex) */ ) { int idValue; /* data read or written to ID port */ int count; /* We should guard this routine since the ID procedure touches * all unactivated adapters. In fact the first three writes should * be guarded against any possible intervening write to any port * 0x100, 0x110, 0x120, ... , 0x1f0. */ sysOutByte (idPort, ID_RESET); /* select the ID port */ sysOutByte (idPort, ID_RESET); /* put adapters in ID-WAIT state */ idValue = ID_SEQUENCE_INITIAL; for (count = ID_SEQUENCE_LENGTH; count > 0; count--) { sysOutByte (idPort, idValue); idValue <<= 1; if ( (idValue & ID_CARRY_BIT) != 0) idValue ^= ID_POLYNOMIAL; } }/********************************************************************************* eltIdEepromRead - read one 16-bit adapter EEPROM register** Read an EEPROM register bitwise by way of the ID port. Used for adapter* contention process and to find out what's in the EEPROM. Addresses are* masked to a valid size; invalid addresses are simply truncated.*/static UINT16 eltIdEepromRead ( int address /* EEPROM register address */ ) { int bitCount; UINT16 value; sysOutByte (ID_PORT, ID_EEPROM_READ | (address & ID_EEPROM_MASK)); taskDelay (2); /* must wait for 162 uS read cycle */ value = 0; for (bitCount = ID_REGISTER_SIZE; bitCount > 0; bitCount--) { value <<= 1; value |= sysInByte (ID_PORT) & 1; } return (value); }/********************************************************************************* eltShow - display statistics for the 3C509 `elt' network interface** This routine displays statistics about the `elt' Ethernet network interface.* It has two parameters: * .iP <unit>* interface unit; should be 0.* .iP <zap>* if 1, all collected statistics are cleared to zero.* .LP** RETURNS: N/A*/void eltShow ( int unit, /* interface unit */ BOOL zap /* 1 = zero totals */ ) { ELT_CTRL * pDrvCtrl; FAST int ix; static char *e_message [] = { "collisions", "crcs", "aligns", "rx no buffers", "rx over-runs", "disabled", "deferring", "tx under-run", "aborts", "out-of-window", "heart-beats", "bad-packet", "short-packet", "tx-no-error", "rx-no-error", "tx-error", "rx-error", "over-write", "wrapped", "interrupts", "reset", "stray-int", "multiple-collisions", "late-collisions", "no-carriers", "jabbers", "tx over-run", "rx under-run",#ifdef ELT_TIMING "rx early", "timer updates", "timer overflows", "timer invalids", "max rx latency", "min rx latency", "max int latency", "current outstanding net rx tasks", "max outstanding rx net tasks", "current outstanding net tx tasks", "max outstanding tx net tasks"#else "rx early"#endif /* ELT_TIMING */ }; pDrvCtrl = pEltCtrl [unit]; /* Disable board interrupts because eltStatFlush() changes reg. window */ eltIntDisable (pDrvCtrl); eltStatFlush (pDrvCtrl); /* get the latest statistics */ eltIntEnable (pDrvCtrl); for (ix = 0; ix < NELEMENTS(e_message); ix++) { printf (" %-30.30s %4d\n", e_message [ix], pDrvCtrl->eltStat.stat [ix]); if (zap) pDrvCtrl->eltStat.stat [ix] = 0; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -