sitara_depot/components/free_rtos/ethernet/eth_tx_flow.cpp

288 lines
7.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* eth_tx_flow.cpp
*
* Created on: 7 мар. 2023 г.
* 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>
#include <task.h>
/*----------------------------------------------------------------------*/
#include "ti_enet_config.h"
/*----------------------------------------------------------------------*/
static void eth_initTxFreePktQ(void * appPriv, EnetDma_PktQ * p_packet_queue, uint32_t qCount)
{
EnetDma_Pkt *pPktInfo;
uint32_t i;
uint32_t scatterSegmentSize[1] = {ENET_MEM_LARGE_POOL_PKT_SIZE};
/* Initialize TX EthPkts and queue them to txFreePktInfoQ */
for (i = 0U; i < qCount; i++)
{
pPktInfo = EnetMem_allocEthPkt(appPriv,
ENETDMA_CACHELINE_ALIGNMENT,
1,
scatterSegmentSize);
EnetAppUtils_assert(pPktInfo != NULL);
ENET_UTILS_SET_PKT_APP_STATE(&pPktInfo->pktState, ENET_PKTSTATE_APP_WITH_FREEQ);
EnetQueue_enq(p_packet_queue, &pPktInfo->node);
}
EnetAppUtils_print("initQs() txFreePktInfoQ initialized with %d pkts\r\n",
EnetQueue_getQCount(p_packet_queue));
}
void free_rtos::txIsrHandler(void *appData)
{
EthTxFlow * tx_flow = (EthTxFlow *)appData;
if(tx_flow == nullptr) {
return;
}
tx_flow->retrieveFreeTxPktQ();
tx_flow->sem_[EthTxFlow::e_signalTxPkt].post();
}
free_rtos::EthTxFlow::EthTxFlow() :
default_port_id_{e_ethMac0},
open_{false},
tx_ch_num_{0}
{
EnetQueue_initQ(&tx_free_pktq_);
}
bool free_rtos::EthTxFlow::open(TEthMacPorts port_id, int32_t enetDmaTxChId)
{
if (port_id >= e_ethMacTotal) {
return false;
}
EnetApp_GetDmaHandleInArgs txInArgs;
EnetApp_GetTxDmaHandleOutArgs txChInfo;
EnetAppUtils_print("tx_flow %u: opening flow...\r\n", port_id);
port_data_[port_id].tx_pkt_counter = 0;
if (open_) {
EnetAppUtils_print("tx_flow %u: tx flow is already open. Do nothing.\r\n", port_id);
return true;
}
/* Open the TX channel */
txInArgs.notifyCb = txIsrHandler;
txInArgs.cbArg = this;
EnetApp_getTxDmaHandle(enetDmaTxChId, &txInArgs, &txChInfo);
default_port_id_ = port_id;
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", port_id);
EnetAppUtils_assert(dma_handle_ != nullptr);
return false;
}
eth_initTxFreePktQ(this, &tx_free_pktq_, ENET_SYSCFG_TOTAL_NUM_TX_PKT);
open_= true;
EnetAppUtils_print("tx_flow %u: tx flow open successfully\r\n", port_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;
}
void free_rtos::EthTxFlow::retrieveFreeTxPktQ()
{
EnetDma_PktQ txFreeQ;
EnetDma_Pkt *pktInfo;
int32_t status;
EnetQueue_initQ(&txFreeQ);
status = EnetDma_retrieveTxPktQ(dma_handle_, &txFreeQ);
if (status != ENET_SOK)
{
EnetAppUtils_print("retrieveFreeTxPktQ() failed to retrieve pkts: %d\r\n", status);
return;
}
EnetAppUtils_validatePacketState( &txFreeQ,
ENET_PKTSTATE_APP_WITH_DRIVER,
ENET_PKTSTATE_APP_WITH_FREEQ);
EnetQueue_append(&tx_free_pktq_, &txFreeQ);
}
EnetDma_Pkt* free_rtos::EthTxFlow::getTxPktInfo()
{
EnetDma_Pkt *txPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&tx_free_pktq_);
while(txPktInfo == NULL)
{
sem_[EthTxFlow::e_signalTxPkt].pend();
txPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&tx_free_pktq_);
}
return txPktInfo;
}
bool free_rtos::EthTxFlow::send(TEthMacPorts port_id, uint8_t * p_data, uint32_t len)
{
if (port_id >= e_ethMacTotal) {
EnetAppUtils_print("Wrong port id\r\n");
return false;
}
if (!port_data_[port_id].tx_enable) {
return false;
}
EnetDma_PktQ txSubmitQ;
EnetDma_Pkt *txPktInfo;
int32_t status;
EnetQueue_initQ(&txSubmitQ);
txPktInfo = getTxPktInfo();
if (txPktInfo == NULL)
{
EnetAppUtils_print("tx_flow %u: Drop due to TX pkt not available\r\n", port_id);
return false;
}
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);
EnetQueue_enq(&txSubmitQ, &txPktInfo->node);
status = EnetDma_submitTxPktQ(dma_handle_, &txSubmitQ);
if (status != ENET_SOK)
{
EnetAppUtils_print("tx_flow %u: Failed to submit TX pkt queue: %d\r\n", port_id, status);
return false;
}
++port_data_[port_id].tx_pkt_counter;
return true;
}
bool free_rtos::EthTxFlow::send(TxFlowHandlerArgs& handlerArgs, uint32_t numScatterSegments)
{
TEthMacPorts port_id = handlerArgs.port_id;
if (port_id >= e_ethMacTotal) {
EnetAppUtils_print("Wrong port id\r\n");
return false;
}
if (port_data_[port_id].tx_enable == false) {
return false;
}
EnetDma_PktQ txSubmitQ;
EnetDma_Pkt *txPktInfo;
int32_t status;
EnetQueue_initQ(&txSubmitQ);
txPktInfo = getTxPktInfo();
if (txPktInfo == NULL)
{
EnetAppUtils_print("tx_flow %u: Drop due to TX pkt not available\r\n", port_id);
return false;
}
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)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);
status = EnetDma_submitTxPktQ(dma_handle_, &txSubmitQ);
if (status != ENET_SOK)
{
EnetAppUtils_print("tx_flow %u: Failed to submit TX pkt queue: %d\r\n", port_id, status);
return false;
}
++port_data_[handlerArgs.port_id].tx_pkt_counter;
return true;
}