📄 el3c90xend.c
字号:
/********************************************************************************* el3c90xDevStop - stop the device** This function stops the adapter and frees up any M_BLKS allocated to the* upload and download descriptors.** RETURNS: N/A*/LOCAL void el3c90xDevStop ( EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */ ) { register int ix; el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_RX_DISABLE, NONE); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_STATS_DISABLE, NONE); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_INTR_ENB, NONE); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_RX_DISCARD, NONE); el3c90xWait(pDrvCtrl); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_TX_DISABLE, NONE); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_COAX_STOP, NONE); el3c90xWait(pDrvCtrl); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_RX_RESET, NONE); el3c90xWait(pDrvCtrl); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_TX_RESET, NONE); el3c90xWait(pDrvCtrl); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_INTR_ACK | EL_STAT_INTLATCH), NONE); /* free the mblks in the upload descriptor lists */ for (ix = 0; ix < EL_UPD_CNT; ix++) { if (pDrvCtrl->rxTxChain.rxChain [ix].pMblk != NULL) { netMblkClChainFree(pDrvCtrl->rxTxChain.rxChain [ix].pMblk); pDrvCtrl->rxTxChain.rxChain [ix].pMblk = NULL; } } bzero ((char *)&pDrvCtrl->pDescBlk->rxDescs, sizeof(pDrvCtrl->pDescBlk->rxDescs)); /* free the download descriptors */ for (ix = 0; ix < EL_DND_CNT; ix++) { if (pDrvCtrl->rxTxChain.txChain [ix].pMblk != NULL) { netMblkClChainFree(pDrvCtrl->rxTxChain.txChain[ix].pMblk); pDrvCtrl->rxTxChain.txChain [ix].pMblk = NULL; } } bzero ((char *)&pDrvCtrl->pDescBlk->txDescs, sizeof(pDrvCtrl->pDescBlk->txDescs)); return; }/********************************************************************************* el3c90xReset - reset the device** This function call resets the device completely** RETURNS: N/A*/LOCAL void el3c90xReset ( EL3C90X_DEVICE * pDrvCtrl ) { /* issue the reset command */ el3c90xCsrWriteWord(pDrvCtrl, EL_COMMAND, EL_CMD_RESET, EL_WIN_0); el3c90xWait(pDrvCtrl); /* wait for the command to complete */ /* wait for a while */ SYS_DELAY(1000); return; }/********************************************************************************* el3c90xIntEnable - 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 el3c90xIntEnable ( EL3C90X_DEVICE * pDrvCtrl /* device structure */ ) { UINT16 status; status = el3c90xCsrReadWord (pDrvCtrl, EL_STATUS, NONE); status &= 0x00ff; el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_INTR_ACK | status), NONE); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_INTR_ENB | EL_INTRS), NONE); }/********************************************************************************* el3c90xIntDisable - 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 el3c90xIntDisable ( EL3C90X_DEVICE * pDrvCtrl /* device structure */ ) { UINT16 status; el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_INTR_ENB, NONE); status = el3c90xCsrReadWord (pDrvCtrl, EL_STATUS, NONE); status &= 0x00ff; el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_INTR_ACK | status), NONE); }/********************************************************************************* el3c90xPollStart - 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 el3c90xPollStart ( EL3C90X_DEVICE * pDrvCtrl /* device to be polled */ ) { int oldLevel; oldLevel = intLock (); /* disable ints during update */ pDrvCtrl->flags |= EL_POLLING; intUnlock (oldLevel); /* now el3c90xInt won't get confused */ el3c90xIntDisable (pDrvCtrl); ENDLOGMSG (("STARTED\n", 1, 2, 3, 4, 5, 6)); return (OK); }/********************************************************************************* el3c90xPollStop - 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 el3c90xPollStop ( EL3C90X_DEVICE * pDrvCtrl /* device structure */ ) { int oldLevel; oldLevel = intLock (); /* disable ints during register updates */ pDrvCtrl->flags &= ~EL_POLLING; intUnlock (oldLevel); el3c90xIntEnable (pDrvCtrl); ENDLOGMSG (("STOPPED\n", 1, 2, 3, 4, 5, 6)); return (OK); }/********************************************************************************* el3c90xUpdInit - initialize the upload descriptor list** This function initializes the upload descriptors and allocates M_BLKs for* them. Note that we arrange the descriptors in a closed ring, so that the* last descriptor points back to the first.** RETURNS: OK or ENOBUFS*/LOCAL int el3c90xUpdInit ( EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */ ) { EL_RX_TX_CHAIN * pRxTxChain; EL_DESC_BLK * pDescBlk; int ix; pRxTxChain = &pDrvCtrl->rxTxChain; pDescBlk = pDrvCtrl->pDescBlk; for (ix = 0; ix < EL_UPD_CNT; ix++) { pRxTxChain->rxChain [ix].pDesc = (EL_SIMPLE_DESC *)&pDescBlk->rxDescs [ix]; if (el3c90xUpdFill(pDrvCtrl, &pRxTxChain->rxChain [ix]) == ENOBUFS) return(ENOBUFS); if (ix == (EL_UPD_CNT - 1)) { pRxTxChain->rxChain [ix].pNextChain = &pRxTxChain->rxChain [0]; pDescBlk->rxDescs [ix].nextDesc = PCI_SWAP ( (UINT32)EL3C90X_CACHE_VIRT_TO_PHYS (&pDescBlk->rxDescs [0]) ); } else { pRxTxChain->rxChain [ix].pNextChain = &pRxTxChain->rxChain [ix + 1]; pDescBlk->rxDescs [ix].nextDesc = PCI_SWAP((UINT32)EL3C90X_CACHE_VIRT_TO_PHYS (&pDescBlk->rxDescs [ix + 1])); } } pRxTxChain->pRxHead = &pRxTxChain->rxChain [0]; return (OK); }/********************************************************************************* el3c90xDndInit - initialize the download descriptor list** This function initializes the download descriptor list** RETURNS: OK*/LOCAL int el3c90xDndInit ( EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */ ) { EL_RX_TX_CHAIN * pRxTxChain; EL_DESC_BLK * pDescBlk; int ix; pRxTxChain = &pDrvCtrl->rxTxChain; pDescBlk = pDrvCtrl->pDescBlk; for (ix = 0; ix < EL_DND_CNT; ix++) { pRxTxChain->txChain [ix].pDesc = &pDescBlk->txDescs [ix]; if (ix == (EL_DND_CNT - 1)) pRxTxChain->txChain [ix].pNextChain = NULL; else pRxTxChain->txChain[ix].pNextChain = &pRxTxChain->txChain [ix + 1]; } pRxTxChain->pTxFree = &pRxTxChain->txChain [0]; pRxTxChain->pTxTail = pRxTxChain->pTxHead = NULL; return(0); }/********************************************************************************* el3c90xHashGet - get a hash filter bit position** This routine is taken from the 3Com Etherlink XL manual,* chapter 10 pg 156. It calculates a CRC of the supplied multicast* group address and returns the lower 8 bits, which are used* as the multicast filter position.* Note: the 3c905B currently only supports a 64-bit hash table,* which means we really only need 6 bits, but the manual indicates* that future chip revisions will have a 256-bit hash table,* hence the routine is set up to calculate 8 bits of position* info in case we need it some day.* Note II, The Sequel: _CURRENT_ versions of the 3c905B have a* 256 bit hash table. This means we have to use all 8 bits regardless.* On older cards, the upper 2 bits will be ignored. Grrrr....** RETURNS: filter bit position*/LOCAL UINT8 el3c90xHashGet ( char * addr ) { UINT32 crc; UINT32 carry; int ix; int jx; UINT8 ch; /* Compute CRC for the address value. */ crc = 0xFFFFFFFF; /* initial value */ for (ix = 0; ix < 6; ix++) { ch = *(addr + ix); for (jx = 0; jx < 8; jx++) { carry = ((crc & 0x80000000) ? 1 : 0) ^ (ch & 0x01); crc <<= 1; ch >>= 1; if (carry) crc = (crc ^ 0x04c11db6) | carry; } } /* return the filter bit position */ return (crc & 0x000000FF); }/********************************************************************************* el3c90xFilterSet - set the multicast filter** NICs older than the 3c905B have only one multicast option, which* is to enable reception of all multicast frames.** RETURNS: N/A*/LOCAL void el3c90xFilterSet ( EL3C90X_DEVICE * pDrvCtrl /* device to be re-configured */ ) { UINT8 rxFilt; rxFilt = el3c90xCsrReadByte(pDrvCtrl, EL_W5_RX_FILTER, EL_WIN_5); if (END_FLAGS_GET (&pDrvCtrl->endObj) & IFF_ALLMULTI) { rxFilt |= EL_RXFILTER_ALLMULTI; el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_RX_SET_FILT | rxFilt), NONE); return; } /* Set up address filter for multicasting. * Multicast bit is set if the address list has one or more entries * Multicasting is disabled if the address list is empty */ if (END_MULTI_LST_CNT (&pDrvCtrl->endObj) > 0) { ENDLOGMSG (("Setting multicast mode on!\n", 1, 2, 3, 4, 5, 6)); rxFilt |= EL_RXFILTER_ALLMULTI; } else { ENDLOGMSG (("Setting multcast mode off!\n", 1, 2, 3, 4, 5, 6)); rxFilt &= ~EL_RXFILTER_ALLMULTI; } el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_RX_SET_FILT | rxFilt), NONE); return; }/********************************************************************************* el3c90xHashFilterSet - set the hash filter for 3c90xB adapters.** This function programs the hash fileter for the 3c905B adapters.** RETURNS: N/A*/LOCAL void el3c90xHashFilterSet ( EL3C90X_DEVICE * pDrvCtrl /* device to be re-configured */ ) { ETHER_MULTI * pCurr; UINT8 rxFilt; int ix; int hash = 0; int mcnt = 0; rxFilt = el3c90xCsrReadByte(pDrvCtrl, EL_W5_RX_FILTER, EL_WIN_5); if (END_FLAGS_GET (&pDrvCtrl->endObj) & IFF_ALLMULTI) { rxFilt |= EL_RXFILTER_ALLMULTI; el3c90xCsrWriteWord (pDrv
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -