sitara_depot/components/free_rtos/ethernet/eth_tx_flow.cpp

285 lines
9.4 KiB
C++
Raw Blame History

/*
* eth_tx_flow.cpp
*
* Created on: 7 <20><><EFBFBD>. 2023 <20>.
* Author: sychev
*/
#include "free_rtos/ethernet/eth_tx_flow.hpp"
#include <cstring>
#include <networking/enet/core/include/core/enet_soc.h>
#include <networking/enet/core/include/core/enet_queue.h>
#include <networking/enet/utils/include/enet_board.h>
#include <networking/enet/utils/include/enet_appmemutils.h>
#include <networking/enet/utils/include/enet_appmemutils_cfg.h>
#include <networking/enet/utils/include/enet_apputils.h>
/*----------------------------------------------------------------------*/
/**
* <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> sysconfig.
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD> <build_name>/syscfg
*/
#include "ti_enet_config.h"
/*----------------------------------------------------------------------*/
/**
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> p_packet_queue
*/
static void eth_initTxFreePktQ(void * appPriv, EnetDma_PktQ * p_packet_queue)
{
EnetDma_Pkt *pPktInfo;
uint32_t i;
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int i_max = (ENET_SYSCFG_TOTAL_NUM_TX_PKT);
/* Initialize TX EthPkts and queue them to txFreePktInfoQ */
for (i = 0U; i < i_max; i++)
{
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
pPktInfo = EnetMem_allocEthPkt(appPriv,
ENET_MEM_LARGE_POOL_PKT_SIZE,
ENETDMA_CACHELINE_ALIGNMENT);
EnetAppUtils_assert(pPktInfo != NULL);
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ENET_UTILS_SET_PKT_APP_STATE(&pPktInfo->pktState, ENET_PKTSTATE_APP_WITH_FREEQ);
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 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);
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
status = EnetDma_retrieveTxPktQ(*p_handle, &txFreeQ);
if (status == ENET_SOK)
{
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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);
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> txFreePktInfoQ
EnetQueue_enq(p_queque, &pktInfo->node);
pktInfo = (EnetDma_Pkt *)EnetQueue_deq(&txFreeQ); /// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
}
}
else
{
EnetAppUtils_print("retrieveFreeTxPkts() failed to retrieve pkts: %d\r\n", status);
}
return txFreeQCnt; /// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
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;
EnetQueue_initQ(&txSubmitQ);
eth_retrieveFreeTxPkts(&dma_handle_, &tx_free_pktq_);
txPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&tx_free_pktq_);
if (txPktInfo != NULL)
{
///<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD>
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 <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> 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);
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> txPktInfo <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> txSubmitQ
EnetQueue_enq(&txSubmitQ, &txPktInfo->node);
}
else
{
EnetAppUtils_print("tx_flow %u: Drop due to TX pkt not available\r\n", id_);
return false;
}
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 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; /// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return true;
}
bool free_rtos::EthTxFlow::send(TxFlowHandlerArgs& handlerArgs, uint32_t numScatterSegments)
{
if (handlerArgs.port_id >= e_ethMacTotal) {
EnetAppUtils_print("Wrong port id\r\n");
return false;
}
if (port_data_[handlerArgs.port_id].tx_enable == false) {
return false;
}
EnetDma_PktQ txSubmitQ;
EnetDma_Pkt *txPktInfo;
int32_t status;
EnetQueue_initQ(&txSubmitQ);
eth_retrieveFreeTxPkts(&dma_handle_, &tx_free_pktq_);
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, 0);
}
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)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; /// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
return true;
}