📄 elt3c509end.c
字号:
( void * pEnd, /* device pointer */ M_BLK_ID pMblk /* packet to send */ ) { int len; int * pLenMask; char * pBuf; ELT3C509_DEVICE * pDrvCtrl; UINT16 txStatus; VOID_TO_DRVCTRL (pEnd, pDrvCtrl); SYS_IN_WORD (pDrvCtrl, pDrvCtrl->port + TX_FREE_BYTES, txStatus); if (txStatus >= TX_IDLE_COUNT) { pBuf = pDrvCtrl->pTxCluster; /* pointer to the transmit cluster */ pLenMask = (UINT32 *)pBuf; /* allow space for the preamble the trasmit buffer is 1520 */ pBuf += sizeof(UINT32); len = netMblkToBufCopy(pMblk, pBuf, NULL); len = max(len, ETHERSMALL); /* set the packet size */ *pLenMask = len | TX_F_INTERRUPT; /* set the preamble */ len = (len + TX_F_PREAMBLE_SIZE + 3) & TX_F_DWORD_MASK; /* place a transmit request */ SYS_OUT_WORD_STRING (pDrvCtrl, pDrvCtrl->port + DATA_REGISTER, (short *)pLenMask, len / 2); /* read the tranmsit status */ SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->port + TX_STATUS, txStatus); /* wait until tramit is complete */ while (!(txStatus & TX_S_COMPLETE)) { SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->port + TX_STATUS, txStatus); } /* clear old status */ SYS_OUT_BYTE (pDrvCtrl, pDrvCtrl->port + TX_STATUS, 0); } else { ENDLOGMSG(("Error in Send, not enough TxFreeBytes\n",1,2,3,4,5,6)); return (EAGAIN); } /* Bump the statistic counter. */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1); ENDLOGMSG (("Poll Send complete\n",1,2,3,4,5,6)); return (OK); }/********************************************************************************* elt3c509PollStart - start polled mode operations** This function starts polled mode operation.** The device interrupts are disabled, the current mode flag is switched* to indicate Polled mode and the device is reconfigured.** RETURNS: OK or ERROR.*/LOCAL STATUS elt3c509PollStart ( ELT3C509_DEVICE * pDrvCtrl /* device to be polled */ ) { int oldLevel; oldLevel = intLock (); /* disable ints during update */ pDrvCtrl->flags |= ELT3C_POLLING; intUnlock (oldLevel); /* now elt3c509Int won't get confused */ elt3c509IntDisable (pDrvCtrl); ENDLOGMSG (("STARTED\n", 1, 2, 3, 4, 5, 6)); elt3c509Config (pDrvCtrl); /* reconfigure device */ return (OK); }/********************************************************************************* elt3c509PollStop - stop polled mode operations** This function terminates polled mode operation. The device returns to* interrupt mode.** The device interrupts are enabled, the current mode flag is switched* to indicate interrupt mode and the device is then reconfigured for* interrupt operation.** RETURNS: OK or ERROR.*/LOCAL STATUS elt3c509PollStop ( ELT3C509_DEVICE * pDrvCtrl /* device structure */ ) { int oldLevel; oldLevel = intLock (); /* disable ints during register updates */ pDrvCtrl->flags &= ~ELT3C_POLLING; intUnlock (oldLevel); elt3c509IntEnable (pDrvCtrl); elt3c509Config (pDrvCtrl); ENDLOGMSG (("STOPPED\n", 1, 2, 3, 4, 5, 6)); return (OK); }/********************************************************************************* elt3c509IntEnable - 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.** RETURNS: N/A.*/LOCAL void elt3c509IntEnable ( ELT3C509_DEVICE * pDrvCtrl /* device structure */ ) { UINT16 status; SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->port + ELT3C509_STATUS, status); status &= 0x00ff; SYS_OUT_WORD (pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, ACK_INTERRUPT | status); SYS_OUT_WORD (pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, MASK_INTERRUPT | ADAPTER_FAILURE | TX_COMPLETE | TX_AVAILABLE | RX_COMPLETE | RX_EARLY | INTERRUPT_REQ | UPDATE_STATS); }/********************************************************************************* elt3c509IntDisable - prevent board from causing interrupts** This routine simply sets all the interrupt mask bits to zero.* It is intended for guarding board-critical sections.** RETURNS: N/A.*/LOCAL void elt3c509IntDisable ( ELT3C509_DEVICE * pDrvCtrl /* device structure */ ) { UINT16 status; SYS_OUT_WORD (pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, MASK_INTERRUPT | 0); SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->port + ELT3C509_STATUS, status); status &= 0x00ff; SYS_OUT_WORD (pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, ACK_INTERRUPT | status); }/********************************************************************************* elt3c509TxStart - turn on board's transmit function** RETURNS: N/A.*/LOCAL void elt3c509TxStart ( ELT3C509_DEVICE * pDrvCtrl /* device structure */ ) { SYS_OUT_WORD (pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, TX_ENABLE); }/********************************************************************************* elt3c509RxStart - enable board to start receiving** RETURNS: N/A.*/LOCAL void elt3c509RxStart ( ELT3C509_DEVICE * pDrvCtrl /* device structure */ ) { SYS_OUT_WORD (pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, SET_RX_FILTER | pDrvCtrl->rxFilter); SYS_OUT_WORD (pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, RX_ENABLE); }/********************************************************************************* elt3c509Reset - reset the elt3c509 interface** Mark interface as inactive and reset the adapter.** RETURNS: N/A.*/LOCAL void elt3c509Reset ( ELT3C509_DEVICE * pDrvCtrl /* device structure */ ) { elt3c509IntDisable (pDrvCtrl); /* prevent device from interrupting */ SYS_OUT_WORD (pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, RX_RESET); SYS_OUT_WORD (pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, TX_RESET); }/********************************************************************************* elt3c509StatFlush - 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.** RETURNS: N/A.*/LOCAL void elt3c509StatFlush ( ELT3C509_DEVICE * pDrvCtrl /* device structure */ ) { int port; UINT16 tempCounter; port = pDrvCtrl->port; SYS_OUT_WORD (pDrvCtrl, port + ELT3C509_COMMAND, SELECT_WINDOW | WIN_STATISTICS); SYS_OUT_WORD (pDrvCtrl, port + ELT3C509_COMMAND, STATS_DISABLE); SYS_IN_BYTE (pDrvCtrl, port+CARRIER_LOSTS, tempCounter); pDrvCtrl->elt3c509Stat.nocarriers += tempCounter & 0x0f; SYS_IN_BYTE (pDrvCtrl, port+SQE_FAILURES, tempCounter); pDrvCtrl->elt3c509Stat.heartbeats += tempCounter & 0x0f; SYS_IN_BYTE (pDrvCtrl, port+MULT_COLLISIONS, tempCounter); pDrvCtrl->elt3c509Stat.multcollisions += tempCounter & 0x3f; SYS_IN_BYTE (pDrvCtrl, port+ONE_COLLISIONS, tempCounter); pDrvCtrl->elt3c509Stat.collisions += tempCounter & 0x3f; SYS_IN_BYTE (pDrvCtrl, port+LATE_COLLISIONS, tempCounter); pDrvCtrl->elt3c509Stat.latecollisions += tempCounter; SYS_IN_BYTE (pDrvCtrl, port+RECV_OVERRUNS, tempCounter); pDrvCtrl->elt3c509Stat.rxoverruns += tempCounter; SYS_IN_BYTE (pDrvCtrl, port+GOOD_TRANSMITS, tempCounter); pDrvCtrl->elt3c509Stat.txnoerror += tempCounter; SYS_IN_BYTE (pDrvCtrl, port+GOOD_RECEIVES, tempCounter); pDrvCtrl->elt3c509Stat.rxnoerror += tempCounter; SYS_IN_BYTE (pDrvCtrl, port+TX_DEFERRALS, tempCounter); pDrvCtrl->elt3c509Stat.deferring += tempCounter; /* Must read all the registers to be sure to clear the interrupt */ SYS_IN_WORD (pDrvCtrl, port + BYTES_RECEIVED, tempCounter); SYS_IN_WORD (pDrvCtrl, port + BYTES_TRANSMITTED, tempCounter); SYS_OUT_WORD (pDrvCtrl, port + ELT3C509_COMMAND, STATS_ENABLE); SYS_OUT_WORD (pDrvCtrl, port + ELT3C509_COMMAND, SELECT_WINDOW | WIN_OPERATING); }/********************************************************************************* elt3c509IntMaskSet - 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.** RETURNS: N/A.*/LOCAL void elt3c509IntMaskSet ( ELT3C509_DEVICE * pDrvCtrl, /* device structure */ int maskBits /* mask bits */ ) { elt3c509IntDisable (pDrvCtrl); pDrvCtrl->intMask |= maskBits; SYS_OUT_WORD (pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, MASK_STATUS | pDrvCtrl->intMask); elt3c509IntEnable (pDrvCtrl); }/********************************************************************************* elt3c509Activate - attempt to 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.** RETURNS: OK or ERROR.*/LOCAL STATUS elt3c509Activate ( ELT3C509_DEVICE * 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; elt3c509IdCommand (ID_PORT); /* wake up all adapters */ SYS_OUT_BYTE (pDrvCtrl, ID_PORT, ID_SET_TAG); /* clear all tags */ /* first see if there's a 3Com 3C5xx board out there at all */ if (elt3c509IdEepromRead (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 { elt3c509IdCommand (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] = elt3c509IdEepromRead (EE_A_OEM_NODE_0); * (UINT16 *) &nodeAddress [2] = elt3c509IdEepromRead (EE_A_OEM_NODE_1); * (UINT16 *) &nodeAddress [4] = elt3c509IdEepromRead (EE_A_OEM_NODE_2); resourceConfig = elt3c509IdEepromRead (EE_A_RESOURCE); addressConfig = elt3c509IdEepromRead (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; ENDLOGMSG (("elt: activate: adapter at 0x%04x\n", selectedPort, 2, 3, 4, 5, 6)); /* tag this adapter so if we don't want it it won't contend again */ SYS_OUT_BYTE (pDrvCtrl, ID_PORT, ID_SET_TAG + 1); } while (selectedPort != adapterPort); if (status != ERROR) { SYS_OUT_BYTE (pDrvCtrl, ID_PORT, ID_ACTIVATE); uswab (nodeAddress, (char *)pDrvCtrl->enetAddr, EA_SIZE); } return (status); }/********************************************************************************* elt3c509IdCommand - 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.** RETUR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -