📄 el3c90xend.c
字号:
pTxChain->pDesc->status |= PCI_SWAP (EL_TXSTAT_DL_INTR); el3c90xDndEnqueue (pDrvCtrl, pTxChain); END_TX_SEM_GIVE (&pDrvCtrl->endObj); /* kick the reciever if blocked, parallel tasking */ el3c90xRxKick (pDrvCtrl); return (OK); }/******************************************************************************* el3c90xMCastAdd - add a multicast address for the device** This routine adds a multicast address to whatever the driver* is already listening for. It then resets the address filter.** RETURNS: OK or ERROR.*/LOCAL STATUS el3c90xMCastAdd ( void * pEnd, /* device pointer */ char * pAddress /* new address to add */ ) { int error; EL3C90X_DEVICE * pDrvCtrl; VOID_TO_DRVCTRL (pEnd, pDrvCtrl); if ((error = etherMultiAdd (&pDrvCtrl->endObj.multiList, pAddress)) == ENETRESET) el3c90xMcastConfig (pDrvCtrl); return (OK); }/******************************************************************************* el3c90xMCastDel - delete a multicast address for the device** This routine removes a multicast address from whatever the driver* is listening for. It then resets the address filter.** RETURNS: OK or ERROR.*/LOCAL STATUS el3c90xMCastDel ( void * pEnd, /* device pointer */ char * pAddress /* address to be deleted */ ) { int error; EL3C90X_DEVICE * pDrvCtrl; VOID_TO_DRVCTRL (pEnd, pDrvCtrl); if ((error = etherMultiDel (&pDrvCtrl->endObj.multiList, (char *)pAddress)) == ENETRESET) el3c90xMcastConfig (pDrvCtrl); return (OK); }/******************************************************************************* el3c90xMCastGet - get the multicast address list for the device** This routine gets the multicast list of whatever the driver* is already listening for.** RETURNS: OK or ERROR.*/LOCAL STATUS el3c90xMCastGet ( void * pEnd, /* device pointer */ MULTI_TABLE * pTable /* address table to be filled in */ ) { EL3C90X_DEVICE * pDrvCtrl; VOID_TO_DRVCTRL (pEnd, pDrvCtrl); return (etherMultiGet (&pDrvCtrl->endObj.multiList, pTable)); }/********************************************************************************* el3c90xPollSend - routine to send a packet in polled mode.** This routine is called by a user to try and send a packet on the* device.** RETURNS: OK upon success. EAGAIN if device is busy.*/LOCAL STATUS el3c90xPollSend ( void * pEnd, /* device pointer */ M_BLK_ID pMblk /* packet to send */ ) { EL3C90X_DEVICE * pDrvCtrl; EL_DESC_CHAIN * pTxChain = NULL; VOID_TO_DRVCTRL (pEnd, pDrvCtrl); DRV_LOG (DRV_DEBUG_POLL_TX, "PTX b\n", 1, 2, 3, 4, 5, 6); /* check if download engine is still busy */ if (el3c90xCsrReadLong (pDrvCtrl, EL_DOWNLIST_PTR, NONE)) { DRV_LOG (DRV_DEBUG_POLL_TX, "transmitter busy\n", 1, 2, 3, 4, 5, 6); return (EAGAIN); } /* check if a download descriptor is available */ if ((pTxChain = el3c90xDndGet (pDrvCtrl)) == NULL) return (EAGAIN); /* Pack the mBlk into the download descriptor. */ if (el3c90xDndMblkPack (pDrvCtrl, pTxChain, pMblk) == ERROR) { el3c90xDndFree (pDrvCtrl, pTxChain); return (EAGAIN); }#ifndef INCLUDE_RFC_1213 /* New RFC 2233 mib2 interface */ /* RFC 2233 mib2 counter update for outgoing packet */ if (pDrvCtrl->endObj.pMib2Tbl != NULL) { pDrvCtrl->endObj.pMib2Tbl->m2PktCountRtn(pDrvCtrl->endObj.pMib2Tbl, M2_PACKET_OUT, pMblk->mBlkHdr.mData, pMblk->mBlkHdr.mLen); }#endif /* INCLUDE_RFC_1213 */ el3c90xCsrWriteLong (pDrvCtrl, EL_DOWNLIST_PTR, (UINT32)EL3C90X_CACHE_VIRT_TO_PHYS (pTxChain->pDesc), NONE); /* wait until download has completed */ while (el3c90xCsrReadLong (pDrvCtrl, EL_DOWNLIST_PTR, NONE)) ; el3c90xDndFree (pDrvCtrl, pTxChain); DRV_LOG (DRV_DEBUG_POLL_TX, "PTX e\n", 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* el3c90xPollRcv - routine to receive a packet in polled mode.** This routine is called by a user to try and get a packet from the* device.** RETURNS: EGAIN or OK*/LOCAL STATUS el3c90xPollRcv ( void * pEnd, /* device pointer */ M_BLK_ID pMblk /* pointer to the mBlk chain */ ) { EL_SIMPLE_DESC_CHAIN * pRxUpd; EL3C90X_DEVICE * pDrvCtrl; M_BLK_ID pMblkTemp; /* pointer to the mBlk */ int len; DRV_LOG (DRV_DEBUG_POLL_RX, "PRX b\n", 1, 2, 3, 4, 5, 6); VOID_TO_DRVCTRL (pEnd, pDrvCtrl); el3c90xRxUnStall (pDrvCtrl); /* get the next upload descriptor */ if ((pRxUpd = el3c90xNextUpdFetch (pDrvCtrl)) == NULL) { DRV_LOG (DRV_DEBUG_POLL_RX, "PRX no upd\n", 1, 2, 3, 4, 5, 6); return (EAGAIN); } /* get the mBlk associated with the upd */ if ((pMblkTemp = el3c90xNextPktFetch (pDrvCtrl, pRxUpd)) == NULL) return (EAGAIN); /* copy the data into the given buffer */ len = netMblkToBufCopy (pMblkTemp, pMblk->mBlkHdr.mData, NULL); netMblkClChainFree (pMblkTemp); if ((pMblk->mBlkHdr.mLen < len) || (!(pMblk->mBlkHdr.mFlags & M_EXT))) { DRV_LOG (DRV_DEBUG_POLL_RX, "PRX bad mblk len:%d flags:%d\n", pMblk->mBlkHdr.mLen, pMblk->mBlkHdr.mFlags, 3, 4, 5, 6); return (EAGAIN); } pMblk->mBlkHdr.mLen = len; pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkPktHdr.len = len;#ifndef INCLUDE_RFC_1213 /* New RFC 2233 mib2 interface */ /* RFC 2233 mib2 counter update for incoming packet */ if (pDrvCtrl->endObj.pMib2Tbl != NULL) { pDrvCtrl->endObj.pMib2Tbl->m2PktCountRtn(pDrvCtrl->endObj.pMib2Tbl, M2_PACKET_IN, pMblk->mBlkHdr.mData, pMblk->mBlkHdr.mLen); }#endif /* INCLUDE_RFC_1213 */ DRV_LOG (DRV_DEBUG_POLL_RX, "PRX ok\n", 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* el3c90xInit - initialize the device** This routine initializes device and enables the device interrupts. It* initializes the descriptor rings** RETURNS: N/A*/LOCAL void el3c90xInit ( EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */ ) { int ix; UINT16 rxFilt = 0; UINT16 phyBMCR = 0; int flags; /* * hack for the 3c905B: the built-in autoneg logic's state * gets reset by el3c90xInit() when we don't want it to. Try * to preserve it. (For 3c905 cards with real external PHYs, * the BMCR register doesn't change, but this doesn't hurt.) */ if (pDrvCtrl->pPhyDevType != NULL) phyBMCR = el3c90xPhyRegRead(pDrvCtrl, PHY_BMCR); /* cancel pending I/O and free all RX/TX buffers. */ el3c90xDevStop(pDrvCtrl); el3c90xWait(pDrvCtrl); /* get the MAC address */ for (ix = 0; ix < EA_SIZE; ix++) { el3c90xCsrWriteByte (pDrvCtrl, EL_W2_STATION_ADDR_LO + ix, pDrvCtrl->enetAddr [ix], EL_WIN_2); } /* clear the station mask */ for (ix = 0; ix < 3; ix++) el3c90xCsrWriteWord (pDrvCtrl, EL_W2_STATION_MASK_LO + (ix * 2), 0, EL_WIN_2); /* reset TX and RX */ el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_RX_RESET, NONE); el3c90xWait(pDrvCtrl); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_TX_RESET, NONE); el3c90xWait(pDrvCtrl); /* init circular upload descriptor list */ if (el3c90xUpdInit(pDrvCtrl) == ENOBUFS) { DRV_LOG (DRV_DEBUG_LOAD, "elPci%d: initialization failed: no " "memory for rx buffers\n", pDrvCtrl->unit, 2, 3, 4, 5, 6); el3c90xDevStop(pDrvCtrl); return; } /* init download descriptors list */ el3c90xDndInit(pDrvCtrl); /* * set the TX freethresh value. * note that this has no effect on 3c905B "cyclone" * cards but is required for 3c900/3c905 "boomerang" * cards in order to enable the download engine. */ el3c90xCsrWriteByte (pDrvCtrl, EL_TX_FREETHRESH, (EL3C90X_BUFSIZ >> 8), NONE); /* * If this is a 3c905B, also set the tx reclaim threshold. * This helps cut down on the number of tx reclaim errors * that could happen on a busy network. The chip multiplies * the register value by 16 to obtain the actual threshold * in bytes, so we divide by 16 when setting the value here. * The existing threshold value can be examined by reading * the register at offset 9 in window 5. */ if (pDrvCtrl->devType == EL_TYPE_905B) { el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_SET_TX_RECLAIM | (EL3C90X_BUFSIZ >> 4)), NONE); } /* set RX filter bits. */ rxFilt = el3c90xCsrReadByte (pDrvCtrl, EL_W5_RX_FILTER, EL_WIN_5); /* set the individual bit to receive frames for this host only. */ rxFilt |= EL_RXFILTER_INDIVIDUAL; flags = END_FLAGS_GET (&pDrvCtrl->endObj); /* if we want promiscuous mode, set the allframes bit. */ if (flags & IFF_PROMISC) { rxFilt |= EL_RXFILTER_ALLFRAMES; el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_RX_SET_FILT | rxFilt), NONE); } else { rxFilt &= ~EL_RXFILTER_ALLFRAMES; el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_RX_SET_FILT | rxFilt), NONE); } /* set capture broadcast bit to capture broadcast frames. */ if (flags & IFF_BROADCAST) { rxFilt |= EL_RXFILTER_BROADCAST; el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_RX_SET_FILT | rxFilt), NONE); } else { rxFilt &= ~EL_RXFILTER_BROADCAST; el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_RX_SET_FILT | rxFilt), NONE); } /* set the multicast filter etc */ el3c90xMcastConfig (pDrvCtrl); /* * load the upload descriptor pointer and start the upload engine * Note that we have to do this after any RX resets have completed * since the uplist register is cleared by a reset. */ el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_UP_STALL, NONE); el3c90xWait(pDrvCtrl); el3c90xCsrWriteLong (pDrvCtrl, EL_UPLIST_PTR, (UINT32) EL3C90X_CACHE_VIRT_TO_PHYS (&pDrvCtrl->pDescBlk->rxDescs[0]), NONE); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_UP_UNSTALL, NONE); /* * if the coax transceiver is on, make sure to enable the DC-DC converter. */ if (pDrvCtrl->xCvr == EL_XCVR_COAX) el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_COAX_START, NONE); else el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_COAX_STOP, NONE); /* Clear out the stats counters. */ el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_STATS_DISABLE, NONE); el3c90xStatUpdate(pDrvCtrl); el3c90xCsrWriteWord (pDrvCtrl, EL_W4_NET_DIAG, EL_NETDIAG_UPPER_BYTES_ENABLE, EL_WIN_4); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_STATS_ENABLE, NONE); /* enable device interrupts */ el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_INTR_ACK|0xFF, NONE); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_STAT_ENB|EL_INTRS, NONE); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_INTR_ENB|EL_INTRS, NONE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -