📄 mpltransmit.c
字号:
else
{
// Only one queue to process
priQSel = 0x01;
}
// Process each queue - Start with highest priority
for (qNum = pMplCtx->txQueueCnt;
(qNum > 0x0) && (status == NS_STATUS_SUCCESS);
qNum--)
{
pQueue = qNum - 1; // 0-Indexed
// Check if this queue has any completed packets
if ((1 << pQueue) & priQSel)
{
// Process the Txd ring
while ((pMplCtx->txQueue[pQueue].curr - pMplCtx->txQueue[pQueue].dirty)
> 0x0)
{
// Get the entry index
entry = pMplCtx->txQueue[pQueue].dirty %
pMplCtx->txQueue[pQueue].descCnt;
currTxd = &pMplCtx->txQueue[pQueue].pRing[entry];
// Check if the hardware is done i.e. OWN is cleared
if (currTxd->cmdSts & CS_OWN_ES)
{
break;
}
// Check if we reached limit
if ((maxEvents != 0x0) && (evtCnt >= maxEvents))
{
status = NS_STATUS_ABORTED;
break;
}
// Check if this is the last Txd for this packet
if (currTxd->cmdSts & CS_MORE_ES)
{
// Go to the next Txd
pMplCtx->txQueue[pQueue].dirty++;
continue;
}
// FM : Define event.. Is it per pkt or per processed Txd?
// Below it is defined as per packet
evtCnt++;
// FM : Need to add Stat code for collecting Tx errors
// Prepare indication event to NSM
pMplCtx->txDone[pktCnt].pNsmPrivate = currTxd->mplPriv;
pMplCtx->txDone[pktCnt].cmdSts = MPL_LTOH32(currTxd->cmdSts);
pMplCtx->txDone[pktCnt++].packetStatus =
(currTxd->cmdSts & CS_OK_ES) ?
NS_STATUS_SUCCESS : NS_STATUS_FAILURE;
// Check if it is time to report to NSM
if (pktCnt >= pMplCtx->maxTxDones)
{
NsmTransmitDone(pMplCtx->pClientHandle, pktCnt, pMplCtx->txDone);
pktCnt = 0x0;
}
// Go to the next Txd
pMplCtx->txQueue[pQueue].dirty++;
}
}
}
// Report remaining completed packets to NSM
if (pktCnt > 0x0)
{
NsmTransmitDone(pMplCtx->pClientHandle, pktCnt, pMplCtx->txDone);
}
EXIT(MplTransmitDone);
return status;
}
//*****************************************************************************
// MplTransmitReset
// Resets the transmit engine on the device and associated resources.
// NOTE: This function is non-reentrant with respect to itself,
// MplTransmit and MplTransmitDone
//
// Parameters
// pMplHandle
// MPL device handle returned following a call to MplInitialize
//
// Return Value
// NS_STATUS_SUCCESS
// The transmit engine was successfully reset.
// NS_STATUS_HARDWARE_FAILURE
// Unexpected hardware error - No reset done notification from Hw
//
//*****************************************************************************
MPL_STATUS
MplTransmitReset (
IN NS_VOID *pMplHandle
)
{
MPL_CONTEXT *pMplCtx = (MPL_CONTEXT *)pMplHandle;
MPL_DESC *currTxd;
NS_UINT pQueue, entry, pktCnt = 0x0;
ENTER(MplTransmitReset);
// Make sure we were initialized to begin with
if (pMplCtx->txQueueCnt == 0x0)
{
EXIT(MplTransmitReset);
return NS_STATUS_SUCCESS;
}
// Tell the hardware to reset its Tx engine
MPL_WRITE32(pMplCtx, CR, TXRESET);
// Total 4msec - Not waiting for notification
OaiSleep(4 * RESETINTERVAL_MAC);
// Process each Tx queue
for (pQueue = 0x0; pQueue < pMplCtx->txQueueCnt; pQueue++)
{
// Process the Txd ring - Look for pending packets
while ((pMplCtx->txQueue[pQueue].curr - pMplCtx->txQueue[pQueue].dirty)
> 0x0)
{
// Get the entry index and corresponding Txd
entry = pMplCtx->txQueue[pQueue].dirty %
pMplCtx->txQueue[pQueue].descCnt;
currTxd = &pMplCtx->txQueue[pQueue].pRing[entry];
// If the current Txd is the last one in a packet, report its
// status as ABORTED to NSM
if ((currTxd->cmdSts & CS_MORE_ES) == 0x0)
{
// Prepare indication event to NSM
pMplCtx->txDone[pktCnt].pNsmPrivate = currTxd->mplPriv;
pMplCtx->txDone[pktCnt].cmdSts = 0x0;
pMplCtx->txDone[pktCnt++].packetStatus = NS_STATUS_ABORTED;
// Check if it is time to report to NSM
if (pktCnt >= pMplCtx->maxTxDones)
{
NsmTransmitDone(pMplCtx->pClientHandle, pktCnt, pMplCtx->txDone);
pktCnt = 0x0;
}
}
// Clear Txd
currTxd->cmdSts = 0x0;
currTxd->bufptrPA = 0x0;
currTxd->mplPriv = 0x0;
// Go to the next Txd
pMplCtx->txQueue[pQueue].dirty++;
}
// Reinit the ring
pMplCtx->txQueue[pQueue].curr = 0x0;
pMplCtx->txQueue[pQueue].dirty = 0x0;
pMplCtx->txQueue[pQueue].ringPA =
pMplCtx->txQueue[pQueue].pRgnHndl->phyAddr;
pMplCtx->txQueue[pQueue].pRing =
(MPL_DESC *)pMplCtx->txQueue[pQueue].pRgnHndl->pAddr;
}
// Report remaining pkts to NSM
if (pktCnt > 0x0)
{
NsmTransmitDone(pMplCtx->pClientHandle, pktCnt, pMplCtx->txDone);
}
// Notify the device about the head node on the ring
MPL_WRITE32(pMplCtx, TXDP, pMplCtx->txQueue[0].ringPA);
MPL_WRITE32(pMplCtx, TXDP1, pMplCtx->txQueue[1].ringPA);
MPL_WRITE32(pMplCtx, TXDP2, pMplCtx->txQueue[2].ringPA);
MPL_WRITE32(pMplCtx, TXDP3, pMplCtx->txQueue[3].ringPA);
EXIT(MplTransmitReset);
return NS_STATUS_SUCCESS;
}
//*****************************************************************************
// setTxCfg
// Set the FIFO and DMA burst related configurations on the device
//
// Parameters
// pMplCtx
// Pointer to MPL Context
// pCfgTransmit
// Pointer to a caller allocated MPL_TRANSMIT_CFG structure with
// configuration values for the transmit engine
//
// Return Value
// None
//
//*****************************************************************************
static
NS_VOID
setTxCfg(
IN MPL_CONTEXT *pMplCtx,
IN MPL_TRANSMIT_CFG *pCfgTransmit
)
{
NS_UINT32 txDma, txCfg, drain , fill;
ENTER(setTxCfg);
// Get the Tx DMA size
txDma = 0x0;
if (pCfgTransmit->maxDmaBurst < 8)
txDma = MXDMA4; //Min
else if (pCfgTransmit->maxDmaBurst < 16)
txDma = MXDMA8;
else
if (pCfgTransmit->maxDmaBurst < 32)
txDma = MXDMA16;
else if (pCfgTransmit->maxDmaBurst < 64)
txDma = MXDMA32;
else if (pCfgTransmit->maxDmaBurst < 128)
txDma = MXDMA64;
else if (pCfgTransmit->maxDmaBurst < 256)
txDma = MXDMA128;
else if (pCfgTransmit->maxDmaBurst < 512)
txDma = MXDMA256;
else if (pCfgTransmit->maxDmaBurst < 1024)
txDma = MXDMA512;
else if (pCfgTransmit->maxDmaBurst < 2048)
txDma = (MXDMA256 | TXDMA4);
else
txDma = (MXDMA512 | TXDMA4); //Max
// Read the Txcfg contents
txCfg = MPL_READ32(pMplCtx, TXCFG);
// Mask the tx settable values
txCfg &= ~TXSET_MASK;
// Generate the TXCFG contents - The fill and drain are specified in
// 32 byte units
drain = (pCfgTransmit->drainThreshold / 32) & TXDRAIN_MASK;
fill = ((pCfgTransmit->fillThreshold / 32) << TXFILL_SHIFT) & TXFILL_MASK;
txCfg |= txDma | fill | drain;
// Write TXCFG
MPL_WRITE32(pMplCtx, TXCFG, txCfg);
EXIT(setTxCfg);
return;
}
//*****************************************************************************
// allocTxdRing
// Alloc all the Txd rings
//
// Parameters
// pMplCtx
// Pointer to MPL Context
//
// Return Value
// NS_STATUS_SUCCESS
// The rings were correctly setup
// NS_STATUS_RESOURCES
// Failed to allocate the resources (transmit control blocks)
//
//*****************************************************************************
static
MPL_STATUS
allocTxdRing(
IN MPL_CONTEXT *pMplCtx
)
{
MPL_STATUS status = NS_STATUS_SUCCESS;
NS_UINT i, j;
ENTER(allocTxdRing);
// Allocate resources for the Tx done indications
pMplCtx->txDone = (MPL_TRANSMIT_DONE *)OaiMalloc(sizeof(MPL_TRANSMIT_DONE) *
pMplCtx->maxTxDones);
if (pMplCtx->txDone == NULL)
{
EXIT(allocTxdRing);
return NS_STATUS_RESOURCES;
}
OaiZeroMem(pMplCtx->txDone, sizeof(MPL_TRANSMIT_DONE) * pMplCtx->maxTxDones);
// Allocate memory for the descriptors
for (i = 0x0; i < pMplCtx->txQueueCnt; i++)
{
if (OaiAllocDmaRegion(pMplCtx->pClientHandle,
sizeof(MPL_DESC) * pMplCtx->txQueue[i].descCnt,
4, // Aligned on 32-bits
&pMplCtx->txQueue[i].pRgnHndl) == NS_FALSE)
{
// Allocation failed - Free all prev allocations
for (j = 0x0; j < i; j++)
{
OaiFreeDmaRegion(pMplCtx->pClientHandle,
pMplCtx->txQueue[j].pRgnHndl);
}
OaiFree(sizeof(MPL_TRANSMIT_DONE) * pMplCtx->maxTxDones,
pMplCtx->txDone);
status = NS_STATUS_RESOURCES;
break;
}
else
{
// Reset mem block
OaiZeroMem(pMplCtx->txQueue[i].pRgnHndl->pAddr,
sizeof(MPL_DESC) * pMplCtx->txQueue[i].descCnt);
}
}
EXIT(allocTxdRing);
return status;
}
//*****************************************************************************
// freeTxdRing
// Free the Txd rings
//
// Parameters
// pMplCtx
// Pointer to MPL Context
//
// Return Value
// None
//
//*****************************************************************************
NS_VOID
freeTxdRing(
IN MPL_CONTEXT *pMplCtx
)
{
NS_UINT i;
ENTER(freeTxdRing);
// Free resources for the Tx done indications
if (pMplCtx->txDone != NULL)
{
OaiFree(sizeof(MPL_TRANSMIT_DONE) * pMplCtx->maxTxDones, pMplCtx->txDone);
pMplCtx->txDone = NULL;
}
// Free memory for the descriptors
for (i = 0x0; i < pMplCtx->txQueueCnt; i++)
{
if (pMplCtx->txQueue[i].pRgnHndl != NULL)
{
OaiFreeDmaRegion(pMplCtx->pClientHandle, pMplCtx->txQueue[i].pRgnHndl);
pMplCtx->txQueue[i].pRgnHndl = NULL;
}
}
EXIT(freeTxdRing);
return;
}
//*****************************************************************************
// setupTxdRing
// Setup the Txd Rings
//
// Parameters
// pMplCtx
// Pointer to MPL Context
//
// Return Value
// None
//
//*****************************************************************************
static
NS_VOID
setupTxdRing(
IN MPL_CONTEXT *pMplCtx
)
{
NS_UINT i, j;
ENTER(setupTxdRing);
// Set the Txd rings on each of enabled queue
for (i = 0x0; i < pMplCtx->txQueueCnt; i++)
{
pMplCtx->txQueue[i].curr = 0x0;
pMplCtx->txQueue[i].dirty = 0x0;
// Note the ring's physical and logical start address
pMplCtx->txQueue[i].ringPA = pMplCtx->txQueue[i].pRgnHndl->phyAddr;
pMplCtx->txQueue[i].pRing =
(MPL_DESC *)pMplCtx->txQueue[i].pRgnHndl->pAddr;
for (j = 0x0; j < pMplCtx->txQueue[i].descCnt; j++)
{
// Link up and form a ring
pMplCtx->txQueue[i].pRing[j].linkPA =
MPL_ADDR_HTOL(pMplCtx->txQueue[i].ringPA +
(sizeof(MPL_DESC) *
((j+1) % (pMplCtx->txQueue[i].descCnt))));
// Clear cmdstatus
pMplCtx->txQueue[i].pRing[j].cmdSts = 0x0;
}
}
EXIT(setupTxdRing);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -