el3c90xEnd.c
资源名称:ixp425BSP.rar [点击查看]
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:136k
源码类别:
VxWorks
开发平台:
C/C++
- /* walk through the list and recalculate the hash filter */
- pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->endObj);
- while (pCurr != NULL)
- {
- hash = el3c90xHashGet ((UINT8 *)&pCurr->addr);
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND,
- (EL_CMD_RX_SET_HASH | EL_HASH_SET | hash), NONE);
- mcnt++;
- pCurr = END_MULTI_LST_NEXT(pCurr);
- }
- if (mcnt)
- rxFilt |= EL_RXFILTER_MULTIHASH;
- else
- rxFilt &= ~EL_RXFILTER_MULTIHASH;
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND,
- (EL_CMD_RX_SET_FILT | rxFilt), NONE);
- return;
- }
- /******************************************************************************
- *
- * el3c90xMcastConfig - reconfigure the interface under us.
- *
- * Reconfigure the interface setting promiscuous mode, and changing the
- * multicast interface list.
- *
- * RETURNS: N/A.
- */
- LOCAL void el3c90xMcastConfig
- (
- EL3C90X_DEVICE * pDrvCtrl /* device to be re-configured */
- )
- {
- if (pDrvCtrl->devType == EL_TYPE_905B)
- el3c90xHashFilterSet (pDrvCtrl);
- else
- el3c90xFilterSet (pDrvCtrl);
- return;
- }
- /*******************************************************************************
- *
- * el3c90xUpdFill - initialize a single upload descriptor
- *
- * This function allocates an mBlk/clBlk/cluster tuple and initialize the
- * upload descriptor.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS el3c90xUpdFill
- (
- EL3C90X_DEVICE * pDrvCtrl, /* ptr to the dev ctrl structure */
- EL_SIMPLE_DESC_CHAIN * pRxUpd /* ptr to the descriptor chain */
- )
- {
- M_BLK_ID pMblk = NULL; /* pointer to the mBlk */
- /* get a mBlk/clBlk/cluster tuple */
- if ((pMblk = netTupleGet (pDrvCtrl->endObj.pNetPool, EL3C90X_BUFSIZ,
- M_DONTWAIT, MT_DATA, FALSE)) == NULL)
- {
- ENDLOGMSG (("Out of M Blocks!n", 1, 2, 3, 4, 5, 6));
- return (ERROR);
- }
- pRxUpd->pMblk = pMblk;
- pRxUpd->pDesc->descFrag.fragAddr =
- PCI_SWAP((UINT32) EL3C90X_CACHE_VIRT_TO_PHYS (pMblk->mBlkHdr.mData));
- pRxUpd->pDesc->status = 0;
- pRxUpd->pDesc->descFrag.fragLen = PCI_SWAP (CL_SIZE_2048 | EL_LAST_FRAG);
- return (OK);
- }
- /*******************************************************************************
- *
- * el3c90xDndGet - get a free down load descriptor
- *
- * This function returns a pointer to the descriptor chain which has a free
- * down load descriptor.
- *
- * RETURNS: EL_DESC_CHAIN * or NULL
- */
- LOCAL EL_DESC_CHAIN * el3c90xDndGet
- (
- EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
- )
- {
- EL_DESC_CHAIN * pFree = NULL;
- if ((pFree = pDrvCtrl->rxTxChain.pTxFree) == NULL)
- return (NULL);
- pDrvCtrl->rxTxChain.pTxFree = pFree->pNextChain;
- pFree->pNextChain = NULL;
- return (pFree);
- }
- /*******************************************************************************
- *
- * el3c90xDndFree - free a down load descriptor
- *
- * This function returns a the down load descriptor chain to the free list.
- *
- * RETURNS: OK
- */
- LOCAL STATUS el3c90xDndFree
- (
- EL3C90X_DEVICE * pDrvCtrl, /* pointer to the device control structure */
- EL_DESC_CHAIN * pTxChain
- )
- {
- pTxChain->pMblk = NULL;
- pTxChain->pNextChain = pDrvCtrl->rxTxChain.pTxFree;
- pDrvCtrl->rxTxChain.pTxFree = pTxChain;
- return (OK);
- }
- /*******************************************************************************
- *
- * el3c90xTxDequeue - dequeue a transmitted descriptor
- *
- * This function dequeues a transmitted descriptor for clean up after
- * transmission.
- *
- * RETURNS: EL_DESC_CHAIN * or NULL
- */
- LOCAL EL_DESC_CHAIN * el3c90xTxDequeue
- (
- EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
- )
- {
- EL_DESC_CHAIN * pTxFree = NULL;
- if ((pTxFree = pDrvCtrl->rxTxChain.pTxHead) == NULL)
- {
- pDrvCtrl->rxTxChain.pTxTail = NULL;
- return (NULL);
- }
- else
- {
- /* we have to use a different test if devType != EL_TYPE_905B. */
- if ((pDrvCtrl->devType == EL_TYPE_905B &&
- !(PCI_SWAP(pTxFree->pDesc->status) & EL_TXSTAT_DL_COMPLETE)) ||
- el3c90xCsrReadLong (pDrvCtrl, EL_DOWNLIST_PTR, NONE))
- {
- if (el3c90xCsrReadLong (pDrvCtrl, EL_DMACTL, NONE) &
- EL_DMACTL_DOWN_STALLED ||
- !el3c90xCsrReadLong(pDrvCtrl, EL_DOWNLIST_PTR, NONE))
- {
- el3c90xCsrWriteLong (pDrvCtrl, EL_DOWNLIST_PTR,
- (UINT32) EL3C90X_CACHE_VIRT_TO_PHYS
- (pTxFree->pDesc), NONE);
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_DOWN_UNSTALL,
- NONE);
- }
- return (NULL);
- }
- }
- pDrvCtrl->rxTxChain.pTxHead = pTxFree->pNextChain;
- pTxFree->pNextChain = NULL;
- return (pTxFree);
- }
- /*******************************************************************************
- *
- * el3c90xDndEnqueue - enqueue a down load descriptor
- *
- * This function enqueues a down load descriptor
- *
- * RETURNS: OK.
- */
- LOCAL STATUS el3c90xDndEnqueue
- (
- EL3C90X_DEVICE * pDrvCtrl, /* pointer to the device control structure */
- EL_DESC_CHAIN * pTxChain
- )
- {
- if (el3c90xCsrReadLong (pDrvCtrl, EL_DOWNLIST_PTR, NONE))
- {
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_DOWN_STALL, NONE);
- el3c90xWait(pDrvCtrl);
- /* check once again */
- if (el3c90xCsrReadLong (pDrvCtrl, EL_DOWNLIST_PTR, NONE))
- {
- /*
- * Place the request for the upload interrupt
- * in the last descriptor in the chain. This way, if
- * we're chaining several packets at once, we'll only
- * get an interupt once for the whole chain rather than
- * once for each packet.
- */
- pDrvCtrl->rxTxChain.pTxTail->pNextChain = pTxChain;
- pDrvCtrl->rxTxChain.pTxTail->pDesc->nextDesc =
- PCI_SWAP((UINT32)EL3C90X_CACHE_VIRT_TO_PHYS(pTxChain->pDesc));
- pDrvCtrl->rxTxChain.pTxTail->pDesc->status &=
- PCI_SWAP(~EL_TXSTAT_DL_INTR);
- pDrvCtrl->rxTxChain.pTxTail = pTxChain;
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_DOWN_UNSTALL,
- NONE);
- return (OK);
- }
- }
- if (pDrvCtrl->rxTxChain.pTxHead == NULL)
- {
- pDrvCtrl->rxTxChain.pTxHead = pTxChain;
- pDrvCtrl->rxTxChain.pTxTail = pTxChain;
- }
- else
- {
- pDrvCtrl->rxTxChain.pTxTail->pNextChain = pTxChain;
- pDrvCtrl->rxTxChain.pTxTail = pTxChain;
- }
- /* load the down load descriptor */
- el3c90xCsrWriteLong (pDrvCtrl, EL_DOWNLIST_PTR,
- (UINT32)EL3C90X_CACHE_VIRT_TO_PHYS (pTxChain->pDesc),
- NONE);
- return (OK);
- }
- /*******************************************************************************
- *
- * el3c90xDndMblkPack - pack a given mBlk into download descriptor
- *
- * This function packs a given mBlk into download descriptor. This function
- * copies the data in a given mBlk into a new mBlk obtained from the pool.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL STATUS el3c90xDndMblkPack
- (
- EL3C90X_DEVICE * pDrvCtrl, /* pointer to the device control structure */
- EL_DESC_CHAIN * pTxChain,
- M_BLK_ID pMblk
- )
- {
- int len = 0;
- EL_FRAG * pFrag = NULL;
- M_BLK_ID pMblkTemp = NULL;
- if (pTxChain == NULL || pMblk == NULL)
- return (ERROR);
- if ((pMblkTemp = netTupleGet (pDrvCtrl->endObj.pNetPool,
- EL3C90X_BUFSIZ,
- M_DONTWAIT, MT_DATA, FALSE)) == NULL)
- {
- ENDLOGMSG (("Out of Tx M Blocks!n", 1, 2, 3, 4, 5, 6));
- return (ERROR);
- }
- len = netMblkToBufCopy (pMblk, pMblkTemp->mBlkHdr.mData, NULL);
- pMblkTemp->mBlkPktHdr.len = pMblkTemp->mBlkHdr.mLen = len;
- pFrag = &pTxChain->pDesc->descFrag [0];
- pFrag->fragAddr =
- PCI_SWAP((UINT32)EL3C90X_CACHE_VIRT_TO_PHYS(pMblkTemp->mBlkHdr.mData));
- pFrag->fragLen = PCI_SWAP (len | EL_LAST_FRAG);
- pTxChain->pMblk = pMblkTemp;
- pTxChain->pDesc->status = PCI_SWAP (len);
- pTxChain->pDesc->nextDesc = 0;
- return(OK);
- }
- /*******************************************************************************
- *
- * el3c90xDndSet - set up a download descriptor
- *
- * This function seta up a download descriptor by setting fragment addresses
- * to the data pointers in the mBlk chain. If the number of fragments
- * exceeds 63 then the whole whole mBlk chain is copied into a contiguous
- * buffer.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL int el3c90xDndSet
- (
- EL3C90X_DEVICE * pDrvCtrl, /* pointer to the device control structure */
- EL_DESC_CHAIN * pTxChain,
- M_BLK_ID pMblkHead
- )
- {
- int len = 0;
- int frag = 0;
- EL_FRAG * pFrag = NULL;
- M_BLK_ID pMblk;
- M_BLK_ID pMblkTemp = NULL;
- /*
- * start packing the M_BLKs in this chain into the fragment pointers.
- * stop when we run out of fragments or hit the end of the M_BLK chain.
- */
- pMblk = pMblkHead;
- for (pMblk = pMblkHead, frag = 0; pMblk != NULL; pMblk = pMblk->m_next)
- {
- if (pMblk->mBlkHdr.mLen != 0)
- {
- if (frag == EL_MAXFRAGS)
- break;
- len += pMblk->mBlkHdr.mLen;
- pTxChain->pDesc->descFrag [frag].fragAddr =
- PCI_SWAP ((UINT32)EL3C90X_CACHE_VIRT_TO_PHYS
- (pMblk->mBlkHdr.mData));
- CACHE_DMA_FLUSH (pMblk->mBlkHdr.mData, pMblk->mBlkHdr.mLen);
- pTxChain->pDesc->descFrag[frag].fragLen =
- PCI_SWAP (pMblk->mBlkHdr.mLen);
- frag++;
- }
- }
- /*
- * Handle special case: we used up all 63 fragments,
- * but we have more M_BLKs left in the chain. Copy the
- * data into an M_BLK cluster. Note that we don't
- * bother clearing the values in the other fragment
- * pointers/counters; it wouldn't gain us anything,
- * and would waste cycles.
- */
- if (pMblk != NULL)
- {
- /* get a mBlk/clBlk/cluster tuple */
- if ((pMblkTemp = netTupleGet (pDrvCtrl->endObj.pNetPool,
- EL3C90X_BUFSIZ,
- M_DONTWAIT, MT_DATA, FALSE)) == NULL)
- {
- ENDLOGMSG (("Out of Tx M Blocks!n", 1, 2, 3, 4, 5, 6));
- return (ERROR);
- }
- len = netMblkToBufCopy (pMblkHead, pMblkTemp->mBlkHdr.mData, NULL);
- pMblkTemp->mBlkPktHdr.len = pMblkTemp->mBlkHdr.mLen = len;
- netMblkClChainFree (pMblkHead); /* free the given mBlk chain */
- pMblkHead = pMblkTemp;
- pFrag = &pTxChain->pDesc->descFrag [0];
- pFrag->fragAddr =
- PCI_SWAP
- (
- (UINT32) EL3C90X_CACHE_VIRT_TO_PHYS (pMblkTemp->mBlkHdr.mData)
- );
- pFrag->fragLen = PCI_SWAP (len);
- frag = 1;
- }
- pTxChain->pMblk = pMblkHead;
- pTxChain->pDesc->descFrag [frag - 1].fragLen |= PCI_SWAP (EL_LAST_FRAG);
- pTxChain->pDesc->status = PCI_SWAP (len);
- pTxChain->pDesc->nextDesc = 0;
- return(OK);
- }
- /******************************************************************************
- *
- * el3c90xNextUpdFetch - fetch the next upload packet descriptor
- *
- * This routine fetches the next upload packet descriptor
- *
- * RETURNS: N/A.
- */
- LOCAL EL_SIMPLE_DESC_CHAIN * el3c90xNextUpdFetch
- (
- EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
- )
- {
- EL_SIMPLE_DESC_CHAIN * pRxChain = NULL;
- UINT16 rxstat;
- if ((rxstat = PCI_SWAP(pDrvCtrl->rxTxChain.pRxHead->pDesc->status)))
- {
- pRxChain = pDrvCtrl->rxTxChain.pRxHead;
- pDrvCtrl->rxTxChain.pRxHead = pRxChain->pNextChain;
- }
- return (pRxChain);
- }
- /******************************************************************************
- *
- * el3c90xNextPktFetch - fetch the next packet buffer
- *
- * This routine fetches the next packet buffer uploaded and returns
- * an mBlk.
- *
- * NOMANUAL
- *
- * RETURNS: M_BLK_ID or NULL
- */
- LOCAL M_BLK_ID el3c90xNextPktFetch
- (
- EL3C90X_DEVICE * pDrvCtrl, /* pointer to control structure */
- EL_SIMPLE_DESC_CHAIN * pRxUpd
- )
- {
- M_BLK_ID pMblk; /* pointer to the mBlk */
- int len;
- /* get a cluster */
- pMblk = pRxUpd->pMblk;
- len = (PCI_SWAP(pRxUpd->pDesc->status) & EL_RXSTAT_LENMASK);
- /* load new buffers into the Upload descriptor */
- if (el3c90xUpdFill (pDrvCtrl, pRxUpd) != OK)
- {
- /* if no buffers available drop the packet */
- #ifdef INCLUDE_RFC_1213
- /* Old RFC 1213 mib2 interface */
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
- #else
- /* New RFC 2233 mib2 interface */
- if (pDrvCtrl->endObj.pMib2Tbl != NULL)
- {
- pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.pMib2Tbl,
- M2_ctrId_ifInErrors, 1);
- }
- #endif /* INCLUDE_RFC_1213 */
- pRxUpd->pDesc->status = 0;
- return (NULL);
- }
- /* update the mBlk fields */
- pMblk->mBlkHdr.mLen = len;
- pMblk->mBlkHdr.mFlags |= M_PKTHDR;
- pMblk->mBlkPktHdr.len = len;
- return (pMblk);
- }
- /******************************************************************************
- *
- * el3c90xRxUnStall - unstall the receiver
- *
- * This routine unstalls the receiver if it the receiver hits an
- * end of channel condition.
- *
- * RETURNS: OK or ERROR
- */
- LOCAL STATUS el3c90xRxUnStall
- (
- EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
- )
- {
- if (el3c90xCsrReadLong (pDrvCtrl, EL_UPLIST_PTR, NONE) == 0 ||
- (el3c90xCsrReadLong (pDrvCtrl, EL_UPLIST_STATUS, NONE) &
- EL_PKTSTAT_UP_STALLED))
- {
- /* stall the receiver */
- 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);
- pDrvCtrl->rxTxChain.pRxHead = &pDrvCtrl->rxTxChain.rxChain [0];
- /* unstall the receiver */
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_UP_UNSTALL, NONE);
- return (OK);
- }
- return (ERROR);
- }
- /******************************************************************************
- *
- * el3c90xRxKick - kicks the receiver if blocked.
- *
- * This routine kicks the receiver if it is stalled.
- * Handle the 'end of channel' condition. When the upload engine hits the
- * end of the RX ring, it will stall. This is our cue to flush the RX ring,
- * reload the uplist pointer register and unstall the engine.
- * With the ThunderLAN chip, you get an interrupt when the receiver hits the end
- * of the receive ring, which tells you exactly when you you need to reload
- * the ring pointer. Here we have to
- * fake it.
- * This function reschedules the receive handler if things get
- * stalled because of high receive traffic. This routine can also be
- * called from the transmit routine after the packet has been queued.
- * This will take advantage of the parallel tasking concept which 3COM
- * is familiar for.
- *
- * RETURNS: N/A.
- */
- LOCAL void el3c90xRxKick
- (
- EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
- )
- {
- /* if the receiver unstalled schedule the receive again */
- if (el3c90xRxUnStall (pDrvCtrl) == OK)
- {
- if (netJobAdd ((FUNCPTR)el3c90xIntrRx, (int) pDrvCtrl, 0, 0, 0, 0)
- != OK)
- logMsg ("elPci: netJobAdd (el3c90xIntrRx) failedn", 0, 0, 0,
- 0, 0, 0);
- }
- }
- /******************************************************************************
- *
- * el3c90xIntrRx - handle receive interrupts
- *
- * This routine handles receive interrupts.
- *
- * RETURNS: N/A.
- */
- LOCAL void el3c90xIntrRx
- (
- EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
- )
- {
- M_BLK_ID pMblk; /* pointer to the mBlk */
- EL_SIMPLE_DESC_CHAIN * pRxUpd;
- UINT32 descStatus;
- while ((pRxUpd = el3c90xNextUpdFetch (pDrvCtrl)) != NULL)
- {
- descStatus = PCI_SWAP(pRxUpd->pDesc->status);
- /*
- * If an error occurs, update stats, clear the
- * status word and leave the M_BLK cluster in place:
- * it should simply get re-used next time this descriptor
- * comes up in the ring.
- */
- if (descStatus & EL_RXSTAT_UP_ERROR)
- {
- #ifdef INCLUDE_RFC_1213
- /* Old RFC 1213 mib2 interface */
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
- #else
- /* New RFC 2233 mib2 interface */
- if (pDrvCtrl->endObj.pMib2Tbl != NULL)
- {
- pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.
- pMib2Tbl,
- M2_ctrId_ifInErrors,
- 1);
- }
- #endif /* INCLUDE_RFC_1213 */
- pRxUpd->pDesc->status = 0;
- continue;
- }
- /*
- * If there error bit was not set, the upload complete
- * bit should be set which means we have a valid packet.
- * If not, something truly strange has happened.
- */
- if (!(descStatus & EL_RXSTAT_UP_CMPLT))
- {
- logMsg ("elPci%d: bad receive status -- packet dropped",
- pDrvCtrl->unit, 0, 0, 0, 0, 0);
- #ifdef INCLUDE_RFC_1213
- /* Old RFC 1213 mib2 interface */
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
- #else
- /* New RFC 2233 mib2 interface */
- if (pDrvCtrl->endObj.pMib2Tbl != NULL)
- {
- pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.
- pMib2Tbl,
- M2_ctrId_ifInErrors,
- 1);
- }
- #endif /* INCLUDE_RFC_1213 */
- pRxUpd->pDesc->status = 0;
- continue;
- }
- if ((pMblk = el3c90xNextPktFetch (pDrvCtrl, pRxUpd)) == NULL)
- continue;
- #ifdef INCLUDE_RFC_1213
- /* Old RFC 1213 mib2 interface */
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
- #else
- /* 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 */
- ENDLOGMSG (("Calling upper layer's recv rtnn", 1, 2, 3, 4, 5, 6));
- END_RCV_RTN_CALL (&pDrvCtrl->endObj, pMblk);
- }
- /* kick the receiver if stalled */
- el3c90xRxKick (pDrvCtrl);
- el3c90xIntrSet (pDrvCtrl, EL_STAT_UP_COMPLETE);
- }
- /******************************************************************************
- *
- * el3c90xIntrTx - handle transmit interrupt
- *
- * This routine handles transmit interrupt
- *
- * RETURNS: N/A.
- */
- LOCAL void el3c90xIntrTx
- (
- EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
- )
- {
- EL_DESC_CHAIN * pTxChain;
- END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
- while ((pTxChain = el3c90xTxDequeue (pDrvCtrl)) != NULL)
- {
- netMblkClChainFree (pTxChain->pMblk);
- el3c90xDndFree (pDrvCtrl, pTxChain);
- }
- END_TX_SEM_GIVE (&pDrvCtrl->endObj);
- el3c90xIntrSet (pDrvCtrl, EL_STAT_DOWN_COMPLETE);
- if (pDrvCtrl->txBlocked)
- {
- pDrvCtrl->txBlocked = FALSE;
- muxTxRestart (&pDrvCtrl->endObj);
- }
- }
- /******************************************************************************
- *
- * el3c90xIntrErr - handle transmit errors
- *
- * This routine handles transmit errors
- *
- * RETURNS: N/A.
- */
- LOCAL void el3c90xIntrErr
- (
- EL3C90X_DEVICE * pDrvCtrl, /* pointer to the device control structure */
- UINT8 txstat
- )
- {
- if (txstat & EL_TXSTATUS_UNDERRUN ||
- txstat & EL_TXSTATUS_JABBER ||
- txstat & EL_TXSTATUS_RECLAIM)
- {
- logMsg ("elPci%d: transmission error: %xn",
- pDrvCtrl->unit, txstat,0,0,0,0);
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_TX_RESET, NONE);
- el3c90xWait(pDrvCtrl);
- if (pDrvCtrl->rxTxChain.pTxHead != NULL)
- {
- el3c90xCsrWriteLong (pDrvCtrl, EL_DOWNLIST_PTR,
- (UINT32) EL3C90X_CACHE_VIRT_TO_PHYS
- (pDrvCtrl->rxTxChain.pTxHead->pDesc),
- NONE);
- }
- /* Remember to set this for the first generation 3c90X chips. */
- el3c90xCsrWriteByte (pDrvCtrl, EL_TX_FREETHRESH,
- (EL3C90X_BUFSIZ >> 8), NONE);
- if (pDrvCtrl->devType == EL_TYPE_905B)
- {
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND,
- (EL_CMD_SET_TX_RECLAIM |
- (EL3C90X_BUFSIZ >> 4)), NONE);
- }
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_TX_ENABLE, NONE);
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_DOWN_UNSTALL, NONE);
- }
- else
- {
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_TX_ENABLE, NONE);
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_DOWN_UNSTALL, NONE);
- }
- #ifdef INCLUDE_RFC_1213
- /* Old RFC 1213 mib2 interface */
- END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
- #else
- /* New RFC 2233 mib2 interface */
- if (pDrvCtrl->endObj.pMib2Tbl != NULL)
- {
- pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.pMib2Tbl,
- M2_ctrId_ifOutErrors, 1);
- }
- #endif /* INCLUDE_RFC_1213 */
- el3c90xIntrSet (pDrvCtrl, EL_STAT_TX_COMPLETE);
- }
- /******************************************************************************
- *
- * el3c90xStatUpdate - handle the stats overflow interrupt
- *
- * This routine handles the stats overflow interrupt
- *
- * RETURNS: N/A.
- */
- LOCAL void el3c90xStatUpdate
- (
- EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
- )
- {
- EL_STATS elStats;
- UINT8 * pChar;
- int ix;
- bzero((char *)&elStats, sizeof(elStats));
- pChar = (UINT8 *)&elStats;
- /* Read all the stats registers. */
- for (ix = 0; ix < 16; ix++)
- *pChar++ = el3c90xCsrReadByte (pDrvCtrl, EL_W6_CARRIER_LOST + ix,
- EL_WIN_6);
- /*
- * Boomerang and cyclone chips have an extra stats counter
- * in window 4 (BadSSD). We have to read this too in order
- * to clear out all the stats registers and avoid a statsoflow
- * interrupt.
- */
- el3c90xCsrReadByte (pDrvCtrl, EL_W4_BADSSD, EL_WIN_4);
- return;
- }
- /******************************************************************************
- *
- * el3c90xInt - interrupt handler for the NIC interrupt
- *
- * This routine is general interrupt handler.
- *
- * RETURNS: N/A.
- */
- LOCAL void el3c90xInt
- (
- EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
- )
- {
- UINT16 status;
- UINT16 intClr = 0;
- UINT8 txstat;
- ENDLOGMSG (("Got an interrupt!n", 1, 2, 3, 4, 5, 6));
- /* read interrupt status */
- status = el3c90xCsrReadWord (pDrvCtrl, EL_STATUS, NONE);
- if ((status & EL_INTRS) == 0)
- return;
- if (status & EL_STAT_UP_COMPLETE)
- {
- if (netJobAdd ((FUNCPTR)el3c90xIntrRx, (int) pDrvCtrl,
- 0, 0, 0, 0) == OK)
- {
- intClr |= EL_STAT_UP_COMPLETE;
- }
- else
- logMsg ("xl: netJobAdd (el3c90xIntrRx) failedn",
- 0, 0, 0, 0, 0, 0);
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND,
- (EL_CMD_INTR_ACK | EL_STAT_UP_COMPLETE), NONE);
- }
- if (status & EL_STAT_DOWN_COMPLETE)
- {
- if (netJobAdd ((FUNCPTR)el3c90xIntrTx, (int) pDrvCtrl,
- 0, 0, 0, 0) == OK)
- {
- intClr |= EL_STAT_DOWN_COMPLETE;
- }
- else
- logMsg ("xl: netJobAdd (el3c90xIntrTx) failedn",
- 0, 0, 0, 0, 0, 0);
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND,
- (EL_CMD_INTR_ACK | EL_STAT_DOWN_COMPLETE), NONE);
- }
- if (status & EL_STAT_TX_COMPLETE)
- {
- txstat = el3c90xCsrReadByte (pDrvCtrl, EL_TX_STATUS, NONE);
- if (netJobAdd ((FUNCPTR)el3c90xIntrErr, (int) pDrvCtrl,
- (int)txstat, 0, 0, 0) == OK)
- {
- intClr |= EL_STAT_TX_COMPLETE;
- }
- else
- logMsg ("xl: netJobAdd (el3c90xIntrErr) failedn",
- 0, 0, 0, 0, 0, 0);
- /*
- * Write an arbitrary byte to the TX_STATUS register
- * to clear this interrupt/error and advance to the next.
- */
- el3c90xCsrWriteByte (pDrvCtrl, EL_TX_STATUS, 0x01, NONE);
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND,
- (EL_CMD_INTR_ACK | EL_STAT_TX_COMPLETE), NONE);
- }
- if (status & EL_STAT_STATSOFLOW)
- {
- el3c90xStatUpdate(pDrvCtrl);
- }
- if (status & EL_STAT_ADFAIL)
- {
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_INTR_ENB, NONE);
- el3c90xReset (pDrvCtrl);
- if (netJobAdd ((FUNCPTR)el3c90xInit, (int) pDrvCtrl,
- 0, 0, 0, 0) != OK)
- logMsg ("xl: netJobAdd (el3c90xInit) failedn",
- 0, 0, 0, 0, 0, 0);
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND,
- (EL_CMD_INTR_ACK | EL_STAT_ADFAIL), NONE);
- el3c90xCsrWriteWord (pDrvCtrl, EL_STATUS,
- (EL_CMD_INTR_ACK | EL_STAT_INTREQ |
- EL_STAT_INTLATCH), NONE);
- return;
- }
- /* acknowledge all interrupts */
- el3c90xCsrWriteWord (pDrvCtrl, EL_STATUS,
- (EL_CMD_INTR_ACK | EL_STAT_INTREQ | EL_STAT_INTLATCH),
- NONE);
- if (intClr)
- el3c90xIntrClr (pDrvCtrl, intClr);
- return;
- }
- /*******************************************************************************
- *
- * el3c90xMiiSync - sync the PHYs
- *
- * This function syncs the PHYs by setting data bit and strobing the
- * clock 32 times.
- *
- * RETURNS: N/A
- */
- LOCAL void el3c90xMiiSync
- (
- EL3C90X_DEVICE * pDrvCtrl
- )
- {
- register int ix;
- EL_MII_SET (EL_MII_DIR | EL_MII_DATA);
- for (ix = 0; ix < 32; ix++)
- {
- EL_MII_SET (EL_MII_CLK);
- SYS_DELAY (1);
- EL_MII_CLR (EL_MII_CLK);
- SYS_DELAY (1);
- }
- return;
- }
- /*******************************************************************************
- *
- * el3c90xMiiSend - clock a series of bits through the MII.
- *
- * This function clocks a series of bits through the MII.
- *
- * RETURNS: N/A
- */
- LOCAL void el3c90xMiiSend
- (
- EL3C90X_DEVICE * pDrvCtrl,
- UINT32 bits,
- int cnt
- )
- {
- int ix;
- EL_MII_CLR (EL_MII_CLK);
- for (ix = (0x1 << (cnt - 1)); ix; ix >>= 1)
- {
- if (bits & ix)
- {
- EL_MII_SET (EL_MII_DATA);
- }
- else
- {
- EL_MII_CLR (EL_MII_DATA);
- }
- SYS_DELAY (1);
- EL_MII_CLR (EL_MII_CLK);
- SYS_DELAY (1);
- EL_MII_SET (EL_MII_CLK);
- }
- }
- /*******************************************************************************
- *
- * el3c90xMiiRegRead - read an PHY register through the MII.
- *
- * This function reads a PHY register through the MII.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL int el3c90xMiiRegRead
- (
- EL3C90X_DEVICE * pDrvCtrl,
- EL_MII_FRAME * pMiiFrame
- )
- {
- int ix;
- int ack;
- /* set up frame for RX. */
- pMiiFrame->stDelim = EL_MII_STARTDELIM;
- pMiiFrame->opCode = EL_MII_READOP;
- pMiiFrame->turnAround = 0;
- pMiiFrame->data = 0;
- /* clear PHY_MGMT register */
- el3c90xCsrWriteWord (pDrvCtrl, EL_W4_PHY_MGMT, 0, EL_WIN_4);
- /* turn on data xmit.*/
- EL_MII_SET (EL_MII_DIR);
- el3c90xMiiSync (pDrvCtrl);
- /* Send command/address info. */
- el3c90xMiiSend (pDrvCtrl, pMiiFrame->stDelim, 2);
- el3c90xMiiSend (pDrvCtrl, pMiiFrame->opCode, 2);
- el3c90xMiiSend (pDrvCtrl, pMiiFrame->phyAddr, 5);
- el3c90xMiiSend (pDrvCtrl, pMiiFrame->regAddr, 5);
- /* idle bit */
- EL_MII_CLR ((EL_MII_CLK | EL_MII_DATA));
- SYS_DELAY (1);
- EL_MII_SET (EL_MII_CLK);
- SYS_DELAY (1);
- /* turn off xmit. */
- EL_MII_CLR (EL_MII_DIR);
- /* Check for ack */
- EL_MII_CLR (EL_MII_CLK);
- SYS_DELAY (1);
- EL_MII_SET (EL_MII_CLK);
- SYS_DELAY (1);
- ack = (el3c90xCsrReadWord (pDrvCtrl, EL_W4_PHY_MGMT, EL_WIN_4) &
- EL_MII_DATA);
- /*
- * Now try reading data bits. If the ack failed, we still
- * need to clock through 16 cycles to keep the PHY(s) in sync.
- */
- if (ack)
- {
- for(ix = 0; ix < 16; ix++)
- {
- EL_MII_CLR (EL_MII_CLK);
- SYS_DELAY (1);
- EL_MII_SET (EL_MII_CLK);
- SYS_DELAY (1);
- }
- goto fail;
- }
- for (ix = 0x8000; ix; ix >>= 1)
- {
- EL_MII_CLR (EL_MII_CLK);
- SYS_DELAY (1);
- if (!ack)
- {
- if (el3c90xCsrReadWord (pDrvCtrl, EL_W4_PHY_MGMT, EL_WIN_4) &
- EL_MII_DATA)
- pMiiFrame->data |= ix;
- SYS_DELAY (1);
- }
- EL_MII_SET (EL_MII_CLK);
- SYS_DELAY (1);
- }
- fail:
- {
- EL_MII_CLR (EL_MII_CLK);
- SYS_DELAY (1);
- EL_MII_SET (EL_MII_CLK);
- SYS_DELAY (1);
- }
- if (ack)
- return (ERROR);
- return (OK);
- }
- /*******************************************************************************
- *
- * el3c90xMiiRegWrite - write to a PHY register through the MII.
- *
- * This function writes to a PHY register through the MII.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL int el3c90xMiiRegWrite
- (
- EL3C90X_DEVICE * pDrvCtrl,
- EL_MII_FRAME * pMiiFrame
- )
- {
- /* set up frame for TX. */
- pMiiFrame->stDelim = EL_MII_STARTDELIM;
- pMiiFrame->opCode = EL_MII_WRITEOP;
- pMiiFrame->turnAround = EL_MII_TURNAROUND;
- /* turn on data output. */
- EL_MII_SET (EL_MII_DIR);
- el3c90xMiiSync (pDrvCtrl);
- el3c90xMiiSend (pDrvCtrl, pMiiFrame->stDelim, 2);
- el3c90xMiiSend (pDrvCtrl, pMiiFrame->opCode, 2);
- el3c90xMiiSend (pDrvCtrl, pMiiFrame->phyAddr, 5);
- el3c90xMiiSend (pDrvCtrl, pMiiFrame->regAddr, 5);
- el3c90xMiiSend (pDrvCtrl, pMiiFrame->turnAround, 2);
- el3c90xMiiSend (pDrvCtrl, pMiiFrame->data, 16);
- /* idle bit. */
- EL_MII_SET (EL_MII_CLK);
- SYS_DELAY (1);
- EL_MII_CLR (EL_MII_CLK);
- SYS_DELAY (1);
- /* Turn off xmit. */
- EL_MII_CLR (EL_MII_DIR);
- return (OK);
- }
- /*******************************************************************************
- *
- * el3c90xPhyRegRead - read a PHY reg
- *
- * This function reads a PHY reg
- *
- * RETURNS: UINT16 value.
- */
- LOCAL UINT16 el3c90xPhyRegRead
- (
- EL3C90X_DEVICE * pDrvCtrl,
- int reg
- )
- {
- EL_MII_FRAME miiFrame;
- bzero ((char *)&miiFrame, sizeof(miiFrame));
- miiFrame.phyAddr = pDrvCtrl->devPhyAddr;
- miiFrame.regAddr = reg;
- el3c90xMiiRegRead (pDrvCtrl, &miiFrame);
- return(miiFrame.data);
- }
- /*******************************************************************************
- *
- * el3c90xPhyRegWrite - write a PHY reg
- *
- * This function writes a PHY reg
- *
- * RETURNS: N/A
- */
- LOCAL void el3c90xPhyRegWrite
- (
- EL3C90X_DEVICE * pDrvCtrl,
- int reg,
- int data
- )
- {
- EL_MII_FRAME frame;
- bzero((char *)&frame, sizeof(frame));
- frame.phyAddr = pDrvCtrl->devPhyAddr;
- frame.regAddr = reg;
- frame.data = data;
- el3c90xMiiRegWrite(pDrvCtrl, &frame);
- return;
- }
- /*******************************************************************************
- *
- * el3c90xAutoNegTx - initiate an autonegotiation session.
- *
- * This function initiates an autonegotiation session.
- *
- * RETURNS: N/A
- */
- LOCAL void el3c90xAutoNegTx
- (
- EL3C90X_DEVICE * pDrvCtrl
- )
- {
- UINT16 phyStatus;
- el3c90xPhyRegWrite (pDrvCtrl, PHY_BMCR, PHY_BMCR_RESET);
- SYS_DELAY (500);
- while (el3c90xPhyRegRead (pDrvCtrl, EL_PHY_GENCTL)
- & PHY_BMCR_RESET);
- phyStatus = el3c90xPhyRegRead (pDrvCtrl, PHY_BMCR);
- phyStatus |= (PHY_BMCR_AUTONEGENBL | PHY_BMCR_AUTONEGRSTR);
- el3c90xPhyRegWrite (pDrvCtrl, PHY_BMCR, phyStatus);
- return;
- }
- /*******************************************************************************
- *
- * el3c90xMiiAutoNeg - invoke autonegotiation on a PHY
- *
- * This function invokes autonegotiation on a PHY. Also used with the
- * 3Com internal autoneg logic which is mapped onto the MII.
- *
- * RETURNS: N/A
- */
- LOCAL void el3c90xMiiAutoNeg
- (
- EL3C90X_DEVICE * pDrvCtrl
- )
- {
- UINT16 phyStatus = 0;
- UINT16 media;
- UINT16 advert;
- UINT16 ability;
- /*
- * The 100baseT4 PHY on the 3c905-T4 has the 'autoneg supported'
- * bit cleared in the status register, but has the 'autoneg enabled'
- * bit set in the control register. This is a contradiction, and
- * I'm not sure how to handle it. If you want to force an attempt
- * to autoneg for 100baseT4 PHYs, #define FORCE_AUTONEG_TFOUR
- * and see what happens.
- */
- #ifndef FORCE_AUTONEG_TFOUR
- /*
- * First, see if autoneg is supported. If not, there's
- * no point in continuing.
- */
- phyStatus = el3c90xPhyRegRead (pDrvCtrl, PHY_BMSR);
- if (!(phyStatus & PHY_BMSR_CANAUTONEG))
- {
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: autonegotiation not supportedn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- media = el3c90xPhyRegRead (pDrvCtrl, PHY_BMCR);
- media &= ~PHY_BMCR_SPEEDSEL;
- media &= ~PHY_BMCR_DUPLEX;
- el3c90xPhyRegWrite (pDrvCtrl, PHY_BMCR, media);
- el3c90xCsrWriteByte (pDrvCtrl, EL_W3_MAC_CTRL,
- (el3c90xCsrReadByte (pDrvCtrl, EL_W3_MAC_CTRL,
- EL_WIN_3) &
- ~EL_MACCTRL_DUPLEX), EL_WIN_3);
- return;
- }
- #endif
- el3c90xAutoNegTx (pDrvCtrl);
- taskDelay (sysClkRateGet() * 2);
- if (el3c90xPhyRegRead (pDrvCtrl, PHY_BMSR) & PHY_BMSR_AUTONEGCOMP)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: autoneg complete, ",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- phyStatus = el3c90xPhyRegRead (pDrvCtrl, PHY_BMSR);
- }
- else
- {
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: autoneg not complete, ",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- }
- media = el3c90xPhyRegRead (pDrvCtrl, PHY_BMCR);
- /* Link is good. Report modes and set duplex mode. */
- if (el3c90xPhyRegRead (pDrvCtrl, PHY_BMSR) & PHY_BMSR_LINKSTAT)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"link status good ", 1, 2, 3, 4, 5, 6);
- advert = el3c90xPhyRegRead (pDrvCtrl, EL_PHY_ANAR);
- ability = el3c90xPhyRegRead (pDrvCtrl, EL_PHY_LPAR);
- if (advert & PHY_ANAR_100BT4 && ability & PHY_ANAR_100BT4)
- {
- media |= PHY_BMCR_SPEEDSEL;
- media &= ~PHY_BMCR_DUPLEX;
- DRV_LOG (DRV_DEBUG_LOAD,"(100baseT4)n", 1, 2, 3, 4, 5, 6);
- }
- else if (advert & PHY_ANAR_100BTXFULL && ability & PHY_ANAR_100BTXFULL)
- {
- media |= PHY_BMCR_SPEEDSEL;
- media |= PHY_BMCR_DUPLEX;
- DRV_LOG (DRV_DEBUG_LOAD,"(full-duplex, 100Mbps)n",
- 1, 2, 3, 4, 5, 6);
- }
- else if (advert & PHY_ANAR_100BTXHALF && ability & PHY_ANAR_100BTXHALF)
- {
- media |= PHY_BMCR_SPEEDSEL;
- media &= ~PHY_BMCR_DUPLEX;
- DRV_LOG (DRV_DEBUG_LOAD,"(half-duplex, 100Mbps)n",
- 1, 2, 3, 4, 5, 6);
- }
- else if (advert & PHY_ANAR_10BTFULL && ability & PHY_ANAR_10BTFULL)
- {
- media &= ~PHY_BMCR_SPEEDSEL;
- media |= PHY_BMCR_DUPLEX;
- DRV_LOG (DRV_DEBUG_LOAD,"(full-duplex, 10Mbps)n",
- 1, 2, 3, 4, 5, 6);
- }
- else if (advert & PHY_ANAR_10BTHALF && ability & PHY_ANAR_10BTHALF)
- {
- media &= ~PHY_BMCR_SPEEDSEL;
- media &= ~PHY_BMCR_DUPLEX;
- DRV_LOG (DRV_DEBUG_LOAD,"(half-duplex, 10Mbps)n",
- 1, 2, 3, 4, 5, 6);
- }
- /* Set ASIC's duplex mode to match the PHY. */
- if (media & PHY_BMCR_DUPLEX)
- el3c90xCsrWriteByte (pDrvCtrl, EL_W3_MAC_CTRL, EL_MACCTRL_DUPLEX,
- EL_WIN_3);
- else
- el3c90xCsrWriteByte (pDrvCtrl, EL_W3_MAC_CTRL,
- (el3c90xCsrReadByte (pDrvCtrl, EL_W3_MAC_CTRL,
- EL_WIN_3) &
- ~EL_MACCTRL_DUPLEX), EL_WIN_3);
- el3c90xPhyRegWrite (pDrvCtrl, PHY_BMCR, media);
- }
- else
- {
- DRV_LOG (DRV_DEBUG_LOAD,"no carrier (forcing half-duplex,"
- "10Mbps)n", 1, 2, 3, 4, 5, 6);
- media &= ~PHY_BMCR_SPEEDSEL;
- media &= ~PHY_BMCR_DUPLEX;
- el3c90xPhyRegWrite (pDrvCtrl, PHY_BMCR, media);
- el3c90xCsrWriteByte (pDrvCtrl, EL_W3_MAC_CTRL,
- (el3c90xCsrReadByte (pDrvCtrl, EL_W3_MAC_CTRL,
- EL_WIN_3) &
- ~EL_MACCTRL_DUPLEX), EL_WIN_3);
- }
- return;
- }
- /*******************************************************************************
- *
- * el3c90xMiiModeGet - get the MII mode
- *
- * This function gets the MII mode and returns the speed of the physical
- * interface. The default speed is 10Mbits/sec.
- *
- * RETURNS: speed of the physical interface.
- */
- LOCAL int el3c90xMiiModeGet
- (
- EL3C90X_DEVICE * pDrvCtrl
- )
- {
- UINT16 bmsr;
- int speed = 10000000;
- bmsr = el3c90xPhyRegRead (pDrvCtrl, PHY_BMSR);
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: PHY status word: %xn", pDrvCtrl->unit,
- bmsr, 3, 4, 5, 6);
- if (bmsr & PHY_BMSR_10BTHALF)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: 10Mbps half-duplex mode supportedn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- }
- if (bmsr & PHY_BMSR_10BTFULL)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: 10Mbps full-duplex mode supportedn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- }
- if (bmsr & PHY_BMSR_100BTXHALF)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d:100Mbps half-duplex mode supportedn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- speed = 100000000;
- }
- if (bmsr & PHY_BMSR_100BTXFULL)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d:100Mbps full-duplex mode supportedn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- speed = 100000000;
- }
- /* Some also support 100BaseT4 */
- if (bmsr & PHY_BMSR_100BT4)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d:100baseT4 mode supportedn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- speed = 100000000;
- #ifdef FORCE_AUTONEG_TFOUR
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d:force on autoneg support for BT4n",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- #endif
- }
- if (bmsr & PHY_BMSR_CANAUTONEG)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: autoneg supportedn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- speed = 10000000;
- }
- return (speed);
- }
- /*******************************************************************************
- *
- * el3c90xMediaSet - set the media access control
- *
- * This function sets the MAC register.
- *
- * RETURNS: N/A
- */
- LOCAL void el3c90xMediaSet
- (
- EL3C90X_DEVICE * pDrvCtrl,
- int media
- )
- {
- UINT32 icfg;
- UINT16 mediastat;
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: selecting ", pDrvCtrl->unit,
- 2, 3, 4, 5, 6);
- mediastat = el3c90xCsrReadWord (pDrvCtrl, EL_W4_MEDIA_STATUS, EL_WIN_4);
- icfg = el3c90xCsrReadLong (pDrvCtrl, EL_W3_INTERNAL_CFG, EL_WIN_3);
- if (pDrvCtrl->devMedia & EL_MEDIAOPT_BT)
- {
- if (IFM_SUBTYPE (media) == IFM_10_T)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"10baseT transceiver, ",
- 1, 2, 3, 4, 5, 6);
- pDrvCtrl->xCvr = EL_XCVR_10BT;
- icfg &= ~EL_ICFG_CONNECTOR_MASK;
- icfg |= (EL_XCVR_10BT << EL_ICFG_CONNECTOR_BITS);
- mediastat |= EL_MEDIASTAT_LINKBEAT|
- EL_MEDIASTAT_JABGUARD;
- mediastat &= ~EL_MEDIASTAT_SQEENB;
- }
- }
- if (pDrvCtrl->devMedia & EL_MEDIAOPT_BFX)
- {
- if (IFM_SUBTYPE (media) == IFM_100_FX)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"100baseFX port, ", 1, 2, 3, 4, 5, 6);
- pDrvCtrl->xCvr = EL_XCVR_100BFX;
- icfg &= ~EL_ICFG_CONNECTOR_MASK;
- icfg |= (EL_XCVR_100BFX << EL_ICFG_CONNECTOR_BITS);
- mediastat |= EL_MEDIASTAT_LINKBEAT;
- mediastat &= ~EL_MEDIASTAT_SQEENB;
- }
- }
- if (pDrvCtrl->devMedia & EL_MEDIAOPT_AUI)
- {
- if (IFM_SUBTYPE (media) == IFM_10_5)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"AUI port, ", 1, 2, 3, 4, 5, 6);
- pDrvCtrl->xCvr = EL_XCVR_AUI;
- icfg &= ~EL_ICFG_CONNECTOR_MASK;
- icfg |= (EL_XCVR_AUI << EL_ICFG_CONNECTOR_BITS);
- mediastat &= ~(EL_MEDIASTAT_LINKBEAT|
- EL_MEDIASTAT_JABGUARD);
- mediastat |= ~EL_MEDIASTAT_SQEENB;
- }
- }
- if (pDrvCtrl->devMedia & EL_MEDIAOPT_BNC)
- {
- if (IFM_SUBTYPE (media) == IFM_10_2)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"BNC port, ", 1, 2, 3, 4, 5, 6);
- pDrvCtrl->xCvr = EL_XCVR_COAX;
- icfg &= ~EL_ICFG_CONNECTOR_MASK;
- icfg |= (EL_XCVR_COAX << EL_ICFG_CONNECTOR_BITS);
- mediastat &= ~(EL_MEDIASTAT_LINKBEAT|
- EL_MEDIASTAT_JABGUARD|
- EL_MEDIASTAT_SQEENB);
- }
- }
- if ((media & IFM_GMASK) == IFM_FDX ||
- IFM_SUBTYPE (media) == IFM_100_FX)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"full duplexn", 1, 2, 3, 4, 5, 6);
- el3c90xCsrWriteByte (pDrvCtrl, EL_W3_MAC_CTRL, EL_MACCTRL_DUPLEX,
- EL_WIN_3);
- }
- else
- {
- DRV_LOG (DRV_DEBUG_LOAD,"half duplexn", 1, 2, 3, 4, 5, 6);
- el3c90xCsrWriteByte (pDrvCtrl, EL_W3_MAC_CTRL,
- (el3c90xCsrReadByte (pDrvCtrl, EL_W3_MAC_CTRL,
- EL_WIN_3) &
- ~EL_MACCTRL_DUPLEX), EL_WIN_3);
- }
- if (IFM_SUBTYPE(media) == IFM_10_2)
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_COAX_START, NONE);
- else
- el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_COAX_STOP, NONE);
- el3c90xCsrWriteLong (pDrvCtrl, EL_W3_INTERNAL_CFG, icfg, EL_WIN_3);
- el3c90xCsrWriteWord (pDrvCtrl, EL_W4_MEDIA_STATUS, mediastat, EL_WIN_4);
- SYS_DELAY(800);
- return;
- }
- /*******************************************************************************
- *
- * el3c90xMediaCheck - check the media on the adapter card.
- *
- * This function checks for the media on the adapter card.
- * This routine is a kludge to work around possible hardware faults
- * or manufacturing defects that can cause the media options register
- * (or reset options register, as it's called for the first generation
- * 3cx90x adapters) to return an incorrect result.
- * one Dell Latitude laptop docking station with an integrated 3c905-TX
- * doesn't have any of the 'mediaopt' bits set. This causes the
- * the attach routine to fail because it doesn't know what media
- * to look for. If we find ourselves in this predicament, this routine
- * will try to guess the media options values and warn the user of a
- * possible manufacturing defect with his adapter/system/whatever.
- *
- * RETURNS: N/A
- */
- LOCAL void el3c90xMediaCheck
- (
- EL3C90X_DEVICE * pDrvCtrl
- )
- {
- UINT16 devid;
- /*
- * if some of the media options bits are set, assume they are
- * correct. If not, try to figure it out down below.
- */
- if (pDrvCtrl->devMedia & (EL_MEDIAOPT_MASK & ~EL_MEDIAOPT_VCO))
- {
- /*
- * Check the XCVR value. If it's not in the normal range
- * of values, we need to fake it up here.
- */
- if (pDrvCtrl->xCvr <= EL_XCVR_AUTO)
- return;
- else
- {
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: bogus xcvr value "
- "in EEPROM (%x)n", pDrvCtrl->unit, pDrvCtrl->xCvr,
- 3, 4, 5, 6);
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: choosing new default based "
- "on card typen", pDrvCtrl->unit, 2, 3, 4, 5, 6);
- }
- }
- else
- {
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: WARNING: no media options bits set"
- "in the media options register!!n", pDrvCtrl->unit,
- 2, 3, 4, 5, 6);
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: this could be a manufacturing"
- "defect in your adapter or systemn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: attempting to guess media type; you "
- "should probably consult your vendorn", pDrvCtrl->unit,
- 2, 3, 4, 5, 6);
- }
- /*
- * Read the device ID from the EEPROM.
- * This is what's loaded into the PCI device ID register, so it has
- * to be correct otherwise we wouldn't have gotten this far.
- */
- el3c90xEprmRead (pDrvCtrl, (caddr_t)&devid, EL_EE_PRODID, 1, 0);
- switch (devid)
- {
- case TC_DEVICEID_BOOMERANG_10BT: /* 3c900-TP */
- case TC_DEVICEID_CYCLONE_10BT: /* 3c900B-TP */
- pDrvCtrl->devMedia = EL_MEDIAOPT_BT;
- pDrvCtrl->xCvr = EL_XCVR_10BT;
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: guessing 10BaseT transceivern",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- break;
- case TC_DEVICEID_BOOMERANG_10BT_COMBO: /* 3c900-COMBO */
- case TC_DEVICEID_CYCLONE_10BT_COMBO: /* 3c900B-COMBO */
- pDrvCtrl->devMedia = (EL_MEDIAOPT_BT |EL_MEDIAOPT_BNC |
- EL_MEDIAOPT_AUI);
- pDrvCtrl->xCvr = EL_XCVR_10BT;
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: guessing COMBO (AUI/BNC/TP)n",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- break;
- case TC_DEVICEID_BOOMERANG_10_100BT: /* 3c905-TX */
- pDrvCtrl->devMedia = EL_MEDIAOPT_MII;
- pDrvCtrl->xCvr = EL_XCVR_MII;
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: guessing MIIn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- break;
- case TC_DEVICEID_BOOMERANG_100BT4: /* 3c905-T4 */
- case TC_DEVICEID_CYCLONE_10_100BT4: /* 3c905B-T4 */
- pDrvCtrl->devMedia = EL_MEDIAOPT_BT4;
- pDrvCtrl->xCvr = EL_XCVR_MII;
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: guessing 100BaseT4/MIIn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- break;
- case TC_DEVICEID_CYCLONE_10_100BT: /* 3c905B-TX */
- case TC_DEVICEID_CYCLONE_10_100BT_SERV: /* 3c980-TX */
- pDrvCtrl->devMedia = EL_MEDIAOPT_BTX;
- pDrvCtrl->xCvr = EL_XCVR_AUTO;
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: guessing 10/100 internaln",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- break;
- default:
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: unknown device ID: %x -- "
- "defaulting to 10baseTn", pDrvCtrl->unit, devid,
- 3, 4, 5, 6);
- pDrvCtrl->devMedia = EL_MEDIAOPT_BT;
- break;
- }
- return;
- }
- /*******************************************************************************
- *
- * el3c90xMediaConfig - configure the media and do auto negotiation
- *
- * This function configures the media and does the auto negotioation.
- *
- * RETURNS: speed or 0
- *
- */
- LOCAL int el3c90xMediaConfig
- (
- EL3C90X_DEVICE * pDrvCtrl /* device control structure */
- )
- {
- EL_DEV_TYPE * pDevType;
- UINT32 icfg;
- int media = IFM_ETHER | IFM_100_TX |IFM_FDX;
- UINT16 phyVendorId;
- UINT16 phyDevId;
- UINT16 phyStatus;
- int speed = 10000000;
- int ix;
- /*
- * now we have to see what sort of media we have.
- * This includes probing for an MII interace and a
- * possible PHY.
- */
- pDrvCtrl->devMedia = el3c90xCsrReadWord (pDrvCtrl, EL_W3_MEDIA_OPT,
- EL_WIN_3);
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: media options word: %xn",
- pDrvCtrl->unit,
- pDrvCtrl->devMedia, 3, 4, 5, 6);
- el3c90xEprmRead (pDrvCtrl, (char *)&pDrvCtrl->xCvr, EL_EE_ICFG_0, 2, 0);
- pDrvCtrl->xCvr &= EL_ICFG_CONNECTOR_MASK;
- pDrvCtrl->xCvr >>= EL_ICFG_CONNECTOR_BITS;
- el3c90xMediaCheck (pDrvCtrl);
- if (pDrvCtrl->devMedia & EL_MEDIAOPT_MII ||
- pDrvCtrl->devMedia & EL_MEDIAOPT_BTX ||
- pDrvCtrl->devMedia & EL_MEDIAOPT_BT4)
- {
- /*
- * in theory we shouldn't need this, but... if this
- * card supports an MII, either an external one or
- * an internal fake one, select it in the internal
- * config register before trying to probe it.
- */
- icfg = el3c90xCsrReadLong (pDrvCtrl, EL_W3_INTERNAL_CFG, EL_WIN_3);
- icfg &= ~EL_ICFG_CONNECTOR_MASK;
- if (pDrvCtrl->devMedia & EL_MEDIAOPT_MII ||
- pDrvCtrl->devMedia & EL_MEDIAOPT_BT4)
- icfg |= (EL_XCVR_MII << EL_ICFG_CONNECTOR_BITS);
- if (pDrvCtrl->devMedia & EL_MEDIAOPT_BTX)
- icfg |= (EL_XCVR_AUTO << EL_ICFG_CONNECTOR_BITS);
- if (pDrvCtrl->devMedia & EL_MEDIAOPT_BFX)
- icfg |= (EL_XCVR_100BFX << EL_ICFG_CONNECTOR_BITS);
- el3c90xCsrWriteLong (pDrvCtrl, EL_W3_INTERNAL_CFG, icfg, EL_WIN_3);
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: probing for a PHYn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- for (ix = EL_PHYADDR_MIN; ix < EL_PHYADDR_MAX + 1; ix++)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: checking address: %dn",
- pDrvCtrl->unit, ix, 3, 4, 5, 6);
- pDrvCtrl->devPhyAddr = ix;
- el3c90xPhyRegWrite (pDrvCtrl, EL_PHY_GENCTL, PHY_BMCR_RESET);
- SYS_DELAY(500);
- while (el3c90xPhyRegRead (pDrvCtrl, EL_PHY_GENCTL)
- & PHY_BMCR_RESET);
- if ((phyStatus = el3c90xPhyRegRead (pDrvCtrl, EL_PHY_GENSTS)))
- break;
- }
- if (phyStatus)
- {
- phyVendorId = el3c90xPhyRegRead (pDrvCtrl, EL_PHY_VENID);
- phyDevId = el3c90xPhyRegRead (pDrvCtrl, EL_PHY_DEVID);
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: found PHY at address %d, ",
- pDrvCtrl->unit, pDrvCtrl->devPhyAddr, 3, 4, 5, 6);
- DRV_LOG (DRV_DEBUG_LOAD,"vendor id: %x device id: %xn",
- phyVendorId, phyDevId, 3, 4, 5, 6);
- pDevType = el3c90xPhyTbl;
- while (pDevType->vendorId)
- {
- if (phyVendorId == pDevType->vendorId &&
- (phyDevId | 0x000F) == pDevType->deviceId)
- {
- pDrvCtrl->pPhyDevType = pDevType;
- break;
- }
- pDevType++;
- }
- if (pDrvCtrl->pPhyDevType == NULL)
- pDrvCtrl->pPhyDevType = &el3c90xPhyTbl [PHY_UNKNOWN];
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: PHY type: %sn",
- pDrvCtrl->unit, pDrvCtrl->pPhyDevType->devName,
- 3, 4, 5, 6);
- }
- else
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: MII without any phy!n",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- }
- if (pDrvCtrl->devMedia & EL_MEDIAOPT_BT)
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: found 10baseTn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- if (pDrvCtrl->devMedia & EL_MEDIAOPT_AUI)
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: found AUIn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- if (pDrvCtrl->devMedia & EL_MEDIAOPT_BNC)
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: found BNCn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- if (pDrvCtrl->devMedia & EL_MEDIAOPT_BTX)
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: found 100baseTXn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- if (pDrvCtrl->devMedia & EL_MEDIAOPT_BFX)
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: found 100baseFXn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- if ((pDrvCtrl->devMedia & EL_MEDIAOPT_BTX) ||
- (pDrvCtrl->devMedia & EL_MEDIAOPT_BFX))
- speed = 100000000;
- /* if there's an MII, we have to probe its modes separately. */
- if (pDrvCtrl->devMedia & EL_MEDIAOPT_MII ||
- pDrvCtrl->devMedia & EL_MEDIAOPT_BT4)
- {
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: found MIIn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- speed = el3c90xMiiModeGet (pDrvCtrl);
- }
- /* Choose a default media. */
- switch (pDrvCtrl->xCvr)
- {
- case EL_XCVR_10BT:
- media = IFM_ETHER | IFM_10_T;
- el3c90xMediaSet (pDrvCtrl, media);
- break;
- case EL_XCVR_AUI:
- media = IFM_ETHER | IFM_10_5;
- el3c90xMediaSet (pDrvCtrl, media);
- break;
- case EL_XCVR_COAX:
- media = IFM_ETHER | IFM_10_2;
- el3c90xMediaSet (pDrvCtrl, media);
- break;
- case EL_XCVR_AUTO:
- el3c90xMiiAutoNeg (pDrvCtrl);
- break;
- case EL_XCVR_100BTX:
- case EL_XCVR_MII:
- el3c90xMiiAutoNeg (pDrvCtrl);
- break;
- case EL_XCVR_100BFX:
- media = IFM_ETHER | IFM_100_FX;
- el3c90xMediaSet (pDrvCtrl, media);
- break;
- default:
- DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: unknown XCVR type: %dn",
- pDrvCtrl->unit, pDrvCtrl->xCvr, 3, 4, 5, 6);
- /*
- * This will probably be wrong, but it prevents
- * the ifmedia code from panicking.
- */
- media = IFM_ETHER | IFM_10_T;
- break;
- }
- return (speed);
- }
- /*******************************************************************************
- *
- * el3c90xEprmWait - wait for eeprom to get ready
- *
- * This function waits for eeprom to get ready
- * EEPROM is slow so give it time to come ready after issuing it a command
- * The standard eeprom wait period is 162 usecs.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL int el3c90xEprmWait
- (
- EL3C90X_DEVICE * pDrvCtrl /* device control structure */
- )
- {
- int ix;
- for (ix = 0; ix < EL_EE_RETRY_CNT; ix++)
- {
- if (el3c90xCsrReadWord (pDrvCtrl, EL_W0_EE_CMD, EL_WIN_0) & EL_EE_BUSY)
- {
- SYS_DELAY (EL_EE_WAIT);
- }
- else
- break;
- }
- if (ix == EL_EE_RETRY_CNT)
- {
- DRV_LOG (DRV_DEBUG_LOAD, "elPci%d: eeprom failed to come readyn",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- return (ERROR);
- }
- return (OK);
- }
- /*******************************************************************************
- *
- * el3c90xEprmRead - read a sequence of words from the eeprom
- *
- * This function reads a sequence of words from the eeprom.
- *
- * NOTE:
- * The ethernet address stored in the EEPROM is in the network byte order.
- *
- * RETURNS: OK or ERROR.
- */
- LOCAL int el3c90xEprmRead
- (
- EL3C90X_DEVICE * pDrvCtrl, /* device control structure */
- char * pDest, /* pointer destination */
- int off, /* offset */
- int cnt, /* number of words to read */
- int swap /* swap or not */
- )
- {
- int ix;
- UINT16 word = 0;
- UINT16 * pWord;
- if (el3c90xEprmWait (pDrvCtrl) != OK)
- return (ERROR);
- for (ix = 0; ix < cnt; ix++)
- {
- el3c90xCsrWriteWord (pDrvCtrl, EL_W0_EE_CMD, EL_EE_READ | (off + ix),
- EL_WIN_0);
- if (el3c90xEprmWait (pDrvCtrl) != OK)
- return (ERROR);
- word = el3c90xCsrReadWord (pDrvCtrl, EL_W0_EE_DATA, EL_WIN_0);
- pWord = (UINT16 *)(pDest + (ix * 2));
- if (swap)
- *pWord = ntohs (word);
- else
- *pWord = PCI_WORD_SWAP(word);
- }
- return (OK);
- }
- /*******************************************************************************
- *
- * el3c90xWait - wait for the command completion
- *
- * This function waits for the command completion
- * It is possible the chip can wedge and the 'command in progress' bit may
- * never clear. Hence, we wait only a finite amount of time to avoid getting
- * caught in an infinite loop. Normally this delay routine would be a macro,
- * but it isn't called during normal operation so we can afford to make it a
- * function.
- *
- * RETURNS: N/A
- */
- LOCAL void el3c90xWait
- (
- EL3C90X_DEVICE * pDrvCtrl /* device control structure */
- )
- {
- register int ix;
- for (ix = 0; ix < EL_TIMEOUT; ix++)
- {
- if (!(el3c90xCsrReadWord (pDrvCtrl, EL_STATUS, NONE) &
- EL_STAT_CMDBUSY))
- break;
- }
- if (ix == EL_TIMEOUT)
- DRV_LOG (DRV_DEBUG_ALL, "elPci%d: command never completed!n",
- pDrvCtrl->unit, 2, 3, 4, 5, 6);
- return;
- }
- /******************************************************************************
- *
- * el3c90xIntrSet - set the appropriate interrupt
- *
- * This routine set the interrupt given in the <flag>
- *
- * RETURNS: N/A.
- */
- LOCAL void el3c90xIntrSet
- (
- EL3C90X_DEVICE * pDrvCtrl, /* pointer to the device control structure */
- UINT16 flag
- )
- {
- USHORT intMask;
- int intLevel;
- intLevel = intLock ();
- /* set the window */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- (EL_CMD_WINSEL | EL_WIN_5));
- SYS_IN_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_W5_STAT_ENB),
- intMask);
- intMask |= flag;
- /* reenable relevant interrupt conditions */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- (EL_CMD_STAT_ENB | intMask));
- intUnlock (intLevel);
- }
- /******************************************************************************
- *
- * el3c90xIntrClr - clear the appropriate interrupt
- *
- * This routine set the interrupt given in the <flag>
- *
- * RETURNS: N/A.
- */
- LOCAL void el3c90xIntrClr
- (
- EL3C90X_DEVICE * pDrvCtrl, /* pointer to the device control structure */
- UINT16 flag
- )
- {
- USHORT intMask;
- int intLevel;
- intLevel = intLock ();
- /* set the window */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- (EL_CMD_WINSEL | EL_WIN_5));
- SYS_IN_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_W5_STAT_ENB),
- intMask);
- intMask &= ~(flag);
- /* reenable relevant interrupt conditions */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- (EL_CMD_STAT_ENB | intMask));
- intUnlock (intLevel);
- }
- /*******************************************************************************
- *
- * el3c90xCsrReadByte - read a byte from a given window and register
- *
- * This function reads a byte from a given window and register
- *
- * RETURNS: UCHAR
- */
- LOCAL UCHAR el3c90xCsrReadByte
- (
- EL3C90X_DEVICE * pDrvCtrl, /* device control structure */
- USHORT reg, /* register offset */
- int window /* window number */
- )
- {
- UCHAR inByte;
- if (window != NONE)
- {
- /* disable interrupts to prevent race conditions */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- EL_CMD_INTR_ENB);
- /* set the window */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- EL_CMD_WINSEL | window);
- /* set the register */
- SYS_IN_BYTE (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), inByte);
- /* reenable interrupts */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- (EL_CMD_INTR_ENB | EL_INTRS));
- }
- else
- SYS_IN_BYTE (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), inByte);
- return (inByte);
- }
- /*******************************************************************************
- *
- * el3c90xCsrReadWord - read a word from a given window and register
- *
- * This function reads a word from a given window and register
- *
- * RETURNS: USHORT
- */
- LOCAL USHORT el3c90xCsrReadWord
- (
- EL3C90X_DEVICE * pDrvCtrl, /* device control structure */
- USHORT reg, /* register offset */
- int window /* window number */
- )
- {
- USHORT inWord;
- if (window != NONE)
- {
- /* disable interrupts to prevent race conditions */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- EL_CMD_INTR_ENB);
- /* set the window */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- EL_CMD_WINSEL | window);
- /* set the register */
- SYS_IN_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), inWord);
- /* reenable interrupts */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- (EL_CMD_INTR_ENB | EL_INTRS));
- }
- else
- SYS_IN_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), inWord);
- return (inWord);
- }
- /*******************************************************************************
- *
- * el3c90xCsrReadLong - read a long word from a given window and register
- *
- * This function reads a long word from a given window and register
- *
- * RETURNS: ULONG
- */
- LOCAL ULONG el3c90xCsrReadLong
- (
- EL3C90X_DEVICE * pDrvCtrl, /* device control structure */
- USHORT reg, /* register offset */
- int window /* window number */
- )
- {
- ULONG inLong;
- if (window != NONE)
- {
- /* disable interrupts to prevent race conditions */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- EL_CMD_INTR_ENB);
- /* set the window */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- EL_CMD_WINSEL | window);
- /* set the register */
- SYS_IN_LONG (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), inLong);
- /* reenable interrupts */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- (EL_CMD_INTR_ENB | EL_INTRS));
- }
- else
- SYS_IN_LONG (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), inLong);
- return (inLong);
- }
- /*******************************************************************************
- *
- * el3c90xCsrWriteByte - write a byte to a given window and register
- *
- * This function writes a byte to a given window and register
- *
- * RETURNS: N/A
- */
- LOCAL void el3c90xCsrWriteByte
- (
- EL3C90X_DEVICE * pDrvCtrl, /* device control structure */
- USHORT reg, /* register offset */
- UCHAR outByte, /* byte to be written */
- int window /* window number */
- )
- {
- if (window != NONE)
- {
- /* disable interrupts to prevent race conditions */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- EL_CMD_INTR_ENB);
- /* set the window */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- EL_CMD_WINSEL | window);
- /* set the register */
- SYS_OUT_BYTE (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), outByte);
- /* reenable interrupts */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- (EL_CMD_INTR_ENB | EL_INTRS));
- }
- else
- SYS_OUT_BYTE (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), outByte);
- }
- /*******************************************************************************
- *
- * el3c90xCsrWriteWord - write a word to a given window and register
- *
- * This function writes a word to a given window and register
- *
- * RETURNS: N/A
- */
- LOCAL void el3c90xCsrWriteWord
- (
- EL3C90X_DEVICE * pDrvCtrl, /* device control structure */
- USHORT reg, /* register offset */
- USHORT outWord, /* word to be written */
- int window /* window number */
- )
- {
- if (window != NONE)
- {
- /* disable interrupts to prevent race conditions */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- EL_CMD_INTR_ENB);
- /* set the window */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- EL_CMD_WINSEL | window);
- /* set the register */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), outWord);
- /* reenable interrupts */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- (EL_CMD_INTR_ENB | EL_INTRS));
- }
- else
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), outWord);
- }
- /*******************************************************************************
- *
- * el3c90xCsrWriteLong - write a long to a given window and register
- *
- * This function writes a long to a given window and register
- *
- * RETURNS: N/A
- */
- LOCAL void el3c90xCsrWriteLong
- (
- EL3C90X_DEVICE * pDrvCtrl, /* device control structure */
- USHORT reg, /* register offset */
- ULONG outLong, /* long word to be written */
- int window /* window number */
- )
- {
- if (window != NONE)
- {
- /* disable interrupts to prevent race conditions */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- EL_CMD_INTR_ENB);
- /* set the window */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- EL_CMD_WINSEL | window);
- /* set the register */
- SYS_OUT_LONG (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), outLong);
- /* reenable interrupts */
- SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
- (EL_CMD_INTR_ENB | EL_INTRS));
- }
- else
- SYS_OUT_LONG (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), outLong);
- }