📄 mplreceive.c
字号:
// FM: Assert Make sure that this Rxd is empty
// Set up the Rxd
currRxd->cmdSts = MPL_HTOL32(currFrag->fragSize);
currRxd->bufptrPA = MPL_ADDR_HTOL(currFrag->physAddr);
currRxd->mplPriv = currFrag; // Note the Frag Ptr
// Get the next fragment
currFrag = currFrag->pNextFrag;
}
// If we managed to replenish some buffers then re-enable the Rx engine
if ((pMplCtx->rxQueue.curr - pMplCtx->rxQueue.dirty) <
pMplCtx->rxQueue.descCnt)
{
MPL_WRITE32(pMplCtx, CR, RX_EN);
}
// If we have some fragments left over, then return it back to NSM
if (bufFragCount)
{
*pFragList = currFrag;
}
EXIT(MplReceiveReplenish);
return NS_STATUS_SUCCESS;
}
//*****************************************************************************
// MplQueryPacketLength
// Returns the size (in bytes) of the data frame within a MPL_PKT structure
//
// Parameters
// pPacket
// Pointer to the MPL_PKT structure who data frame length is being
// queried.
//
// Return Value
// The total size of the data frame in bytes (could be 0x0 also).
//
//*****************************************************************************
NS_UINT
MplQueryPacketLength (
IN MPL_PKT *pPacket
)
{
ENTER(MplQueryPacketLength);
EXIT(MplQueryPacketLength);
// Return the packet size
return pPacket->packetSize;
}
//*****************************************************************************
// MplReceiveReset
// Resets the receive engine on the device and associated software
// resources.
//
// Parameters
// pMplHandle
// MPL device handle returned following a call to MplInitialize
//
// Return Value
// NS_STATUS_SUCCESS
// The receive engine was successfully reset.
// NS_STATUS_HARDWARE_FAILURE
// Unexpected hardware error - No reset done notification from Hw
//
//*****************************************************************************
MPL_STATUS
MplReceiveReset (
IN NS_VOID *pMplHandle
)
{
MPL_CONTEXT *pMplCtx = (MPL_CONTEXT *)pMplHandle;
NS_UINT entry, pendRxds;
MPL_PKT_FRAG *currFrag;
MPL_DESC *currRxd;
ENTER(MplReceiveReset);
// Make sure we were initialized to begin with
if (pMplCtx->rxQueue.pRgnHndl == NULL)
{
EXIT(MplReceiveReset);
return NS_STATUS_SUCCESS;
}
// Tell the hardware to reset its Rx engine
MPL_WRITE32(pMplCtx, CR, RXRESET);
// Total 4msec - Not waiting for notification
OaiSleep(4 * RESETINTERVAL_MAC);
// Get the starting Rxd and number of Rxds to process
entry = pMplCtx->rxQueue.curr % pMplCtx->rxQueue.descCnt;
currRxd = &pMplCtx->rxQueue.pRing[entry];
pendRxds = pMplCtx->rxQueue.dirty + pMplCtx->rxQueue.descCnt
- pMplCtx->rxQueue.curr;
// Process the Rxd ring - Collect all data buffers in all pending
// Rxds and report them in one big blob
while (pendRxds)
{
// Software OWNs them all
currRxd->cmdSts = CS_OWN_ES;
// Get the frag ptr
currFrag = (MPL_PKT_FRAG *)currRxd->mplPriv;
currRxd->mplPriv = NULL;
// We link all the buffers together
if (pMplCtx->rxQueue.pFragHead == NULL)
pMplCtx->rxQueue.pFragHead = currFrag; // Head frag
else
pMplCtx->rxQueue.pFragTail->pNextFrag = currFrag; // Tail Frag
pMplCtx->rxQueue.fragCnt++;
// Accumulate the frag sizes
pMplCtx->rxQueue.packetSize +=
(MPL_LTOH32(currRxd->cmdSts) & CS_LEN_MASK);
// Add to the tail of pending list
pMplCtx->rxQueue.pFragTail = currFrag;
// Get the next Rxd and Read its cmdSts
entry = (++pMplCtx->rxQueue.curr) % pMplCtx->rxQueue.descCnt;
currRxd = &pMplCtx->rxQueue.pRing[entry];
pendRxds--;
}
// If we managed to salvage any buffer fragments, report it in one blob
if (pMplCtx->rxQueue.fragCnt)
{
// We have all Rxd frags for this abort pkt - Prepare a indication
pMplCtx->rxDone[0x0].fragCount = pMplCtx->rxQueue.fragCnt;
pMplCtx->rxDone[0x0].pFragHead = pMplCtx->rxQueue.pFragHead;
pMplCtx->rxDone[0x0].rxOOB.cmdSts = 0x0;
pMplCtx->rxDone[0x0].packetSize = pMplCtx->rxQueue.packetSize;
pMplCtx->rxDone[0x0].packetStatus = NS_STATUS_ABORTED;
NsmReceive(pMplCtx->pClientHandle, 0x1, pMplCtx->rxDone);
}
// Clean up partial tracker
pMplCtx->rxQueue.pFragHead = pMplCtx->rxQueue.pFragTail = NULL;
pMplCtx->rxQueue.fragCnt = pMplCtx->rxQueue.packetSize = 0x0 ;
// Reset pointers
pMplCtx->rxQueue.dirty = 0x0;
pMplCtx->rxQueue.curr = pMplCtx->rxQueue.descCnt;
pMplCtx->rxQueue.ringPA = pMplCtx->rxQueue.pRgnHndl->phyAddr;
pMplCtx->rxQueue.pRing = (MPL_DESC *)pMplCtx->rxQueue.pRgnHndl->pAddr;
// Notify the device about the head node on the ring
MPL_WRITE32(pMplCtx, RXDP, pMplCtx->rxQueue.ringPA);
EXIT(MplReceiveReset);
return NS_STATUS_SUCCESS;
}
//*****************************************************************************
// MplReceiveGetEmptyDesc
// Returns the count of the Rxds that are empty i.e. no attached buffers
//
// Parameters
// pMplHandle
// MPL device handle returned following a call to MplInitialize
// pQueue
// Queue (1,2...max tx queues) from which the empty count is desired
// pRxdCnt
// Pointer to a caller allocated fields in which the count of empty
// receive descriptors is returned
//
// Return Value
// NS_STATUS_SUCCESS
// The count was successfully returned.
// NS_STATUS_INVALID_PARM
// The priority queue count is invalid
//
//*****************************************************************************
MPL_STATUS
MplReceiveGetEmptyDesc (
IN NS_VOID *pMplHandle,
IN NS_UINT8 pQueue,
OUT NS_UINT *pRxdCnt
)
{
MPL_CONTEXT *pMplCtx = (MPL_CONTEXT *)pMplHandle;
ENTER(MplReceiveGetEmptyDesc);
// Get the empty Rxd count
*pRxdCnt = pMplCtx->rxQueue.curr - pMplCtx->rxQueue.dirty;
EXIT(MplReceiveGetEmptyDesc);
return NS_STATUS_SUCCESS;
}
//+++++ Local Functions
//#####################
//*****************************************************************************
// setRxCfg
// Set the FIFO and DMA burst related configurations on the device
//
// Parameters
// pMplCtx
// Pointer to MPL Context
// pCfgReceive
// Pointer to a caller allocated MPL_RECEIVE_CFG structure with
// configuration values for the receive engine
//
// Return Value
// None
//
//*****************************************************************************
static
NS_VOID
setRxCfg(
IN MPL_CONTEXT *pMplCtx,
IN MPL_RECEIVE_CFG *pCfgReceive
)
{
NS_UINT32 rxDma, rxCfg, drain;
ENTER(setRxCfg);
// Get the Rx DMA size
rxDma = 0x0;
if (pCfgReceive->maxDmaBurst < 8)
rxDma = MXDMA4; //Min
else if (pCfgReceive->maxDmaBurst < 16)
rxDma = MXDMA8;
else
if (pCfgReceive->maxDmaBurst < 32)
rxDma = MXDMA16;
else if (pCfgReceive->maxDmaBurst < 64)
rxDma = MXDMA32;
else if (pCfgReceive->maxDmaBurst < 128)
rxDma = MXDMA64;
else if (pCfgReceive->maxDmaBurst < 256)
rxDma = MXDMA128;
else if (pCfgReceive->maxDmaBurst < 512)
rxDma = MXDMA256;
else if (pCfgReceive->maxDmaBurst < 1024)
rxDma = MXDMA512;
else if (pCfgReceive->maxDmaBurst < 2048)
rxDma = (MXDMA256 | RXDMA4);
else
rxDma = (MXDMA512 | RXDMA4); //Max
// Read the Rxcfg contents
rxCfg = MPL_READ32(pMplCtx, RXCFG);
// Mask the rx settable values
rxCfg &= ~RXSET_MASK;
// Generate the RXCFG contents - The drain threshold is specified in
// 8 byte units
drain = ((pCfgReceive->drainThreshold / 8) & 0x1F) << RXDRAIN_SHIFT;
rxCfg |= rxDma | drain;
// Write RXCFG
MPL_WRITE32(pMplCtx, RXCFG, rxCfg);
EXIT(setRxCfg);
return;
}
//*****************************************************************************
// allocRxdRing
// Alloc all the Rxd 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 (receive control blocks)
//
//*****************************************************************************
static
MPL_STATUS
allocRxdRing(
IN MPL_CONTEXT *pMplCtx
)
{
MPL_STATUS status = NS_STATUS_SUCCESS;
ENTER(allocRxdRing);
// Allocate resources for the Rx done indication packets
pMplCtx->rxDone = (MPL_PKT *)
OaiMalloc(sizeof(MPL_PKT) * pMplCtx->maxRxDones);
if (pMplCtx->rxDone == NULL)
{
return NS_STATUS_RESOURCES;
}
OaiZeroMem(pMplCtx->rxDone, sizeof(MPL_PKT) * pMplCtx->maxRxDones);
// Allocate memory for the descriptors
if (OaiAllocDmaRegion(pMplCtx->pClientHandle,
sizeof(MPL_DESC) * pMplCtx->rxQueue.descCnt,
4, // Aligned on 32-bits
&pMplCtx->rxQueue.pRgnHndl) == NS_FALSE)
{
// Allocation failed - Free all prev allocations
OaiFree(sizeof(MPL_PKT) * pMplCtx->maxRxDones, pMplCtx->rxDone);
status = NS_STATUS_RESOURCES;
}
else
{
// Reset mem block
OaiZeroMem(pMplCtx->rxQueue.pRgnHndl->pAddr,
sizeof(MPL_DESC) * pMplCtx->rxQueue.descCnt);
}
EXIT(allocRxdRing);
return status;
}
//*****************************************************************************
// freeRxdRing
// Free the Rxd rings
//
// Parameters
// pMplCtx
// Pointer to MPL Context
//
// Return Value
// None
//
//*****************************************************************************
NS_VOID
freeRxdRing(
IN MPL_CONTEXT *pMplCtx
)
{
ENTER(freeRxdRing);
// Free resources for the Rx done indications
if (pMplCtx->rxDone != NULL)
{
OaiFree(sizeof(MPL_PKT) * pMplCtx->maxRxDones, pMplCtx->rxDone);
pMplCtx->rxDone = NULL;
}
// Free memory for the descriptors
if (pMplCtx->rxQueue.pRgnHndl != NULL)
{
OaiFreeDmaRegion(pMplCtx->pClientHandle, pMplCtx->rxQueue.pRgnHndl);
pMplCtx->rxQueue.pRgnHndl = NULL;
}
EXIT(freeRxdRing);
return;
}
//*****************************************************************************
// setupRxdRing
// Setup the Rxd Ring
//
// Parameters
// pMplCtx
// Pointer to MPL Context
//
// Return Value
// None
//
//*****************************************************************************
static
NS_VOID
setupRxdRing(
IN MPL_CONTEXT *pMplCtx
)
{
NS_UINT j;
// Dirty % Ring_Size = First empty Rxd (i.e. no buf attached)
// Curr % Ring_Size = First full Rxd (i.e. buf attached)
// If (Curr == Dirty) => All Rxds have data bufs attached
// If ((Curr - Dirty) == Ring_Size) => None of the Rxds have data bufs
// attached
ENTER(setupRxdRing);
pMplCtx->rxQueue.dirty = 0x0;
pMplCtx->rxQueue.curr = pMplCtx->rxQueue.descCnt;
pMplCtx->rxQueue.ringPA = pMplCtx->rxQueue.pRgnHndl->phyAddr;
pMplCtx->rxQueue.pRing = (MPL_DESC *)pMplCtx->rxQueue.pRgnHndl->pAddr;
for (j = 0x0; j < pMplCtx->rxQueue.descCnt; j++)
{
// Link up and form a ring
pMplCtx->rxQueue.pRing[j].linkPA =
MPL_ADDR_HTOL(pMplCtx->rxQueue.ringPA +
(sizeof(MPL_DESC) *
((j+1) % (pMplCtx->rxQueue.descCnt))));
// We OWN the Rxd (Till it is attached with a buffer)
pMplCtx->rxQueue.pRing[j].cmdSts = CS_OWN_ES;
pMplCtx->rxQueue.pRing[j].bufptrPA = 0x0;
}
// Link up the Rx Indication packets also
for (j = 0x0; j < (pMplCtx->maxRxDones - 1); j++)
{
pMplCtx->rxDone[j].pNextPacket = &pMplCtx->rxDone[j+1];
}
EXIT(setupRxdRing);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -