📄 m5200fecend.c
字号:
bufLen = pCurr->mBlkHdr.mLen; pCurr = ((M_BLK *) pCurr->mBlkHdr.mNext); if (bufLen == 0) continue; /* just in case we have to pad it */ totLen += bufLen; /* flush the cache, if necessary */ MOT_FEC_CACHE_FLUSH (pBuf, bufLen); /* get and set up the current TBD */ pTbd = pTbdList->pTbd; MOT_FEC_BD_LONG_WR (pTbd, MOT_FEC_BD_ADDR_OFF, (UINT32) pBuf); MOT_FEC_BD_WORD_RD (pTbd, MOT_FEC_BD_STAT_OFF, tbdStatus); /* * complete TBD construction based on whether or not this is the last * fragment */ if (--fragNum > 0) { MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend more mblks \n"), 1, 2, 3, 4, 5, 6); MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_LEN_OFF, bufLen); MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_STAT_OFF, (tbdStatus | MOT_FEC_TBD_RDY)); } else { MOT_FEC_LOG (MOT_FEC_DBG_TX, ("before bufLen: 0x%x ETHERSMALL: 0x%x\n"), bufLen, ETHERSMALL, 0, 0, 0, 0); if (totLen < ETHERSMALL) bufLen = max (bufLen, (ETHERSMALL - totLen + bufLen)); MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend last len=0x%x\n"), bufLen, 2, 3, 4, 5, 6); MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_LEN_OFF, bufLen); MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_STAT_OFF, (MOT_FEC_TBD_LAST | MOT_FEC_TBD_CRC | MOT_FEC_TBD_RDY | tbdStatus)); } /* move on to the next element */ pTbdList = pTbdList->pNext; } /* kick the transmitter */ SDMA_TASK_ENABLE(SDMA_TCR, txTaskId); return (OK); }/******************************************************************************** motFecPktCopyTransmit - copy and transmit a packet** This routine transmits the packet described by the given parameters* over the network, after copying the mBlk to the driver's buffer.* It also updates statistics.** RETURNS: OK, or ERROR if no resources were available.*/LOCAL STATUS motFecPktCopyTransmit ( DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */ M_BLK * pMblk, /* pointer to the mBlk */ UINT8 fragNum, /* number of fragments */ UINT16 pktType /* packet type */ ) { UINT16 len = 0; /* length of data to be sent */ char * pBuf = NULL; /* pointer to data to be sent */ MOT_FEC_TBD_ID pTbd = NULL; /* pointer to the current ready TBD */ MOT_FEC_TBD_LIST_ID pTbdList = NULL;/* pointer to the TBD list*/ UINT16 tbdStatus; /* holder for the TBD status */ MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend...\n"), 1, 2, 3, 4, 5, 6); /* get a cluster buffer from the pool */ pBuf = NET_BUF_ALLOC(); if (pBuf == NULL) { /* set to stall condition */ pDrvCtrl->txStall = TRUE; return (ERROR); } /* get the current free TBD list */ pTbdList = motFecTbdListSet (pDrvCtrl, fragNum); if (pTbdList == (MOT_FEC_TBD_LIST_ID) NULL) { /* set to stall condition */ NET_BUF_FREE ((UCHAR *) pBuf); pDrvCtrl->txStall = TRUE; return (ERROR); } /* store the packet type */ pTbdList->pktType = pktType; /* store the buffer pointer and its type */ pTbdList->bufType = BUF_TYPE_CL; pTbdList->pBuf = (UINT8 *)pBuf; /* copy data and free the Mblk */ len = netMblkToBufCopy (pMblk, (char *) pBuf, NULL); netMblkClChainFree (pMblk); len = max (ETHERSMALL, len); /* flush the cache, if necessary */ MOT_FEC_CACHE_FLUSH (pBuf, len); /* get and set up the current TBD */ pTbd = pTbdList->pTbd; MOT_FEC_BD_LONG_WR (pTbd, MOT_FEC_BD_ADDR_OFF, (UINT32) pBuf); MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_LEN_OFF, len); MOT_FEC_BD_WORD_RD (pTbd, MOT_FEC_BD_STAT_OFF, tbdStatus); MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_STAT_OFF, (MOT_FEC_TBD_LAST | MOT_FEC_TBD_CRC | MOT_FEC_TBD_RDY | tbdStatus)); /* kick the transmitter */ SDMA_TASK_ENABLE(SDMA_TCR, txTaskId); return (OK); }/******************************************************************************** motFecMblkWalk - walk the mBlk** This routine walks the mBlk whose address is in <pMblk>, computes* the number of fragments it is made of, and returns it in the parameter* <pFragNum>. In addition, it finds out whether the specified packet* is unicast or multicast, and sets <pPktType> accordingly.** RETURNS: OK, or ERROR in case of invalid mBlk.*/LOCAL STATUS motFecMblkWalk ( M_BLK * pMblk, /* pointer to the mBlk */ UINT8 * pFragNum, /* number of fragments */ UINT16 * pPktType /* packet type */ ) { M_BLK * pCurr = pMblk; /* the current mBlk */ if (pMblk == NULL) { MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend: invalid pMblk\n"), 0, 0, 0, 0, 0, 0); return (ERROR); } /* walk this mBlk */ while (pCurr != NULL) { /* keep track of the number of fragments in this mBlk */ if (pCurr->mBlkHdr.mLen != 0) (*pFragNum)++; pCurr = ((M_BLK *) pCurr->mBlkHdr.mNext); } /* set the packet type to multicast or unicast */ if (pMblk->mBlkHdr.mData[0] & (UINT8) 0x01) { (*pPktType) = PKT_TYPE_MULTI; } else { (*pPktType) = PKT_TYPE_UNI; } return (OK); }/******************************************************************************** motFecTbdListSet - set up a list of available transmit descriptors** This routine sets up a list of available buffer descriptors for use by* the send routine.** RETURNS: a pointer to a transmit descriptors list, or NULL.*/LOCAL MOT_FEC_TBD_LIST_ID motFecTbdListSet ( DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */ UINT8 tbdNum /* number of tbd */ ) { MOT_FEC_TBD_ID pTbd = NULL; /* pointer to the current TBD */ UINT16 tbdIndex = pDrvCtrl->tbdIndex; /* TBD index */ UINT16 nextIndex = 0; /* index to the next TBD */ UINT16 currIndex = 0; /* index to the current TBD */ UINT16 i = 0; /* an index */ MOT_FEC_TBD_LIST_ID pTbdList = NULL; /* set the number of TBDs in this list */ pDrvCtrl->pTbdList [tbdIndex]->fragNum = tbdNum; /* initialize the list */ for (i = 0; i < tbdNum; i++) { /* get the current free TBD */ if ((pTbd = motFecTbdGet (pDrvCtrl)) == NULL) { return (NULL); } currIndex = pDrvCtrl->tbdIndex; nextIndex = (currIndex + 1) % (pDrvCtrl->tbdNum); pTbdList = pDrvCtrl->pTbdList [currIndex]; pTbdList->pTbd = pTbd; pTbdList->pBuf = NULL; pTbdList->pNext = pDrvCtrl->pTbdList [nextIndex]; /* update some indeces for a correct handling of the TBD ring */ pDrvCtrl->tbdIndex = (pDrvCtrl->tbdIndex + 1) % pDrvCtrl->tbdNum; } /* terminate the list properly */ pTbdList->pNext = NULL; /* keep track of the clean TBDs */ pDrvCtrl->cleanTbdNum -= tbdNum; return (pDrvCtrl->pTbdList [tbdIndex]); }/******************************************************************************** motFecTbdGet - get the first available transmit descriptor** This routine gets the first available buffer descriptor in the transmit* ring. It checks the descriptor is owned by the host and it has been* cleaned by the motFecTbdClean() routine.** RETURNS: an available transmit descriptor, otherwise NULL.*/LOCAL MOT_FEC_TBD_ID motFecTbdGet ( DRV_CTRL * pDrvCtrl /* pointer to DRV_CTRL structure */ ) { MOT_FEC_TBD_ID nextTbd = NULL; /* holder for the next TBD */ UINT16 tbdStatus; /* holder for the TBD status */ MOT_FEC_NEXT_TBD (pDrvCtrl, nextTbd); /* Make cache consistent with memory */ MOT_FEC_BD_CACHE_INVAL (nextTbd, MOT_FEC_TBD_SZ); MOT_FEC_BD_WORD_RD ((char *) nextTbd, MOT_FEC_BD_STAT_OFF, tbdStatus); if ((tbdStatus & MOT_FEC_TBD_RDY) == MOT_FEC_TBD_RDY) { MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend... not our Tbd \n"), 1, 2, 3, 4, 5, 6); return (NULL); } return ((MOT_FEC_TBD_ID) nextTbd); }/******************************************************************************** motFecTbdClean - clean the transmit buffer descriptors ring** This routine is run in netTask's context. It cleans the transmit* buffer descriptors ring. It also calls motFecTbdCheck() to check* for any transmit errors, and possibly up-dates statistics.** SEE ALSO: motFecTbdCheck()** RETURNS: N/A.*/LOCAL void motFecTbdClean ( DRV_CTRL * pDrvCtrl /* pointer to DRV_CTRL structure */ ) { MOT_FEC_TBD_ID pUsedTbd; /* first used TBD */ UINT32 retVal = 0; /* return value */ MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecTbdClean\n"), 1, 2, 3, 4, 5, 6); END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER); /* process all the consumed TBDs */ while (pDrvCtrl->cleanTbdNum < pDrvCtrl->tbdNum) { MOT_FEC_TBD_LIST_ID pTbdList; MOT_FEC_TBD_LIST_ID pTempList; pTbdList = pDrvCtrl->pTbdList [pDrvCtrl->usedTbdIndex]; pTempList = pTbdList; /* first, we detect abnormal events */ while (pTempList != NULL) { pUsedTbd = pTempList->pTbd; /* check on this TBD */ retVal = motFecTbdCheck (pDrvCtrl, pUsedTbd); if (retVal == MOT_FEC_TBD_BUSY) { END_TX_SEM_GIVE (&pDrvCtrl->endObj); return; } if (retVal == MOT_FEC_TBD_ERROR) { break; } /* move on to the next element in the list */ pTempList = pTempList->pNext; } /* free the Mblk or the cluster, whichever is appropriate */ if ((pTbdList->bufType == ((UINT16) BUF_TYPE_MBLK)) && (pTbdList->pBuf != NULL)) { netMblkClChainFree ((M_BLK *) pTbdList->pBuf); pTbdList->pBuf = NULL; } else { if ((pTbdList->bufType == ((UINT16) BUF_TYPE_CL)) && (pTbdList->pBuf != NULL)) { /* it's a cluster */ NET_BUF_FREE (pTbdList->pBuf); pTbdList->pBuf = NULL; } } pTempList = pTbdList; /* finally, we clean this TBD list */ while (pTempList != NULL) { pUsedTbd = pTempList->pTbd; /* clean this buffer descriptor, mirror motFecTbdInit() */ if (pDrvCtrl->usedTbdIndex == (pDrvCtrl->tbdNum - 1)) { MOT_FEC_BD_WORD_WR (pUsedTbd, MOT_FEC_BD_STAT_OFF, MOT_FEC_TBD_WRAP); } else { MOT_FEC_BD_WORD_WR (pUsedTbd, MOT_FEC_BD_STAT_OFF, 0); } /* update some indeces for a correct handling of the TBD ring */ pDrvCtrl->cleanTbdNum++; pDrvCtrl->usedTbdIndex = (pDrvCt
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -