📄 ethernet.c
字号:
* ETH_ERROR in case the routine can not access Tx desc ring.* ETH_QUEUE_LAST_RESOURCE if the routine uses the last Tx resource.* ETH_OK otherwise.********************************************************************************/ETH_STATUS ethPortSend(ETH_PORT_INFO *pEthPortCtrl, ETH_PORT_TX_QUEUE txQueue, PKT_INFO *pPktInfo){ volatile ETH_TX_DESC *pTxDescFirst; volatile ETH_TX_DESC* pTxDescCurr; volatile ETH_TX_DESC* pTxNextDescCurr; volatile ETH_TX_DESC* pTxDescUsed; unsigned int commandStatus; /* Do not process Tx ring in case of Tx ring resource error */ if(pEthPortCtrl->txResourceErr[txQueue]) return ETH_QUEUE_FULL; /* Get the Tx Desc ring indexes */ CURR_TFD_GET (pTxDescCurr, txQueue); USED_TFD_GET (pTxDescUsed, txQueue); if(pTxDescCurr == 0) return ETH_ERROR; /* The following parameters are used to save readings from memory */ pTxNextDescCurr = TX_NEXT_DESC_PTR(pTxDescCurr, txQueue); commandStatus = pPktInfo->cmdSts | ETH_ZERO_PADDING | ETH_GEN_CRC; if (commandStatus & (ETH_FIRST_DESC)) { /* Update first desc */ FIRST_TFD_SET(pTxDescCurr, txQueue); pTxDescFirst = pTxDescCurr; } else { FIRST_TFD_GET(pTxDescFirst, txQueue); commandStatus |= ETH_BUFFER_OWNED_BY_DMA; } /* Buffers with a payload smaller than 8 bytes must be aligned to 64-bit */ /* boundary. We use the memory allocated for Tx descriptor. This memory */ /* located in TX_BUF_OFFSET_IN_DESC offset within the Tx descriptor. */ if(pPktInfo->byteCnt <= 8) { pTxDescCurr->bufPtr = (unsigned int)pTxDescCurr + TX_BUF_OFFSET_IN_DESC; ethBCopy(pPktInfo->bufPtr, pTxDescCurr->bufPtr, pPktInfo->byteCnt); pTxDescCurr->bufPtr = pEthPortCtrl->portVirtToPhys(pTxDescCurr->bufPtr); } else pTxDescCurr->bufPtr = pPktInfo->bufPtr; pTxDescCurr->byteCnt = pPktInfo->byteCnt; pTxDescCurr->returnInfo = pPktInfo->returnInfo; if (pPktInfo->cmdSts & (ETH_LAST_DESC)) { /* Set last desc with DMA ownership and interrupt enable. */ pTxDescCurr->cmdSts = commandStatus | ETH_BUFFER_OWNED_BY_DMA | ETH_ENABLE_INTERRUPT; if(pTxDescCurr != pTxDescFirst) pTxDescFirst->cmdSts |= ETH_BUFFER_OWNED_BY_DMA; /* Flush CPU pipe */ D_CACHE_FLUSH_LINE ((unsigned int)pTxDescCurr, 0); D_CACHE_FLUSH_LINE ((unsigned int)pTxDescFirst, 0); CPU_PIPE_FLUSH; /* Apply send command */ ETH_SDMA_START_TX(txQueue); /* Finish Tx packet. Update first desc in case of Tx resource error */ pTxDescFirst = pTxNextDescCurr; FIRST_TFD_SET(pTxDescFirst, txQueue); } else { pTxDescCurr->cmdSts = commandStatus; D_CACHE_FLUSH_LINE ((unsigned int)pTxDescCurr, 0); } /* Check for ring index overlap in the Tx desc ring */ if(pTxNextDescCurr == pTxDescUsed) { /* Update the current descriptor */ CURR_TFD_SET(pTxDescFirst, txQueue); pEthPortCtrl->txResourceErr[txQueue] = 1; return ETH_QUEUE_LAST_RESOURCE; } else { /* Update the current descriptor */ CURR_TFD_SET(pTxNextDescCurr, txQueue); return ETH_OK; }}/******************************************************************************** ethTxReturnDesc - Free all used Tx descriptors and mBlks.** DESCRIPTION:* This routine returns the transmitted packet information to the caller.* It uses the 'first' index to support Tx desc return in case a transmit * of a packet spanned over multiple buffer still in process.* In case the Tx queue was in "resource error" condition, where there are * no available Tx resources, the function resets the resource error flag.** INPUT:* ETH_PORT_INFO *pEthPortCtrl Ethernet Port Control srtuct. * ETH_QUEUE txQueue Number of Tx queue.* PKT_INFO *pPktInfo User packet buffer.** OUTPUT:* Tx ring 'first' and 'used' indexes are updated. ** RETURN:* ETH_ERROR in case the routine can not access Tx desc ring.* ETH_RETRY in case there is transmission in process.* ETH_END_OF_JOB if the routine has nothing to release.* ETH_OK otherwise.********************************************************************************/ETH_STATUS ethTxReturnDesc(ETH_PORT_INFO *pEthPortCtrl, ETH_PORT_TX_QUEUE txQueue, PKT_INFO *pPktInfo){ volatile ETH_TX_DESC* pTxDescUsed = 0; volatile ETH_TX_DESC* pTxDescFirst = 0; unsigned int commandStatus; /* Get the Tx Desc ring indexes */ USED_TFD_GET (pTxDescUsed, txQueue); FIRST_TFD_GET(pTxDescFirst, txQueue); /* Sanity check */ if(pTxDescUsed == 0) return ETH_ERROR; commandStatus = pTxDescUsed->cmdSts; /* Still transmitting... */ if (commandStatus & (ETH_BUFFER_OWNED_BY_DMA)) { D_CACHE_FLUSH_LINE ((unsigned int)pTxDescUsed, 0); return ETH_RETRY; } /* Stop release. About to overlap the current available Tx descriptor */ if((pTxDescUsed == pTxDescFirst) && (pEthPortCtrl->txResourceErr[txQueue] == 0)) { D_CACHE_FLUSH_LINE ((unsigned int)pTxDescUsed, 0); return ETH_END_OF_JOB; } /* Pass the packet information to the caller */ pPktInfo->cmdSts = commandStatus; pPktInfo->returnInfo = pTxDescUsed->returnInfo; /* Update the next descriptor to release. */ USED_TFD_SET(TX_NEXT_DESC_PTR(pTxDescUsed, txQueue), txQueue); /* Any Tx return cancels the Tx resource error status */ if(pEthPortCtrl->txResourceErr[txQueue]) pEthPortCtrl->txResourceErr[txQueue] = 0; D_CACHE_FLUSH_LINE((unsigned int)pTxDescUsed, 0); return ETH_OK;}/******************************************************************************** ethPortReceive - Get received information from Rx ring.** DESCRIPTION:* This routine returns the received data to the caller. There is no * data copying during routine operation. All information is returned * using pointer to packet information struct passed from the caller. * If the routine exhausts Rx ring resources then the resource error flag * is set. ** INPUT:* ETH_PORT_INFO *pEthPortCtrl Ethernet Port Control srtuct. * ETH_QUEUE rxQueue Number of Rx queue.* PKT_INFO *pPktInfo User packet buffer.** OUTPUT:* Rx ring current and used indexes are updated. ** RETURN:* ETH_ERROR in case the routine can not access Rx desc ring.* ETH_QUEUE_FULL if Rx ring resources are exhausted.* ETH_END_OF_JOB if there is no received data.* ETH_OK otherwise.********************************************************************************/ETH_STATUS ethPortReceive(ETH_PORT_INFO *pEthPortCtrl, ETH_PORT_RX_QUEUE rxQueue, PKT_INFO *pPktInfo){ volatile ETH_RX_DESC *pRxCurrDesc; volatile ETH_RX_DESC *pRxNextCurrDesc; volatile ETH_RX_DESC *pRxUsedDesc; unsigned int commandStatus; /* Do not process Rx ring in case of Rx ring resource error */ if(pEthPortCtrl->rxResourceErr[rxQueue]) return ETH_QUEUE_FULL; /* Get the Rx Desc ring 'curr and 'used' indexes */ CURR_RFD_GET (pRxCurrDesc, rxQueue); USED_RFD_GET (pRxUsedDesc, rxQueue); /* Sanity check */ if (pRxCurrDesc == 0) return ETH_ERROR; /* The following parameters are used to save readings from memory */ pRxNextCurrDesc = RX_NEXT_DESC_PTR(pRxCurrDesc, rxQueue); commandStatus = pRxCurrDesc->cmdSts; /* Nothing to receive... */ if (commandStatus & (ETH_BUFFER_OWNED_BY_DMA)) { D_CACHE_FLUSH_LINE ((unsigned int)pRxCurrDesc, 0); return ETH_END_OF_JOB; } pPktInfo->byteCnt = pRxCurrDesc->byteCnt; pPktInfo->cmdSts = commandStatus; pPktInfo->bufPtr = pRxCurrDesc->bufPtr; pPktInfo->returnInfo = pRxCurrDesc->returnInfo; /* Clean the return info field to indicate that the packet has been */ /* moved to the upper layers */ pRxCurrDesc->returnInfo = 0; /* Update 'curr' in data structure */ CURR_RFD_SET(pRxNextCurrDesc, rxQueue); /* Rx cluster resource exhausted. Set the Rx ring resource error flag */ if (pRxNextCurrDesc == pRxUsedDesc) pEthPortCtrl->rxResourceErr[rxQueue] = 1; D_CACHE_FLUSH_LINE ((unsigned int)pRxCurrDesc, 0); return ETH_OK;}/******************************************************************************** ethRxReturnBuff - Returns a Rx buffer back to the Rx ring.** DESCRIPTION:* This routine returns a Rx buffer back to the Rx ring. It retrieves the * next 'used' descriptor and attached the returned buffer to it.* In case the Rx ring was in "resource error" condition, where there are * no available Rx resources, the function resets the resource error flag.** INPUT:* ETH_PORT_INFO *pEthPortCtrl Ethernet Port Control srtuct. * ETH_QUEUE rxQueue Number of Rx queue.* PKT_INFO *pPktInfo Information on the returned buffer.** OUTPUT:* New available Rx resource in Rx descriptor ring.** RETURN:* ETH_ERROR in case the routine can not access Rx desc ring.* ETH_OK otherwise.********************************************************************************/ETH_STATUS ethRxReturnBuff(ETH_PORT_INFO *pEthPortCtrl, ETH_PORT_RX_QUEUE rxQueue, PKT_INFO *pPktInfo){ volatile ETH_RX_DESC *pUsedRxDesc; /* Where to return Rx resource */ /* Get 'used' Rx descriptor */ USED_RFD_GET(pUsedRxDesc, rxQueue); /* Sanity check */ if (pUsedRxDesc == 0) return ETH_ERROR; pUsedRxDesc->bufPtr = pPktInfo->bufPtr; pUsedRxDesc->returnInfo = pPktInfo->returnInfo; pUsedRxDesc->bufSize = pPktInfo->byteCnt; /* Flush the write pipe */ CPU_PIPE_FLUSH; /* Return the descriptor to DMA ownership */ pUsedRxDesc->cmdSts = ETH_BUFFER_OWNED_BY_DMA | ETH_ENABLE_INTERRUPT; /* Flush descriptor and CPU pipe */ D_CACHE_FLUSH_LINE ((unsigned int)pUsedRxDesc, 0); CPU_PIPE_FLUSH; /* Move the used descriptor pointer to the next descriptor */ USED_RFD_SET(RX_NEXT_DESC_PTR(pUsedRxDesc, rxQueue), rxQueue); /* Any Rx return cancels the Rx resource error status */ if(pEthPortCtrl->rxResourceErr[rxQueue]) pEthPortCtrl->rxResourceErr[rxQueue] = 0; return ETH_OK;}/******************************************************************************** ethBCopy - Copy bytes from source to destination** DESCRIPTION:* This function supports the eight bytes limitation on Tx buffer size. * The routine will zero eight bytes starting from the destination address* followed by copying bytes from the source address to the destination.** INPUT:* unsigned int srcAddr 32 bit source address.* unsigned int dstAddr 32 bit destination address.* int byteCount Number of bytes to copy.** OUTPUT:* See description.** RETURN:* None.********************************************************************************/void ethBCopy(unsigned int srcAddr, unsigned int dstAddr, int byteCount){ while(byteCount != 0) { *(char*)dstAddr = *(char*)srcAddr; dstAddr++; srcAddr++; byteCount--; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -