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

VxWorks

开发平台:

C/C++

  1.                 }
  2.             else
  3.                 {
  4.         pTbdList = &pDrvCtrl->pTbdList[pDrvCtrl->usedTbdIndex];
  5.         /* free the Mblk or the cluster, whichever is appropriate */
  6.         if ((bdStatus & M8260_FETH_TBD_L) && (pBuf = pTbdList->pBuf))
  7.                     {
  8.                     motFccJobQAdd(pDrvCtrl, (FUNCPTR)motFccTxFreeJob, 
  9.                                   (int) pDrvCtrl, (int) pBuf, pTbdList->info, 
  10.                                   0, 0);
  11.                     /* If motFccJobQueue() isn't on the netJobRing put it on */
  12.                     if (!pDrvCtrl->txJobQState)
  13.                         {
  14.                         pDrvCtrl->txJobQState = TRUE;
  15.                         netJobAdd((FUNCPTR)motFccJobQueue,
  16.                                   (int)pDrvCtrl, 0, 0, 0, 0);
  17.                         }  
  18.             }
  19.         pTbdList->pBuf = NULL;
  20.         pTbdList->info = 0;
  21.         ++pDrvCtrl->cleanTbdNum;
  22.         pDrvCtrl->usedTbdIndex = (pDrvCtrl->usedTbdIndex + 1) % 
  23.                                           (pDrvCtrl->tbdNum);
  24.                 }
  25.             }
  26.         }
  27.     /* notify upper protocols TBDs are available */
  28.     if (pDrvCtrl->txStall && 
  29.         (pDrvCtrl->cleanTbdNum >= pDrvCtrl->unStallThresh))
  30.         {
  31. MOT_FCC_LOG (MOT_FCC_DBG_TX,"Restart mux n",0,0,0,0,0,0);
  32. if (netJobAdd ((FUNCPTR)muxTxRestart,(int)&pDrvCtrl->endObj,
  33.             0,0,0,0) == OK)
  34.             {
  35.     ++pDrvCtrl->Stats->numStallsCleared;
  36.     pDrvCtrl->txStall = FALSE;
  37.     }
  38.         }
  39.     /* handle graceful transmit stop */
  40.     if (status & M8260_FEM_ETH_GRA)
  41.         {
  42.         MOT_FCC_LOG (MOT_FCC_DBG_INT, 
  43.                      "motFccInt: graceful stopn", 0, 0, 0, 0, 0, 0);
  44.         /* signal the Stop task that TX_STOP has happened */
  45.         MOT_FCC_GRA_SEM_GIVE;
  46.         }
  47.     if ((pDrvCtrl->RxBufCount && !pDrvCtrl->rxHandling) || 
  48.         (!pDrvCtrl->RxFree && pDrvCtrl->RxEmpty))
  49.         {
  50.         if (netJobAdd((FUNCPTR)motFccHandleRXFrames,
  51.             (int)pDrvCtrl,0,0,0,0)== OK)
  52.             {
  53.             pDrvCtrl->rxHandling = 1 ;
  54.                 }
  55.         else 
  56.             {
  57.             logMsg("netJobAdd((FUNCPTR)motFccHandleRXFrames() failed",
  58.                     0,0,0,0,0,0);
  59.             }        
  60.         }
  61.     ++pDrvCtrl->Stats->numIsrExits;
  62.     }
  63. /******************************************************************************
  64. *
  65. * motFccPhyLSCInt - 
  66. *
  67. *
  68. * RETURNS: None
  69. */
  70. LOCAL void motFccPhyLSCInt
  71.     (
  72.     DRV_CTRL *pDrvCtrl
  73.     )
  74.     {
  75.     /* if no link status change job is pending */
  76.     if(!pDrvCtrl->lscHandling)
  77. {
  78. /* and the BSP has supplied a duplex mode function */
  79. if(_func_motFccPhyDuplex)
  80.     {
  81.             if(!netJobAdd((FUNCPTR)motFccHandleLSCJob,(int)pDrvCtrl,0,0,0,0))
  82. {
  83. pDrvCtrl->lscHandling = 1;
  84. }
  85.     }
  86. else
  87.     {    
  88.     /* 
  89.      * If the BSP didn't supply a FUNC for getting duplex mode
  90.      * there's no reason to schedule the link status change job.
  91.      */
  92.     }
  93.         }
  94.     }
  95. /******************************************************************************
  96. *
  97. * motFccPktTransmit - transmit a packet
  98. *
  99. * This routine transmits the packet described by the given parameters
  100. * over the network, without copying the mBlk to a driver buffer. 
  101. * It also updates statistics.
  102. *
  103. * RETURNS: OK, or ERROR if no resources were available.
  104. */
  105. LOCAL STATUS motFccPktTransmit
  106.     (
  107.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  108.     M_BLK *  pMblk,          /* pointer to the mBlk */
  109.     UINT8  fragNum, /* number of fragments */
  110.     UINT16  pktType /* packet type */
  111.     )
  112.     {
  113.     int   intLevel;   /* current intr level */
  114.     int   bufLen;   /* length of this fragment */
  115.     char   *pBuf;   /* pointer to data to be sent */
  116.     FCC_BD   *pTbd = NULL, *pFirst;  /* pointer to the current ready TBD */
  117.     FCC_TBD_LIST  *pTbdList = NULL;       /* pointer to the TBD list*/
  118.     M_BLK   *pCurr;   /* holder for the current mBlk */
  119.     UINT16   status;
  120.     int   workIx;
  121.     MOT_FCC_LOG(MOT_FCC_DBG_TX,"motFccPktTransmit...n",1,2,3,4,5,6);
  122.     ++pDrvCtrl->Stats->numZcopySends;
  123.     pFirst = &pDrvCtrl->tbdBase[pDrvCtrl->tbdIndex];
  124.     status = 0;
  125.     pCurr = pMblk;
  126.     workIx = pDrvCtrl->tbdIndex;
  127.     while (pCurr)
  128.         {
  129.   /* for each mBlk fragment, set up a BD */
  130. pTbd = &pDrvCtrl->tbdBase[workIx];
  131. pTbdList = &pDrvCtrl->pTbdList[workIx];
  132. pTbdList->pBuf = 0; /* clear the BD 'list' array */
  133. pTbdList->info = 0; /* as we go through 'real' BDs */
  134. pTbd->bdAddr = (ULONG)pBuf = pCurr->mBlkHdr.mData;
  135. pTbd->bdLen = bufLen = pCurr->mBlkHdr.mLen;
  136. if (workIx == (pDrvCtrl->tbdNum - 1))
  137.             {
  138.     pTbd->word1 = status | M8260_FETH_TBD_W;
  139.     }
  140.         else
  141.             {
  142.     pTbd->word1 = status;
  143.     }
  144. MOT_FCC_CACHE_FLUSH(pBuf, bufLen); /* flush cache, if necessary */
  145.         /* bump the working BD index */
  146. workIx = (workIx + 1) % pDrvCtrl->tbdNum;
  147. pCurr = (M_BLK *)pCurr->mBlkHdr.mNext;
  148. if(!status)         
  149.             {
  150.             /* OR in the READY bit for rest of BDs */
  151.             status |= M8260_FETH_TBD_R;
  152.             }
  153.         }
  154.     /*
  155.      * we exited the above loop with pTbd pointing at the last BD 
  156.      * of the frame, pFirst pointing at the first BD of the frame,
  157.      * and pTbdList pointing at the BD list element corresponding to
  158.      * the last BD for this frame. pTbd and pFirst will be the same
  159.      * when there is only one fragment in the mBlk chain.
  160.      */
  161.     intLevel = intLock();
  162.     /* only the BD list element corresponding to the final 'real' BD */
  163.     /* (the last in a frame) gets any info -- all the others are cleared. */
  164.     /* store the Mblk pointer */
  165.     pTbdList->pBuf = pMblk;
  166.     /* so we know what to free in ISR */
  167.     pTbdList->info = (pktType | BUF_TYPE_MBLK);
  168.     /* keep accurate count of clean BDs */
  169.     pDrvCtrl->cleanTbdNum -= fragNum;
  170.     /* only update index while interrupts are disabled */
  171.     pDrvCtrl->tbdIndex = workIx;
  172.     pTbd->word1 |=
  173. ( M8260_FETH_TBD_R
  174. | M8260_FETH_TBD_L
  175. | M8260_FETH_TBD_TC
  176. | M8260_FETH_TBD_I
  177. | M8260_FETH_TBD_PAD
  178. );
  179.     if(pTbd != pFirst)
  180.         {
  181. /*
  182.  * if pTbd == pFirst, there is only one BD and we just
  183.  * set its READY bit --  it must not be set twice.
  184.  */
  185. pFirst->word1 |= M8260_FETH_TBD_R;
  186.         }
  187.     intUnlock (intLevel);
  188.     CACHE_PIPE_FLUSH (); /* Flush the write pipe */
  189.     return OK;
  190.     }
  191. /******************************************************************************
  192. *
  193. * motFccPktCopyTransmit - copy and transmit a packet
  194. *
  195. * This routine transmits the packet described by the given parameters
  196. * over the network, after copying the mBlk to the driver's buffer. 
  197. * It also updates statistics.
  198. *
  199. * RETURNS: OK, or END_ERR_BLOCK if no resources were available.
  200. */
  201. LOCAL STATUS motFccPktCopyTransmit
  202.     (
  203.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  204.     M_BLK *  pMblk,          /* pointer to the mBlk */
  205.     UINT16  pktType /* packet type */
  206.     )
  207.     {
  208.     int   intLevel; /* current intr level */
  209.     int   len; /* length of data to be sent */
  210.     char   *pBuf; /* pointer to data to be sent */
  211.     FCC_BD   *pTbd; /* pointer to the current ready TBD */
  212.     FCC_TBD_LIST*  pTbdList; /* pointer to the TBD list*/
  213.     MOT_FCC_LOG (MOT_FCC_DBG_TX, "motFccPktCopyTransmit...n", 
  214.                  1, 2, 3, 4, 5, 6);
  215.     pTbd = &pDrvCtrl->tbdBase[pDrvCtrl->tbdIndex];
  216.     pTbdList = &pDrvCtrl->pTbdList[pDrvCtrl->tbdIndex];
  217.     if(!(pBuf = NET_BUF_ALLOC()))
  218.         {
  219. return END_ERR_BLOCK;
  220.         }
  221.     ++pDrvCtrl->Stats->numNonZcopySends;
  222.     /* copy data and free the Mblk */
  223.     len = netMblkToBufCopy(pMblk,pBuf,NULL);
  224.     netMblkClChainFree(pMblk);
  225.     /* flush the cache, if necessary */
  226.     MOT_FCC_CACHE_FLUSH(pBuf,len);
  227.     pTbd->bdLen = len;
  228.     pTbd->bdAddr = (unsigned long)pBuf;
  229.     pTbdList->pBuf = pBuf; /* store the Cluster pointer */
  230.     pTbdList->info = (pktType | BUF_TYPE_CL); /* what to free in ISR */
  231.     intLevel = intLock();
  232.     pDrvCtrl->cleanTbdNum -= 1; /* keep accurate count of clean BDs */
  233.     if (pDrvCtrl->tbdIndex == (pDrvCtrl->tbdNum - 1))
  234.         {
  235. pTbd->word1 =
  236. ( M8260_FETH_TBD_R
  237. | M8260_FETH_TBD_L
  238. | M8260_FETH_TBD_TC
  239. | M8260_FETH_TBD_I
  240. | M8260_FETH_TBD_W
  241. | M8260_FETH_TBD_PAD
  242. );
  243.         }
  244.     else
  245.         {
  246. pTbd->word1 =
  247. ( M8260_FETH_TBD_R
  248. | M8260_FETH_TBD_L
  249. | M8260_FETH_TBD_TC
  250. | M8260_FETH_TBD_I
  251. | M8260_FETH_TBD_PAD
  252. );
  253.         }
  254.     /* move on to the next element */
  255.     pDrvCtrl->tbdIndex = (pDrvCtrl->tbdIndex + 1) % pDrvCtrl->tbdNum;
  256.     intUnlock (intLevel);
  257.     CACHE_PIPE_FLUSH (); /* Flush the write pipe */
  258.     return OK;
  259.     }
  260. /*******************************************************************************
  261. * motFccSend - send an Ethernet packet
  262. *
  263. * This routine() takes a M_BLK_ID and sends off the data in the M_BLK_ID.
  264. * The buffer must already have the addressing information properly installed
  265. * in it. This is done by a higher layer.
  266. *
  267. * muxSend() calls this routine each time it wants to send a packet.
  268. *
  269. * RETURNS: OK, or END_ERR_BLOCK, if no resources are available, or ERROR,
  270. * if the device is currently working in polling mode.
  271. */
  272. LOCAL STATUS motFccSend
  273.     (
  274.     DRV_CTRL *pDrvCtrl, M_BLK *pMblk
  275.     )
  276.     {
  277.     int intLevel; /* current intr level */
  278.     int fragNum = 0; /* number of fragments in this mBlk */
  279.     UINT16 pktType = 0; /* packet type (unicast or multicast) */
  280.     M_BLK *pCurr;
  281.     BOOL zFlag;
  282.     MOT_FCC_LOG (MOT_FCC_DBG_TX, "motFccSend...n", 1, 2, 3, 4, 5, 6);
  283.     END_TX_SEM_TAKE(&pDrvCtrl->endObj, WAIT_FOREVER);
  284.     if (MOT_FCC_FLAG_ISSET(MOT_FCC_POLLING))
  285.         { /* check device mode */
  286.         netMblkClChainFree(pMblk); /* free the given mBlk chain */
  287. END_TX_SEM_GIVE(&pDrvCtrl->endObj);
  288.         errno = EINVAL;
  289.         return ERROR;
  290.         }
  291.     /* check we are not already stalled and have enough resources */
  292.     if (pDrvCtrl->txStall || (pDrvCtrl->cleanTbdNum < (MOT_FCC_TBD_MIN / 2)))
  293.         {
  294. /* the choice of 1/2 min tbds as a stall threshold is arbitrary. */
  295. goto tx_stall_exit;
  296.         }
  297.     if (pMblk->mBlkHdr.mData[0] & (UINT8)0x01)
  298.         {
  299. pktType = PKT_TYPE_MULTI; /* packet type is multicast */
  300.         }
  301.     else
  302.         {
  303. pktType = PKT_TYPE_UNI; /* packet type is unicast */
  304.         }
  305.     fragNum = -1;
  306.     if ((zFlag = pDrvCtrl->zeroBufFlag) )
  307.         {
  308. if ((pCurr = pMblk) != NULL)
  309.             {
  310.     while(pCurr)
  311.                 {
  312. if(pCurr->mBlkHdr.mLen)
  313.                     {
  314.     ++fragNum;
  315.     pCurr = (M_BLK*)pCurr->mBlkHdr.mNext;
  316.     }
  317.                 else
  318.                     {
  319.     fragNum = 1; /* force a copy send */
  320.     zFlag = 0; /* force a copy send */
  321.     break;
  322.     }
  323.         }
  324.     ++fragNum;
  325.     }
  326. if(fragNum <= 0 || fragNum > (pDrvCtrl->tbdNum / 2))
  327.             {
  328.     netMblkClChainFree(pMblk); /* free the given mBlk chain */
  329.     END_ERR_ADD(&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
  330.     END_TX_SEM_GIVE(&pDrvCtrl->endObj);
  331.     return ERROR;
  332.     }
  333.         } 
  334.     else
  335.         {
  336.         fragNum = 1;
  337.         }
  338.     if(zFlag && pDrvCtrl->cleanTbdNum > fragNum)
  339.         {
  340. /* transmit the packet in zero-copy mode */
  341. if(motFccPktTransmit(pDrvCtrl, pMblk, fragNum, pktType) != OK)
  342.             {
  343.     goto tx_stall_exit;
  344.     }
  345.         }
  346.     else
  347.         {
  348. /* transmit the packet in copy mode */
  349. if(motFccPktCopyTransmit(pDrvCtrl, pMblk, pktType) != OK)
  350.             {
  351.     goto tx_stall_exit;
  352.     }
  353.         }
  354.     END_TX_SEM_GIVE(&pDrvCtrl->endObj);
  355.     MOT_FCC_LOG(MOT_FCC_DBG_TX, "motFccSend...Donen", 1, 2, 3, 4, 5, 6);
  356.     return OK;
  357. tx_stall_exit:
  358.     END_ERR_ADD(&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
  359.     intLevel = intLock();
  360.     if(!pDrvCtrl->txStall)
  361.         {
  362. pDrvCtrl->txStall = TRUE;
  363. ++pDrvCtrl->Stats->numStallsEntered;
  364.         }
  365.     intUnlock (intLevel);
  366.     END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  367.     return END_ERR_BLOCK;
  368.     }
  369. /**************************************************************************
  370. *
  371. * motFccTbdInit - initialize the transmit buffer ring
  372. *
  373. * This routine initializes the transmit buffer descriptors ring.
  374. *
  375. * SEE ALSO: motFccRbdInit()
  376. * RETURNS: OK, or ERROR.
  377. */
  378. LOCAL STATUS motFccTbdInit
  379.     (
  380.     DRV_CTRL *pDrvCtrl
  381.     )
  382.     {
  383.     UINT16 ix; /* a counter */
  384.     FCC_BD *pTbd; /* generic TBD pointer */
  385.     /* carve up the shared-memory region */
  386.     pDrvCtrl->tbdBase = pTbd = (FCC_BD *)pDrvCtrl->pBdBase;
  387.     for(ix = 0; ix < pDrvCtrl->tbdNum; ix++)
  388.         {
  389. pTbd->word1 = 0;
  390. ++pTbd;
  391.         }
  392.     /* set the wrap bit in last BD */
  393.     --pTbd;
  394.     pTbd->word1 = M8260_FETH_TBD_W;
  395.     /* get a cluster buffer from the pool */
  396.     pDrvCtrl->pTxPollBuf = NET_BUF_ALLOC();
  397.     if (pDrvCtrl->pTxPollBuf == NULL)
  398. return ERROR;
  399.     return OK;
  400.     }
  401. /******************************************************************************
  402. *
  403. * motFccHandleRXFrames - task-level receive frames processor
  404. *
  405. * This routine is run in netTask's context.
  406. *
  407. * RETURNS: N/A
  408. */
  409. LOCAL void motFccHandleRXFrames
  410.     (
  411.     DRV_CTRL *pDrvCtrl
  412.     )
  413.     {
  414.     UINT16 rbdStatus = 0; /* holder for the status of this rbd */
  415.     BPOOL *bpoolp;
  416.     FCC_BD *pRbd;
  417.     M_BLK *pMblk; /* MBLK to send upstream */
  418.     CL_BLK *pClBlk; /* pointer to clBlk */
  419.     int         len,s;
  420.                  /* A replacement buffer for the current container */
  421.     char *pBuf;
  422.     char *pData; /* Data pointer for the current container */
  423.     void *retVal;
  424.     MOT_FCC_LOG (MOT_FCC_DBG_RX, "motFccHandleRecvInt: n", 0, 0, 0, 0, 0, 0);
  425.     ++pDrvCtrl->Stats->numRXFHandlerEntries;
  426.     /* 
  427.      * empty containers have no buffer associated with them.
  428.      * here, we try to get buffers for as many empties as can.
  429.      */
  430.     while (pDrvCtrl->RxEmpty)
  431.         {
  432. if (!(pBuf = NET_BUF_ALLOC()))
  433.             {
  434.     ++pDrvCtrl->Stats->numRXFHandlerEmptyLoopBreaks;
  435.     break;
  436.     }
  437. /* 
  438.          * since the empty list is only manipulated here in this function,
  439.  * we don't need to lock out interrupts while we remove empties.
  440.  */
  441. bpoolp = pDrvCtrl->RxEmpty;
  442. pDrvCtrl->RxEmpty = bpoolp->next;
  443. bpoolp->pBuf = pBuf;
  444. /* ISR code also manipulates the free list, so do intLock(). */
  445. s = intLock(); /* start critical region */
  446. bpoolp->next = pDrvCtrl->RxFree;
  447. pDrvCtrl->RxFree = bpoolp;
  448. intUnlock(s); /* end critical region */
  449.         }
  450.     pMblk = NULL;
  451.     pClBlk = NULL;
  452.     while (pDrvCtrl->RxBufCount)
  453.         {
  454. if (!pMblk)    
  455.             pMblk  = NET_MBLK_ALLOC();
  456.             
  457. if (!pClBlk)   
  458.             pClBlk = NET_CL_BLK_ALLOC(); 
  459. if (!pMblk || !pClBlk)
  460.             {
  461.     /* If we couldn't obtain the resources to send this packet up
  462.      * the ladder right now, we'll just leave it at the head of the
  463.      * receive linked list and return.
  464.      * If either ptr is not NULL, it will be freed outside this loop.
  465.      */
  466.             /* Tell the mux to give back some clusters */
  467.             pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
  468.             muxError(&pDrvCtrl->endObj, &pDrvCtrl->lastError);
  469.     MOT_FCC_RX_MEM_ADD(pDrvCtrl);
  470.     MOT_FCC_LOG (MOT_FCC_DBG_RX, 
  471.                          "motFccReceive mem problemn", 0, 0, 0, 0, 0, 0);
  472.     ++pDrvCtrl->Stats->numRXFHandlerErrQuits;
  473.     break;
  474.     }
  475. s = intLock(); /* start critical region */
  476. bpoolp = pDrvCtrl->RxHead;
  477. pDrvCtrl->RxHead = bpoolp->next; /* remove BD container from RX chain */
  478. if ( --pDrvCtrl->RxBufCount == 0 )
  479.             {
  480.     pDrvCtrl->RxHead = NULL;
  481.     pDrvCtrl->RxTail = NULL;
  482.     }
  483. intUnlock(s); /* end critical region */
  484. /* 
  485.          * At this point, the container is off the input chain 
  486.  * take what we need out of it and, if the frame is OK, 
  487.          * pass it up to the stack 
  488.          */
  489. ++pDrvCtrl->Stats->numRXFHandlerFramesProcessed;
  490. pRbd = &bpoolp->desc;
  491. /* 
  492.          * Get the original cluster buffer address which we must pass to 
  493.          * NET_CL_BLK_JOIN 
  494.          */
  495. pBuf = bpoolp->pBuf;
  496. /* 
  497.          * get the actual receive buffer address -- the 
  498.          * rounded-up-to-cache-boundary address 
  499.          */
  500. pData = (char*)pRbd->bdAddr;
  501. len = pRbd->bdLen;
  502. rbdStatus = pRbd->word1;
  503. if (rbdStatus & (M8260_FETH_RBD_MC|M8260_FETH_RBD_BC))
  504.             {
  505.     pDrvCtrl->endObj.mib2Tbl.ifInNUcastPkts += 1;
  506.     }
  507.         else
  508.             {
  509.     END_ERR_ADD(&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
  510.     }
  511. /* 
  512.          * Handle errata CPM-21... this code should NOT break the driver
  513.  *  when CPM-21 is ultimately fixed.
  514.  */
  515. if ((rbdStatus & 
  516.             (M8260_FETH_RBD_CL | M8260_FETH_RBD_CR)) == M8260_FETH_RBD_CL)
  517.             {
  518.     rbdStatus &= (UINT16)(~M8260_FETH_RBD_CL);
  519.     }
  520. if(rbdStatus & MOT_FCC_RBD_ERR)
  521.             {
  522.     ++pDrvCtrl->Stats->numRXFHandlerFramesRejected;
  523.     logMsg("RX addr = 0x%x  Len = 0x%x  Stat = 0x%xn",
  524. (unsigned int)pData,len,rbdStatus,0,0,0);
  525.     /* 
  526.              * This container already has a buffer in it, but contains a bad 
  527.              * frame just put it back onto the free chain and we'll re-use 
  528.              * the buffer 
  529.              */
  530.     s = intLock(); /* start critical region */
  531.     /* memset((void*)&bpoolp->desc,0,8); */
  532.     bpoolp->next = pDrvCtrl->RxFree;
  533.     pDrvCtrl->RxFree = bpoolp;
  534.     intUnlock(s); /* end critical region */
  535.     continue; /* go back and process remaining (if any) containers */
  536.     /* 
  537.              * note that pMblk and pClBlk are not NULL and will be used in 
  538.              * next iteration 
  539.              */
  540.     }
  541. NET_CL_BLK_JOIN (pClBlk, pBuf, MOT_FCC_MAX_CL_LEN, retVal);
  542. NET_MBLK_CL_JOIN(pMblk, pClBlk, retVal);
  543. /* 
  544.          * After joining the original cluster address, adjust the M_BLK to 
  545.          * account for alignment 
  546.          */
  547. pMblk->mBlkHdr.mData += ( (unsigned int)pData - (unsigned int)pBuf );
  548. pMblk->mBlkHdr.mFlags  |= M_PKTHDR; /* set the packet header flag */
  549. pMblk->mBlkHdr.mLen     = (len - MII_CRC_LEN) & ~0xc000;    
  550. pMblk->mBlkPktHdr.len   = pMblk->mBlkHdr.mLen;
  551. /* Make cache consistent with memory */
  552. MOT_FCC_CACHE_INVAL(pData, pMblk->mBlkHdr.mLen);
  553.         /* send the frame to the upper layer */
  554. END_RCV_RTN_CALL(&pDrvCtrl->endObj,pMblk);
  555. CACHE_PIPE_FLUSH(); /* Flush the write pipe */
  556. /* at this point, we're done with pMblk and pClBlk -- NULL them out */
  557. pMblk = NULL;
  558. pClBlk = NULL;
  559.         /* Now try to allocate a replacement buffer for the container */
  560. pBuf = NET_BUF_ALLOC();
  561. s = intLock(); /* start critical region */
  562. /* memset((void*)&bpoolp->desc,0,8); */
  563. if ((bpoolp->pBuf = pBuf))
  564.             {
  565.             /* buf_alloc succeeded */
  566.     bpoolp->next = pDrvCtrl->RxFree; /* put container on free list */
  567.     pDrvCtrl->RxFree = bpoolp;
  568.     }
  569.         else
  570.             {
  571.     bpoolp->next = pDrvCtrl->RxEmpty;  /* buf_alloc failed */
  572.     pDrvCtrl->RxEmpty = bpoolp;        /* put container on empty list */
  573.     }
  574.         intUnlock(s); /* end critical region */
  575.         }
  576.     s = intLock(); /* start critical region */
  577.    
  578.     pDrvCtrl->rxHandling = FALSE; 
  579.     ++pDrvCtrl->Stats->numRXFHandlerExits;
  580.     intUnlock(s); /* end critical region */
  581.     /* if the only (or last) frame had an error, these pointers
  582.      * will not have been freed so do it now...
  583.      */
  584.     if(pMblk)
  585.         NET_MBLK_FREE(pMblk);
  586.     if(pClBlk)
  587.         NET_CL_BLK_FREE(pClBlk);
  588.     MOT_FCC_LOG (MOT_FCC_DBG_RX, "motFccHandleRecvInt... Done, n", 
  589.                  0, 0, 0, 0, 0, 0);
  590.     }
  591. /**************************************************************************
  592. *
  593. * motFccRbdInit - initialize the receive buffer ring
  594. *
  595. * This routine initializes the receive buffer descriptors ring.
  596. *
  597. * SEE ALSO: motFccTbdInit()
  598. * RETURNS: OK, or ERROR if not enough clusters were available.
  599. */
  600. LOCAL STATUS motFccRbdInit
  601.     (
  602.     DRV_CTRL *pDrvCtrl
  603.     )
  604.     {
  605.     char *pBuf; /* a rx data pointer */
  606.     FCC_BD *pRbd; /* generic rbd pointer */
  607.     BPOOL *bpoolp;
  608.     void **pRbuf;
  609.     int         ix,nContainers;
  610.     nContainers = pDrvCtrl->rbdNum;
  611. #define EXTRA_CONTAINERS 1
  612. #if EXTRA_CONTAINERS
  613.     nContainers += pDrvCtrl->rbdNum /* / 2 */ ;
  614. #endif
  615.     if (!pDrvCtrl->RxContainers)
  616.         {
  617.         pDrvCtrl->RxContainers = (BPOOL *)calloc(sizeof(BPOOL),nContainers + 1);
  618. pDrvCtrl->RxFree = NULL;
  619. pDrvCtrl->RxEmpty = NULL;
  620. pDrvCtrl->RxHead = NULL;
  621. pDrvCtrl->RxTail = NULL;
  622.         }
  623.     for (ix = 0; ix < nContainers; ix++) 
  624.         {
  625. if (!(pBuf = NET_BUF_ALLOC()))
  626.             {
  627.     logMsg("motFCCRbdInit() need more clustersn",0,0,0,0,0,0);
  628.     return ERROR;
  629.     }
  630. bpoolp = &pDrvCtrl->RxContainers[ix];
  631. bpoolp->pBuf = pBuf;
  632. bpoolp->next = pDrvCtrl->RxFree;
  633. pDrvCtrl->RxFree = bpoolp;
  634.         }
  635.     /* the receive ring is located right after the transmit ring */
  636.     pDrvCtrl->rbdBase = (FCC_BD *) (pDrvCtrl->pBdBase + 
  637.                         (MOT_FCC_TBD_SZ * pDrvCtrl->tbdNum));
  638.     pRbd = pDrvCtrl->rbdBase;
  639.     pRbuf = pDrvCtrl->rBufList;
  640.     for (ix = 0; ix < pDrvCtrl->rbdNum; ix++) 
  641.         {
  642. if (!(pBuf = NET_BUF_ALLOC()))
  643.             {
  644.     logMsg("motFCCRbdInit() need more clustersn",0,0,0,0,0,0);
  645.     return ERROR;
  646.     }
  647. pRbd->bdLen = 0;
  648. *pRbuf = pBuf;
  649. pRbd->bdAddr = ROUND_UP( (unsigned long)pBuf, MOT_FCC_BUF_ALIGN );
  650. pRbd->word1 = (M8260_FETH_RBD_E | M8260_FETH_RBD_I);
  651. ++pRbd;
  652. ++pRbuf;
  653.         }
  654.     --pRbd;
  655.     pRbd->word1 |= M8260_FETH_RBD_W;
  656.     return OK;
  657.     }
  658. /**************************************************************************
  659. *
  660. * motFccBufFree - free the receive and transmit buffers
  661. *
  662. * This routine frees the netpool clusters associated with the receive 
  663. * buffer descriptors ring. It is called by motFccStop(), in order to
  664. * properly release the driver's resources when the device is stopped.
  665. *
  666. * SEE ALSO: motFccStop()
  667. * RETURNS: OK, always.
  668. */
  669. LOCAL STATUS motFccBdFree
  670.     (
  671.     DRV_CTRL *pDrvCtrl
  672.     )
  673.     {
  674.     MOT_FCC_RBD_ID pRbd = NULL; /* generic rbd pointer */
  675.     void *pBuf;
  676.     UINT16 ix; /* a counter */
  677.     pRbd = (MOT_FCC_RBD_ID) (pDrvCtrl->rbdBase);
  678.     for (ix = 0; ix < pDrvCtrl->rbdNum; ix++) 
  679.         {
  680. /* return the cluster buffer to the pool */
  681. if((pBuf = pDrvCtrl->rBufList[ix]))
  682.     NET_BUF_FREE(pBuf);
  683.         }
  684.     /* free lists and clusters */
  685.     for (ix = 0; ix < pDrvCtrl->tbdNum; ix++) 
  686.         {
  687. if((pBuf = pDrvCtrl->pTbdList[ix].pBuf))
  688.             {
  689.     /* free the Mblk or the cluster, whichever is appropriate */
  690.     if(pDrvCtrl->pTbdList[ix].info & BUF_TYPE_MBLK)
  691.                 {
  692. netMblkClChainFree((M_BLK*)pBuf);
  693.         }
  694.             else if(pDrvCtrl->pTbdList[ix].info & BUF_TYPE_CL)
  695.                 {
  696. NET_BUF_FREE(pBuf);
  697.         }
  698.     }
  699. pDrvCtrl->pTbdList[ix].pBuf = NULL;
  700. pDrvCtrl->pTbdList[ix].info = 0;
  701.         }
  702.     /* free the transmit poll buffer */
  703.     if ((pDrvCtrl->pTxPollBuf) != NULL)
  704. NET_BUF_FREE ((UCHAR *) (pDrvCtrl->pTxPollBuf));
  705.     return OK;
  706.     }
  707. /**************************************************************************
  708. *
  709. * motFccInit - initialize the chip 
  710. *
  711. * This routine programs both the internal ram registers and the parameter
  712. * RAM in the DPRAM for Ethernet operation. It calls motFccPramInit () and
  713. * motFccIramInit () to do the job.
  714. *
  715. * SEE ALSO: motFccPramInit (), motFccIramInit ().
  716. * RETURNS: OK, or ERROR.
  717. */
  718. LOCAL STATUS motFccInit
  719.     (
  720.     DRV_CTRL *pDrvCtrl
  721.     )
  722.     {
  723.     /* initialize the parameter RAM for Ethernet operation */
  724.     if (motFccPramInit (pDrvCtrl) != OK)
  725. return ERROR;
  726.     /* initialize the internal RAM for Ethernet operation */
  727.     if (motFccIramInit (pDrvCtrl) != OK)
  728. return ERROR;
  729.     return OK;
  730.     }
  731. /**************************************************************************
  732. *
  733. * motFccPramInit - initialize the parameter RAM for this FCC
  734. *
  735. * This routine programs the parameter ram registers for this FCC and set it
  736. * to work for Ethernet operation. It follows the initialization sequence 
  737. * recommended in the MPC8260 PowerQuicc II User's Manual.
  738. *
  739. * SEE ALSO: motFccIramInit (), motFccInit ().
  740. * RETURNS: OK, always.
  741. */
  742. LOCAL STATUS motFccPramInit
  743.     (
  744.     DRV_CTRL *pDrvCtrl
  745.     )
  746.     {
  747.     UINT32     fcrVal;
  748.     FCC_PARAM_T     *pParam;
  749.     FCC_ETH_PARAM_T *pEthPar;
  750.     /* get to the beginning of the parameter area */
  751.     pParam = pDrvCtrl->fccPar;
  752.     pEthPar = pDrvCtrl->fccEthPar;
  753.     memset(pParam,0,sizeof(*pParam));
  754.     /* figure out the value for the FCR registers */
  755.     fcrVal = MOT_FCC_FCR_DEF_VAL;
  756.     if (MOT_FCC_USR_FLAG_ISSET (MOT_FCC_USR_BD_LBUS))
  757.         {
  758. fcrVal |= M8260_FCR_BDB;
  759.         }
  760.     if (MOT_FCC_USR_FLAG_ISSET (MOT_FCC_USR_BUF_LBUS))
  761.         {
  762. fcrVal |= M8260_FCR_DTB;
  763.         }
  764.     fcrVal <<= M8260_FCR_SHIFT;
  765.     /* Allocate DPRAM memory for the riptr & tiptr */
  766.     if (MOT_FCC_USR_FLAG_ISSET(MOT_FCC_USR_DPRAM_ALOC))
  767. {
  768. /* Use auto allocation */
  769.         /* Test that function pointers are populated. */
  770.         if (_func_m82xxDpramFccMalloc == NULL || _func_m82xxDpramFree == NULL ||
  771.             _func_m82xxDpramFccFree == NULL )
  772.             {
  773.             return ERROR;
  774.             }
  775.         else
  776.             {
  777.     if ((pParam->riptr = (0xffff & 
  778.                                  (ULONG)_func_m82xxDpramFccMalloc(32,32))) == 0)
  779.                 {
  780.         return ERROR;
  781.                 }    
  782.     if ((pParam->tiptr = (0xffff & 
  783.                                  (ULONG)_func_m82xxDpramFccMalloc(32,32))) == 0)
  784.                 {
  785.         return ERROR;
  786.                 }
  787.             } 
  788. }
  789. else
  790. {
  791. /* Use hardcoded allocation */
  792.         pParam->riptr = MOT_FCC_RIPTR_VAL;
  793.         pParam->tiptr = MOT_FCC_TIPTR_VAL;
  794. }
  795.     pParam->mrblr = 1536; /* MII_ETH_MAX_PCK_SZ; */
  796.     pParam->rstate = fcrVal;
  797.     pParam->rbase = (unsigned long)pDrvCtrl->rbdBase;
  798.     pParam->tstate = fcrVal;
  799.     pParam->tbase = (unsigned long)pDrvCtrl->tbdBase;
  800.     pEthPar->c_mask = MOT_FCC_C_MASK_VAL;
  801.     pEthPar->c_pres = MOT_FCC_C_PRES_VAL;
  802.     pEthPar->ret_lim = /* 4 */ MOT_FCC_RET_LIM_VAL;
  803.     pEthPar->maxflr = MII_ETH_MAX_PCK_SZ;
  804.     pEthPar->minflr = MOT_FCC_MINFLR_VAL;
  805.     pEthPar->maxd1 = MOT_FCC_MAXD_VAL;
  806.     pEthPar->maxd2 = MOT_FCC_MAXD_VAL;
  807.     pEthPar->pad_ptr = MOT_FCC_PAD_VAL;
  808.     /* program the individual physical address */
  809.     if (motFccAddrSet (pDrvCtrl, (UCHAR *) MOT_FCC_ADDR_GET (&pDrvCtrl->endObj),
  810.                        M8260_FCC_PADDR_H_OFF) != OK)
  811.         {
  812. return ERROR;
  813.         }
  814.     CACHE_PIPE_FLUSH (); /* Flush the write pipe */
  815.     return OK;
  816.     }
  817. /**************************************************************************
  818. *
  819. * motFccIramInit - initialize the internal RAM for this FCC
  820. *
  821. * This routine programs the internal ram registers for this FCC and set it
  822. * to work for Ethernet operation. It follows the initialization sequence 
  823. * recommended in the MPC8260 PowerQuicc II User's Manual. It also issues
  824. * a rx/tx init command to the CP.
  825. *
  826. * SEE ALSO: motFccPramInit (), motFccInit ().
  827. * RETURNS: OK, always.
  828. */
  829. LOCAL STATUS motFccIramInit 
  830.     (
  831.     DRV_CTRL *pDrvCtrl
  832.     )
  833.     {
  834.     UINT32 fccIramAddr = 0; /* a convenience */
  835.     UINT8 command = 0; /* command to issue to the CP */
  836.     fccIramAddr = pDrvCtrl->fccIramAddr;
  837.     /* 
  838.      * program the GSMR, but enable neither the transmitter
  839.      * nor the receiver for now.
  840.      */
  841. #ifdef INCLUDE_GFMR_TCI
  842.     MOT_FCC_REG_LONG_WR (fccIramAddr + M8260_FCC_GFMR_OFF,
  843.  (M8260_GFMR_ETHERNET | M8260_GFMR_NORM
  844.   | M8260_GFMR_RENC_NRZ | M8260_GFMR_TCI));
  845. #else
  846.     /* Leave TCI low to correct problem in 100Base-TX mode */
  847.     MOT_FCC_REG_LONG_WR (fccIramAddr + M8260_FCC_GFMR_OFF,
  848.  (M8260_GFMR_ETHERNET | M8260_GFMR_NORM
  849.   | M8260_GFMR_RENC_NRZ));
  850. #endif
  851.     /* program the DSR */
  852.     MOT_FCC_REG_WORD_WR (fccIramAddr + M8260_FCC_FDSR_OFF, MOT_FCC_DSR_VAL);
  853.     /* zero-out the TODR for the sake of clarity */
  854.     MOT_FCC_REG_WORD_WR (fccIramAddr + M8260_FCC_FTODR_OFF, MOT_FCC_CLEAR_VAL);
  855.     /* the value for the FPSMR */
  856.     if (motFccFpsmrValSet (pDrvCtrl) != OK)
  857. return ERROR;
  858.     /* 
  859.      * we enable the following event interrupts:
  860.      * graceful transmit command;
  861.      * tx error;
  862.      * rx frame;
  863.      * busy condition;
  864.      * tx buffer, although we'll only enable the last TBD in a frame
  865.      * to generate interrupts. See motFccSend ();
  866.      */
  867.     pDrvCtrl->intMask = (M8260_FEM_ETH_GRA | M8260_FEM_ETH_TXE
  868. | M8260_FEM_ETH_RXF | M8260_FEM_ETH_BSY
  869. | M8260_FEM_ETH_TXB);
  870.     MOT_FCC_REG_WORD_WR (fccIramAddr + M8260_FCC_FCCMR_OFF, 
  871.                          (pDrvCtrl->intMask));
  872.     /* clear all events */
  873.     MOT_FCC_REG_WORD_WR (fccIramAddr + M8260_FCC_FCCER_OFF, MOT_FCC_FCCE_VAL);
  874.     /* issue a init rx/tx command to the CP */
  875.     command = M8260_CPCR_RT_INIT;
  876.     return motFccCpcrCommand (pDrvCtrl, command);
  877.     }
  878. /**************************************************************************
  879. *
  880. * motFccAddrSet - set an address to some internal register
  881. *
  882. * This routine writes the address pointed to by <pAddr> to some FCC's internal 
  883. * register. It may be used to set the individual physical address, or
  884. * an address to be added to the hash table filter. It assumes that <offset>
  885. * is the offset in the parameter RAM to the highest-order halfword that
  886. * will contain the address.
  887. * RETURNS: OK, always.
  888. */
  889. LOCAL STATUS motFccAddrSet
  890.     (
  891.     DRV_CTRL *  pDrvCtrl, /* pointer to DRV_CTRL structure */
  892.     UCHAR * pAddr, /* address to write to register */
  893.     UINT32 offset /* offset to highest-word in register */
  894.     )
  895.     {
  896.     UINT16 word; /* a convenience */
  897.     UINT32 fccPramAddr = 0; /* a convenience */
  898.     /* get to the beginning of the parameter area */
  899.     fccPramAddr = pDrvCtrl->fccPramAddr;
  900.     word = (((UINT16) (pAddr [5])) << 8) | (pAddr [4]);
  901.     MOT_FCC_REG_WORD_WR (fccPramAddr + offset, 
  902.  word);
  903.     word = (((UINT16) (pAddr [3])) << 8) | (pAddr [2]);
  904.     MOT_FCC_REG_WORD_WR (fccPramAddr + offset + 2, 
  905.  word);
  906.     word = (((UINT16) (pAddr [1])) << 8) | (pAddr [0]);
  907.     MOT_FCC_REG_WORD_WR (fccPramAddr + offset + 4, 
  908.  word);
  909.     return (OK);
  910.     }
  911. /**************************************************************************
  912. *
  913. * motFccFpsmrValSet - set the proper value for the FPSMR
  914. *
  915. * This routine finds out the proper value to be programmed in the
  916. * FPSMR register by looking at some of the user/driver flags. It deals
  917. * with options like promiscous mode, full duplex, loopback mode, RMON
  918. * mode, and heartbeat control. It then writes to the FPSMR.
  919. *
  920. * SEE ALSO: motFccIramInit (), motFccInit ()
  921. * RETURNS: OK, always.
  922. */
  923. LOCAL STATUS motFccFpsmrValSet
  924.     (
  925.     DRV_CTRL *pDrvCtrl
  926.     )
  927.     {
  928.     UINT32 fpsmrVal = 0; /* a convenience */
  929.     UINT32 fccIramAddr = 0; /* a convenience */
  930.     /* get to the beginning of the internal memory for this FCC */
  931.     fccIramAddr = pDrvCtrl->fccIramAddr;
  932.     /* use the standard CCITT CRC */
  933.     fpsmrVal |= M8260_FPSMR_ETH_CRC_32;
  934.     /* set the heartbeat check if the user wants it */
  935.     if (MOT_FCC_USR_FLAG_ISSET (MOT_FCC_USR_HBC)) 
  936.         {
  937. fpsmrVal |= M8260_FPSMR_ETH_HBC;
  938. MOT_FCC_LOG (MOT_FCC_DBG_START, 
  939.                      ("motFccFpsmrValSet: heartbeat control n"), 
  940.                      0, 0, 0, 0, 0, 0);
  941.         } 
  942.     else
  943.         {
  944. fpsmrVal &= ~M8260_FPSMR_ETH_HBC;
  945.         }
  946.     /* set RMON mode if the user requests it */
  947.     if (MOT_FCC_USR_FLAG_ISSET (MOT_FCC_USR_RMON)) 
  948.         {
  949. fpsmrVal |= M8260_FPSMR_ETH_MON;
  950. MOT_FCC_LOG (MOT_FCC_DBG_START, 
  951.                      ("motFccFpsmrValSet: heartbeat control n"), 
  952.                      0, 0, 0, 0, 0, 0);
  953.         }
  954.     else
  955.         {
  956. fpsmrVal &= ~M8260_FPSMR_ETH_MON;
  957.         }
  958.     /* deal with promiscous mode */
  959.     if (MOT_FCC_FLAG_ISSET (MOT_FCC_PROM)) 
  960.         {
  961. fpsmrVal |= M8260_FPSMR_ETH_PRO;
  962. MOT_FCC_LOG (MOT_FCC_DBG_START, 
  963.                      ("motFccFpsmrValSet: promiscous mode n"), 
  964.                      0, 0, 0, 0, 0, 0);
  965.         }
  966.     else
  967.         {
  968. fpsmrVal &= ~M8260_FPSMR_ETH_PRO;
  969.         }
  970.     /* 
  971.      * Handle user's diddling with LPB first. That way, if we must 
  972.      * set LPB due to FD it will stick. 
  973.      */
  974.     /* 
  975.      * If the user wishes to go in external loopback mode,
  976.      * enable it. Do not enable internal loopback mode.
  977.      */
  978.     if (MOT_FCC_USR_FLAG_ISSET (MOT_FCC_USR_LOOP)) 
  979.         {
  980. fpsmrVal |= M8260_FPSMR_ETH_LPB;
  981. MOT_FCC_LOG (MOT_FCC_DBG_START, 
  982.                      ("motFccFpsmrValSet: loopback mode n"), 0, 0, 0, 0, 0, 0);
  983.         }
  984.     else
  985.         {
  986. fpsmrVal &= ~M8260_FPSMR_ETH_LPB;
  987.         }
  988.     /* 
  989.      * Enable full duplex mode if the PHY was configured to work in 
  990.      * full duplex mode. 
  991.      */
  992.     if (MOT_FCC_PHY_FLAGS_ISSET (MII_PHY_FD)) 
  993.         {
  994. fpsmrVal |= (M8260_FPSMR_ETH_LPB | M8260_FPSMR_ETH_FDE);
  995. MOT_FCC_LOG (MOT_FCC_DBG_START, 
  996.                      ("motFccFpsmrValSet: full duplex n"), 0, 0, 0, 0, 0, 0);
  997.         }
  998.     else
  999.         {
  1000. fpsmrVal &= ~M8260_FPSMR_ETH_FDE;
  1001.         }
  1002.     MOT_FCC_REG_LONG_WR (fccIramAddr + M8260_FCC_FPSMR_OFF, fpsmrVal);
  1003.     return OK;
  1004.     }
  1005. /*******************************************************************************
  1006. * motFccIoctl - interface ioctl procedure
  1007. *
  1008. * Process an interface ioctl request.
  1009. *
  1010. * RETURNS: OK, or ERROR.
  1011. */
  1012. LOCAL int motFccIoctl
  1013.     (
  1014.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1015.     int         cmd, /* command to process */
  1016.     caddr_t     data            /* pointer to data */
  1017.     )
  1018.     {
  1019.     int         error = OK;
  1020.     INT8        savedFlags;
  1021.     long        value;
  1022.     END_OBJ *   pEndObj=&pDrvCtrl->endObj;
  1023.     MOT_FCC_LOG (MOT_FCC_DBG_IOCTL,
  1024.  ("Ioctl unit=0x%x cmd=%d data=0x%xn"),
  1025.  pDrvCtrl->unit, cmd, (int)data, 0, 0, 0);
  1026.     switch (cmd)
  1027.         {
  1028.         case EIOCSADDR:
  1029.             if (data == NULL)
  1030.                 error = EINVAL;
  1031.             else
  1032.                 {
  1033.                 /* Copy and install the new address */
  1034. bcopy ((char *) data,
  1035.        (char *) MOT_FCC_ADDR_GET (&pDrvCtrl->endObj),
  1036.        MOT_FCC_ADDR_LEN_GET (&pDrvCtrl->endObj));
  1037. /* stop the FCC */
  1038. if (motFccStop (pDrvCtrl) != OK)
  1039.     return (ERROR);
  1040. /* program the individual enet address */
  1041. if (motFccAddrSet (pDrvCtrl, (UCHAR *) data, 
  1042.    M8260_FCC_PADDR_H_OFF) 
  1043.     != OK)
  1044.     return (ERROR);
  1045. /* restart the FCC */
  1046. if (motFccStart (pDrvCtrl) != OK)
  1047.     return (ERROR);
  1048.                 }
  1049.             break;
  1050.         case EIOCGADDR:                      
  1051.             if (data == NULL)
  1052.                 error = EINVAL;
  1053.             else
  1054. bcopy ((char *) MOT_FCC_ADDR_GET (&pDrvCtrl->endObj),
  1055.        (char *) data,
  1056.        MOT_FCC_ADDR_LEN_GET (&pDrvCtrl->endObj));
  1057.             break;
  1058.         case EIOCSFLAGS:
  1059.             value = (long) data;
  1060.             if (value < 0)
  1061.                 {
  1062.                 value = -value;
  1063.                 value--;
  1064.                 END_FLAGS_CLR (pEndObj, value);
  1065.                 }
  1066.             else
  1067.                 END_FLAGS_SET (pEndObj, value);
  1068.             MOT_FCC_LOG (MOT_FCC_DBG_IOCTL, ("endFlags=0x%x n"),
  1069.      END_FLAGS_GET(pEndObj), 
  1070.      0, 0, 0, 0, 0);
  1071.             /* handle IFF_PROMISC */
  1072.             savedFlags = MOT_FCC_FLAG_GET();
  1073.             if (END_FLAGS_ISSET (IFF_PROMISC))
  1074. {
  1075.                 MOT_FCC_FLAG_SET (MOT_FCC_PROM);
  1076. if ((MOT_FCC_FLAG_GET () != savedFlags) &&
  1077.     (END_FLAGS_GET (pEndObj) & IFF_UP))
  1078.     {
  1079.     /* config down */
  1080.     END_FLAGS_CLR (pEndObj, IFF_UP | IFF_RUNNING); 
  1081.     /* program the FPSMR to promiscous mode */
  1082.     if (motFccFpsmrValSet (pDrvCtrl) == ERROR)
  1083. return (ERROR);
  1084.     /* config up */
  1085.     END_FLAGS_SET (pEndObj, IFF_UP | IFF_RUNNING); 
  1086.     }
  1087. }
  1088.             else
  1089.                 MOT_FCC_FLAG_CLEAR (MOT_FCC_PROM);
  1090.             MOT_FCC_LOG (MOT_FCC_DBG_IOCTL, ("EIOCSFLAGS: 0x%x: 0x%xn"),
  1091.      pEndObj->flags, savedFlags, 
  1092.      0, 0, 0, 0);
  1093.             break;
  1094.         case EIOCGFLAGS:
  1095.             MOT_FCC_LOG (MOT_FCC_DBG_IOCTL, ("EIOCGFLAGS: 0x%x: 0x%xn"),
  1096.     pEndObj->flags, *(long *)data, 
  1097.     0, 0, 0, 0);
  1098.             if (data == NULL)
  1099.                 error = EINVAL;
  1100.             else
  1101.                 *(long *)data = END_FLAGS_GET(pEndObj);
  1102.             break;
  1103.         case EIOCMULTIADD:
  1104.             error = motFccMCastAddrAdd (pDrvCtrl, (UCHAR *) data);
  1105.             break;
  1106.         case EIOCMULTIDEL:
  1107.             error = motFccMCastAddrDel (pDrvCtrl, (UCHAR *) data);
  1108.             break;
  1109.         case EIOCMULTIGET:
  1110.             error = motFccMCastAddrGet (pDrvCtrl, (MULTI_TABLE *) data);
  1111.             break;
  1112.         case EIOCPOLLSTART:
  1113.     MOT_FCC_LOG (MOT_FCC_DBG_POLL, ("IOCTL call motFccPollStartn"), 
  1114.     0, 0, 0, 0, 0, 0);
  1115.             motFccPollStart (pDrvCtrl);
  1116.             break;
  1117.         case EIOCPOLLSTOP:
  1118.     MOT_FCC_LOG (MOT_FCC_DBG_POLL, ("IOCTL call motFccPollStopn"), 
  1119.     0, 0, 0, 0, 0, 0);
  1120.             motFccPollStop (pDrvCtrl);
  1121.             break;
  1122.         case EIOCGMIB2:  
  1123.             if (data == NULL)
  1124.                 error=EINVAL;
  1125.             else
  1126. bcopy ((char *) &pEndObj->mib2Tbl, (char *) data,
  1127. sizeof (pEndObj->mib2Tbl));
  1128.             break;
  1129.         default:
  1130.             MOT_FCC_LOG (MOT_FCC_DBG_IOCTL, ("INVALID IO COMMAND!! n"),
  1131.      0, 0, 0, 0, 0, 0);
  1132.             error = EINVAL;
  1133.         }
  1134.     return (error);
  1135.     }
  1136. /**************************************************************************
  1137. *
  1138. * motFccCpcrCommand - issue a command to the CP
  1139. *
  1140. * This routine issues the command specified in <command> to the Communication
  1141. * Processor (CP).
  1142. *
  1143. * RETURNS: OK, or ERROR if the command was unsuccessful.
  1144. *
  1145. */
  1146. LOCAL STATUS motFccCpcrCommand
  1147.     (
  1148.     DRV_CTRL *pDrvCtrl, UINT8 command
  1149.     )
  1150.     {
  1151.     UINT32     immrVal = pDrvCtrl->immrVal; /* holder for the immr value */
  1152.     volatile UINT32 cpcrVal = 0;  /* a convenience */
  1153.     UINT32     ix = 0;                  /* a counter */
  1154.     UINT8     fccNum = pDrvCtrl->fccNum;  /* holder for the fcc number */
  1155.     UINT8     fcc = fccNum - 1;  /* a convenience */
  1156.     /* wait until the CP is clear */
  1157.     do {
  1158. MOT_FCC_REG_LONG_RD (M8260_CPCR (immrVal), cpcrVal);
  1159. if (ix++ == M8260_CPCR_LATENCY)
  1160.     break;
  1161.     } while (cpcrVal & M8260_CPCR_FLG);
  1162.     if (ix >= M8260_CPCR_LATENCY) 
  1163.         {
  1164.         MOT_FCC_LOG (MOT_FCC_DBG_ANY, 
  1165.                      "motFccCpcrCommand: cpcr problem n", 0, 0, 0, 0, 0, 0);
  1166. return ERROR;
  1167.         }
  1168.     /* issue the command to the CP */
  1169.     cpcrVal = (M8260_CPCR_OP (command)
  1170.        | M8260_CPCR_SBC (M8260_CPCR_SBC_FCC1 | (fcc * 0x1))
  1171.        | M8260_CPCR_PAGE (M8260_CPCR_PAGE_FCC1 | (fcc * 0x1))
  1172.        | M8260_CPCR_MCN (M8260_CPCR_MCN_ETH)
  1173.        | M8260_CPCR_FLG);
  1174.     MOT_FCC_LOG (MOT_FCC_DBG_START, 
  1175.                  "motFccCpcrCommand: cpcr=0x%x n", cpcrVal, 0, 0, 0, 0, 0);
  1176.     MOT_FCC_REG_LONG_WR (M8260_CPCR (immrVal), cpcrVal);
  1177.     CACHE_PIPE_FLUSH (); /* Flush the write pipe */
  1178.     /* wait until the CP is clear */
  1179.     ix = 0;
  1180.     do {
  1181. MOT_FCC_REG_LONG_RD (M8260_CPCR (immrVal), cpcrVal);
  1182. if (ix++ == M8260_CPCR_LATENCY)
  1183.     break;
  1184.     } while (cpcrVal & M8260_CPCR_FLG) ;
  1185.     if (ix >= M8260_CPCR_LATENCY) 
  1186.         {
  1187. MOT_FCC_LOG (MOT_FCC_DBG_ANY, 
  1188.                      "motFccCpcrCommand: cpcr problem n", 0, 0, 0, 0, 0, 0);
  1189. return ERROR;
  1190.         }
  1191.     MOT_FCC_LOG (MOT_FCC_DBG_START, 
  1192.                  "motFccCpcrCommand: done n", 0, 0, 0, 0, 0, 0);
  1193.     return OK;
  1194.     }
  1195. /**************************************************************************
  1196. *
  1197. * motFccMiiRead - read the MII interface
  1198. *
  1199. * This routine reads the register specified by <phyReg> in the PHY device
  1200. * whose address is <phyAddr>. The value read is returned in the location
  1201. * pointed to by <miiData>.
  1202. *
  1203. * SEE ALSO: motFccMiiWrite()
  1204. * RETURNS: OK, or ERROR.
  1205. *
  1206. */
  1207. LOCAL STATUS motFccMiiRead
  1208.     (
  1209.     DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */
  1210.     UINT8 phyAddr, /* the PHY being read */
  1211.     UINT8 regAddr, /* the PHY's register being read */
  1212.     UINT16 * miiData /* value read from the MII interface */
  1213.     )
  1214.     {
  1215.     UINT16  temp = 0; /* temporary variable */
  1216.     /* write the preamble pattern first */
  1217.     MOT_FCC_MII_WR (MII_MF_PREAMBLE, MII_MF_PREAMBLE_LEN);
  1218.     /* write the start of frame */
  1219.     MOT_FCC_MII_WR (MII_MF_ST, MII_MF_ST_LEN);
  1220.     /* write the operation code */
  1221.     MOT_FCC_MII_WR (MII_MF_OP_RD, MII_MF_OP_LEN);
  1222.     /* write the PHY address */
  1223.     MOT_FCC_MII_WR (phyAddr, MII_MF_ADDR_LEN);
  1224.     /* write the PHY register */
  1225.     MOT_FCC_MII_WR (regAddr, MII_MF_REG_LEN);
  1226.     /* write the turnaround pattern */
  1227.     SYS_FCC_MII_BIT_WR ((INT32) NONE);
  1228.     SYS_FCC_MII_BIT_WR (0);
  1229.     /* read the data on the MDIO */
  1230.     MOT_FCC_MII_RD (temp, MII_MF_DATA_LEN);
  1231.     /* leave it in idle state */
  1232.     SYS_FCC_MII_BIT_WR ((INT32) NONE);
  1233.     *miiData = temp;
  1234.     MOT_FCC_LOG (MOT_FCC_DBG_MII, ("motFccMiiRead reg=%d 
  1235.    PHY=%d data=0x%xn"),
  1236.    regAddr, phyAddr, *miiData, 0, 0, 0);
  1237.     return (OK);
  1238.     }
  1239. /**************************************************************************
  1240. *
  1241. * motFccMiiWrite - write to the MII register
  1242. *
  1243. * This routine writes the register specified by <phyReg> in the PHY device,
  1244. * whose address is <phyAddr>, with the 16-bit value included in <miiData>.
  1245. *
  1246. * SEE ALSO: motFccMiiRead()
  1247. * RETURNS: OK, or ERROR.
  1248. */
  1249. LOCAL STATUS motFccMiiWrite
  1250.     (
  1251.     DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */
  1252.     UINT8 phyAddr, /* the PHY being written */
  1253.     UINT8 regAddr, /* the PHY's register being written */
  1254.     UINT16  miiData /* value written to the MII interface */
  1255.     )
  1256.     {
  1257.     /* write the preamble pattern first */
  1258.     MOT_FCC_MII_WR (MII_MF_PREAMBLE, MII_MF_PREAMBLE_LEN);
  1259.     /* write the start of frame */
  1260.     MOT_FCC_MII_WR (MII_MF_ST, MII_MF_ST_LEN);
  1261.     /* write the operation code */
  1262.     MOT_FCC_MII_WR (MII_MF_OP_WR, MII_MF_OP_LEN);
  1263.     /* write the PHY address */
  1264.     MOT_FCC_MII_WR (phyAddr, MII_MF_ADDR_LEN);
  1265.     /* write the PHY register */
  1266.     MOT_FCC_MII_WR (regAddr, MII_MF_REG_LEN);
  1267.     /* write the turnaround pattern */
  1268.     SYS_FCC_MII_BIT_WR (1);
  1269.     SYS_FCC_MII_BIT_WR (0);
  1270.     /* write the data on the MDIO */
  1271.     MOT_FCC_MII_WR (miiData, MII_MF_DATA_LEN);
  1272.     /* leave it in idle state @@@ */
  1273.     SYS_FCC_MII_BIT_WR ((INT32) NONE);
  1274.     MOT_FCC_LOG (MOT_FCC_DBG_MII, ("motFccMiiWrite reg=%d 
  1275.    PHY=%d data=0x%xn"),
  1276.    regAddr, phyAddr, miiData, 0, 0, 0);
  1277.     return (OK);
  1278.     }
  1279. /**************************************************************************
  1280. *
  1281. * motFccPhyPreInit - initialize some fields in the phy info structure
  1282. *
  1283. * This routine initializes some fields in the phy info structure, 
  1284. * for use of the phyInit() routine.
  1285. *
  1286. * RETURNS: OK, or ERROR if could not obtain memory.
  1287. */
  1288. LOCAL STATUS motFccPhyPreInit
  1289.     (
  1290.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  1291.     )
  1292.     {
  1293.     /* set some default values */
  1294.     pDrvCtrl->phyInfo->pDrvCtrl = (void *) pDrvCtrl;
  1295.     /* in case of link failure, set a default mode for the PHY */
  1296.     pDrvCtrl->phyInfo->phyFlags = MII_PHY_DEF_SET;
  1297.     pDrvCtrl->phyInfo->phyWriteRtn = (FUNCPTR) motFccMiiWrite;
  1298.     pDrvCtrl->phyInfo->phyReadRtn = (FUNCPTR) motFccMiiRead;
  1299.     pDrvCtrl->phyInfo->phyDelayRtn = (FUNCPTR) taskDelay;
  1300.     pDrvCtrl->phyInfo->phyMaxDelay = MII_PHY_DEF_DELAY;
  1301.     pDrvCtrl->phyInfo->phyDelayParm = 1;
  1302.     /* handle some user-to-physical flags */
  1303.     if (!(MOT_FCC_USR_FLAG_ISSET (MOT_FCC_USR_PHY_NO_AN)))
  1304. MOT_FCC_PHY_FLAGS_SET (MII_PHY_AUTO);
  1305.     else
  1306. MOT_FCC_PHY_FLAGS_CLEAR (MII_PHY_AUTO);
  1307.     if (MOT_FCC_USR_FLAG_ISSET (MOT_FCC_USR_PHY_TBL))
  1308. MOT_FCC_PHY_FLAGS_SET (MII_PHY_TBL);
  1309.     else
  1310. MOT_FCC_PHY_FLAGS_CLEAR (MII_PHY_TBL);
  1311.     if (!(MOT_FCC_USR_FLAG_ISSET (MOT_FCC_USR_PHY_NO_100)))
  1312. MOT_FCC_PHY_FLAGS_SET (MII_PHY_100);
  1313.     else
  1314. MOT_FCC_PHY_FLAGS_CLEAR (MII_PHY_100);
  1315.     if (!(MOT_FCC_USR_FLAG_ISSET (MOT_FCC_USR_PHY_NO_FD)))
  1316. MOT_FCC_PHY_FLAGS_SET (MII_PHY_FD);
  1317.     else
  1318. MOT_FCC_PHY_FLAGS_CLEAR (MII_PHY_FD);
  1319.     if (!(MOT_FCC_USR_FLAG_ISSET (MOT_FCC_USR_PHY_NO_10)))
  1320. MOT_FCC_PHY_FLAGS_SET (MII_PHY_10);
  1321.     else
  1322. MOT_FCC_PHY_FLAGS_CLEAR (MII_PHY_10);
  1323.     if (!(MOT_FCC_USR_FLAG_ISSET (MOT_FCC_USR_PHY_NO_HD)))
  1324. MOT_FCC_PHY_FLAGS_SET (MII_PHY_HD);
  1325.     else
  1326. MOT_FCC_PHY_FLAGS_CLEAR (MII_PHY_HD);
  1327.     /* mark it as pre-initilized */
  1328.     MOT_FCC_PHY_FLAGS_SET (MII_PHY_PRE_INIT);
  1329.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("motFccPhyPreInit phyInfo = 0x%x read=0x%x
  1330.    write=0x%x tbl=0x%x addr=0x%x 
  1331.    flags=0x%x n"), 
  1332.    (int) pDrvCtrl->phyInfo,
  1333.    (int) pDrvCtrl->phyInfo->phyReadRtn,
  1334.    (int) pDrvCtrl->phyInfo->phyWriteRtn,
  1335.    (int) pDrvCtrl->phyInfo->phyAnOrderTbl,
  1336.    (int) pDrvCtrl->phyInfo->phyAddr, 
  1337.    (int) pDrvCtrl->phyInfo->phyFlags);
  1338.     return (OK);
  1339.     }
  1340. /*******************************************************************************
  1341. * motFccMCastAddrAdd - add a multicast address for the device
  1342. *
  1343. * This routine adds a multicast address to whatever the driver
  1344. * is already listening for.
  1345. *
  1346. * SEE ALSO: motFccMCastAddrDel() motFccMCastAddrGet()
  1347. * RETURNS: OK or ERROR.
  1348. */
  1349. LOCAL STATUS motFccMCastAddrAdd
  1350.     (
  1351.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1352.     UCHAR *      pAddr /* address to be added */
  1353.     )
  1354.     {
  1355.     int retVal; /* convenient holder for return value */
  1356.     MOT_FCC_LOG (MOT_FCC_DBG_IOCTL, ("motFccMCastAddrAdd addr = 0x%x 0x%x
  1357.      0x%x 0x%x 0x%x 0x%xn"), 
  1358.      (int) *(UCHAR*) (pAddr + 0),
  1359.      (int) *(UCHAR*) (pAddr + 1), 
  1360.      (int) *(UCHAR*) (pAddr + 2), 
  1361.      (int) *(UCHAR*) (pAddr + 3), 
  1362.      (int) *(UCHAR*) (pAddr + 4), 
  1363.      (int) *(UCHAR*) (pAddr + 5));
  1364.     retVal = etherMultiAdd (&pDrvCtrl->endObj.multiList, pAddr);
  1365.     if (retVal == ENETRESET)
  1366. {
  1367.         pDrvCtrl->endObj.nMulti++;
  1368.  
  1369. return (motFccHashTblAdd (pDrvCtrl, pAddr));
  1370. }
  1371.     return ((retVal == OK) ? OK : ERROR);
  1372.     }
  1373. /*****************************************************************************
  1374. *
  1375. * motFccMCastAddrDel - delete a multicast address for the device
  1376. *
  1377. * This routine deletes a multicast address from the current list of
  1378. * multicast addresses.
  1379. *
  1380. * SEE ALSO: motFccMCastAddrAdd() motFccMCastAddrGet()
  1381. * RETURNS: OK or ERROR.
  1382. */
  1383. LOCAL STATUS motFccMCastAddrDel
  1384.     (
  1385.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1386.     UCHAR *      pAddr /* address to be deleted */
  1387.     )
  1388.     {
  1389.     int retVal; /* convenient holder for return value */
  1390.     MOT_FCC_LOG (MOT_FCC_DBG_IOCTL, ("motFccMCastAddrDel addr = 0x%x 0x%x
  1391.      0x%x 0x%x 0x%x 0x%xn"), 
  1392.      (int) *(pAddr + 0), (int) *(pAddr + 1), 
  1393.      (int) *(pAddr + 2), (int) *(pAddr + 3), 
  1394.      (int) *(pAddr + 4), (int) *(pAddr + 5));
  1395.     retVal = etherMultiDel (&pDrvCtrl->endObj.multiList, pAddr);
  1396.     if (retVal == ENETRESET)
  1397. {
  1398. pDrvCtrl->endObj.nMulti--;
  1399. /* stop the FCC */
  1400. if (motFccStop (pDrvCtrl) != OK)
  1401.     return (ERROR);
  1402. /* populate the hash table */
  1403. retVal = motFccHashTblPopulate (pDrvCtrl);
  1404. /* restart the FCC */
  1405. if (motFccStart (pDrvCtrl) != OK)
  1406.     return (ERROR);
  1407. }
  1408.     return ((retVal == OK) ? OK : ERROR);
  1409.     }
  1410. /*******************************************************************************
  1411. * motFccMCastAddrGet - get the current multicast address list
  1412. *
  1413. * This routine returns the current multicast address list in <pTable>
  1414. *
  1415. * SEE ALSO: motFccMCastAddrAdd() motFccMCastAddrDel()
  1416. *
  1417. * RETURNS: OK or ERROR.
  1418. */
  1419. LOCAL STATUS motFccMCastAddrGet
  1420.     (
  1421.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1422.     MULTI_TABLE *pTable /* table into which to copy addresses */
  1423.     )
  1424.     {
  1425.     MOT_FCC_LOG (MOT_FCC_DBG_IOCTL, ("motFccMCastAddrGetn"), 
  1426.      0, 0, 0, 0, 0, 0);
  1427.     return (etherMultiGet (&pDrvCtrl->endObj.multiList, pTable));
  1428.     }
  1429. /*******************************************************************************
  1430. * motFccHashTblAdd - add an entry to the hash table
  1431. *
  1432. * This routine adds an entry to the hash table for the address pointed to
  1433. * by <pAddr>.
  1434. *
  1435. * RETURNS: OK, or ERROR.
  1436. */
  1437. LOCAL STATUS motFccHashTblAdd
  1438.     (
  1439.     DRV_CTRL *  pDrvCtrl,       /* pointer to DRV_CTRL structure */
  1440.     UCHAR *     pAddr /* address to be added */
  1441.     )
  1442.     {
  1443.     UINT8 command = 0; /* command to issue to the CP */
  1444.     MOT_FCC_LOG (MOT_FCC_DBG_IOCTL, ("motFccHashTblAdd addr = 0x%x 0x%x
  1445.      0x%x 0x%x 0x%x 0x%xn"), 
  1446.      (int) *(pAddr + 0), (int) *(pAddr + 1), 
  1447.      (int) *(pAddr + 2), (int) *(pAddr + 3), 
  1448.      (int) *(pAddr + 4), (int) *(pAddr + 5));
  1449.     /* program the group enet address */
  1450.     if (motFccAddrSet (pDrvCtrl, (UCHAR *) pAddr, 
  1451.        M8260_FCC_TADDR_H_OFF) != OK)
  1452. return (ERROR);
  1453.     /* issue a set group address command to the CP */
  1454.     command = M8260_CPCR_SET_GROUP;
  1455.     if (motFccCpcrCommand (pDrvCtrl, command) == ERROR)
  1456. return (ERROR);
  1457.     MOT_FCC_LOG (MOT_FCC_DBG_IOCTL, ("motFccHashTblAdd endn"), 
  1458.      0, 0, 0, 0, 0, 0);
  1459.     return (OK);
  1460.     }
  1461. /*******************************************************************************
  1462. * motFccHashTblPopulate - populate the hash table
  1463. *
  1464. * This routine populates the hash table with the entries found in the
  1465. * multicast table. We have to reset the hash registers first, and 
  1466. * populate them again, as more than one address may be mapped to
  1467. * the same bit.
  1468. *
  1469. * RETURNS: OK, or ERROR.
  1470. */
  1471. LOCAL STATUS motFccHashTblPopulate
  1472.     (
  1473.     DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  1474.     )
  1475.     {
  1476.     ETHER_MULTI * mCastNode = NULL;
  1477.     UINT32 fccPramAddr = 0; /* a convenience */
  1478.     /* get to the beginning of the parameter area */
  1479.     fccPramAddr = pDrvCtrl->fccPramAddr;
  1480.     /* reset the hash table registers first */
  1481.     MOT_FCC_REG_LONG_WR (fccPramAddr + M8260_FCC_GADDR_H_OFF, 
  1482.  MOT_FCC_CLEAR_VAL);
  1483.     MOT_FCC_REG_LONG_WR (fccPramAddr + M8260_FCC_GADDR_L_OFF, 
  1484.  MOT_FCC_CLEAR_VAL);
  1485.     /* scan the multicast address list */
  1486.     for (mCastNode = (ETHER_MULTI *) lstFirst (&pDrvCtrl->endObj.multiList);
  1487.  mCastNode != NULL; 
  1488.  mCastNode = (ETHER_MULTI *) lstNext (&mCastNode->node))
  1489. {
  1490. /* add this entry */
  1491. if (motFccHashTblAdd (pDrvCtrl, mCastNode->addr) == ERROR)
  1492.     return (ERROR);
  1493. }
  1494.     return (OK);
  1495.     }
  1496. /***************************************************************************** 
  1497. * motFccPollSend - transmit a packet in polled mode
  1498. *
  1499. * This routine is called by a user to try and send a packet on the
  1500. * device. It sends a packet directly on the network, without having to
  1501. * go through the normal process of queuing a packet on an output queue
  1502. * and then waiting for the device to decide to transmit it.
  1503. *
  1504. * These routine should not call any kernel functions.
  1505. *
  1506. * SEE ALSO: motFccPollReceive()
  1507. *
  1508. * RETURNS: OK or EAGAIN.
  1509. */
  1510. LOCAL STATUS motFccPollSend
  1511.     (
  1512.     DRV_CTRL *pDrvCtrl, M_BLK_ID pMblk
  1513.     )
  1514.     {
  1515.     UINT16 pktType = 0; /* packet type (unicast or multicast) */
  1516.     int         retVal = OK; /* holder for return value */
  1517.     char *pBuf = NULL; /* pointer to data to be sent */
  1518.     FCC_BD *pTbd = NULL; /* pointer to the current ready TBD */
  1519.     int  ix = 0; /* a counter */
  1520.     int         len = 0; /* length of data to be sent */
  1521.     UINT16 tbdStatus; /* holder for the TBD status */
  1522.     MOT_FCC_LOG (MOT_FCC_DBG_POLL, ("motFccPollSendn"), 0, 0, 0, 0, 0, 0);
  1523.     if (!pMblk)
  1524.         {
  1525. END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
  1526. return EAGAIN;
  1527.         }
  1528.     if (pMblk->mBlkHdr.mData[0] & (UINT8)0x01)
  1529.         {
  1530. pktType = PKT_TYPE_MULTI; /* packet type is multicast */
  1531.         }
  1532.     else
  1533.         {
  1534. pktType = PKT_TYPE_UNI; /* packet type is unicast */
  1535.         }
  1536.     pTbd = &pDrvCtrl->tbdBase[pDrvCtrl->tbdIndex];
  1537.     pBuf = pDrvCtrl->pTxPollBuf;
  1538.     /* copy data but do not free the Mblk */
  1539.     len = netMblkToBufCopy (pMblk, (char *) pBuf, NULL);
  1540.     len = max(MOT_FCC_MIN_TX_PKT_SZ, len); 
  1541.     MOT_FCC_CACHE_FLUSH (pBuf, len); /* flush the cache, if necessary */
  1542.     pTbd->bdAddr = (unsigned long)pBuf;
  1543.     pTbd->bdLen = len;
  1544.     if (pDrvCtrl->tbdIndex == (pDrvCtrl->tbdNum - 1))
  1545.         {
  1546. pTbd->word1 = (M8260_FETH_TBD_R | M8260_FETH_TBD_L | M8260_FETH_TBD_TC |                       M8260_FETH_TBD_PAD | M8260_FETH_TBD_W);
  1547.         }
  1548.     else
  1549.         {
  1550. pTbd->word1 = (M8260_FETH_TBD_R | M8260_FETH_TBD_L | M8260_FETH_TBD_TC |
  1551.                        M8260_FETH_TBD_PAD);
  1552.         }
  1553.     CACHE_PIPE_FLUSH (); /* Flush the write pipe */
  1554.     ix = 0;
  1555.     while ((tbdStatus = pTbd->word1) & M8260_FETH_TBD_R)
  1556.         {
  1557. CACHE_PIPE_FLUSH (); /* Flush the write pipe */
  1558. if(++ix == MOT_FCC_WAIT_MAX)
  1559.             {
  1560.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
  1561.     return EAGAIN; /* going to need to do way more than this */
  1562.     }
  1563.         }
  1564.     if (tbdStatus & (M8260_FETH_TBD_LC | M8260_FETH_TBD_RL |
  1565.             M8260_FETH_TBD_UN | M8260_FETH_TBD_HB | M8260_FETH_TBD_CSL))
  1566.         {
  1567. END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
  1568. #ifdef MOT_FCC_DBG
  1569. if ((tbdStatus & M8260_FETH_TBD_LC))
  1570.             {
  1571.     MOT_FCC_LOG (MOT_FCC_DBG_TX, 
  1572.                          ("motFccTbdCheck: late collisionn"), 
  1573.                          1, 2, 3, 4, 5, 6);
  1574.     ++pDrvCtrl->Stats->motFccTxLcErr;
  1575.     }
  1576. if ((tbdStatus & M8260_FETH_TBD_RL))
  1577.             {
  1578.     MOT_FCC_LOG (MOT_FCC_DBG_TX, 
  1579.                          ("motFccTbdCheck: retransmit limitn"), 
  1580.                          1, 2, 3, 4, 5, 6);
  1581.     ++pDrvCtrl->Stats->motFccTxRlErr;
  1582.     }
  1583. if ((tbdStatus & M8260_FETH_TBD_UN))
  1584.             {
  1585.     MOT_FCC_LOG (MOT_FCC_DBG_TX, 
  1586.                          ("motFccTbdCheck: tx underrunn"), 1, 2, 3, 4, 5, 6);
  1587.     ++pDrvCtrl->Stats->motFccTxUrErr;
  1588.     }
  1589. if ((tbdStatus & M8260_FETH_TBD_CSL))
  1590.             {
  1591.     MOT_FCC_LOG (MOT_FCC_DBG_TX, 
  1592.                          ("motFccTbdCheck: carrier sensen"), 1, 2, 3, 4, 5, 6);
  1593.     ++pDrvCtrl->Stats->motFccTxCslErr;
  1594.     }
  1595. #endif /* MOT_FCC_DBG */
  1596. retVal = EAGAIN;
  1597.         }
  1598.     else
  1599.         {
  1600. /* up-date statistics */
  1601. if(pktType == PKT_TYPE_MULTI)
  1602.             {
  1603.             pDrvCtrl->endObj.mib2Tbl.ifOutNUcastPkts += 1;
  1604.     }
  1605.         else
  1606.             {
  1607.             END_ERR_ADD(&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
  1608.     }
  1609. retVal = OK;
  1610.         }
  1611.     /* clean this buffer descriptor, mirror motFccTbdInit() */
  1612.     if (pDrvCtrl->tbdIndex == (pDrvCtrl->tbdNum - 1))
  1613.         {
  1614. pTbd->word1 = M8260_FETH_TBD_W;
  1615.         }
  1616.     else
  1617.         {
  1618. pTbd->word1 = 0;
  1619.         }
  1620.     CACHE_PIPE_FLUSH (); /* Flush the write pipe */
  1621.     /* update some indices for correct handling of the TBD ring */
  1622.     pDrvCtrl->tbdIndex = (pDrvCtrl->tbdIndex + 1) % (pDrvCtrl->tbdNum);
  1623.     pDrvCtrl->usedTbdIndex = (pDrvCtrl->usedTbdIndex + 1) % (pDrvCtrl->tbdNum);
  1624.     return retVal;
  1625.     }
  1626. /*******************************************************************************
  1627. * motFccPollReceive - receive a packet in polled mode
  1628. *
  1629. * This routine is called by a user to try and get a packet from the
  1630. * device. It returns EAGAIN if no packet is available. The caller must
  1631. * supply a M_BLK_ID with enough space to contain the received packet. If
  1632. * enough buffer is not available then EAGAIN is returned.
  1633. *
  1634. * These routine should not call any kernel functions.
  1635. *
  1636. * SEE ALSO: motFccPollSend()
  1637. *
  1638. * RETURNS: OK or EAGAIN.
  1639. */
  1640. LOCAL STATUS motFccPollReceive
  1641.     (
  1642.     DRV_CTRL *pDrvCtrl, M_BLK *pMblk
  1643.     )
  1644.     {
  1645.     int retVal = OK; /* holder for return value */
  1646.     FCC_BD *pRbd = NULL; /* generic rbd pointer */
  1647.     UINT16 rbdStatus = 0; /* holder for the status of this RBD */
  1648.     UINT16 rbdLen = 0; /* number of bytes received */
  1649.     char *pData = NULL; /* a rx data pointer */
  1650.     MOT_FCC_LOG (MOT_FCC_DBG_POLL, ("motFccPollReceiven"), 0, 0, 0, 0, 0, 0);
  1651.     if ((pMblk->mBlkHdr.mFlags & M_EXT) != M_EXT)
  1652.         return EAGAIN;
  1653.     /* get the first available RBD */
  1654.     pRbd = &pDrvCtrl->rbdBase[pDrvCtrl->rbdIndex];
  1655.     rbdStatus = pRbd->word1; /* read the RBD status word */
  1656.     rbdLen = pRbd->bdLen; /* get the actual amount of received data */
  1657.     /* if it's not ready, don't touch it! */
  1658.     if ((rbdStatus & M8260_FETH_RBD_E))
  1659. return EAGAIN;
  1660.     /* up-date statistics */
  1661.     if (rbdStatus & (M8260_FETH_RBD_MC|M8260_FETH_RBD_BC) )
  1662.         {
  1663. pDrvCtrl->endObj.mib2Tbl.ifInNUcastPkts += 1;
  1664.         }
  1665.     else
  1666.         {
  1667. END_ERR_ADD(&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
  1668.         }
  1669.     /* 
  1670.      * Handle errata CPM-21... this code should NOT break the driver
  1671.      * when CPM-21 is ultimately fixed.
  1672.      */
  1673.     if ((rbdStatus & (M8260_FETH_RBD_CL | M8260_FETH_RBD_CR)) == 
  1674.                      M8260_FETH_RBD_CL)
  1675.         {
  1676. rbdStatus &= (UINT16)(~M8260_FETH_RBD_CL);
  1677.         }
  1678.     /* 
  1679.      * pass the packet up only if reception was Ok AND buffer is large enough,       */
  1680.     if ((rbdStatus & MOT_FCC_RBD_ERR) || pMblk->mBlkHdr.mLen < rbdLen)
  1681.         {
  1682. MOT_FCC_LOG (MOT_FCC_DBG_POLL, 
  1683.                      ("motFccReceive: bad rbdn"), 1, 2, 3, 4, 5, 6);
  1684. END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  1685. retVal = EAGAIN;
  1686.         }
  1687.     else
  1688.         {
  1689. pData = (char*)pRbd->bdAddr;
  1690. /* set up the mBlk properly */
  1691. pMblk->mBlkHdr.mFlags |= M_PKTHDR;
  1692. pMblk->mBlkHdr.mLen    = (rbdLen - MII_CRC_LEN) & ~0xc000;    
  1693. pMblk->mBlkPktHdr.len  = pMblk->mBlkHdr.mLen;
  1694. /* Make cache consistent with memory */
  1695. MOT_FCC_CACHE_INVAL ((char *) pData, pMblk->mBlkHdr.mLen);
  1696. bcopy ((char *) pData, (char *) pMblk->mBlkHdr.mData, 
  1697.                ((rbdLen - MII_CRC_LEN) & ~0xc000));
  1698. retVal = OK;
  1699.     }
  1700.     pRbd->bdLen = 0;
  1701.     /* up-date the status word: treat the last RBD in the ring differently */
  1702.     if ((pDrvCtrl->rbdIndex) == (pDrvCtrl->rbdNum - 1)) 
  1703.         {
  1704. pRbd->word1 = M8260_FETH_RBD_W | M8260_FETH_RBD_E | M8260_FETH_RBD_I;
  1705.         }
  1706.     else
  1707.         {
  1708. pRbd->word1 = M8260_FETH_RBD_E | M8260_FETH_RBD_I;
  1709.         }
  1710.     /* move on to the next used RBD */
  1711.     pDrvCtrl->rbdIndex = (pDrvCtrl->rbdIndex + 1) % (pDrvCtrl->rbdNum);
  1712.     return retVal;
  1713.     }
  1714. /*******************************************************************************
  1715. * motFccPollStart - start polling mode
  1716. *
  1717. * This routine starts polling mode by disabling ethernet interrupts and
  1718. * setting the polling flag in the END_CTRL stucture.
  1719. *
  1720. * SEE ALSO: motFccPollStop()
  1721. *
  1722. * RETURNS: OK, or ERROR if polling mode could not be started.
  1723. */
  1724. LOCAL STATUS motFccPollStart
  1725.     (
  1726.     DRV_CTRL    * pDrvCtrl       /* pointer to DRV_CTRL structure */
  1727.     )
  1728.     {
  1729.     int         intLevel; /* current intr level */
  1730.     int retVal; /* convenient holder for return value */
  1731.     MOT_FCC_LOG (MOT_FCC_DBG_POLL, ("motFccPollStartn"), 0, 0, 0, 0, 0, 0);
  1732.     intLevel = intLock();
  1733.     /* disable system interrupt: reset relevant bit in SIMNR_L */
  1734.     SYS_FCC_INT_DISABLE (pDrvCtrl, retVal);
  1735.     if (retVal == ERROR)
  1736. return (ERROR);
  1737.     /* mask chip interrupts   */
  1738.     MOT_FCC_INT_DISABLE;   
  1739.     MOT_FCC_FLAG_SET (MOT_FCC_POLLING);
  1740.     intUnlock (intLevel);
  1741.     return (OK);
  1742.     }
  1743. /*******************************************************************************
  1744. * motFccPollStop - stop polling mode
  1745. *
  1746. * This routine stops polling mode by enabling ethernet interrupts and
  1747. * resetting the polling flag in the END_CTRL structure.
  1748. *
  1749. * SEE ALSO: motFccPollStart()
  1750. *
  1751. * RETURNS: OK, or ERROR if polling mode could not be stopped.
  1752. */
  1753. LOCAL STATUS motFccPollStop
  1754.     (
  1755.     DRV_CTRL    * pDrvCtrl       /* pointer to DRV_CTRL structure */
  1756.     )
  1757.     {
  1758.     int         intLevel;
  1759.     int retVal; /* convenient holder for return value */
  1760.     intLevel = intLock();
  1761.     /* enable system interrupt: set relevant bit in SIMNR_L */
  1762.     SYS_FCC_INT_ENABLE (pDrvCtrl, retVal);
  1763.     if (retVal == ERROR)
  1764. return (ERROR);
  1765.     /* enable chip interrupts */
  1766.     MOT_FCC_INT_ENABLE;   
  1767.     /* set flags */
  1768.     MOT_FCC_FLAG_CLEAR (MOT_FCC_POLLING);
  1769.     intUnlock (intLevel);
  1770.     MOT_FCC_LOG (MOT_FCC_DBG_POLL, ("motFccPollStop... endn"), 
  1771.     0, 0, 0, 0, 0, 0);
  1772.     return (OK);
  1773.     }
  1774. #ifdef MOT_FCC_DBG 
  1775. void motFccIramShow
  1776.     (
  1777.     )
  1778.     {
  1779.     UINT32 temp32; /* a convenience */
  1780.     volatile UINT16 temp16; /* a convenience */
  1781.     DRV_CTRL * pDrvCtrl = pDrvCtrlDbg;
  1782.     UINT32 fccIramAddr = 0; /* a convenience */
  1783.     fccIramAddr = pDrvCtrl->fccIramAddr;
  1784.     MOT_FCC_REG_LONG_RD (fccIramAddr + M8260_FCC_GFMR_OFF,
  1785.  temp32);
  1786.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("gfmr=0x%xn"),
  1787.     temp32, 0, 0, 0, 0, 0);
  1788.     MOT_FCC_REG_LONG_RD (fccIramAddr + M8260_FCC_FPSMR_OFF,
  1789.  temp32);
  1790.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("fpsmr=0x%xn"),
  1791.     temp32, 0, 0, 0, 0, 0);
  1792.     MOT_FCC_REG_WORD_RD (fccIramAddr + M8260_FCC_FDSR_OFF, 
  1793.  temp16);
  1794.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("fdsr=0x%xn"),
  1795.     temp16, 0, 0, 0, 0, 0);
  1796.     MOT_FCC_REG_WORD_RD (fccIramAddr + M8260_FCC_FTODR_OFF, 
  1797.  temp16);
  1798.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("ftodr=0x%xn"),
  1799.     temp16, 0, 0, 0, 0, 0);
  1800.     MOT_FCC_REG_WORD_RD (fccIramAddr + M8260_FCC_FCCMR_OFF,
  1801.  temp16);
  1802.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("fccmr=0x%xn"),
  1803.     temp16, 0, 0, 0, 0, 0);
  1804.     MOT_FCC_REG_WORD_RD (fccIramAddr + M8260_FCC_FCCER_OFF,
  1805.  temp16);
  1806.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("fccer=0x%xn"),
  1807.     temp16, 0, 0, 0, 0, 0);
  1808.     }
  1809. void motFccPramShow
  1810.     (
  1811.     )
  1812.     {
  1813.     UINT32 tempVal [6]; /* a convenience */
  1814.     DRV_CTRL * pDrvCtrl = pDrvCtrlDbg; /* the driver control struct */
  1815.     UINT32 fccPramAddr = 0; /* a convenience */
  1816.     fccPramAddr = pDrvCtrl->fccPramAddr;
  1817.     MOT_FCC_REG_WORD_RD (fccPramAddr + M8260_FCC_RIPTR_OFF, 
  1818.  tempVal [0]);
  1819.     MOT_FCC_REG_WORD_RD (fccPramAddr + M8260_FCC_TIPTR_OFF, 
  1820.  tempVal [1]);
  1821.     MOT_FCC_REG_LONG_RD (fccPramAddr + M8260_FCC_RSTATE_OFF,
  1822.  tempVal[2]);
  1823.     MOT_FCC_REG_LONG_RD (fccPramAddr + M8260_FCC_RBASE_OFF,
  1824.  tempVal[3]);
  1825.     MOT_FCC_REG_LONG_RD (fccPramAddr + M8260_FCC_TSTATE_OFF,
  1826.  tempVal[4]);
  1827.     MOT_FCC_REG_LONG_RD (fccPramAddr + M8260_FCC_TBASE_OFF,
  1828.  tempVal[5]);
  1829.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("nriptr=0x%x 
  1830.     tiptr=0x%x
  1831.     rstate=0x%x 
  1832.     rbase=0x%x
  1833.     tstate=0x%x
  1834.     tbase=0x%xn"),
  1835.     tempVal [0], tempVal [1], tempVal [2], 
  1836.     tempVal [3], tempVal [4], tempVal [5]);
  1837.     MOT_FCC_REG_WORD_RD (fccPramAddr + M8260_FCC_RET_LIM_OFF, 
  1838.  tempVal [0]);
  1839.     MOT_FCC_REG_LONG_RD (fccPramAddr + M8260_FCC_C_MASK_OFF, 
  1840.  tempVal [1]);
  1841.     MOT_FCC_REG_LONG_RD (fccPramAddr + M8260_FCC_C_PRES_OFF,
  1842.  tempVal[2]);
  1843.     MOT_FCC_REG_LONG_RD (fccPramAddr + M8260_FCC_CRCEC_OFF,
  1844.  tempVal[3]);
  1845.     MOT_FCC_REG_LONG_RD (fccPramAddr + M8260_FCC_ALEC_OFF,
  1846.  tempVal[4]);
  1847.     MOT_FCC_REG_LONG_RD (fccPramAddr + M8260_FCC_DISFC_OFF,
  1848.  tempVal[5]);
  1849.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("nretry limit=%d
  1850.     crc mask=0x%x
  1851.     preset crc=0x%x 
  1852.     crc errored frames=0x%x
  1853.     misaligned frames=0x%x
  1854.     discarded frames=0x%xn"),
  1855.     tempVal [0], tempVal [1], tempVal [2], 
  1856.     tempVal [3], tempVal [4], tempVal [5]);
  1857.     MOT_FCC_REG_LONG_RD (fccPramAddr + M8260_FCC_GADDR_H_OFF,
  1858.  tempVal[0]);
  1859.     MOT_FCC_REG_LONG_RD (fccPramAddr + M8260_FCC_GADDR_L_OFF,
  1860.  tempVal[1]);
  1861.     MOT_FCC_REG_LONG_RD (fccPramAddr + M8260_FCC_IADDR_H_OFF,
  1862.  tempVal[2]);
  1863.     MOT_FCC_REG_LONG_RD (fccPramAddr + M8260_FCC_IADDR_L_OFF,
  1864.  tempVal[3]);
  1865.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("ngroup addr filter high=0x%x
  1866.     group addr filter low=0x%x
  1867.     individual addr filter high=0x%x 
  1868.     individual addr filter low=0x%x n"),
  1869.     tempVal [0], tempVal [1], tempVal [2], 
  1870.     tempVal [3], 0, 0);
  1871.     MOT_FCC_REG_WORD_RD (fccPramAddr + M8260_FCC_PADDR_H_OFF,
  1872.  tempVal[0]);
  1873.     MOT_FCC_REG_WORD_RD (fccPramAddr + M8260_FCC_PADDR_M_OFF,
  1874.  tempVal[1]);
  1875.     MOT_FCC_REG_WORD_RD (fccPramAddr + M8260_FCC_PADDR_L_OFF,
  1876.  tempVal[2]);
  1877.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("nindividual addr high=0x%x 
  1878.     individual addr medium=0x%x 
  1879.     individual addr low=0x%x n"),
  1880.     tempVal [0], tempVal [1], tempVal [2], 
  1881.     0, 0, 0);
  1882.     MOT_FCC_REG_WORD_RD (fccPramAddr + M8260_FCC_MRBLR_OFF,
  1883.  tempVal[0]);
  1884.     MOT_FCC_REG_WORD_RD (fccPramAddr + M8260_FCC_MFLR_OFF,
  1885.  tempVal[1]);
  1886.     MOT_FCC_REG_WORD_RD (fccPramAddr + M8260_FCC_MINFLR_OFF,
  1887.  tempVal[2]);
  1888.     MOT_FCC_REG_WORD_RD (fccPramAddr + M8260_FCC_MAXD1_OFF,
  1889.  tempVal[3]);
  1890.     MOT_FCC_REG_WORD_RD (fccPramAddr + M8260_FCC_MAXD2_OFF,
  1891.  tempVal[4]);
  1892.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("nmax rx buf length=0x%x 
  1893.     max frame length=0x%x 
  1894.     min frame length=0x%x
  1895.     max DMA1 length=0x%x
  1896.     max DMA2 length=0x%x n"),
  1897.     tempVal [0], tempVal [1], tempVal [2], 
  1898.     tempVal [3], tempVal [4], 0);
  1899.     MOT_FCC_REG_LONG_RD (fccPramAddr + M8260_FCC_CAM_PTR_OFF,
  1900.  tempVal[0]);
  1901.     MOT_FCC_REG_WORD_RD (fccPramAddr + M8260_FCC_P_PER_OFF,
  1902.  tempVal[1]);
  1903.     MOT_FCC_REG_WORD_RD (fccPramAddr + M8260_FCC_PAD_PTR_OFF,
  1904.  tempVal[2]);
  1905.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("ncam address pointer=0x%x
  1906.     persistence=0x%x 
  1907.     internal pad pointer=0x%x n"),
  1908.     tempVal [0], tempVal [1], tempVal [2], 
  1909.     0, 0, 0);
  1910.     }
  1911. void motFccRbdShow(int rbdNum)
  1912. {
  1913. FCC_BD *pBd;
  1914.     pBd = &global_pDrvCtrl->rbdBase[rbdNum];
  1915.     MOT_FCC_LOG (MOT_FCC_DBG_ANY,
  1916. ("rbdStatus=0x%x rbdLen=0x%x rbdBuf=0x%xn"),
  1917. pBd->word1, pBd->bdLen, pBd->bdAddr, 0, 0, 0);
  1918. }
  1919. void motFccTbdShow(int tbdNum)
  1920. {
  1921. FCC_BD *pBd;
  1922.  
  1923.     pBd = &global_pDrvCtrl->tbdBase[tbdNum];
  1924.     MOT_FCC_LOG (MOT_FCC_DBG_ANY,
  1925. ("tbdStatus=0x%x tbdLen=0x%x tbdBuf=0x%xn"),
  1926. pBd->word1, pBd->bdLen, pBd->bdAddr, 0, 0, 0);
  1927.     }
  1928.  
  1929. void motFccErrorShow (void)
  1930. {
  1931.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("nTxErr=0x%x 
  1932.    RxBsy=0x%xn"),
  1933.    motFccTxErr, 
  1934.    motFccRxBsyErr, 
  1935.    0, 0, 0, 0);
  1936.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("nTxLc=0x%x 
  1937.        TxUr=0x%x 
  1938.    TxCsl=0x%x 
  1939.    TxRl=0x%xn"),
  1940.    motFccTxLcErr, 
  1941.    motFccTxUrErr, 
  1942.    motFccTxCslErr, 
  1943.    motFccTxRlErr, 
  1944.    0, 0);
  1945.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("nRxLg=0x%x 
  1946.        RxNo=0x%x 
  1947.    RxCrc=0x%x 
  1948.    RxOv=0x%x 
  1949.    RxLc=0x%x 
  1950.    RxSh=0x%x n"),
  1951.    motFccRxLgErr, 
  1952.    motFccRxNoErr, 
  1953.    motFccRxCrcErr, 
  1954.    motFccRxOvErr, 
  1955.    motFccRxLcErr, 
  1956.    motFccRxShErr);
  1957.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("nRxMem=0x%xn"),
  1958.    motFccRxMemErr, 
  1959.    0, 0, 0, 0, 0);
  1960. }
  1961. void motFccDrvShow
  1962.     (
  1963.     )
  1964.     {
  1965.     DRV_CTRL * pDrvCtrl = pDrvCtrlDbg;
  1966.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, "pDrvCtrl=0x%x pNetPool=0x%x pClPool=0x%xn",
  1967.    (int) pDrvCtrl, 
  1968.    (int) pDrvCtrl->endObj.pNetPool, 
  1969.    (int) pDrvCtrl->pClPoolId, 0, 0, 0);
  1970.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, "bdBase=0x%x bdSize=0x%x pClBlkArea=0x%x "
  1971.                                   "clBlkSize=0x%x pMBlkArea=0x%x mBlkSize=0x%xn",
  1972.    (int) pDrvCtrl->pBdBase,
  1973.    pDrvCtrl->bdSize,
  1974.    (int) pDrvCtrl->pBufBase,
  1975.    pDrvCtrl->bufSize,
  1976.    (int) pDrvCtrl->pMBlkArea, 
  1977.    pDrvCtrl->mBlkSize);
  1978.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("tbdNum=%d 
  1979.    tbdBase=0x%x
  1980.    tbdIndex=%d 
  1981.    usedTbdIndex=%d 
  1982.    cleanTbdNum=%d 
  1983.    txStall=%d n"),
  1984.    pDrvCtrl->tbdNum, 
  1985.    (int) pDrvCtrl->tbdBase, 
  1986.    pDrvCtrl->tbdIndex,
  1987.    pDrvCtrl->usedTbdIndex,
  1988.    pDrvCtrl->cleanTbdNum, 
  1989.    pDrvCtrl->txStall);
  1990.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("rbdNum=%d 
  1991.    rbdBase=0x%x 
  1992.    rbdIndex=%d
  1993.    iramAddr=0x%x 
  1994.    pramAddr=0x%x
  1995.    fccNum=%d n"),
  1996.    pDrvCtrl->rbdNum, 
  1997.    (int) pDrvCtrl->rbdBase, 
  1998.    pDrvCtrl->rbdIndex,
  1999.    pDrvCtrl->fccIramAddr,
  2000.    pDrvCtrl->fccPramAddr,
  2001.    pDrvCtrl->fccNum);
  2002.     }
  2003. void motFccMiiShow
  2004.     (
  2005.     )
  2006.     {
  2007.     DRV_CTRL *  pDrvCtrl = pDrvCtrlDbg;
  2008.     UCHAR       speed [20];
  2009.     UCHAR       mode [20];
  2010.  
  2011.     strcpy ((char *) speed, (pDrvCtrl->phyInfo->phySpeed == MOT_FCC_100MBS) ?
  2012.                     "100Mbit/s" : "10Mbit/s");
  2013.  
  2014.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("nphySpeed=%s 
  2015.    phyMode=%s 
  2016.    phyAddr=0x%x
  2017.                                    phyFlags=0x%x
  2018.                                    phyDefMode=0x%xn"),
  2019.                                    (int) &speed[0],
  2020.                                    (int) &mode[0],
  2021.                                    pDrvCtrl->phyInfo->phyAddr,
  2022.                                    pDrvCtrl->phyInfo->phyFlags,
  2023.                                    pDrvCtrl->phyInfo->phyDefMode,
  2024.    0);
  2025.  
  2026.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("nphyStatus=0x%x 
  2027.    phyCtrl=0x%x 
  2028.    phyAds=0x%x
  2029.                                    phyPrtn=0x%x 
  2030.    phyExp=0x%x 
  2031.    phyNext=0x%xn"),
  2032.                                    pDrvCtrl->phyInfo->miiRegs.phyStatus,
  2033.                                    pDrvCtrl->phyInfo->miiRegs.phyCtrl,
  2034.                                    pDrvCtrl->phyInfo->miiRegs.phyAds,
  2035.                                    pDrvCtrl->phyInfo->miiRegs.phyPrtn,
  2036.                                    pDrvCtrl->phyInfo->miiRegs.phyExp,
  2037.                                    pDrvCtrl->phyInfo->miiRegs.phyNext);
  2038.     }
  2039. void motFccMibShow
  2040.     (
  2041.     )
  2042.     {
  2043.     DRV_CTRL *  pDrvCtrl = pDrvCtrlDbg;
  2044.  
  2045.     MOT_FCC_LOG (MOT_FCC_DBG_ANY, ("nifOutNUcastPkts=%d 
  2046.    ifOutUcastPkts=%d
  2047.                                    ifInNUcastPkts=%d
  2048.                                    ifInUcastPkts=%d 
  2049.    ifOutErrors=%dn"),
  2050.                                    pDrvCtrl->endObj.mib2Tbl.ifOutNUcastPkts,
  2051.                                    pDrvCtrl->endObj.mib2Tbl.ifOutUcastPkts,
  2052.                                    pDrvCtrl->endObj.mib2Tbl.ifInNUcastPkts,
  2053.                                    pDrvCtrl->endObj.mib2Tbl.ifInUcastPkts,
  2054.                                    pDrvCtrl->endObj.mib2Tbl.ifOutErrors,
  2055.                                    0);
  2056.  
  2057.     }
  2058. UINT16 motFccMiiRegRead
  2059.     (
  2060.     UINT8 regAddr
  2061.     )
  2062.     {
  2063.     int status;
  2064.     UINT16 value;
  2065.     status = motFccMiiRead(pDrvCtrlDbg, 
  2066.    pDrvCtrlDbg->phyInfo->phyAddr, 
  2067.    regAddr,
  2068.    &value);
  2069.     if (status != OK)
  2070. MOT_FCC_LOG (MOT_FCC_DBG_MII, ("motFccMiiRead failed, retval %dn"),
  2071.        status, 2, 3, 4, 5, 6);
  2072.     
  2073.     return(value);
  2074.     }
  2075. #endif /* MOT_FCC_DBG */