el3c90xEnd.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:136k
源码类别:

VxWorks

开发平台:

C/C++

  1.     /* walk through the list and recalculate the hash filter */
  2.     pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->endObj);
  3.     while (pCurr != NULL)
  4. {
  5.         hash = el3c90xHashGet ((UINT8 *)&pCurr->addr);
  6.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND,
  7.                              (EL_CMD_RX_SET_HASH | EL_HASH_SET | hash), NONE);
  8.         mcnt++;
  9. pCurr = END_MULTI_LST_NEXT(pCurr);
  10.         }
  11.     
  12.     if (mcnt)
  13.         rxFilt |= EL_RXFILTER_MULTIHASH;
  14.     else
  15.         rxFilt &= ~EL_RXFILTER_MULTIHASH;
  16.     el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND,
  17.                          (EL_CMD_RX_SET_FILT | rxFilt), NONE);
  18.     return;
  19.     }
  20. /******************************************************************************
  21. *
  22. * el3c90xMcastConfig - reconfigure the interface under us.
  23. *
  24. * Reconfigure the interface setting promiscuous mode, and changing the
  25. * multicast interface list.
  26. *
  27. * RETURNS: N/A.
  28. */
  29. LOCAL void el3c90xMcastConfig
  30.     (
  31.     EL3C90X_DEVICE * pDrvCtrl /* device to be re-configured */
  32.     )
  33.     {
  34.     if (pDrvCtrl->devType == EL_TYPE_905B)
  35.         el3c90xHashFilterSet (pDrvCtrl);
  36.     else
  37.         el3c90xFilterSet (pDrvCtrl);
  38.     return;
  39.     }
  40. /*******************************************************************************
  41. *
  42. * el3c90xUpdFill - initialize a single upload descriptor
  43. *
  44. * This function allocates an mBlk/clBlk/cluster tuple and initialize the
  45. * upload descriptor.
  46. *
  47. * RETURNS: OK or ERROR.
  48. */
  49. LOCAL STATUS el3c90xUpdFill
  50.     (
  51.     EL3C90X_DEVICE *  pDrvCtrl, /* ptr to the dev ctrl structure */
  52.     EL_SIMPLE_DESC_CHAIN *  pRxUpd   /* ptr to the descriptor chain */
  53.     )
  54.     {
  55.     M_BLK_ID  pMblk = NULL; /* pointer to the mBlk */
  56.     /* get a mBlk/clBlk/cluster tuple */
  57.     if ((pMblk = netTupleGet (pDrvCtrl->endObj.pNetPool, EL3C90X_BUFSIZ,
  58.                               M_DONTWAIT, MT_DATA, FALSE)) == NULL)
  59.         {
  60.         ENDLOGMSG (("Out of M Blocks!n", 1, 2, 3, 4, 5, 6));
  61.         return (ERROR);
  62.         }
  63.     pRxUpd->pMblk = pMblk;
  64.     pRxUpd->pDesc->descFrag.fragAddr =
  65.         PCI_SWAP((UINT32) EL3C90X_CACHE_VIRT_TO_PHYS (pMblk->mBlkHdr.mData));
  66.     pRxUpd->pDesc->status = 0;
  67.     pRxUpd->pDesc->descFrag.fragLen = PCI_SWAP (CL_SIZE_2048 | EL_LAST_FRAG);
  68.     return (OK);
  69.     }
  70. /*******************************************************************************
  71. *
  72. * el3c90xDndGet - get a free down load descriptor
  73. *
  74. * This function returns a pointer to the descriptor chain which has a free
  75. * down load descriptor.
  76. *
  77. * RETURNS: EL_DESC_CHAIN * or NULL
  78. */
  79. LOCAL EL_DESC_CHAIN * el3c90xDndGet
  80.     (
  81.     EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
  82.     )
  83.     {
  84.     EL_DESC_CHAIN *  pFree = NULL;
  85.     if ((pFree = pDrvCtrl->rxTxChain.pTxFree) == NULL)
  86.         return (NULL);
  87.     pDrvCtrl->rxTxChain.pTxFree = pFree->pNextChain;
  88.     pFree->pNextChain = NULL;
  89.     return (pFree);
  90.     }
  91. /*******************************************************************************
  92. *
  93. * el3c90xDndFree - free a down load descriptor
  94. *
  95. * This function returns a the down load descriptor chain to the free list.
  96. *
  97. * RETURNS: OK
  98. */
  99. LOCAL STATUS el3c90xDndFree
  100.     (
  101.     EL3C90X_DEVICE *  pDrvCtrl, /* pointer to the device control structure */
  102.     EL_DESC_CHAIN *  pTxChain
  103.     )
  104.     {
  105.     pTxChain->pMblk = NULL;
  106.     
  107.     pTxChain->pNextChain = pDrvCtrl->rxTxChain.pTxFree;
  108.     pDrvCtrl->rxTxChain.pTxFree = pTxChain;
  109.     return (OK);
  110.     }
  111. /*******************************************************************************
  112. *
  113. * el3c90xTxDequeue - dequeue a transmitted descriptor 
  114. *
  115. * This function dequeues a transmitted descriptor for clean up after
  116. * transmission.
  117. *
  118. * RETURNS: EL_DESC_CHAIN * or NULL
  119. */
  120. LOCAL EL_DESC_CHAIN * el3c90xTxDequeue
  121.     (
  122.     EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
  123.     )
  124.     {
  125.     EL_DESC_CHAIN *  pTxFree = NULL;
  126.     if ((pTxFree = pDrvCtrl->rxTxChain.pTxHead) == NULL)
  127.         {
  128.         pDrvCtrl->rxTxChain.pTxTail = NULL;
  129.         return (NULL);
  130.         }
  131.     else
  132.         {
  133.         /* we have to use a different test if devType != EL_TYPE_905B. */
  134.         
  135.         if ((pDrvCtrl->devType == EL_TYPE_905B &&
  136.              !(PCI_SWAP(pTxFree->pDesc->status) & EL_TXSTAT_DL_COMPLETE)) ||
  137.             el3c90xCsrReadLong (pDrvCtrl, EL_DOWNLIST_PTR, NONE))
  138.             {
  139.             if (el3c90xCsrReadLong (pDrvCtrl, EL_DMACTL, NONE) &
  140.                 EL_DMACTL_DOWN_STALLED ||
  141.                 !el3c90xCsrReadLong(pDrvCtrl, EL_DOWNLIST_PTR, NONE))
  142.                 {
  143.                 el3c90xCsrWriteLong (pDrvCtrl, EL_DOWNLIST_PTR,
  144.                                      (UINT32) EL3C90X_CACHE_VIRT_TO_PHYS
  145.                                      (pTxFree->pDesc), NONE);
  146.                 el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_DOWN_UNSTALL,
  147.                                      NONE);
  148.                 }
  149.             return (NULL);
  150.             }
  151.         }
  152.     pDrvCtrl->rxTxChain.pTxHead = pTxFree->pNextChain;
  153.     pTxFree->pNextChain = NULL;
  154.     return (pTxFree);
  155.     }
  156. /*******************************************************************************
  157. *
  158. * el3c90xDndEnqueue - enqueue a down load descriptor 
  159. *
  160. * This function enqueues a down load descriptor 
  161. *
  162. * RETURNS: OK.
  163. */
  164. LOCAL STATUS el3c90xDndEnqueue
  165.     (
  166.     EL3C90X_DEVICE *  pDrvCtrl, /* pointer to the device control structure */
  167.     EL_DESC_CHAIN *  pTxChain
  168.     )
  169.     {
  170.     if (el3c90xCsrReadLong (pDrvCtrl, EL_DOWNLIST_PTR, NONE))
  171.         {
  172.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_DOWN_STALL, NONE);
  173.         el3c90xWait(pDrvCtrl);
  174.         /* check once again */
  175.         
  176.         if (el3c90xCsrReadLong (pDrvCtrl, EL_DOWNLIST_PTR, NONE)) 
  177.             {
  178.             /*
  179.              * Place the request for the upload interrupt
  180.              * in the last descriptor in the chain. This way, if
  181.              * we're chaining several packets at once, we'll only
  182.              * get an interupt once for the whole chain rather than
  183.              * once for each packet.
  184.              */
  185.             pDrvCtrl->rxTxChain.pTxTail->pNextChain = pTxChain;
  186.             pDrvCtrl->rxTxChain.pTxTail->pDesc->nextDesc =
  187.                 PCI_SWAP((UINT32)EL3C90X_CACHE_VIRT_TO_PHYS(pTxChain->pDesc));
  188.             pDrvCtrl->rxTxChain.pTxTail->pDesc->status &=
  189.                 PCI_SWAP(~EL_TXSTAT_DL_INTR);
  190.             pDrvCtrl->rxTxChain.pTxTail = pTxChain;
  191.             el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_DOWN_UNSTALL,
  192.                                  NONE);
  193.             return (OK);
  194.             }
  195.         }
  196.     if (pDrvCtrl->rxTxChain.pTxHead == NULL)
  197.         {
  198.         pDrvCtrl->rxTxChain.pTxHead = pTxChain;
  199.         pDrvCtrl->rxTxChain.pTxTail = pTxChain;
  200.         }
  201.     else
  202.         {
  203.         pDrvCtrl->rxTxChain.pTxTail->pNextChain = pTxChain;
  204.         pDrvCtrl->rxTxChain.pTxTail = pTxChain;
  205.         }
  206.     /* load the down load descriptor */
  207.     el3c90xCsrWriteLong (pDrvCtrl, EL_DOWNLIST_PTR,
  208.                          (UINT32)EL3C90X_CACHE_VIRT_TO_PHYS (pTxChain->pDesc),
  209.                          NONE);
  210.     return (OK);
  211.     }
  212. /*******************************************************************************
  213. *
  214. * el3c90xDndMblkPack - pack a given mBlk into download descriptor
  215. *
  216. * This function packs a given mBlk into download descriptor. This function
  217. * copies the data in a given mBlk into a new mBlk obtained from the pool.
  218. *
  219. * RETURNS: OK or ERROR.
  220. */
  221. LOCAL STATUS el3c90xDndMblkPack
  222.     (
  223.     EL3C90X_DEVICE *  pDrvCtrl, /* pointer to the device control structure */
  224.     EL_DESC_CHAIN * pTxChain,
  225.     M_BLK_ID pMblk
  226.     )
  227.     {
  228.     int len = 0;
  229.     EL_FRAG * pFrag = NULL;
  230.     M_BLK_ID pMblkTemp = NULL;
  231.     if (pTxChain == NULL || pMblk == NULL)
  232.         return (ERROR);
  233.     
  234.     if ((pMblkTemp = netTupleGet (pDrvCtrl->endObj.pNetPool,
  235.                                   EL3C90X_BUFSIZ,
  236.                                   M_DONTWAIT, MT_DATA, FALSE)) == NULL)
  237.         {
  238.         ENDLOGMSG (("Out of Tx M Blocks!n", 1, 2, 3, 4, 5, 6));
  239.         return (ERROR);
  240.         }
  241.     len = netMblkToBufCopy (pMblk, pMblkTemp->mBlkHdr.mData, NULL);
  242.     pMblkTemp->mBlkPktHdr.len = pMblkTemp->mBlkHdr.mLen = len;
  243.     
  244.     pFrag = &pTxChain->pDesc->descFrag [0];
  245.     pFrag->fragAddr =
  246.         PCI_SWAP((UINT32)EL3C90X_CACHE_VIRT_TO_PHYS(pMblkTemp->mBlkHdr.mData));
  247.     pFrag->fragLen = PCI_SWAP (len | EL_LAST_FRAG);
  248.     pTxChain->pMblk = pMblkTemp;
  249.     pTxChain->pDesc->status = PCI_SWAP (len);
  250.     pTxChain->pDesc->nextDesc = 0;
  251.     return(OK);
  252.     }
  253. /*******************************************************************************
  254. *
  255. * el3c90xDndSet - set up a download descriptor 
  256. *
  257. * This function seta up a download descriptor by setting fragment addresses
  258. * to the data pointers in the mBlk chain. If the number of fragments
  259. * exceeds 63 then the whole whole mBlk chain is copied into a contiguous
  260. * buffer.
  261. *
  262. * RETURNS: OK or ERROR.
  263. */
  264. LOCAL int el3c90xDndSet
  265.     (
  266.     EL3C90X_DEVICE *  pDrvCtrl, /* pointer to the device control structure */
  267.     EL_DESC_CHAIN * pTxChain,
  268.     M_BLK_ID pMblkHead
  269.     )
  270.     {
  271.     int len = 0;
  272.     int frag = 0;
  273.     EL_FRAG * pFrag = NULL;
  274.     M_BLK_ID pMblk;
  275.     M_BLK_ID pMblkTemp = NULL;
  276.     /*
  277.      * start packing the M_BLKs in this chain into the fragment pointers.
  278.      * stop when we run out of fragments or hit the end of the M_BLK chain.
  279.      */
  280.     pMblk = pMblkHead;
  281.     for (pMblk = pMblkHead, frag = 0; pMblk != NULL; pMblk = pMblk->m_next)
  282.         {
  283.         if (pMblk->mBlkHdr.mLen != 0)
  284.             {
  285.             if (frag == EL_MAXFRAGS)
  286.                 break;
  287.             len += pMblk->mBlkHdr.mLen;
  288.             pTxChain->pDesc->descFrag [frag].fragAddr =
  289.                 PCI_SWAP ((UINT32)EL3C90X_CACHE_VIRT_TO_PHYS
  290.                           (pMblk->mBlkHdr.mData));
  291.             CACHE_DMA_FLUSH (pMblk->mBlkHdr.mData, pMblk->mBlkHdr.mLen);
  292.             pTxChain->pDesc->descFrag[frag].fragLen =
  293.                 PCI_SWAP (pMblk->mBlkHdr.mLen);
  294.             frag++;
  295.             }
  296.         }
  297.     /*
  298.      * Handle special case: we used up all 63 fragments,
  299.      * but we have more M_BLKs left in the chain. Copy the
  300.      * data into an M_BLK cluster. Note that we don't
  301.      * bother clearing the values in the other fragment
  302.      * pointers/counters; it wouldn't gain us anything,
  303.      * and would waste cycles.
  304.      */
  305.     if (pMblk != NULL)
  306.         {
  307.         /* get a mBlk/clBlk/cluster tuple */
  308.         if ((pMblkTemp = netTupleGet (pDrvCtrl->endObj.pNetPool,
  309.                                       EL3C90X_BUFSIZ,
  310.                                       M_DONTWAIT, MT_DATA, FALSE)) == NULL)
  311.             {
  312.             ENDLOGMSG (("Out of Tx M Blocks!n", 1, 2, 3, 4, 5, 6));
  313.             return (ERROR);
  314.             }
  315.         len = netMblkToBufCopy (pMblkHead, pMblkTemp->mBlkHdr.mData, NULL);
  316.         pMblkTemp->mBlkPktHdr.len = pMblkTemp->mBlkHdr.mLen = len;
  317.         netMblkClChainFree (pMblkHead); /* free the given mBlk chain */
  318.         pMblkHead = pMblkTemp;
  319.         pFrag = &pTxChain->pDesc->descFrag [0];
  320.         pFrag->fragAddr =
  321.             PCI_SWAP
  322.             (
  323.             (UINT32) EL3C90X_CACHE_VIRT_TO_PHYS (pMblkTemp->mBlkHdr.mData)
  324.             );
  325.         pFrag->fragLen = PCI_SWAP (len);
  326.         frag = 1;
  327. }
  328.     pTxChain->pMblk = pMblkHead;
  329.     pTxChain->pDesc->descFrag [frag - 1].fragLen |=  PCI_SWAP (EL_LAST_FRAG);
  330.     pTxChain->pDesc->status = PCI_SWAP (len);
  331.     pTxChain->pDesc->nextDesc = 0;
  332.     return(OK);
  333.     }
  334. /******************************************************************************
  335. *
  336. * el3c90xNextUpdFetch - fetch the next upload packet descriptor
  337. *
  338. * This routine fetches the next upload packet descriptor
  339. *
  340. * RETURNS: N/A.
  341. */
  342. LOCAL EL_SIMPLE_DESC_CHAIN * el3c90xNextUpdFetch
  343.     (
  344.     EL3C90X_DEVICE *  pDrvCtrl /* pointer to the device control structure */
  345.     )
  346.     {
  347.     EL_SIMPLE_DESC_CHAIN *  pRxChain = NULL;
  348.     UINT16 rxstat;
  349.     if ((rxstat = PCI_SWAP(pDrvCtrl->rxTxChain.pRxHead->pDesc->status)))
  350.         {
  351.         pRxChain = pDrvCtrl->rxTxChain.pRxHead;
  352.         pDrvCtrl->rxTxChain.pRxHead = pRxChain->pNextChain;
  353.         }
  354.     return (pRxChain);
  355.     }
  356. /******************************************************************************
  357. *
  358. * el3c90xNextPktFetch - fetch the next packet buffer
  359. *
  360. * This routine fetches the next packet buffer uploaded and returns
  361. * an mBlk. 
  362. *
  363. * NOMANUAL
  364. *
  365. * RETURNS: M_BLK_ID or NULL
  366. */
  367. LOCAL M_BLK_ID el3c90xNextPktFetch
  368.     (
  369.     EL3C90X_DEVICE *  pDrvCtrl, /* pointer to control structure */
  370.     EL_SIMPLE_DESC_CHAIN *  pRxUpd
  371.     )
  372.     {
  373.     M_BLK_ID  pMblk; /* pointer to the mBlk */
  374.     int len;
  375.     /* get a cluster */
  376.     pMblk = pRxUpd->pMblk;
  377.     
  378.     len = (PCI_SWAP(pRxUpd->pDesc->status) & EL_RXSTAT_LENMASK);
  379.     /* load new buffers into the Upload descriptor */
  380.     if (el3c90xUpdFill (pDrvCtrl, pRxUpd) != OK)
  381.         {
  382.         /* if no buffers available drop the packet */
  383. #ifdef INCLUDE_RFC_1213
  384.        
  385.         /* Old RFC 1213 mib2 interface */
  386.         END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  387. #else 
  388.         /* New RFC 2233 mib2 interface */
  389.         if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  390.             {
  391.             pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.pMib2Tbl,
  392.                                                       M2_ctrId_ifInErrors, 1);
  393.             }
  394. #endif /* INCLUDE_RFC_1213 */
  395.         pRxUpd->pDesc->status = 0;
  396.         return (NULL);
  397.         }
  398.     /* update the mBlk fields */
  399.     pMblk->mBlkHdr.mLen   = len;
  400.     pMblk->mBlkHdr.mFlags |= M_PKTHDR;
  401.     pMblk->mBlkPktHdr.len = len;
  402.     return (pMblk);
  403.     }
  404. /******************************************************************************
  405. *
  406. * el3c90xRxUnStall - unstall the receiver
  407. *
  408. * This routine unstalls the receiver if it the receiver hits an
  409. * end of channel condition.
  410. *
  411. * RETURNS: OK or ERROR
  412. */
  413. LOCAL STATUS el3c90xRxUnStall
  414.     (
  415.     EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
  416.     )
  417.     {
  418.     if (el3c90xCsrReadLong (pDrvCtrl, EL_UPLIST_PTR, NONE) == 0 ||
  419.         (el3c90xCsrReadLong (pDrvCtrl, EL_UPLIST_STATUS, NONE) &
  420.          EL_PKTSTAT_UP_STALLED))
  421.         {
  422.         /* stall the receiver */
  423.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_UP_STALL, NONE);
  424.         el3c90xWait(pDrvCtrl);
  425.         el3c90xCsrWriteLong (pDrvCtrl, EL_UPLIST_PTR,
  426.                              (UINT32) EL3C90X_CACHE_VIRT_TO_PHYS
  427.                              (&pDrvCtrl->pDescBlk->rxDescs [0]), NONE);
  428.         pDrvCtrl->rxTxChain.pRxHead = &pDrvCtrl->rxTxChain.rxChain [0];
  429.         /* unstall the receiver */
  430.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_UP_UNSTALL, NONE);
  431.         return (OK);
  432.         }
  433.     return (ERROR);
  434.     }
  435. /******************************************************************************
  436. *
  437. * el3c90xRxKick - kicks the receiver if blocked.
  438. *
  439. * This routine kicks the receiver if it is stalled.
  440. * Handle the 'end of channel' condition. When the upload engine hits the
  441. * end of the RX ring, it will stall. This is our cue to flush the RX ring,
  442. * reload the uplist pointer register and unstall the engine.
  443. * With the ThunderLAN chip, you get an interrupt when the receiver hits the end
  444. * of the receive ring, which tells you exactly when you you need to reload
  445. * the ring pointer. Here we have to
  446. * fake it.
  447. * This function reschedules the receive handler if things get
  448. * stalled because of high receive traffic. This routine can also be
  449. * called from the transmit routine after the packet has been queued.
  450. * This will take advantage of the parallel tasking concept which 3COM
  451. * is familiar for.
  452. *
  453. * RETURNS: N/A.
  454. */
  455. LOCAL void el3c90xRxKick
  456.     (
  457.     EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
  458.     )
  459.     {
  460.     /* if the receiver unstalled schedule the receive again */
  461.     if (el3c90xRxUnStall (pDrvCtrl) == OK)
  462.         {
  463.         if (netJobAdd ((FUNCPTR)el3c90xIntrRx, (int) pDrvCtrl, 0, 0, 0, 0)
  464.             != OK)
  465.             logMsg ("elPci: netJobAdd (el3c90xIntrRx) failedn", 0, 0, 0,
  466.                     0, 0, 0);
  467.         }
  468.     }
  469. /******************************************************************************
  470. *
  471. * el3c90xIntrRx - handle receive interrupts 
  472. *
  473. * This routine handles receive interrupts. 
  474. *
  475. * RETURNS: N/A.
  476. */
  477. LOCAL void el3c90xIntrRx
  478.     (
  479.     EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
  480.     )
  481.     {
  482.     M_BLK_ID  pMblk; /* pointer to the mBlk */
  483.     EL_SIMPLE_DESC_CHAIN *  pRxUpd;
  484.     UINT32 descStatus;
  485.     while ((pRxUpd = el3c90xNextUpdFetch (pDrvCtrl)) != NULL)
  486.         {
  487.         descStatus = PCI_SWAP(pRxUpd->pDesc->status);
  488.         
  489.         /*
  490.          * If an error occurs, update stats, clear the
  491.          * status word and leave the M_BLK cluster in place:
  492.          * it should simply get re-used next time this descriptor
  493.          * comes up in the ring.
  494.          */
  495.         if (descStatus & EL_RXSTAT_UP_ERROR)
  496.             {
  497. #ifdef INCLUDE_RFC_1213
  498.             /* Old RFC 1213 mib2 interface */
  499.             END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  500. #else
  501.             /* New RFC 2233 mib2 interface */
  502.             if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  503.                 {
  504.                 pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.
  505.                                                                     pMib2Tbl,
  506.                                                           M2_ctrId_ifInErrors,
  507.                                                           1);
  508.                 }
  509. #endif /* INCLUDE_RFC_1213 */
  510.             pRxUpd->pDesc->status = 0;
  511.             continue;
  512.             }
  513.         /*
  514.          * If there error bit was not set, the upload complete
  515.          * bit should be set which means we have a valid packet.
  516.          * If not, something truly strange has happened.
  517.          */
  518.         if (!(descStatus & EL_RXSTAT_UP_CMPLT))
  519.             {
  520.             logMsg ("elPci%d: bad receive status -- packet dropped",
  521.                     pDrvCtrl->unit, 0, 0, 0, 0, 0);
  522. #ifdef INCLUDE_RFC_1213
  523.             /* Old RFC 1213 mib2 interface */
  524.             END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  525. #else
  526.             /* New RFC 2233 mib2 interface */
  527.             
  528.             if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  529.                 {
  530.                 pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.
  531.                                                                     pMib2Tbl,
  532.                                                           M2_ctrId_ifInErrors,
  533.                                                           1);
  534.                 }
  535. #endif /* INCLUDE_RFC_1213 */
  536.             pRxUpd->pDesc->status = 0;
  537.             continue;
  538.             }
  539.         if ((pMblk = el3c90xNextPktFetch (pDrvCtrl, pRxUpd)) == NULL)
  540.             continue;
  541. #ifdef INCLUDE_RFC_1213
  542.         /* Old RFC 1213 mib2 interface */
  543.         END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
  544. #else
  545.         /* New RFC 2233 mib2 interface */
  546.         /* RFC 2233 mib2 counter update for incoming packet */
  547.         if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  548.             {
  549.             pDrvCtrl->endObj.pMib2Tbl->m2PktCountRtn(pDrvCtrl->endObj.pMib2Tbl,
  550.                                                      M2_PACKET_IN,
  551.                                                      pMblk->mBlkHdr.mData,
  552.                                                      pMblk->mBlkHdr.mLen);
  553.             }
  554. #endif /* INCLUDE_RFC_1213 */
  555.         ENDLOGMSG (("Calling upper layer's recv rtnn", 1, 2, 3, 4, 5, 6));
  556.         END_RCV_RTN_CALL (&pDrvCtrl->endObj, pMblk);
  557.         }
  558.     /* kick the receiver if stalled */
  559.     
  560.     el3c90xRxKick (pDrvCtrl);
  561.     el3c90xIntrSet (pDrvCtrl, EL_STAT_UP_COMPLETE);
  562.     }
  563. /******************************************************************************
  564. *
  565. * el3c90xIntrTx - handle transmit interrupt
  566. *
  567. * This routine handles transmit interrupt
  568. *
  569. * RETURNS: N/A.
  570. */
  571. LOCAL void el3c90xIntrTx
  572.     (
  573.     EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
  574.     )
  575.     {
  576.     EL_DESC_CHAIN *  pTxChain;
  577.     END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
  578.     while ((pTxChain = el3c90xTxDequeue (pDrvCtrl)) != NULL)
  579.         {
  580.         netMblkClChainFree (pTxChain->pMblk);
  581.         el3c90xDndFree (pDrvCtrl, pTxChain);
  582.         }
  583.     END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  584.     el3c90xIntrSet (pDrvCtrl, EL_STAT_DOWN_COMPLETE);
  585.     if (pDrvCtrl->txBlocked)
  586.         {
  587.         pDrvCtrl->txBlocked = FALSE;
  588.         muxTxRestart (&pDrvCtrl->endObj);
  589.         }
  590.     }
  591. /******************************************************************************
  592. *
  593. * el3c90xIntrErr - handle transmit errors
  594. *
  595. * This routine handles transmit errors
  596. *
  597. * RETURNS: N/A.
  598. */
  599. LOCAL void el3c90xIntrErr
  600.     (
  601.     EL3C90X_DEVICE *  pDrvCtrl, /* pointer to the device control structure */
  602.     UINT8 txstat
  603.     )
  604.     {
  605.     if (txstat & EL_TXSTATUS_UNDERRUN ||
  606.         txstat & EL_TXSTATUS_JABBER ||
  607.         txstat & EL_TXSTATUS_RECLAIM)
  608.         {
  609.         logMsg ("elPci%d: transmission error: %xn",
  610.                 pDrvCtrl->unit, txstat,0,0,0,0);
  611.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_TX_RESET, NONE);
  612.         el3c90xWait(pDrvCtrl);
  613.         if (pDrvCtrl->rxTxChain.pTxHead != NULL)
  614.             {
  615.             el3c90xCsrWriteLong (pDrvCtrl, EL_DOWNLIST_PTR,
  616.                                  (UINT32) EL3C90X_CACHE_VIRT_TO_PHYS
  617.                                  (pDrvCtrl->rxTxChain.pTxHead->pDesc),
  618.                                  NONE);
  619.             }
  620.         /* Remember to set this for the first generation 3c90X chips. */
  621.         el3c90xCsrWriteByte (pDrvCtrl, EL_TX_FREETHRESH,
  622.                              (EL3C90X_BUFSIZ >> 8), NONE);
  623.         if (pDrvCtrl->devType == EL_TYPE_905B)
  624.             {
  625.             el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND,
  626.                                  (EL_CMD_SET_TX_RECLAIM |
  627.                                   (EL3C90X_BUFSIZ >> 4)), NONE);
  628.             }
  629.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_TX_ENABLE, NONE);
  630.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_DOWN_UNSTALL, NONE);
  631.         }
  632.     else
  633.         {
  634.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_TX_ENABLE, NONE);
  635.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_DOWN_UNSTALL, NONE);
  636.         }
  637. #ifdef INCLUDE_RFC_1213
  638.     /* Old RFC 1213 mib2 interface */
  639.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
  640. #else
  641.     /* New RFC 2233 mib2 interface */
  642.     if (pDrvCtrl->endObj.pMib2Tbl != NULL)
  643.         {
  644.         pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.pMib2Tbl,
  645.                                                   M2_ctrId_ifOutErrors, 1);
  646.         }
  647. #endif /* INCLUDE_RFC_1213 */
  648.     el3c90xIntrSet (pDrvCtrl, EL_STAT_TX_COMPLETE);
  649.     }
  650. /******************************************************************************
  651. *
  652. * el3c90xStatUpdate - handle the stats overflow interrupt 
  653. *
  654. * This routine handles the stats overflow interrupt 
  655. *
  656. * RETURNS: N/A.
  657. */
  658. LOCAL void el3c90xStatUpdate
  659.     (
  660.     EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
  661.     )
  662.     {
  663.     EL_STATS elStats;
  664.     UINT8 * pChar;
  665.     int ix;
  666.     bzero((char *)&elStats, sizeof(elStats));
  667.     pChar = (UINT8 *)&elStats;
  668.     /* Read all the stats registers. */
  669.     for (ix = 0; ix < 16; ix++)
  670.         *pChar++ = el3c90xCsrReadByte (pDrvCtrl, EL_W6_CARRIER_LOST + ix,
  671.                                        EL_WIN_6);
  672.     /*
  673.      * Boomerang and cyclone chips have an extra stats counter
  674.      * in window 4 (BadSSD). We have to read this too in order
  675.      * to clear out all the stats registers and avoid a statsoflow
  676.      * interrupt.
  677.      */
  678.     el3c90xCsrReadByte (pDrvCtrl, EL_W4_BADSSD, EL_WIN_4);
  679.     return;
  680.     }
  681. /******************************************************************************
  682. *
  683. * el3c90xInt - interrupt handler for the NIC interrupt
  684. *
  685. * This routine is general interrupt handler.
  686. *
  687. * RETURNS: N/A.
  688. */
  689. LOCAL void el3c90xInt
  690.     (
  691.     EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */
  692.     )
  693.     {
  694.     UINT16 status;
  695.     UINT16 intClr = 0;
  696.     UINT8 txstat;
  697.     
  698.     ENDLOGMSG (("Got an interrupt!n", 1, 2, 3, 4, 5, 6));
  699.     /* read interrupt status */
  700.     status = el3c90xCsrReadWord (pDrvCtrl, EL_STATUS, NONE); 
  701.     if ((status & EL_INTRS) == 0)
  702.         return;
  703.     if (status & EL_STAT_UP_COMPLETE)
  704.         {
  705.         if (netJobAdd ((FUNCPTR)el3c90xIntrRx, (int) pDrvCtrl,
  706.                        0, 0, 0, 0) == OK)
  707.             {
  708.             intClr |= EL_STAT_UP_COMPLETE;
  709.             }
  710.         else
  711.             logMsg ("xl: netJobAdd (el3c90xIntrRx) failedn",
  712.                     0, 0, 0, 0, 0, 0);
  713.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND,
  714.                              (EL_CMD_INTR_ACK | EL_STAT_UP_COMPLETE), NONE);
  715.         }
  716.     if (status & EL_STAT_DOWN_COMPLETE)
  717.         {
  718.         if (netJobAdd ((FUNCPTR)el3c90xIntrTx, (int) pDrvCtrl,
  719.                        0, 0, 0, 0) == OK)
  720.             {
  721.             intClr |= EL_STAT_DOWN_COMPLETE;
  722.             }
  723.         else
  724.             logMsg ("xl: netJobAdd (el3c90xIntrTx) failedn",
  725.                     0, 0, 0, 0, 0, 0);
  726.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND,
  727.                              (EL_CMD_INTR_ACK | EL_STAT_DOWN_COMPLETE), NONE);
  728.         }
  729.     if (status & EL_STAT_TX_COMPLETE)
  730.         {
  731.         txstat = el3c90xCsrReadByte (pDrvCtrl, EL_TX_STATUS, NONE);
  732.         if (netJobAdd ((FUNCPTR)el3c90xIntrErr, (int) pDrvCtrl,
  733.                        (int)txstat, 0, 0, 0) == OK)
  734.             {
  735.             intClr |= EL_STAT_TX_COMPLETE;
  736.             }
  737.         else
  738.             logMsg ("xl: netJobAdd (el3c90xIntrErr) failedn",
  739.                     0, 0, 0, 0, 0, 0);
  740.         /*
  741.          * Write an arbitrary byte to the TX_STATUS register
  742.          * to clear this interrupt/error and advance to the next.
  743.          */
  744.         el3c90xCsrWriteByte (pDrvCtrl, EL_TX_STATUS, 0x01, NONE);
  745.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND,
  746.                              (EL_CMD_INTR_ACK | EL_STAT_TX_COMPLETE), NONE);
  747.         }
  748.     if (status & EL_STAT_STATSOFLOW)
  749.         {
  750.         el3c90xStatUpdate(pDrvCtrl);
  751.         }
  752.     if (status & EL_STAT_ADFAIL)
  753.         {
  754.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_INTR_ENB, NONE);
  755.         el3c90xReset (pDrvCtrl);
  756.         if (netJobAdd ((FUNCPTR)el3c90xInit, (int) pDrvCtrl,
  757.                        0, 0, 0, 0) != OK)
  758.             logMsg ("xl: netJobAdd (el3c90xInit) failedn",
  759.                     0, 0, 0, 0, 0, 0);
  760.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND,
  761.                              (EL_CMD_INTR_ACK | EL_STAT_ADFAIL), NONE);
  762.         el3c90xCsrWriteWord (pDrvCtrl, EL_STATUS,
  763.                              (EL_CMD_INTR_ACK | EL_STAT_INTREQ |
  764.                               EL_STAT_INTLATCH), NONE);
  765.         return; 
  766.         }
  767.     /* acknowledge all interrupts */
  768.     el3c90xCsrWriteWord (pDrvCtrl, EL_STATUS,
  769.                          (EL_CMD_INTR_ACK | EL_STAT_INTREQ | EL_STAT_INTLATCH),
  770.                          NONE);
  771.     if (intClr)
  772.         el3c90xIntrClr (pDrvCtrl, intClr);
  773.     return;
  774.     }
  775. /*******************************************************************************
  776. *
  777. * el3c90xMiiSync - sync the PHYs
  778. *
  779. * This function syncs the PHYs by setting data bit and strobing the
  780. * clock 32 times.
  781. *
  782. * RETURNS: N/A
  783. */
  784. LOCAL void el3c90xMiiSync
  785.     (
  786.     EL3C90X_DEVICE *  pDrvCtrl
  787.     )
  788.     {
  789.     register int   ix;
  790.     EL_MII_SET (EL_MII_DIR | EL_MII_DATA);
  791.     for (ix = 0; ix < 32; ix++)
  792.         {
  793.         EL_MII_SET (EL_MII_CLK);
  794.         SYS_DELAY (1);
  795.         EL_MII_CLR (EL_MII_CLK);
  796.         SYS_DELAY (1);
  797. }
  798.     return;
  799.     }
  800. /*******************************************************************************
  801. *
  802. * el3c90xMiiSend - clock a series of bits through the MII.
  803. *
  804. * This function clocks a series of bits through the MII.
  805. *
  806. * RETURNS: N/A
  807. */
  808. LOCAL void el3c90xMiiSend
  809.     (
  810.     EL3C90X_DEVICE * pDrvCtrl,
  811.     UINT32 bits,
  812.     int cnt
  813.     )
  814.     {
  815.     int ix;
  816.     EL_MII_CLR (EL_MII_CLK);
  817.     for (ix = (0x1 << (cnt - 1)); ix; ix >>= 1)
  818.         {
  819.         if (bits & ix)
  820.             {
  821.             EL_MII_SET (EL_MII_DATA);
  822.             }
  823.         else
  824.             {
  825.             EL_MII_CLR (EL_MII_DATA);
  826.             }
  827.         SYS_DELAY (1);
  828.         EL_MII_CLR (EL_MII_CLK);
  829.         SYS_DELAY (1);
  830.         EL_MII_SET (EL_MII_CLK);
  831. }
  832.     }
  833. /*******************************************************************************
  834. *
  835. * el3c90xMiiRegRead - read an PHY register through the MII.
  836. *
  837. * This function reads a PHY register through the MII.
  838. *
  839. * RETURNS: OK or ERROR.
  840. */
  841. LOCAL int el3c90xMiiRegRead
  842.     (
  843.     EL3C90X_DEVICE * pDrvCtrl,
  844.     EL_MII_FRAME * pMiiFrame
  845.     )
  846.     {
  847.     int ix;
  848.     int ack;
  849.     /* set up frame for RX. */
  850.     pMiiFrame->stDelim = EL_MII_STARTDELIM;
  851.     pMiiFrame->opCode = EL_MII_READOP;
  852.     pMiiFrame->turnAround = 0;
  853.     pMiiFrame->data = 0;
  854.     /* clear PHY_MGMT register */
  855.     
  856.     el3c90xCsrWriteWord (pDrvCtrl, EL_W4_PHY_MGMT, 0, EL_WIN_4);
  857.     /* turn on data xmit.*/
  858.     EL_MII_SET (EL_MII_DIR);
  859.     el3c90xMiiSync (pDrvCtrl);
  860.     /* Send command/address info. */
  861.     el3c90xMiiSend (pDrvCtrl, pMiiFrame->stDelim, 2);
  862.     el3c90xMiiSend (pDrvCtrl, pMiiFrame->opCode, 2);
  863.     el3c90xMiiSend (pDrvCtrl, pMiiFrame->phyAddr, 5);
  864.     el3c90xMiiSend (pDrvCtrl, pMiiFrame->regAddr, 5);
  865.     /* idle bit */
  866.     EL_MII_CLR ((EL_MII_CLK | EL_MII_DATA));
  867.     SYS_DELAY (1);
  868.     EL_MII_SET (EL_MII_CLK);
  869.     SYS_DELAY (1);
  870.     /* turn off xmit. */
  871.     EL_MII_CLR (EL_MII_DIR);
  872.     /* Check for ack */
  873.     EL_MII_CLR (EL_MII_CLK);
  874.     SYS_DELAY (1);
  875.     EL_MII_SET (EL_MII_CLK);
  876.     SYS_DELAY (1);
  877.     ack = (el3c90xCsrReadWord (pDrvCtrl, EL_W4_PHY_MGMT, EL_WIN_4) &
  878.            EL_MII_DATA);
  879.     /*
  880.      * Now try reading data bits. If the ack failed, we still
  881.      * need to clock through 16 cycles to keep the PHY(s) in sync.
  882.      */
  883.     if (ack)
  884.         {
  885.         for(ix = 0; ix < 16; ix++)
  886.             {
  887.             EL_MII_CLR (EL_MII_CLK);
  888.             SYS_DELAY (1);
  889.             EL_MII_SET (EL_MII_CLK);
  890.             SYS_DELAY (1);
  891.             }
  892.         goto fail;
  893. }
  894.     for (ix = 0x8000; ix; ix >>= 1)
  895.         {
  896.         EL_MII_CLR (EL_MII_CLK);
  897.         SYS_DELAY (1);
  898.         if (!ack)
  899.             {
  900.             if (el3c90xCsrReadWord (pDrvCtrl, EL_W4_PHY_MGMT, EL_WIN_4) &
  901.                 EL_MII_DATA)
  902.                 pMiiFrame->data |= ix;
  903.             SYS_DELAY (1);
  904.             }
  905.         EL_MII_SET (EL_MII_CLK);
  906.         SYS_DELAY (1);
  907. }
  908.     fail:
  909.         {
  910.         EL_MII_CLR (EL_MII_CLK);
  911.         SYS_DELAY (1);
  912.         EL_MII_SET (EL_MII_CLK);
  913.         SYS_DELAY (1);
  914.         }
  915.     if (ack)
  916.         return (ERROR);
  917.     return (OK);
  918.     }
  919. /*******************************************************************************
  920. *
  921. * el3c90xMiiRegWrite - write to a PHY register through the MII.
  922. *
  923. * This function writes to a PHY register through the MII.
  924. *
  925. * RETURNS: OK or ERROR.
  926. */
  927. LOCAL int el3c90xMiiRegWrite
  928.     (
  929.     EL3C90X_DEVICE * pDrvCtrl,
  930.     EL_MII_FRAME * pMiiFrame
  931.     )
  932.     {
  933.     /* set up frame for TX. */
  934.     pMiiFrame->stDelim = EL_MII_STARTDELIM;
  935.     pMiiFrame->opCode = EL_MII_WRITEOP;
  936.     pMiiFrame->turnAround = EL_MII_TURNAROUND;
  937.     /* turn on data output. */
  938.     EL_MII_SET (EL_MII_DIR);
  939.     el3c90xMiiSync (pDrvCtrl);
  940.     el3c90xMiiSend (pDrvCtrl, pMiiFrame->stDelim, 2);
  941.     el3c90xMiiSend (pDrvCtrl, pMiiFrame->opCode, 2);
  942.     el3c90xMiiSend (pDrvCtrl, pMiiFrame->phyAddr, 5);
  943.     el3c90xMiiSend (pDrvCtrl, pMiiFrame->regAddr, 5);
  944.     el3c90xMiiSend (pDrvCtrl, pMiiFrame->turnAround, 2);
  945.     el3c90xMiiSend (pDrvCtrl, pMiiFrame->data, 16);
  946.     /* idle bit. */
  947.     EL_MII_SET (EL_MII_CLK);
  948.     SYS_DELAY (1);
  949.     EL_MII_CLR (EL_MII_CLK);
  950.     SYS_DELAY (1);
  951.     /* Turn off xmit. */
  952.     EL_MII_CLR (EL_MII_DIR);
  953.     return (OK);
  954.     }
  955. /*******************************************************************************
  956. *
  957. * el3c90xPhyRegRead - read a PHY reg
  958. *
  959. * This function reads a PHY reg
  960. *
  961. * RETURNS: UINT16 value.
  962. */
  963. LOCAL UINT16 el3c90xPhyRegRead
  964.     (
  965.     EL3C90X_DEVICE * pDrvCtrl,
  966.     int reg
  967.     )
  968.     {
  969.     EL_MII_FRAME miiFrame;
  970.     bzero ((char *)&miiFrame, sizeof(miiFrame));
  971.     miiFrame.phyAddr = pDrvCtrl->devPhyAddr;
  972.     miiFrame.regAddr = reg;
  973.     el3c90xMiiRegRead (pDrvCtrl, &miiFrame);
  974.     return(miiFrame.data);
  975.     }
  976. /*******************************************************************************
  977. *
  978. * el3c90xPhyRegWrite - write a PHY reg
  979. *
  980. * This function writes a PHY reg
  981. *
  982. * RETURNS: N/A
  983. */
  984. LOCAL void el3c90xPhyRegWrite
  985.     (
  986.     EL3C90X_DEVICE * pDrvCtrl,
  987.     int reg,
  988.     int data
  989.     )
  990.     {
  991.     EL_MII_FRAME frame;
  992.     bzero((char *)&frame, sizeof(frame));
  993.     frame.phyAddr = pDrvCtrl->devPhyAddr;
  994.     frame.regAddr = reg;
  995.     frame.data = data;
  996.     el3c90xMiiRegWrite(pDrvCtrl, &frame);
  997.     return;
  998.     }
  999. /*******************************************************************************
  1000. *
  1001. * el3c90xAutoNegTx - initiate an autonegotiation session.
  1002. *
  1003. * This function initiates an autonegotiation session.
  1004. *
  1005. * RETURNS: N/A
  1006. */
  1007. LOCAL void el3c90xAutoNegTx
  1008.     (
  1009.     EL3C90X_DEVICE * pDrvCtrl
  1010.     )
  1011.     {
  1012.     UINT16 phyStatus;
  1013.     el3c90xPhyRegWrite (pDrvCtrl, PHY_BMCR, PHY_BMCR_RESET);
  1014.     SYS_DELAY (500);
  1015.     while (el3c90xPhyRegRead (pDrvCtrl, EL_PHY_GENCTL)
  1016.            & PHY_BMCR_RESET);
  1017.     phyStatus = el3c90xPhyRegRead (pDrvCtrl, PHY_BMCR);
  1018.     phyStatus |= (PHY_BMCR_AUTONEGENBL | PHY_BMCR_AUTONEGRSTR);
  1019.     el3c90xPhyRegWrite (pDrvCtrl, PHY_BMCR, phyStatus);
  1020.     return;
  1021.     }
  1022. /*******************************************************************************
  1023. *
  1024. * el3c90xMiiAutoNeg - invoke autonegotiation on a PHY
  1025. *
  1026. * This function invokes autonegotiation on a PHY. Also used with the
  1027. * 3Com internal autoneg logic which is mapped onto the MII.
  1028. *
  1029. * RETURNS: N/A
  1030. */
  1031. LOCAL void el3c90xMiiAutoNeg
  1032.     (
  1033.     EL3C90X_DEVICE * pDrvCtrl
  1034.     )
  1035.     {
  1036.     UINT16 phyStatus = 0;
  1037.     UINT16 media;
  1038.     UINT16 advert;
  1039.     UINT16 ability;
  1040.     /*
  1041.      * The 100baseT4 PHY on the 3c905-T4 has the 'autoneg supported'
  1042.      * bit cleared in the status register, but has the 'autoneg enabled'
  1043.      * bit set in the control register. This is a contradiction, and
  1044.      * I'm not sure how to handle it. If you want to force an attempt
  1045.      * to autoneg for 100baseT4 PHYs, #define FORCE_AUTONEG_TFOUR
  1046.      * and see what happens.
  1047.      */
  1048. #ifndef FORCE_AUTONEG_TFOUR
  1049.     /*
  1050.      * First, see if autoneg is supported. If not, there's
  1051.      * no point in continuing.
  1052.      */
  1053.     phyStatus = el3c90xPhyRegRead (pDrvCtrl, PHY_BMSR);
  1054.     if (!(phyStatus & PHY_BMSR_CANAUTONEG))
  1055.         {
  1056.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: autonegotiation not supportedn",
  1057.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1058.         media = el3c90xPhyRegRead (pDrvCtrl, PHY_BMCR);
  1059.         media &= ~PHY_BMCR_SPEEDSEL;
  1060.         media &= ~PHY_BMCR_DUPLEX;
  1061.         el3c90xPhyRegWrite (pDrvCtrl, PHY_BMCR, media);
  1062.         el3c90xCsrWriteByte (pDrvCtrl, EL_W3_MAC_CTRL,
  1063.                              (el3c90xCsrReadByte (pDrvCtrl, EL_W3_MAC_CTRL,
  1064.                                                   EL_WIN_3) &
  1065.                               ~EL_MACCTRL_DUPLEX), EL_WIN_3);
  1066.         return;
  1067. }
  1068. #endif
  1069.     el3c90xAutoNegTx (pDrvCtrl);
  1070.     taskDelay (sysClkRateGet() * 2);
  1071.     if (el3c90xPhyRegRead (pDrvCtrl, PHY_BMSR) & PHY_BMSR_AUTONEGCOMP)
  1072.         {
  1073.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: autoneg complete, ",
  1074.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1075.         phyStatus = el3c90xPhyRegRead (pDrvCtrl, PHY_BMSR);
  1076. }
  1077.     else
  1078.         {
  1079.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: autoneg not complete, ",
  1080.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1081. }
  1082.     media = el3c90xPhyRegRead (pDrvCtrl, PHY_BMCR);
  1083.     /* Link is good. Report modes and set duplex mode. */
  1084.     
  1085.     if (el3c90xPhyRegRead (pDrvCtrl, PHY_BMSR) & PHY_BMSR_LINKSTAT)
  1086.         {
  1087.         DRV_LOG (DRV_DEBUG_LOAD,"link status good ", 1, 2, 3, 4, 5, 6);
  1088.         advert = el3c90xPhyRegRead (pDrvCtrl, EL_PHY_ANAR);
  1089.         ability = el3c90xPhyRegRead (pDrvCtrl, EL_PHY_LPAR);
  1090.         if (advert & PHY_ANAR_100BT4 && ability & PHY_ANAR_100BT4)
  1091.             {
  1092.             media |= PHY_BMCR_SPEEDSEL;
  1093.             media &= ~PHY_BMCR_DUPLEX;
  1094.             DRV_LOG (DRV_DEBUG_LOAD,"(100baseT4)n", 1, 2, 3, 4, 5, 6);
  1095.             }
  1096.         else if (advert & PHY_ANAR_100BTXFULL && ability & PHY_ANAR_100BTXFULL)
  1097.             {
  1098.             media |= PHY_BMCR_SPEEDSEL;
  1099.             media |= PHY_BMCR_DUPLEX;
  1100.             DRV_LOG (DRV_DEBUG_LOAD,"(full-duplex, 100Mbps)n",
  1101.                      1, 2, 3, 4, 5, 6);
  1102.             }
  1103.         else if (advert & PHY_ANAR_100BTXHALF && ability & PHY_ANAR_100BTXHALF)
  1104.             {
  1105.             media |= PHY_BMCR_SPEEDSEL;
  1106.             media &= ~PHY_BMCR_DUPLEX;
  1107.             DRV_LOG (DRV_DEBUG_LOAD,"(half-duplex, 100Mbps)n",
  1108.                      1, 2, 3, 4, 5, 6);
  1109.             }
  1110.         else if (advert & PHY_ANAR_10BTFULL && ability & PHY_ANAR_10BTFULL)
  1111.             {
  1112.             media &= ~PHY_BMCR_SPEEDSEL;
  1113.             media |= PHY_BMCR_DUPLEX;
  1114.             DRV_LOG (DRV_DEBUG_LOAD,"(full-duplex, 10Mbps)n",
  1115.                      1, 2, 3, 4, 5, 6);
  1116.             }
  1117.         else if (advert & PHY_ANAR_10BTHALF && ability & PHY_ANAR_10BTHALF)
  1118.             {
  1119.             media &= ~PHY_BMCR_SPEEDSEL;
  1120.             media &= ~PHY_BMCR_DUPLEX;
  1121.             DRV_LOG (DRV_DEBUG_LOAD,"(half-duplex, 10Mbps)n",
  1122.                      1, 2, 3, 4, 5, 6);
  1123.             }
  1124.         /* Set ASIC's duplex mode to match the PHY. */
  1125.         
  1126.         if (media & PHY_BMCR_DUPLEX)
  1127.             el3c90xCsrWriteByte (pDrvCtrl, EL_W3_MAC_CTRL, EL_MACCTRL_DUPLEX,
  1128.                                  EL_WIN_3);
  1129.         else
  1130.             el3c90xCsrWriteByte (pDrvCtrl, EL_W3_MAC_CTRL,
  1131.                                  (el3c90xCsrReadByte (pDrvCtrl, EL_W3_MAC_CTRL,
  1132.                                                       EL_WIN_3) &
  1133.                                   ~EL_MACCTRL_DUPLEX), EL_WIN_3);
  1134.         el3c90xPhyRegWrite (pDrvCtrl, PHY_BMCR, media);
  1135. }
  1136.     else
  1137.         {
  1138.         DRV_LOG (DRV_DEBUG_LOAD,"no carrier (forcing half-duplex,"
  1139.                  "10Mbps)n", 1, 2, 3, 4, 5, 6);
  1140.         media &= ~PHY_BMCR_SPEEDSEL;
  1141.         media &= ~PHY_BMCR_DUPLEX;
  1142.         el3c90xPhyRegWrite (pDrvCtrl, PHY_BMCR, media);
  1143.         el3c90xCsrWriteByte (pDrvCtrl, EL_W3_MAC_CTRL,
  1144.                              (el3c90xCsrReadByte (pDrvCtrl, EL_W3_MAC_CTRL,
  1145.                                                   EL_WIN_3) &
  1146.                               ~EL_MACCTRL_DUPLEX), EL_WIN_3);
  1147.         }
  1148.     return;
  1149.     }
  1150. /*******************************************************************************
  1151. *
  1152. * el3c90xMiiModeGet - get the MII mode
  1153. *
  1154. * This function gets the MII mode and returns the speed of the physical
  1155. * interface. The default speed is 10Mbits/sec.
  1156. *
  1157. * RETURNS: speed of the physical interface.
  1158. */
  1159. LOCAL int el3c90xMiiModeGet
  1160.     (
  1161.     EL3C90X_DEVICE * pDrvCtrl
  1162.     )
  1163.     {
  1164.     UINT16 bmsr;
  1165.     int speed = 10000000;
  1166.     bmsr = el3c90xPhyRegRead (pDrvCtrl, PHY_BMSR);
  1167.     DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: PHY status word: %xn", pDrvCtrl->unit,
  1168.              bmsr, 3, 4, 5, 6);
  1169.     if (bmsr & PHY_BMSR_10BTHALF)
  1170.         {
  1171.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: 10Mbps half-duplex mode supportedn",
  1172.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1173. }
  1174.     if (bmsr & PHY_BMSR_10BTFULL)
  1175.         {
  1176.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: 10Mbps full-duplex mode supportedn",
  1177.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1178. }
  1179.     if (bmsr & PHY_BMSR_100BTXHALF)
  1180.         {
  1181.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d:100Mbps half-duplex mode supportedn",
  1182.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1183.         speed = 100000000;
  1184. }
  1185.     if (bmsr & PHY_BMSR_100BTXFULL)
  1186.         {
  1187.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d:100Mbps full-duplex mode supportedn",
  1188.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1189.         speed = 100000000;
  1190. }
  1191.     /* Some also support 100BaseT4 */
  1192.     if (bmsr & PHY_BMSR_100BT4)
  1193.         {
  1194.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d:100baseT4 mode supportedn",
  1195.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1196.         speed = 100000000;
  1197. #ifdef FORCE_AUTONEG_TFOUR
  1198.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d:force on autoneg support for BT4n",
  1199.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1200. #endif
  1201. }
  1202.     if (bmsr & PHY_BMSR_CANAUTONEG)
  1203.         {
  1204.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: autoneg supportedn",
  1205.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1206.         speed = 10000000;
  1207. }
  1208.     
  1209.     return (speed);
  1210.     }
  1211. /*******************************************************************************
  1212. *
  1213. * el3c90xMediaSet - set the media access control
  1214. *
  1215. * This function sets the MAC register.
  1216. *
  1217. * RETURNS: N/A
  1218. */
  1219. LOCAL void el3c90xMediaSet
  1220.     (
  1221.     EL3C90X_DEVICE * pDrvCtrl,
  1222.     int media
  1223.     )
  1224.     {
  1225.     UINT32 icfg;
  1226.     UINT16 mediastat;
  1227.     DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: selecting ", pDrvCtrl->unit,
  1228.              2, 3, 4, 5, 6);
  1229.     mediastat = el3c90xCsrReadWord (pDrvCtrl, EL_W4_MEDIA_STATUS, EL_WIN_4);
  1230.     
  1231.     icfg = el3c90xCsrReadLong (pDrvCtrl, EL_W3_INTERNAL_CFG, EL_WIN_3);
  1232.     if (pDrvCtrl->devMedia & EL_MEDIAOPT_BT)
  1233.         {
  1234.         if (IFM_SUBTYPE (media) == IFM_10_T)
  1235.             {
  1236.             DRV_LOG (DRV_DEBUG_LOAD,"10baseT transceiver, ",
  1237.                      1, 2, 3, 4, 5, 6);
  1238.             pDrvCtrl->xCvr = EL_XCVR_10BT;
  1239.             icfg &= ~EL_ICFG_CONNECTOR_MASK;
  1240.             icfg |= (EL_XCVR_10BT << EL_ICFG_CONNECTOR_BITS);
  1241.             mediastat |= EL_MEDIASTAT_LINKBEAT|
  1242.                 EL_MEDIASTAT_JABGUARD;
  1243.             mediastat &= ~EL_MEDIASTAT_SQEENB;
  1244.             }
  1245. }
  1246.     if (pDrvCtrl->devMedia & EL_MEDIAOPT_BFX)
  1247.         {
  1248.         if (IFM_SUBTYPE (media) == IFM_100_FX)
  1249.             {
  1250.             DRV_LOG (DRV_DEBUG_LOAD,"100baseFX port, ", 1, 2, 3, 4, 5, 6);
  1251.             pDrvCtrl->xCvr = EL_XCVR_100BFX;
  1252.             icfg &= ~EL_ICFG_CONNECTOR_MASK;
  1253.             icfg |= (EL_XCVR_100BFX << EL_ICFG_CONNECTOR_BITS);
  1254.             mediastat |= EL_MEDIASTAT_LINKBEAT;
  1255.             mediastat &= ~EL_MEDIASTAT_SQEENB;
  1256.             }
  1257. }
  1258.     if (pDrvCtrl->devMedia & EL_MEDIAOPT_AUI)
  1259.         {
  1260.         if (IFM_SUBTYPE (media) == IFM_10_5)
  1261.             {
  1262.             DRV_LOG (DRV_DEBUG_LOAD,"AUI port, ", 1, 2, 3, 4, 5, 6);
  1263.             pDrvCtrl->xCvr = EL_XCVR_AUI;
  1264.             icfg &= ~EL_ICFG_CONNECTOR_MASK;
  1265.             icfg |= (EL_XCVR_AUI << EL_ICFG_CONNECTOR_BITS);
  1266.             mediastat &= ~(EL_MEDIASTAT_LINKBEAT|
  1267.                            EL_MEDIASTAT_JABGUARD);
  1268.             mediastat |= ~EL_MEDIASTAT_SQEENB;
  1269.             }
  1270. }
  1271.     if (pDrvCtrl->devMedia & EL_MEDIAOPT_BNC)
  1272.         {
  1273.         if (IFM_SUBTYPE (media) == IFM_10_2)
  1274.             {
  1275.             DRV_LOG (DRV_DEBUG_LOAD,"BNC port, ", 1, 2, 3, 4, 5, 6);
  1276.             pDrvCtrl->xCvr = EL_XCVR_COAX;
  1277.             icfg &= ~EL_ICFG_CONNECTOR_MASK;
  1278.             icfg |= (EL_XCVR_COAX << EL_ICFG_CONNECTOR_BITS);
  1279.             mediastat &= ~(EL_MEDIASTAT_LINKBEAT|
  1280.                            EL_MEDIASTAT_JABGUARD|
  1281.                            EL_MEDIASTAT_SQEENB);
  1282.             }
  1283. }
  1284.     if ((media & IFM_GMASK) == IFM_FDX ||
  1285.         IFM_SUBTYPE (media) == IFM_100_FX)
  1286.         {
  1287.         DRV_LOG (DRV_DEBUG_LOAD,"full duplexn", 1, 2, 3, 4, 5, 6);
  1288.         el3c90xCsrWriteByte (pDrvCtrl, EL_W3_MAC_CTRL, EL_MACCTRL_DUPLEX,
  1289.                              EL_WIN_3);
  1290. }
  1291.     else
  1292.         {
  1293.         DRV_LOG (DRV_DEBUG_LOAD,"half duplexn", 1, 2, 3, 4, 5, 6);
  1294.         el3c90xCsrWriteByte (pDrvCtrl, EL_W3_MAC_CTRL,
  1295.                              (el3c90xCsrReadByte (pDrvCtrl, EL_W3_MAC_CTRL,
  1296.                                                   EL_WIN_3) &
  1297.                               ~EL_MACCTRL_DUPLEX), EL_WIN_3);
  1298. }
  1299.     if (IFM_SUBTYPE(media) == IFM_10_2)
  1300.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_COAX_START, NONE);
  1301.     else
  1302.         el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_COAX_STOP, NONE);
  1303.     el3c90xCsrWriteLong (pDrvCtrl, EL_W3_INTERNAL_CFG, icfg, EL_WIN_3);
  1304.     el3c90xCsrWriteWord (pDrvCtrl, EL_W4_MEDIA_STATUS, mediastat, EL_WIN_4);
  1305.     SYS_DELAY(800);
  1306.     return;
  1307.     }
  1308. /*******************************************************************************
  1309. *
  1310. * el3c90xMediaCheck - check the media on the adapter card.
  1311. *
  1312. * This function checks for the media on the adapter card.
  1313. * This routine is a kludge to work around possible hardware faults
  1314. * or manufacturing defects that can cause the media options register
  1315. * (or reset options register, as it's called for the first generation
  1316. * 3cx90x adapters) to return an incorrect result.
  1317. * one Dell Latitude laptop docking station with an integrated 3c905-TX
  1318. * doesn't have any of the 'mediaopt' bits set. This causes the
  1319. * the attach routine to fail because it doesn't know what media
  1320. * to look for. If we find ourselves in this predicament, this routine
  1321. * will try to guess the media options values and warn the user of a
  1322. * possible manufacturing defect with his adapter/system/whatever.
  1323. *
  1324. * RETURNS: N/A
  1325. */
  1326. LOCAL void el3c90xMediaCheck
  1327.     (
  1328.     EL3C90X_DEVICE * pDrvCtrl
  1329.     )
  1330.     {
  1331.     UINT16 devid;
  1332.     /*
  1333.      * if some of the media options bits are set, assume they are
  1334.      * correct. If not, try to figure it out down below.
  1335.      */
  1336.     if (pDrvCtrl->devMedia & (EL_MEDIAOPT_MASK & ~EL_MEDIAOPT_VCO))
  1337.         {
  1338.         /*
  1339.          * Check the XCVR value. If it's not in the normal range
  1340.          * of values, we need to fake it up here.
  1341.          */
  1342.         if (pDrvCtrl->xCvr <= EL_XCVR_AUTO)
  1343.             return;
  1344.         else
  1345.             {
  1346.             DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: bogus xcvr value "
  1347.                      "in EEPROM (%x)n", pDrvCtrl->unit, pDrvCtrl->xCvr,
  1348.                      3, 4, 5, 6);
  1349.             DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: choosing new default based "
  1350.                      "on card typen", pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1351.             }
  1352. }
  1353.     else
  1354.         {
  1355.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: WARNING: no media options bits set"
  1356.                  "in the media options register!!n", pDrvCtrl->unit,
  1357.                  2, 3, 4, 5, 6);
  1358.             
  1359.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: this could be a manufacturing"
  1360.                  "defect in your adapter or systemn",
  1361.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1362.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: attempting to guess media type; you "
  1363.                  "should probably consult your vendorn", pDrvCtrl->unit,
  1364.                  2, 3, 4, 5, 6);
  1365. }
  1366.     /*
  1367.      * Read the device ID from the EEPROM.
  1368.      * This is what's loaded into the PCI device ID register, so it has
  1369.      * to be correct otherwise we wouldn't have gotten this far.
  1370.      */
  1371.     
  1372.     el3c90xEprmRead (pDrvCtrl, (caddr_t)&devid, EL_EE_PRODID, 1, 0);
  1373.     switch (devid) 
  1374.         {
  1375. case TC_DEVICEID_BOOMERANG_10BT: /* 3c900-TP */
  1376. case TC_DEVICEID_CYCLONE_10BT: /* 3c900B-TP */
  1377.             pDrvCtrl->devMedia = EL_MEDIAOPT_BT;
  1378.             pDrvCtrl->xCvr = EL_XCVR_10BT;
  1379.             DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: guessing 10BaseT transceivern",
  1380.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1381.             break;
  1382.             
  1383. case TC_DEVICEID_BOOMERANG_10BT_COMBO: /* 3c900-COMBO */
  1384. case TC_DEVICEID_CYCLONE_10BT_COMBO: /* 3c900B-COMBO */
  1385.             pDrvCtrl->devMedia = (EL_MEDIAOPT_BT |EL_MEDIAOPT_BNC |
  1386.                                   EL_MEDIAOPT_AUI);
  1387.             pDrvCtrl->xCvr = EL_XCVR_10BT;
  1388.             DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: guessing COMBO (AUI/BNC/TP)n",
  1389.                      pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1390.             break;
  1391.             
  1392. case TC_DEVICEID_BOOMERANG_10_100BT: /* 3c905-TX */
  1393.             pDrvCtrl->devMedia = EL_MEDIAOPT_MII;
  1394.             pDrvCtrl->xCvr = EL_XCVR_MII;
  1395.             DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: guessing MIIn",
  1396.                      pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1397.             break;
  1398.             
  1399. case TC_DEVICEID_BOOMERANG_100BT4: /* 3c905-T4 */
  1400. case TC_DEVICEID_CYCLONE_10_100BT4: /* 3c905B-T4 */
  1401.             pDrvCtrl->devMedia = EL_MEDIAOPT_BT4;
  1402.             pDrvCtrl->xCvr = EL_XCVR_MII;
  1403.             DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: guessing 100BaseT4/MIIn",
  1404.                      pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1405.             break;
  1406.             
  1407. case TC_DEVICEID_CYCLONE_10_100BT: /* 3c905B-TX */
  1408. case TC_DEVICEID_CYCLONE_10_100BT_SERV: /* 3c980-TX */
  1409.             pDrvCtrl->devMedia = EL_MEDIAOPT_BTX;
  1410.             pDrvCtrl->xCvr = EL_XCVR_AUTO;
  1411.             DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: guessing 10/100 internaln",
  1412.                      pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1413.             break;
  1414. default:
  1415.             DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: unknown device ID: %x -- "
  1416.                    "defaulting to 10baseTn", pDrvCtrl->unit, devid,
  1417.                        3, 4, 5, 6);
  1418.             pDrvCtrl->devMedia = EL_MEDIAOPT_BT;
  1419.             break;
  1420. }
  1421.     return;
  1422.     }
  1423. /*******************************************************************************
  1424. *
  1425. * el3c90xMediaConfig - configure the media and do auto negotiation
  1426. *
  1427. * This function configures the media and does the auto negotioation.
  1428. *
  1429. * RETURNS: speed or 0
  1430. *
  1431. */
  1432. LOCAL int el3c90xMediaConfig
  1433.     (
  1434.     EL3C90X_DEVICE *  pDrvCtrl /* device control structure */
  1435.     )
  1436.     {
  1437.     EL_DEV_TYPE * pDevType;
  1438.     UINT32 icfg;
  1439.     int media = IFM_ETHER | IFM_100_TX |IFM_FDX;
  1440.     UINT16 phyVendorId;
  1441.     UINT16 phyDevId;
  1442.     UINT16 phyStatus;
  1443.     int speed = 10000000;
  1444.     int ix;
  1445.     /*
  1446.      * now we have to see what sort of media we have.
  1447.      * This includes probing for an MII interace and a
  1448.      * possible PHY.
  1449.      */
  1450.     pDrvCtrl->devMedia = el3c90xCsrReadWord (pDrvCtrl, EL_W3_MEDIA_OPT,
  1451.                                              EL_WIN_3);
  1452.     DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: media options word: %xn",
  1453.              pDrvCtrl->unit,
  1454.              pDrvCtrl->devMedia, 3, 4, 5, 6);
  1455.     el3c90xEprmRead (pDrvCtrl, (char *)&pDrvCtrl->xCvr, EL_EE_ICFG_0, 2, 0);
  1456.     pDrvCtrl->xCvr &= EL_ICFG_CONNECTOR_MASK;
  1457.     pDrvCtrl->xCvr >>= EL_ICFG_CONNECTOR_BITS;
  1458.     el3c90xMediaCheck (pDrvCtrl);
  1459.     if (pDrvCtrl->devMedia & EL_MEDIAOPT_MII ||
  1460.         pDrvCtrl->devMedia & EL_MEDIAOPT_BTX ||
  1461.         pDrvCtrl->devMedia & EL_MEDIAOPT_BT4)
  1462.         {
  1463.         /*
  1464.          * in theory we shouldn't need this, but... if this
  1465.          * card supports an MII, either an external one or
  1466.          * an internal fake one, select it in the internal
  1467.          * config register before trying to probe it.
  1468.          */
  1469.         icfg = el3c90xCsrReadLong (pDrvCtrl, EL_W3_INTERNAL_CFG, EL_WIN_3);
  1470.         icfg &= ~EL_ICFG_CONNECTOR_MASK;
  1471.         if (pDrvCtrl->devMedia & EL_MEDIAOPT_MII ||
  1472.             pDrvCtrl->devMedia & EL_MEDIAOPT_BT4)
  1473.             icfg |= (EL_XCVR_MII << EL_ICFG_CONNECTOR_BITS);
  1474.         
  1475.         if (pDrvCtrl->devMedia & EL_MEDIAOPT_BTX)
  1476.             icfg |= (EL_XCVR_AUTO << EL_ICFG_CONNECTOR_BITS);
  1477.         
  1478.         if (pDrvCtrl->devMedia & EL_MEDIAOPT_BFX)
  1479.             icfg |= (EL_XCVR_100BFX << EL_ICFG_CONNECTOR_BITS);
  1480.         
  1481.         el3c90xCsrWriteLong (pDrvCtrl, EL_W3_INTERNAL_CFG, icfg, EL_WIN_3);
  1482.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: probing for a PHYn",
  1483.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1484.         for (ix = EL_PHYADDR_MIN; ix < EL_PHYADDR_MAX + 1; ix++)
  1485.             {
  1486.             DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: checking address: %dn",
  1487.                      pDrvCtrl->unit, ix, 3, 4, 5, 6);
  1488.             pDrvCtrl->devPhyAddr = ix;
  1489.             
  1490.             el3c90xPhyRegWrite (pDrvCtrl, EL_PHY_GENCTL, PHY_BMCR_RESET);
  1491.             SYS_DELAY(500);
  1492.             while (el3c90xPhyRegRead (pDrvCtrl, EL_PHY_GENCTL)
  1493.                    & PHY_BMCR_RESET);
  1494.             if ((phyStatus = el3c90xPhyRegRead (pDrvCtrl, EL_PHY_GENSTS)))
  1495.                 break;
  1496.             }
  1497.         if (phyStatus)
  1498.             {
  1499.             phyVendorId = el3c90xPhyRegRead (pDrvCtrl, EL_PHY_VENID);
  1500.             phyDevId = el3c90xPhyRegRead (pDrvCtrl, EL_PHY_DEVID);
  1501.             DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: found PHY at address %d, ",
  1502.                      pDrvCtrl->unit, pDrvCtrl->devPhyAddr, 3, 4, 5, 6);
  1503.             DRV_LOG (DRV_DEBUG_LOAD,"vendor id: %x device id: %xn",
  1504.                      phyVendorId, phyDevId, 3, 4, 5, 6);
  1505.             pDevType = el3c90xPhyTbl;
  1506.             while (pDevType->vendorId)
  1507.                 {
  1508.                 if (phyVendorId == pDevType->vendorId &&
  1509.                     (phyDevId | 0x000F) == pDevType->deviceId)
  1510.                     {
  1511.                     pDrvCtrl->pPhyDevType = pDevType;
  1512.                     break;
  1513.                     }
  1514.                 pDevType++;
  1515.                 }
  1516.             
  1517.             if (pDrvCtrl->pPhyDevType == NULL)
  1518.                 pDrvCtrl->pPhyDevType = &el3c90xPhyTbl [PHY_UNKNOWN];
  1519.             DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: PHY type: %sn",
  1520.                      pDrvCtrl->unit, pDrvCtrl->pPhyDevType->devName,
  1521.                      3, 4, 5, 6);
  1522.             }
  1523.         else
  1524.             DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: MII without any phy!n",
  1525.                      pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1526. }
  1527.     if (pDrvCtrl->devMedia & EL_MEDIAOPT_BT)
  1528.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: found 10baseTn",
  1529.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1530.     if (pDrvCtrl->devMedia & EL_MEDIAOPT_AUI)
  1531.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: found AUIn",
  1532.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1533.     if (pDrvCtrl->devMedia & EL_MEDIAOPT_BNC)
  1534.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: found BNCn",
  1535.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1536.     
  1537.     if (pDrvCtrl->devMedia & EL_MEDIAOPT_BTX)
  1538.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: found 100baseTXn",
  1539.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1540.             
  1541.     if (pDrvCtrl->devMedia & EL_MEDIAOPT_BFX)
  1542.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: found 100baseFXn",
  1543.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1544.     if ((pDrvCtrl->devMedia & EL_MEDIAOPT_BTX) ||
  1545.         (pDrvCtrl->devMedia & EL_MEDIAOPT_BFX))
  1546.         speed = 100000000;
  1547.     /* if there's an MII, we have to probe its modes separately. */
  1548.     if (pDrvCtrl->devMedia & EL_MEDIAOPT_MII ||
  1549.         pDrvCtrl->devMedia & EL_MEDIAOPT_BT4)
  1550.         {
  1551.         DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: found MIIn",
  1552.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1553.         speed = el3c90xMiiModeGet (pDrvCtrl);
  1554. }
  1555.     /* Choose a default media. */
  1556.     switch (pDrvCtrl->xCvr)
  1557.         {
  1558. case EL_XCVR_10BT:
  1559.             media = IFM_ETHER | IFM_10_T;
  1560.             el3c90xMediaSet (pDrvCtrl, media);
  1561.             break;
  1562.             
  1563. case EL_XCVR_AUI:
  1564.             media = IFM_ETHER | IFM_10_5;
  1565.             el3c90xMediaSet (pDrvCtrl, media);
  1566.             break;
  1567.             
  1568. case EL_XCVR_COAX:
  1569.             media = IFM_ETHER | IFM_10_2;
  1570.             el3c90xMediaSet (pDrvCtrl, media);
  1571.             break;
  1572.             
  1573. case EL_XCVR_AUTO:
  1574.             el3c90xMiiAutoNeg (pDrvCtrl);
  1575.             break;
  1576.             
  1577. case EL_XCVR_100BTX:
  1578. case EL_XCVR_MII:
  1579.             el3c90xMiiAutoNeg (pDrvCtrl);
  1580.             break;
  1581.             
  1582. case EL_XCVR_100BFX:
  1583.             media = IFM_ETHER | IFM_100_FX;
  1584.             el3c90xMediaSet (pDrvCtrl, media);
  1585.             break;
  1586. default:
  1587.             DRV_LOG (DRV_DEBUG_LOAD,"elPci%d: unknown XCVR type: %dn",
  1588.                      pDrvCtrl->unit, pDrvCtrl->xCvr, 3, 4, 5, 6);
  1589.             /*
  1590.              * This will probably be wrong, but it prevents
  1591.              * the ifmedia code from panicking.
  1592.              */
  1593.             media = IFM_ETHER | IFM_10_T;
  1594.             break;
  1595. }
  1596.     return (speed);
  1597.     }
  1598. /*******************************************************************************
  1599. *
  1600. * el3c90xEprmWait - wait for eeprom to get ready 
  1601. *
  1602. * This function waits for eeprom to get ready 
  1603. * EEPROM is slow so give it time to come ready after issuing it a command
  1604. * The standard eeprom wait period is 162 usecs.
  1605. *
  1606. * RETURNS: OK or ERROR.
  1607. */
  1608. LOCAL int el3c90xEprmWait
  1609.     (
  1610.     EL3C90X_DEVICE *  pDrvCtrl /* device control structure */
  1611.     )
  1612.     {
  1613.     int ix;
  1614.     for (ix = 0; ix < EL_EE_RETRY_CNT; ix++)
  1615.         {
  1616.         if (el3c90xCsrReadWord (pDrvCtrl, EL_W0_EE_CMD, EL_WIN_0) & EL_EE_BUSY)
  1617.             {
  1618.             SYS_DELAY (EL_EE_WAIT);
  1619.             }
  1620.         else
  1621.             break;
  1622. }
  1623.     if (ix == EL_EE_RETRY_CNT)
  1624.         {
  1625.         DRV_LOG (DRV_DEBUG_LOAD, "elPci%d: eeprom failed to come readyn",
  1626.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1627.         return (ERROR);
  1628. }
  1629.     return (OK);
  1630.     }
  1631. /*******************************************************************************
  1632. *
  1633. * el3c90xEprmRead - read a sequence of words from the eeprom 
  1634. *
  1635. * This function reads a sequence of words from the eeprom.
  1636. *
  1637. * NOTE:
  1638. * The ethernet address stored in the EEPROM is in the network byte order.
  1639. *
  1640. * RETURNS: OK or ERROR.
  1641. */
  1642. LOCAL int el3c90xEprmRead
  1643.     (
  1644.     EL3C90X_DEVICE *  pDrvCtrl, /* device control structure */
  1645.     char * pDest, /* pointer destination */
  1646.     int off, /* offset */
  1647.     int cnt, /* number of words to read */
  1648.     int swap /* swap or not */
  1649.     )
  1650.     {
  1651.     int ix;
  1652.     UINT16 word = 0;
  1653.     UINT16 * pWord;
  1654.     if (el3c90xEprmWait (pDrvCtrl) != OK)
  1655.         return (ERROR);
  1656.     for (ix = 0; ix < cnt; ix++)
  1657.         {
  1658.         el3c90xCsrWriteWord (pDrvCtrl, EL_W0_EE_CMD, EL_EE_READ | (off + ix),
  1659.                              EL_WIN_0);
  1660.         if (el3c90xEprmWait (pDrvCtrl) != OK)
  1661.             return (ERROR);
  1662.         word = el3c90xCsrReadWord (pDrvCtrl, EL_W0_EE_DATA, EL_WIN_0);
  1663.         pWord = (UINT16 *)(pDest + (ix * 2));
  1664.         if (swap)
  1665.             *pWord = ntohs (word);
  1666.         else
  1667.             *pWord = PCI_WORD_SWAP(word);
  1668. }
  1669.     return (OK);
  1670.     }
  1671. /*******************************************************************************
  1672. *
  1673. * el3c90xWait - wait for the command completion
  1674. *
  1675. * This function waits for the command completion
  1676. * It is possible the chip can wedge and the 'command in progress' bit may
  1677. * never clear. Hence, we wait only a finite amount of time to avoid getting
  1678. * caught in an infinite loop. Normally this delay routine would be a macro,
  1679. * but it isn't called during normal operation so we can afford to make it a
  1680. * function.
  1681. *
  1682. * RETURNS: N/A
  1683. */
  1684. LOCAL void el3c90xWait
  1685.     (
  1686.     EL3C90X_DEVICE *  pDrvCtrl /* device control structure */
  1687.     )
  1688.     {
  1689.     register int ix;
  1690.     for (ix = 0; ix < EL_TIMEOUT; ix++)
  1691.         {
  1692.         if (!(el3c90xCsrReadWord (pDrvCtrl, EL_STATUS, NONE) &
  1693.               EL_STAT_CMDBUSY))
  1694.             break;
  1695. }
  1696.     if (ix == EL_TIMEOUT)
  1697.         DRV_LOG (DRV_DEBUG_ALL, "elPci%d: command never completed!n",
  1698.                  pDrvCtrl->unit, 2, 3, 4, 5, 6);
  1699.     return;
  1700.     }
  1701. /******************************************************************************
  1702. *
  1703. * el3c90xIntrSet - set the appropriate interrupt
  1704. *
  1705. * This routine set the interrupt given in the <flag>
  1706. *
  1707. * RETURNS: N/A.
  1708. */
  1709. LOCAL void el3c90xIntrSet
  1710.     (
  1711.     EL3C90X_DEVICE * pDrvCtrl, /* pointer to the device control structure */
  1712.     UINT16      flag
  1713.     )
  1714.     {
  1715.     USHORT intMask;
  1716.     int intLevel;
  1717.     intLevel = intLock ();
  1718.     /* set the window */
  1719.     SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1720.                    (EL_CMD_WINSEL | EL_WIN_5));
  1721.     
  1722.     SYS_IN_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_W5_STAT_ENB),
  1723.                   intMask);
  1724.     intMask |= flag;
  1725.     /* reenable relevant interrupt conditions */
  1726.     SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1727.                    (EL_CMD_STAT_ENB | intMask));
  1728.     intUnlock (intLevel);
  1729.     }
  1730. /******************************************************************************
  1731. *
  1732. * el3c90xIntrClr - clear the appropriate interrupt
  1733. *
  1734. * This routine set the interrupt given in the <flag>
  1735. *
  1736. * RETURNS: N/A.
  1737. */
  1738. LOCAL void el3c90xIntrClr
  1739.     (
  1740.     EL3C90X_DEVICE * pDrvCtrl, /* pointer to the device control structure */
  1741.     UINT16      flag
  1742.     )
  1743.     {
  1744.     USHORT intMask;
  1745.     int intLevel;
  1746.     intLevel = intLock ();
  1747.     /* set the window */
  1748.     SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1749.                    (EL_CMD_WINSEL | EL_WIN_5));
  1750.     
  1751.     SYS_IN_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_W5_STAT_ENB),
  1752.                   intMask);
  1753.     intMask &= ~(flag);
  1754.     /* reenable relevant interrupt conditions */
  1755.     SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1756.                    (EL_CMD_STAT_ENB | intMask));
  1757.     intUnlock (intLevel);
  1758.     }
  1759. /*******************************************************************************
  1760. *
  1761. * el3c90xCsrReadByte - read a byte from a given window and register
  1762. *
  1763. * This function reads a byte from a given window and register
  1764. *
  1765. * RETURNS: UCHAR
  1766. */
  1767. LOCAL UCHAR el3c90xCsrReadByte
  1768.     (
  1769.     EL3C90X_DEVICE *  pDrvCtrl, /* device control structure */
  1770.     USHORT reg, /* register offset */
  1771.     int window /* window number */
  1772.     )
  1773.     {
  1774.     UCHAR inByte;
  1775.     if (window != NONE)
  1776.         {
  1777.         /* disable interrupts to prevent race conditions */
  1778.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1779.                        EL_CMD_INTR_ENB);
  1780.         /* set the window */
  1781. SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1782.                                   EL_CMD_WINSEL | window);
  1783.         /* set the register */
  1784.         SYS_IN_BYTE (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), inByte);
  1785.         /* reenable interrupts */
  1786.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1787.                        (EL_CMD_INTR_ENB | EL_INTRS));
  1788.         }
  1789.     else
  1790.         SYS_IN_BYTE (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), inByte);
  1791.     return (inByte);
  1792.     }
  1793. /*******************************************************************************
  1794. *
  1795. * el3c90xCsrReadWord - read a word from a given window and register
  1796. *
  1797. * This function reads a word from a given window and register
  1798. *
  1799. * RETURNS: USHORT
  1800. */
  1801. LOCAL USHORT el3c90xCsrReadWord
  1802.     (
  1803.     EL3C90X_DEVICE *  pDrvCtrl, /* device control structure */
  1804.     USHORT reg, /* register offset */
  1805.     int window /* window number */
  1806.     )
  1807.     {
  1808.     USHORT inWord;
  1809.     if (window != NONE)
  1810.         {
  1811.         /* disable interrupts to prevent race conditions */
  1812.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1813.                        EL_CMD_INTR_ENB);
  1814.         /* set the window */
  1815. SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1816.                                   EL_CMD_WINSEL | window);
  1817.         /* set the register */
  1818.         SYS_IN_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), inWord);
  1819.         /* reenable interrupts */
  1820.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1821.                        (EL_CMD_INTR_ENB | EL_INTRS));
  1822.         }
  1823.     else
  1824.         SYS_IN_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), inWord);
  1825.     return (inWord);
  1826.     }
  1827. /*******************************************************************************
  1828. *
  1829. * el3c90xCsrReadLong - read a long word from a given window and register
  1830. *
  1831. * This function reads a long word from a given window and register
  1832. *
  1833. * RETURNS: ULONG
  1834. */
  1835. LOCAL ULONG el3c90xCsrReadLong
  1836.     (
  1837.     EL3C90X_DEVICE *  pDrvCtrl, /* device control structure */
  1838.     USHORT reg, /* register offset */
  1839.     int window /* window number */
  1840.     )
  1841.     {
  1842.     ULONG inLong;
  1843.     if (window != NONE)
  1844.         {
  1845.         /* disable interrupts to prevent race conditions */
  1846.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1847.                        EL_CMD_INTR_ENB);
  1848.         /* set the window */
  1849. SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1850.                                   EL_CMD_WINSEL | window);
  1851.         /* set the register */
  1852.         SYS_IN_LONG (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), inLong);
  1853.         /* reenable interrupts */
  1854.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1855.                        (EL_CMD_INTR_ENB | EL_INTRS));
  1856.         }
  1857.     else
  1858.         SYS_IN_LONG (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), inLong);
  1859.     return (inLong);
  1860.     }
  1861. /*******************************************************************************
  1862. *
  1863. * el3c90xCsrWriteByte - write a byte to a given window and register
  1864. *
  1865. * This function writes a byte to a given window and register
  1866. *
  1867. * RETURNS: N/A
  1868. */
  1869. LOCAL void el3c90xCsrWriteByte
  1870.     (
  1871.     EL3C90X_DEVICE *  pDrvCtrl, /* device control structure */
  1872.     USHORT reg, /* register offset */
  1873.     UCHAR outByte, /* byte to be written */
  1874.     int window /* window number */
  1875.     )
  1876.     {
  1877.     if (window != NONE)
  1878.         {
  1879.         /* disable interrupts to prevent race conditions */
  1880.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1881.                        EL_CMD_INTR_ENB);
  1882.         /* set the window */
  1883.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1884.                        EL_CMD_WINSEL | window);
  1885.         /* set the register */
  1886.         SYS_OUT_BYTE (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), outByte);
  1887.         /* reenable interrupts */
  1888.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1889.                        (EL_CMD_INTR_ENB | EL_INTRS));
  1890.         }
  1891.     else
  1892.         SYS_OUT_BYTE (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), outByte);
  1893.     }
  1894. /*******************************************************************************
  1895. *
  1896. * el3c90xCsrWriteWord - write a word to a given window and register
  1897. *
  1898. * This function writes a word to a given window and register
  1899. *
  1900. * RETURNS: N/A
  1901. */
  1902. LOCAL void el3c90xCsrWriteWord
  1903.     (
  1904.     EL3C90X_DEVICE *  pDrvCtrl, /* device control structure */
  1905.     USHORT reg, /* register offset */
  1906.     USHORT outWord, /* word to be written */
  1907.     int window /* window number */
  1908.     )
  1909.     {
  1910.     if (window != NONE)
  1911.         {
  1912.         /* disable interrupts to prevent race conditions */
  1913.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1914.                        EL_CMD_INTR_ENB);
  1915.         /* set the window */
  1916. SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1917.                                   EL_CMD_WINSEL | window);
  1918.         /* set the register */
  1919.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), outWord);
  1920.         /* reenable interrupts */
  1921.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1922.                        (EL_CMD_INTR_ENB | EL_INTRS));
  1923.         }
  1924.     else
  1925.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), outWord);
  1926.     }
  1927. /*******************************************************************************
  1928. *
  1929. * el3c90xCsrWriteLong - write a long to a given window and register
  1930. *
  1931. * This function writes a long to a given window and register
  1932. *
  1933. * RETURNS: N/A
  1934. */
  1935. LOCAL void el3c90xCsrWriteLong
  1936.     (
  1937.     EL3C90X_DEVICE *  pDrvCtrl, /* device control structure */
  1938.     USHORT reg, /* register offset */
  1939.     ULONG outLong, /* long word to be written */
  1940.     int window /* window number */
  1941.     )
  1942.     {
  1943.     if (window != NONE)
  1944.         {
  1945.         /* disable interrupts to prevent race conditions */
  1946.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1947.                        EL_CMD_INTR_ENB);
  1948.         /* set the window */
  1949. SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1950.                        EL_CMD_WINSEL | window);
  1951.         /* set the register */
  1952.         SYS_OUT_LONG (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), outLong);
  1953.         /* reenable interrupts */
  1954.         SYS_OUT_SHORT (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)EL_COMMAND),
  1955.                        (EL_CMD_INTR_ENB | EL_INTRS));
  1956.         }
  1957.     else
  1958.         SYS_OUT_LONG (pDrvCtrl, (pDrvCtrl->devAdrs + (UINT32)reg), outLong);
  1959.     }