/* * eth_tx_flow.cpp * * Created on: 7 ���. 2023 �. * Author: sychev */ #include "free_rtos/ethernet/eth_tx_flow.hpp" #include #include #include #include #include #include #include /*----------------------------------------------------------------------*/ /** * ����� ������������ sysconfig. * ������������ ����� ������� � ���������� � ����� /syscfg */ #include "ti_enet_config.h" /*----------------------------------------------------------------------*/ /** * �������� ������ ��� ��������� ������ � ������ �� � ������� p_packet_queue */ static void eth_initTxFreePktQ(void * appPriv, EnetDma_PktQ * p_packet_queue) { EnetDma_Pkt *pPktInfo; uint32_t i; /// ������������ ���������� ������� int i_max = ENET_SYSCFG_TOTAL_NUM_TX_PKT; /* Initialize TX EthPkts and queue them to txFreePktInfoQ */ for (i = 0U; i < i_max; i++) { /// �������� ������ pPktInfo = EnetMem_allocEthPkt(appPriv, ENET_MEM_LARGE_POOL_PKT_SIZE, ENETDMA_CACHELINE_ALIGNMENT); EnetAppUtils_assert(pPktInfo != NULL); /// ��������� ��� ���� ����� �������� ENET_UTILS_SET_PKT_APP_STATE(&pPktInfo->pktState, ENET_PKTSTATE_APP_WITH_FREEQ); /// ������ ����� � ������� p_packet_queue EnetQueue_enq(p_packet_queue, &pPktInfo->node); } EnetAppUtils_print("initQs() txFreePktInfoQ initialized with %d pkts\r\n", EnetQueue_getQCount(p_packet_queue)); } static uint32_t eth_retrieveFreeTxPkts(EnetDma_TxChHandle * p_handle, EnetDma_PktQ * p_queque) { EnetDma_PktQ txFreeQ; EnetDma_Pkt *pktInfo; uint32_t txFreeQCnt = 0U; int32_t status; EnetQueue_initQ(&txFreeQ); /// ��������� ������ ������� ���� ������� �������� �� ������� ���������� �������� status = EnetDma_retrieveTxPktQ(*p_handle, &txFreeQ); if (status == ENET_SOK) { /// ���������� ������� � ������� txFreeQCnt = EnetQueue_getQCount(&txFreeQ); pktInfo = (EnetDma_Pkt *)EnetQueue_deq(&txFreeQ); while (NULL != pktInfo) { EnetDma_checkPktState(&pktInfo->pktState, ENET_PKTSTATE_MODULE_APP, ENET_PKTSTATE_APP_WITH_DRIVER, ENET_PKTSTATE_APP_WITH_FREEQ); /// �������� ����� � ������� ��������� ������� txFreePktInfoQ EnetQueue_enq(p_queque, &pktInfo->node); pktInfo = (EnetDma_Pkt *)EnetQueue_deq(&txFreeQ); /// ����� ��������� ��������� ����� } } else { EnetAppUtils_print("retrieveFreeTxPkts() failed to retrieve pkts: %d\r\n", status); } return txFreeQCnt; /// ���������� ��������� ������� } free_rtos::EthTxFlow::EthTxFlow() : id_{0}, open_{false}, tx_ch_num_{0} { EnetQueue_initQ(&tx_free_pktq_); } bool free_rtos::EthTxFlow::open(uint32_t id, int32_t enetDmaTxChId) { if (id >= e_ethMacTotal) { return false; } EnetApp_GetDmaHandleInArgs txInArgs; EnetApp_GetTxDmaHandleOutArgs txChInfo; EnetAppUtils_print("tx_flow %u: opening flow...\r\n", id); port_data_[id].tx_pkt_counter = 0; if (open_) { EnetAppUtils_print("tx_flow %u: tx flow is already open. Do nothing.\r\n", id_); return true; } /* Open the TX channel */ txInArgs.notifyCb = nullptr; txInArgs.cbArg = nullptr; EnetApp_getTxDmaHandle(enetDmaTxChId, &txInArgs, &txChInfo); tx_ch_num_ = txChInfo.txChNum; dma_handle_ = txChInfo.hTxCh; EnetAppUtils_assert(txChInfo.useGlobalEvt == true); EnetAppUtils_assert(txChInfo.maxNumTxPkts >= ENET_SYSCFG_TOTAL_NUM_TX_PKT); if (dma_handle_ == nullptr) { EnetAppUtils_print("tx_flow %u: failed to open tx dma flow\r\n", id_); EnetAppUtils_assert(dma_handle_ != nullptr); return false; } eth_initTxFreePktQ(this, &tx_free_pktq_); open_= true; EnetAppUtils_print("tx_flow %u: tx flow open successfully\r\n", id_); return true; } void free_rtos::EthTxFlow::enable(TEthMacPorts port_id) { if (port_id >= e_ethMacTotal) { return; } port_data_[port_id].tx_enable = true; } void free_rtos::EthTxFlow::disable(TEthMacPorts port_id) { if (port_id >= e_ethMacTotal) { return; } port_data_[port_id].tx_enable = false; } bool free_rtos::EthTxFlow::send(TEthMacPorts port_id, uint8_t * p_data, uint32_t len) { if (port_id >= e_ethMacTotal) { return false; } if (!port_data_[port_id].tx_enable) { return false; } EnetDma_PktQ txSubmitQ; EnetDma_Pkt *txPktInfo; int32_t status; /* * ������������ ��������� ������ � �������� enet � ������ �� � ������� ��������� ������� txFreePktInfoQ */ eth_retrieveFreeTxPkts(&dma_handle_, &tx_free_pktq_); /// �������������� ���� txSubmitQ EnetQueue_initQ(&txSubmitQ); /* ������� �� ������� ���� ��������� ����� TX Eth */ txPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&tx_free_pktq_); if (txPktInfo != NULL) { ///�������� ������ ������ � ����� memcpy(txPktInfo->sgList.list[0].bufPtr, p_data, len); txPktInfo->sgList.list[0].segmentFilledLen = len; txPktInfo->sgList.numScatterSegments = 1; txPktInfo->chkSumInfo = 0U; txPktInfo->appPriv = nullptr; txPktInfo->tsInfo.txPktSeqId = 0; txPktInfo->txPktTc = 0; /// Traffic class ����� ��� IPv6 txPktInfo->tsInfo.enableHostTxTs = false; txPktInfo->txPortNum = (Enet_MacPort)port_id; EnetDma_checkPktState(&txPktInfo->pktState, ENET_PKTSTATE_MODULE_APP, ENET_PKTSTATE_APP_WITH_FREEQ, ENET_PKTSTATE_APP_WITH_DRIVER); /// ������ ����� txPktInfo � ������� txSubmitQ EnetQueue_enq(&txSubmitQ, &txPktInfo->node); } else { EnetAppUtils_print("tx_flow %u: Drop due to TX pkt not available\r\n", id_); return false; } /// ������ ������� � ������� DMA status = EnetDma_submitTxPktQ(dma_handle_, &txSubmitQ); if (status != ENET_SOK) { EnetAppUtils_print("tx_flow %u: Failed to submit TX pkt queue: %d\r\n", id_, status); return false; } ++port_data_[port_id].tx_pkt_counter; /// ������� ���������� ������� return true; } bool free_rtos::EthTxFlow::send(TxFlowHandlerArgs& handlerArgs, uint32_t numScatterSegments) { if (handlerArgs.port_id >= e_ethMacTotal) { return false; } if (!port_data_[handlerArgs.port_id].tx_enable) { return false; } EnetDma_PktQ txSubmitQ; EnetDma_Pkt *txPktInfo; int32_t status; eth_retrieveFreeTxPkts(&dma_handle_, &tx_free_pktq_); EnetQueue_initQ(&txSubmitQ); txPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&tx_free_pktq_); if (txPktInfo != NULL) { for(size_t scatter_segment = 0; scatter_segment < numScatterSegments; scatter_segment++) { handlerArgs.buffer = txPktInfo->sgList.list[scatter_segment].bufPtr; txPktInfo->sgList.list[scatter_segment].segmentFilledLen = handlerArgs.stack_handler->Sender(handlerArgs, scatter_segment); } txPktInfo->sgList.numScatterSegments = numScatterSegments; txPktInfo->chkSumInfo = 0U; txPktInfo->appPriv = nullptr; txPktInfo->tsInfo.txPktSeqId = 0; txPktInfo->txPktTc = 0; /// Traffic class ����� ��� IPv6 txPktInfo->tsInfo.enableHostTxTs = false; txPktInfo->txPortNum = (Enet_MacPort)handlerArgs.port_id; EnetDma_checkPktState(&txPktInfo->pktState, ENET_PKTSTATE_MODULE_APP, ENET_PKTSTATE_APP_WITH_FREEQ, ENET_PKTSTATE_APP_WITH_DRIVER); EnetQueue_enq(&txSubmitQ, &txPktInfo->node); } else { EnetAppUtils_print("tx_flow %u: Drop due to TX pkt not available\r\n", id_); return false; } status = EnetDma_submitTxPktQ(dma_handle_, &txSubmitQ); if (status != ENET_SOK) { EnetAppUtils_print("tx_flow %u: Failed to submit TX pkt queue: %d\r\n", id_, status); return false; } ++port_data_[handlerArgs.port_id].tx_pkt_counter; /// ������� ���������� ������� return true; }