📄 fei82557end.c
字号:
ETHERMTU, speed) == ERROR) goto errorExit; /* Mark the device ready */ END_OBJ_READY (&pDrvCtrl->endObj, IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST); DRV_LOG (DRV_DEBUG_LOAD, ("fei82557Load... Done \n"), 1, 2, 3, 4, 5, 6); return (&pDrvCtrl->endObj);errorExit: DRV_LOG (DRV_DEBUG_LOAD, "fei82557Load failed\n", 0,0,0,0,0,0); fei82557Unload (pDrvCtrl); free ((char *) pDrvCtrl); return NULL; }/********************************************************************************* fei82557Unload - unload a driver from the system** RETURNS: N/A*/LOCAL STATUS fei82557Unload ( DRV_CTRL *pDrvCtrl /* pointer to DRV_CTRL structure */ ) { DRV_LOG (DRV_DEBUG_LOAD, ("Unloading end..."), 1, 2, 3, 4, 5, 6); pDrvCtrl->attached = FALSE; /* free lists */ END_OBJECT_UNLOAD (&pDrvCtrl->endObj); /* free allocated memory if necessary */ if ((FEI_FLAG_ISSET (FEI_OWN_MEM)) && (pDrvCtrl->pMemBase != NULL)) cacheDmaFree (pDrvCtrl->pMemBase); /* free allocated memory if necessary */ cfree (pDrvCtrl->pMemArea); DRV_LOG (DRV_DEBUG_LOAD, ("fei82557Unload... Done\n"), 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* fei82557InitParse - parse parameter values from initString** RETURNS: OK or ERROR*/LOCAL STATUS fei82557InitParse ( DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */ char * initString /* parameter string */ ) { char * tok; /* an initString token */ char * holder = NULL; /* points to initString fragment beyond tok */ tok = strtok_r (initString, ":", &holder); if (tok == NULL) return ERROR; pDrvCtrl->unit = atoi (tok); tok = strtok_r (NULL, ":", &holder); if (tok == NULL) return ERROR; pDrvCtrl->pMemBase = (char *) strtoul (tok, NULL, 16); tok = strtok_r (NULL, ":", &holder); if (tok == NULL) return ERROR; pDrvCtrl->memSize = strtoul (tok, NULL, 16); tok = strtok_r (NULL, ":", &holder); if (tok == NULL) return ERROR; pDrvCtrl->nCFDs = strtoul (tok, NULL, 16); tok = strtok_r (NULL, ":", &holder); if (tok == NULL) return ERROR; pDrvCtrl->nRFDs = strtoul (tok, NULL, 16); tok = strtok_r (NULL, ":", &holder); if (tok == NULL) return ERROR; pDrvCtrl->flags = atoi (tok); /* offset value is optional, default is zero */ pDrvCtrl->offset = 0; tok = strtok_r (NULL, ":", &holder); if (tok != NULL) pDrvCtrl->offset = atoi (tok); if (!pDrvCtrl->nCFDs || pDrvCtrl->nCFDs <= 2) { FEI_FLAG_SET (FEI_INV_NCFD); pDrvCtrl->nCFDs = DEF_NUM_CFDS; } if (!pDrvCtrl->nRFDs || pDrvCtrl->nRFDs <= 2) { FEI_FLAG_SET (FEI_INV_NRFD); pDrvCtrl->nRFDs = DEF_NUM_RFDS; } DRV_LOG (DRV_DEBUG_LOAD, "fei82557EndLoad: unit=%d pMemBase=0x%x memSize=0x%x\n", pDrvCtrl->unit, (int) pDrvCtrl->pMemBase, (int) pDrvCtrl->memSize, 0,0,0); DRV_LOG (DRV_DEBUG_LOAD, "fei82557EndLoad: nCFDs=%d nRFDs=%d flags=%d offset=%d\n", pDrvCtrl->nCFDs, pDrvCtrl->nRFDs, pDrvCtrl->flags, pDrvCtrl->offset, 0, 0); return (OK); }/********************************************************************************* fei82557InitMem - initialize memory** RETURNS: OK or ERROR*/LOCAL STATUS fei82557InitMem ( DRV_CTRL * pDrvCtrl /* pointer to DRV_CTRL structure */ ) { volatile CFD_ID pCFD; /* pointer to CFDs */ volatile RFD_ID pRFD; /* pointer to RFDs */ UINT32 size; /* temporary size holder */ int ix; /* a counter */ int nRFDLoan; /* number of loaning RFDs */ BOOL firstCFD = TRUE;/* is this the first CFD? */ BOOL firstRFD = TRUE;/* is this the first RFD? */ M_CL_CONFIG fei82557MclBlkConfig = { /* * mBlkNum clBlkNum memArea memSize * ----------- ---- ------- ------- */ 0, 0, NULL, 0 }; CL_DESC fei82557ClDescTbl [] = { /* * clusterSize num memArea memSize * ----------- ---- ------- ------- */ {ETHERMTU + EH_SIZE + 2, 0, NULL, 0} }; int fei82557ClDescTblNumEnt = (NELEMENTS (fei82557ClDescTbl)); /* initialize the netPool */ if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof (NET_POOL))) == NULL) return (ERROR); /* it looks sensible */ nRFDLoan = (pDrvCtrl->nRFDs * FEI_RFD_LOAN_MULTIPLIER); /* * the final 4 is to allow for alignment */ size = (((pDrvCtrl->nRFDs) * CL_RFD_SIZE) + (nRFDLoan * CL_RFD_SIZE) + ((pDrvCtrl->nCFDs) * CFD_SIZE) + 4); /* * Establish the memory area that we will share with the device. If * the caller has provided an area, then we assume it is non-cacheable * and will not require the use of the special cache routines. * If the caller did not provide an area, then we must obtain it from * the system, using the cache savvy allocation routine. */ switch ((int) pDrvCtrl->pMemBase) { case NONE : /* we must obtain it */ /* 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); } pDrvCtrl->pMemBase = cacheDmaMalloc (size); if (pDrvCtrl->pMemBase == NULL) /* no memory available */ { DRV_LOG (DRV_DEBUG_LOAD, ("fei82557EndLoad: could not obtain memory\n"), 1, 2, 3, 4, 5, 6); return (ERROR); } pDrvCtrl->memSize = size; FEI_FLAG_SET (FEI_OWN_MEM); pDrvCtrl->cacheFuncs = cacheDmaFuncs; break; default : /* the user provided an area */ if (pDrvCtrl->memSize == 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. */ if (FEI_FLAG_ISSET (FEI_INV_NCFD) && FEI_FLAG_ISSET (FEI_INV_NRFD)) { pDrvCtrl->nCFDs = pDrvCtrl->nRFDs = (FEI_SAFE_MEM (pDrvCtrl) / ((2 * CL_RFD_SIZE) + CFD_SIZE)); } else if (FEI_FLAG_ISSET (FEI_INV_NCFD)) { pDrvCtrl->nCFDs = ((FEI_SAFE_MEM (pDrvCtrl) - (2 * FEI_RFD_MEM (pDrvCtrl))) / (CFD_SIZE)); } else if (FEI_FLAG_ISSET (FEI_INV_NRFD)) { pDrvCtrl->nRFDs = ((FEI_SAFE_MEM (pDrvCtrl) - FEI_CFD_MEM (pDrvCtrl)) / (2 * CL_RFD_SIZE)); } else { if (pDrvCtrl->memSize < size) { DRV_LOG (DRV_DEBUG_LOAD, ("fei82557EndLoad: not enough memory\n"), 1, 2, 3, 4, 5, 6); return (ERROR); } } if ((pDrvCtrl->nCFDs <= 2) || (pDrvCtrl->nRFDs <= 2)) { DRV_LOG (DRV_DEBUG_LOAD, ("fei82557EndLoad: not enough memory\n"), 1, 2, 3, 4, 5, 6); return (ERROR); } FEI_FLAG_CLEAR (FEI_OWN_MEM); pDrvCtrl->cacheFuncs = cacheNullFuncs; break; } /* zero the shared memory */ memset (pDrvCtrl->pMemBase, 0, (int) pDrvCtrl->memSize); /* pool of mblks */ if (fei82557MclBlkConfig.mBlkNum == 0) fei82557MclBlkConfig.mBlkNum = (pDrvCtrl->nRFDs) * 4; /* pool of clusters, including loaning buffers */ if (fei82557ClDescTbl[0].clNum == 0) { fei82557ClDescTbl[0].clNum = ((pDrvCtrl->nRFDs) * 2); fei82557ClDescTbl[0].clSize = RFD_SIZE; } fei82557ClDescTbl[0].memSize = (fei82557ClDescTbl[0].clNum * (fei82557ClDescTbl[0].clSize + CL_OVERHEAD)); fei82557ClDescTbl[0].memArea = pDrvCtrl->pMemBase + (pDrvCtrl->nCFDs * CFD_SIZE); /* align the shared memory */ fei82557ClDescTbl[0].memArea = (char *) (((u_long) fei82557ClDescTbl[0].memArea + 0x3) & ~0x3); /* pool of cluster blocks */ if (fei82557MclBlkConfig.clBlkNum == 0) fei82557MclBlkConfig.clBlkNum = fei82557ClDescTbl[0].clNum; /* get memory for mblks */ if (fei82557MclBlkConfig.memArea == NULL) { /* memory size adjusted to hold the netPool pointer at the head */ fei82557MclBlkConfig.memSize = ((fei82557MclBlkConfig.mBlkNum * (M_BLK_SZ + 4)) + (fei82557MclBlkConfig.clBlkNum * CL_BLK_SZ + 4)); if ((fei82557MclBlkConfig.memArea = (char *) memalign (4, fei82557MclBlkConfig.memSize)) == NULL) return (ERROR); /* store the pointer to the cluster area */ pDrvCtrl->pMemArea = fei82557MclBlkConfig.memArea; } /* init the mem pool */ if (netPoolInit (pDrvCtrl->endObj.pNetPool, &fei82557MclBlkConfig, &fei82557ClDescTbl[0], fei82557ClDescTblNumEnt, NULL) == ERROR) return (ERROR); if ((pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->endObj.pNetPool, RFD_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->pMemBase; /* 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)); 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); /* 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)); /* set the used CFDs ring to the free one */ pDrvCtrl->pUsedCFD = pDrvCtrl->pFreeCFD; /* * N.B. * Use RFD_C_EL to tie the end of the RBD ring, and not RFD_C_SUSP * This is because we want the option of inserting a new RFD into * the ring on the fly (i.e., via an SCB_RUSTART command). Why would * we do this? Buffer loaning.... A suspend/resume reception model * will not allow us to do this, so we must use an idle/start model. */ /* initialize the RFD ring, some of the fields will be done * in fei82557Start */ for (ix = 0; ix < pDrvCtrl->nRFDs; ix++) { volatile RFD_ID pRFDOld; if ((pRFD = (RFD_ID) netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPoolId)) == NULL) return (ERROR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -