📄 fei82557end.c
字号:
DRV_CTRL * pDrvCtrl /* pointer to DRV_CTRL structure */
)
{
CFD_ID pCFD; /* pointer to CFDs */
RFD_ID pRFD; /* pointer to RFDs */
RFD_TAG * pRfdTag;
RBD_ID pRBD; /* pointer to RFDs */
RBD_TAG * pRbdTag;
UINT32 clSize; /* size of allocation for clusters */
UINT32 clusterSize; /* size of allocation for clusters */
UINT32 memSize; /* size of allocation passed by BSP */
UINT32 nSubtract = 1; /* number of RFDs to subtract */
UINT32 rfdSize; /* size of allocation for RFDs */
UINT32 rbdSize; /* size of allocation for RBDs */
UINT32 cfdSize; /* size of allocation for CFDs */
int ix; /* index counter */
BOOL firstCFD = TRUE;/* the first CFD? */
int firstOrLast;
M_CL_CONFIG fei82557MclBlkConfig =
{
/*
* mBlkNum clBlkNum memArea memSize
* ----------- ---- ------- -------
*/
0, 0, NULL, 0
};
CL_DESC fei82557ClDescTbl [] =
{
/*
* clusterSize num memArea memSize
* ----------- ---- ------- -------
*/
{CLUSTER_SIZE, 0, NULL, 0}
};
int fei82557ClDescTblNumEnt = (NELEMENTS (fei82557ClDescTbl));
/* initialize the netPool */
if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof (NET_POOL))) == NULL)
return (ERROR);
/* this driver can't handle write incoherent caches */
if (!CACHE_DMA_IS_WRITE_COHERENT ())
{
DRV_LOG (DRV_DEBUG_LOAD, ("fei82557EndLoad: shared
memory not cache coherent\n"),
1, 2, 3, 4, 5, 6);
return (ERROR);
}
switch ((int) pDrvCtrl->pClusterBase)
{
case NONE : /* we must obtain it */
clSize = (pDrvCtrl->nClusters * CLUSTER_SIZE);
/* Add one to rfdSize, rbdSize, & cfdSize to accomodate alignment */
rfdSize = ((pDrvCtrl->nRFDs + 1) * RFD_DESC_SIZE);
rbdSize = ((pDrvCtrl->nRBDs + 1) * RBD_SIZE);
cfdSize = ((pDrvCtrl->nCFDs + 1) * CFD_SIZE);
/* Align on 32 byte boundries */
if ((pDrvCtrl->pRfdBase = cacheDmaMalloc (rfdSize + rbdSize +
cfdSize)) == NULL)
{
return (ERROR);
}
memset (pDrvCtrl->pRfdBase, 0, (rfdSize + rbdSize + cfdSize));
pDrvCtrl->pRfdBase = (char *)ROUND_UP((UINT32) pDrvCtrl->pRfdBase,
32);
pDrvCtrl->rfdTags = (RFD_TAG *)pDrvCtrl->pRfdBase;
pDrvCtrl->pRFD = (RFD_ID)pDrvCtrl->pRfdBase;
pDrvCtrl->pRbdBase = (char *)((int)pDrvCtrl->pRfdBase + rfdSize);
pDrvCtrl->rbdTags = (RBD_TAG *)pDrvCtrl->pRbdBase;
pDrvCtrl->pCfdBase = (char *)((int)pDrvCtrl->pRbdBase + rbdSize);
pDrvCtrl->pClusterBase = memalign (_CACHE_ALIGN_SIZE, clSize);
if (pDrvCtrl->pClusterBase == NULL) /* no memory available */
{
DRV_LOG (DRV_DEBUG_LOAD, ("fei82557EndLoad: could not
obtain memory\n"),
1, 2, 3, 4, 5, 6);
return (ERROR);
}
/* zero the shared memory */
memset(pDrvCtrl->pClusterBase,0,clSize);
pDrvCtrl->clMemSize = clSize;
FEI_FLAG_SET (FEI_OWN_MEM);
pDrvCtrl->cacheDmaFuncs = cacheDmaFuncs;
pDrvCtrl->cacheFuncs = cacheUserFuncs;
pDrvCtrl->pSendRtn = (FUNCPTR)fei82557GatherSend;
break;
default : /* the user provided an area */
if (pDrvCtrl->clMemSize == 0)
{
DRV_LOG (DRV_DEBUG_LOAD, ("fei82557EndLoad: not enough
memory\n"),
1, 2, 3, 4, 5, 6);
return (ERROR);
}
/*
* check the user provided enough memory with reference
* to the given number of receive/transmit frames, if any.
*/
while ((pDrvCtrl->nRBDs * RBD_SIZE) > (nSubtract * CLUSTER_SIZE))
{
nSubtract++;
}
rfdSize = ((pDrvCtrl->nRFDs + 1) * RFD_DESC_SIZE);
rbdSize = ((pDrvCtrl->nRBDs + 1) * RBD_SIZE);
cfdSize = (pDrvCtrl->nCFDs * (CFD_SIZE + CLUSTER_SIZE));
clusterSize = (((pDrvCtrl->nRFDs + 1) * 2) * CLUSTER_SIZE);
memSize = rfdSize + rbdSize + cfdSize + clusterSize;
if (pDrvCtrl->clMemSize < memSize)
{
DRV_LOG (DRV_DEBUG_LOAD, ("fei82557EndLoad: not enough
memory\n"), 1, 2, 3, 4, 5, 6);
return (ERROR);
}
/* zero the shared memory */
memset(pDrvCtrl->pClusterBase,0,pDrvCtrl->clMemSize);
memSize = pDrvCtrl->clMemSize - (rfdSize + rbdSize + cfdSize);
pDrvCtrl->nClusters = ((memSize / CLUSTER_SIZE) - nSubtract);
pDrvCtrl->pRfdBase = pDrvCtrl->pClusterBase;
pDrvCtrl->rfdTags = (RFD_TAG *)pDrvCtrl->pRfdBase;
pDrvCtrl->pRFD = (RFD_ID)pDrvCtrl->pRfdBase;
pDrvCtrl->pRbdBase = (char *)((int)pDrvCtrl->pRfdBase + rfdSize);
pDrvCtrl->rbdTags = (RBD_TAG *)pDrvCtrl->pRbdBase;
pDrvCtrl->pClusterBase = (char *)((int)pDrvCtrl->pRbdBase +
rbdSize);
pDrvCtrl->pCfdBase = (char *)((int)pDrvCtrl->pClusterBase +
(pDrvCtrl->nClusters * CLUSTER_SIZE));
FEI_FLAG_CLEAR (FEI_OWN_MEM);
pDrvCtrl->cacheDmaFuncs = cacheNullFuncs;
pDrvCtrl->cacheFuncs = cacheDmaFuncs;
pDrvCtrl->pSendRtn = (FUNCPTR)fei82557CopySend;
break;
}
/* pool of mblks */
if (fei82557MclBlkConfig.mBlkNum == 0)
fei82557MclBlkConfig.mBlkNum = pDrvCtrl->nClusters * 10;
/* pool of clusters */
if (fei82557ClDescTbl[0].clNum == 0)
{
fei82557ClDescTbl[0].clNum = pDrvCtrl->nClusters;
fei82557ClDescTbl[0].clSize = CLUSTER_SIZE;
}
fei82557ClDescTbl[0].memSize = pDrvCtrl->clMemSize;
fei82557ClDescTbl[0].memArea = pDrvCtrl->pClusterBase;
DRV_LOG (DRV_DEBUG_LOAD, ("fei82557EndLoad: pClusterBase %p nClusters %d
cluster size %x\n"),
(int)pDrvCtrl->pClusterBase,pDrvCtrl->nClusters,
CLUSTER_SIZE,0,0,0);
/* pool of cluster blocks */
if (fei82557MclBlkConfig.clBlkNum == 0)
fei82557MclBlkConfig.clBlkNum = (fei82557ClDescTbl[0].clNum * 2);
/* get memory for mblks */
if (fei82557MclBlkConfig.memArea == NULL)
{
/* memory size adjusted to hold the netPool pointer at the head */
fei82557MclBlkConfig.memSize = (((fei82557MclBlkConfig.mBlkNum + 1) *
MBLK_SIZE) +
((fei82557MclBlkConfig.clBlkNum + 1) *
CLBLK_SIZE));
if ((fei82557MclBlkConfig.memArea =
(char *) (memalign (_CACHE_ALIGN_SIZE,
fei82557MclBlkConfig.memSize)) +
(MBLK_SIZE - sizeof(long)))
== NULL)
return (ERROR);
/* store the pointer to the cluster block area */
pDrvCtrl->pMclBlkMemArea = fei82557MclBlkConfig.memArea;
}
/* init the mem pool */
if (netPoolInit (pDrvCtrl->endObj.pNetPool, &fei82557MclBlkConfig,
&fei82557ClDescTbl[0], fei82557ClDescTblNumEnt,
_pEndNetPoolFuncTbl) == ERROR)
return (ERROR);
if ((pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->endObj.pNetPool,
CLUSTER_SIZE, FALSE)) == NULL)
return (ERROR);
/* carve up the shared-memory region */
/*
* N.B.
* We are setting up the CFD ring as a ring of TxCBs, tied off with a
* CFD_C_SUSP as frames are copied into the data buffers. The
* susp/resume model is used because the links to the next CFDs do
* not change -- it is a fixed ring. Also note that if a CFD is needed
* for anything else (e.g., DIAG, NOP, DUMP, CONFIG, or IASETUP comands),
* then the commands will use the current CFD in the ring. After the
* command is complete, it will be set back to a TxCB by fei82557Action().
*/
/* First ready CFD pointer */
pCFD = pDrvCtrl->pFreeCFD = (CFD_ID) pDrvCtrl->pCfdBase;
/* initialize the CFD ring */
for (ix = 0; ix < pDrvCtrl->nCFDs; ix++)
{
CFD_WORD_WR (pCFD, CFD_STAT_OFFSET,
(CFD_S_COMPLETE | CFD_S_OK));
/* tie the current CFD to the next one */
CFD_NEXT_WR (pCFD, ((UINT32) pCFD + CFD_SIZE));
CFD_LONG_WR (pCFD, CFD_SW_NEXT_OFFSET, ((UINT32) pCFD + CFD_SIZE));
if (!firstCFD)
{
/* Previous CFD pointer */
CFD_LONG_WR (pCFD, CFD_PREV_OFFSET,
((UINT32) pCFD - CFD_SIZE));
}
else
{
/* remember this CFD */
pDrvCtrl->pFreeCFD = pCFD;
/* tie the first CFD to the last one */
CFD_LONG_WR (pCFD, CFD_PREV_OFFSET,
((UINT32) pCFD + (CFD_SIZE * (pDrvCtrl->nCFDs - 1))));
firstCFD = FALSE;
}
/* no TBDs used */
CFD_TBD_WR (pCFD, (UINT32) TBD_NOT_USED);
CFD_BYTE_WR (pCFD, CFD_NUM_OFFSET, 0);
CFD_LONG_WR (pCFD, CFD_MBLK_OFFSET, 0);
/* set the thresh value */
CFD_BYTE_WR (pCFD, CFD_THRESH_OFFSET,
pDrvCtrl->board.tcbTxThresh);
/* bump to the next CFD */
pCFD = (CFD_ID) ((UINT32) pCFD + CFD_SIZE);
}
pCFD = (CFD_ID) ((UINT32) pCFD - CFD_SIZE);
/* tie the last CFD to the first one */
CFD_NEXT_WR (pCFD, ((UINT32) pDrvCtrl->pFreeCFD));
CFD_LONG_WR (pCFD, CFD_SW_NEXT_OFFSET, ((UINT32) pDrvCtrl->pFreeCFD));
/* set the used CFDs ring to the free one */
pDrvCtrl->pUsedCFD = pDrvCtrl->pFreeCFD;
/* Initialize the RFDs and RBDs */
for (ix = 0; ix < pDrvCtrl->nRFDs; ix++)
{
pRFD = (RFD_ID)((int)pDrvCtrl->pRfdBase + (ix * RFD_DESC_SIZE));
pRBD = (RBD_ID)((int)pDrvCtrl->pRbdBase + (ix * RBD_SIZE));
pRbdTag = (RBD_TAG *)pRBD;
pRbdTag->pRBD = pRBD;
pRbdTag->pRFD = pRFD;
pRbdTag->index = ix;
if ((pRbdTag->pMblk = netTupleGet(pDrvCtrl->endObj.pNetPool,CLUSTER_SIZE,
M_DONTWAIT, MT_DATA,0)) == NULL)
{
return (ERROR);
}
pRbdTag->pMblk->mBlkHdr.mData =
(char *)((int)pRbdTag->pMblk->mBlkHdr.mData +
pDrvCtrl->offset);
RBD_BUF_WR (pRBD, (UINT32)pRbdTag->pMblk->mBlkHdr.mData);
pRfdTag = (RFD_TAG *)pRFD;
pRfdTag->index = ix;
pRfdTag->nextIndex = (ix + 1) % pDrvCtrl->nRFDs;
pRfdTag->status = 0;
pRfdTag->pRFD = pRFD;
if (ix == 0)
firstOrLast = FIRST_RFD;
else if (ix == pDrvCtrl->nRFDs - 1)
firstOrLast = LAST_RFD;
else
firstOrLast = MID_RFD;
switch (firstOrLast)
{
case FIRST_RFD: /* first */
/* Set first RFD's RBD address pointer to first RBD */
RFD_RBD_WR (pRFD, (UINT32)pDrvCtrl->pRbdBase);
/* Set the RFD's next pointer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -