📄 ibmemacend.c
字号:
* MAL this EMAC is attached to. */ tok = strtok_r (NULL, ":", ppHolder); if (tok == NULL) return ERROR; pDrvCtrl->pMalData = (MAL_DATA *)strtoul (tok, NULL, 16); /* * Fourteenth parameter is the OPB bus speed in MHz. */ tok = strtok_r (NULL, ":", ppHolder); if (tok == NULL) return ERROR; pDrvCtrl->opbSpeedMhz = atoi (tok); return OK; }/********************************************************************************* ibmEmacMemInit - initialize memory required for the driver** Using data in the control structure (some of which came from the* initialization string), setup and initialize the memory regions as needed.** RETURNS: OK or ERROR.*/LOCAL STATUS ibmEmacMemInit ( EMAC_DRV_CTRL * pDrvCtrl ) { UINT32 tempSize; int i, j; MAL_BD * pTempDesc; char * pTempBuf; /* * If a memory region was specified in the initialization string, determine * if it is large enough to hold the minimum number of buffers (clusters). * It is assumed that this memory is not cached. Descriptor memory has * already been allocated by malLib. */ if ((int)pDrvCtrl->memInputAdrs != NONE) { pDrvCtrl->memAdrs = pDrvCtrl->memInputAdrs; pDrvCtrl->memSize = pDrvCtrl->memInputSize; /* If not properly aligned, align it */ while ((int)pDrvCtrl->memAdrs & (pDrvCtrl->cacheLineSize - 1)) { pDrvCtrl->memAdrs++; pDrvCtrl->memSize--; } /* initialize the space */ bzero((char *)pDrvCtrl->memAdrs, pDrvCtrl->memSize); if (pDrvCtrl->memSize > EMAC_MIN_MEM_SIZE) { /* * Determine the number of buffers this region can hold, and * determine the numbers of descriptors needed for both TX and * RX. */ tempSize = pDrvCtrl->memSize; if (tempSize > EMAC_MAX_MEM_SIZE) tempSize = EMAC_MAX_MEM_SIZE; /* * Give half of the descriptors to the RX channel, the rest to the * TX channel(s). */ tempSize = tempSize / EMAC_BSC_MEM_SIZE; pDrvCtrl->numRxD = tempSize / 2; if (pDrvCtrl->inputFlags & EMAC_INPUT_TX_2_CHANNEL) { pDrvCtrl->txInfo[0].numTxD = (tempSize - pDrvCtrl->numRxD) / 2; pDrvCtrl->txInfo[1].numTxD = pDrvCtrl->txInfo[0].numTxD; } else { pDrvCtrl->txInfo[0].numTxD = tempSize - pDrvCtrl->numRxD; } /* Assume the memory is cache safe, copy null structure */ pDrvCtrl->cacheFuncs = cacheNullFuncs; } else { printf("MemSize specified in the ibmEmacEnd load string is not\n"); printf("large enough. It must be at least %d bytes.\n", EMAC_MIN_MEM_SIZE); } } /* * If a memory region was not specified in the load string, allocate one * (default size). Buffer memory does NOT have to be cache safe (i.e. * uncached) If buffer memory is cached, this driver will manage cache * coherency. */ if ((int)pDrvCtrl->memInputAdrs == NONE) { /* * Allocate the default sized chunk of memory to hold buffers. * The inputFlags parameter that was passed into the load string * indicates whether the buffers should be allocated from cached * or cache safe memory. * Add the size of a cache line because it may have to be * adjusted for proper cache line alignment. */ pDrvCtrl->memSizeMalloc = EMAC_DFT_MEM_SIZE + pDrvCtrl->cacheLineSize; if (pDrvCtrl->inputFlags & EMAC_INPUT_UNCACHED_BUF) { /* Allocate cache safe (uncached) memory for buffers */ pDrvCtrl->memAdrsMalloc = cacheDmaMalloc(pDrvCtrl->memSizeMalloc); pDrvCtrl->cacheFuncs = cacheDmaFuncs; } else { /* * Allocate cached memory for buffers * Specify the flush and invalidate functions needed to maintain * data cache coherency. */ pDrvCtrl->memAdrsMalloc = malloc(pDrvCtrl->memSizeMalloc); pDrvCtrl->cacheFuncs.flushRtn = cacheFlush; pDrvCtrl->cacheFuncs.invalidateRtn = cacheInvalidate; } if (pDrvCtrl->memAdrsMalloc == NULL) { printf("Could not allocate memory for ibmEmacEnd\n"); return(ERROR); } /* Initialize region to zeros */ bzero((char *)pDrvCtrl->memAdrsMalloc, pDrvCtrl->memSizeMalloc); /* Adjust the alignment. Put on a cache line boundary */ pDrvCtrl->memAdrs = pDrvCtrl->memAdrsMalloc; pDrvCtrl->memSize = pDrvCtrl->memSizeMalloc; while ((int)pDrvCtrl->memAdrs & (pDrvCtrl->cacheLineSize - 1)) { pDrvCtrl->memAdrs++; pDrvCtrl->memSize--; } DRV_LOG (DRV_DEBUG_INFO, "Buffer space = 0x%x size = 0x%x\n", pDrvCtrl->memAdrs, pDrvCtrl->memSize, 3, 4, 5, 6); pDrvCtrl->numRxD = EMAC_RXD_DFT; /* * Depending on how many TX channels are being used, TX channel 0 gets * all of the allotted TX descriptors, or half. TX channel 1 gets what * is left. */ pDrvCtrl->txInfo[0].numTxD = EMAC_TXD_DFT / pDrvCtrl->numTxChannels; pDrvCtrl->txInfo[1].numTxD = EMAC_TXD_DFT - pDrvCtrl->txInfo[0].numTxD; } /* Get the address of the TX descriptor tables */ malChannelDescTblPtrGet(pDrvCtrl->pMalData, MAL_TX_TYPE, pDrvCtrl->txChn0MalChannel, &pDrvCtrl->txInfo[0].pTxDesc); DRV_LOG (DRV_DEBUG_INFO, "TX 0 Desc Ring 0x%x\n", pDrvCtrl->txInfo[0].pTxDesc, 2, 3, 4, 5, 6); malChannelDescTblPtrGet(pDrvCtrl->pMalData, MAL_TX_TYPE, pDrvCtrl->txChn1MalChannel, &pDrvCtrl->txInfo[1].pTxDesc); DRV_LOG (DRV_DEBUG_INFO, "TX 1 Desc Ring 0x%x\n", pDrvCtrl->txInfo[1].pTxDesc, 2, 3, 4, 5, 6); /* * Initialize the arrays that will be used by SendCleanup to free clusters * or mBlks after a packet has been transmitted. */ for (i = 0; i < pDrvCtrl->numTxChannels; i++) { for (j = 0; j < pDrvCtrl->txInfo[i].numTxD; j++) { pDrvCtrl->txInfo[i].txFree[j].typeFree = EMAC_TX_FREE_NONE; pDrvCtrl->txInfo[i].txFree[j].pFree = NULL; } } /* * Allocate memory for a net pool structure, and initialize it. * There will be one cluster for each descriptor, one cluster block * for each cluster, and two mBlks for each cluster block. */ pDrvCtrl->end.pNetPool = malloc(sizeof(NET_POOL)); if (pDrvCtrl->end.pNetPool == NULL) return (ERROR); pDrvCtrl->clDesc.clNum = (pDrvCtrl->numRxD * EMAC_RXD_LOAN_X) + pDrvCtrl->txInfo[0].numTxD + pDrvCtrl->txInfo[1].numTxD; pDrvCtrl->mClCfg.clBlkNum = pDrvCtrl->clDesc.clNum; pDrvCtrl->mClCfg.mBlkNum = pDrvCtrl->mClCfg.clBlkNum * 2; /* Determine the memory required to hold all mBlks and clBlks */ pDrvCtrl->mClCfg.memSize = (pDrvCtrl->mClCfg.mBlkNum * (M_BLK_SZ + sizeof (long))) + (pDrvCtrl->mClCfg.clBlkNum * (CL_BLK_SZ + sizeof (long))); /* Allocate memory to hold the mBlk and clBlk structures*/ pDrvCtrl->mClCfg.memArea = memalign(sizeof(long), pDrvCtrl->mClCfg.memSize); if (pDrvCtrl->mClCfg.memArea == NULL) return (ERROR); DRV_LOG (DRV_DEBUG_INFO, "mBlk clBlk storage = 0x%x size = 0x%x\n", pDrvCtrl->mClCfg.memArea, pDrvCtrl->mClCfg.memSize, 3, 4, 5, 6); /* * Finally determine the memory required to hold all of the clusters. * The size of a cluster MUST be an even multiple of the cache line size. * Memory for the clusters was allocated above. */ pDrvCtrl->clDesc.clSize = EMAC_BUF_SIZE; pDrvCtrl->clDesc.memSize = pDrvCtrl->clDesc.clNum * (pDrvCtrl->clDesc.clSize + sizeof(long)); pDrvCtrl->clDesc.memArea = (char *)pDrvCtrl->memAdrs; /* Initialize the net pool */ if (netPoolInit (pDrvCtrl->end.pNetPool, &pDrvCtrl->mClCfg, &pDrvCtrl->clDesc, 1, NULL) == ERROR) { DRV_LOG (DRV_DEBUG_ERROR, "Could not init buffering\n", 1, 2, 3, 4, 5, 6); return (ERROR); } /* Get and save the net cluster pool id */ pDrvCtrl->pClPoolId = clPoolIdGet(pDrvCtrl->end.pNetPool, EMAC_BUF_SIZE, FALSE); /* * Get the address of the RX channel descriptor table. * Go ahead and get a cluster from the pool for each of the RX descriptors. * Assign each of the clusters to one of the RX descriptors. * This is done to make the driver almost ready to receive packets. */ malChannelDescTblPtrGet(pDrvCtrl->pMalData, MAL_RX_TYPE, pDrvCtrl->rxChn0MalChannel, &pDrvCtrl->pRxDesc); DRV_LOG (DRV_DEBUG_INFO, "RX Desc Ring 0x%x\n", pDrvCtrl->pRxDesc, 2, 3, 4, 5, 6); pTempDesc = pDrvCtrl->pRxDesc; for (i = 0; i < pDrvCtrl->numRxD; i++) { pTempBuf = netClusterGet(pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId); if (pTempBuf == NULL) { DRV_LOG (DRV_DEBUG_LOAD, "Get RX cluster from pool failed\n", 1, 2, 3, 4, 5, 6); return (ERROR); } /* Put the cluster address in the buffer addr field of the descriptor */ pTempDesc[i].bufferAdrs = pTempBuf; } return OK; }/********************************************************************************* ibmEmacStart - start the device** This function calls BSP functions to connect interrupts and start the* device running in interrupt mode.** RETURNS: OK or ERROR*/LOCAL STATUS ibmEmacStart ( EMAC_DRV_CTRL * pDrvCtrl ) { int rc; DRV_LOG (DRV_DEBUG_START, "ibmEmacStart \n", 1, 2, 3, 4, 5, 6); pDrvCtrl->localFlags &= ~EMAC_TX_CLEAN_RUNNING; pDrvCtrl->localFlags &= ~EMAC_TX_BLOCKED; /* * Connect, clear status, then enable the Ethernet interrupt. * This interrupt is primarily for error conditions. * MAL handles interrupts for TX/RX end-of-buffer, and descriptor errors. */ EMAC_INT_CONNECT (pDrvCtrl, ibmEmacInt, pDrvCtrl, &rc); EMAC_REG_WRITE(pDrvCtrl, EMAC_ISR, 0xFFFFFFFF); EMAC_INT_ENABLE (pDrvCtrl); /* Allow MAL EOB and Descriptor error interrupts */ malChannelIntMaskSet(pDrvCtrl->pMalData, MAL_TX_TYPE, pDrvCtrl->txChn0MalChannel, MAL_EOB_INT_EN | MAL_DE_INT_EN | MAL_SERR_INT_EN); if (pDrvCtrl->inputFlags & EMAC_INPUT_TX_2_CHANNEL) malChannelIntMaskSet(pDrvCtrl->pMalData, MAL_TX_TYPE, pDrvCtrl->txChn1MalChannel, MAL_EOB_INT_EN | MAL_DE_INT_EN | MAL_SERR_INT_EN); malChannelIntMaskSet(pDrvCtrl->pMalData, MAL_RX_TYPE, pDrvCtrl->rxChn0MalChannel, MAL_EOB_INT_EN | MAL_DE_INT_EN | MAL_SERR_INT_EN); DRV_LOG (DRV_DEBUG_START, "TX and RX channels active.\n", 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* ibmEmacInt - handle EMAC controller interrupt** This routine is called at interrupt level in response to an interrupt from* the EMAC controller. The interrupt occurs because of TX or RX error* conditions.**/LOCAL void ibmEmacInt ( EMAC_DRV_CTRL * pDrvCtrl ) { UINT isrReg; UINT isrClear; /* Read the EMAC interrupt status register */ EMAC_REG_READ(pDrvCtrl, EMAC_ISR, isrReg); pDrvCtrl->errorEmac = isrReg; DRV_LOG (DRV_DEBUG_ENET_INT, "EMAC Ethernet int 0x%x\n", isrReg, 2, 3, 4, 5, 6); /* * Check to see if there was a TX error. If there was, the Dead bit * will be set. Clear the status bits for the TX error, and clear the * dead bit. Keep count of these errors in the main device structure. * * Note that non-zero values of EMAC_ISR_TX_INTS are used primarily * for debugging. When EMAC_ISR_TX_INTS is zero, some compilers * may warn about an always-false conditional expression. */ if (isrReg & EMAC_ISR_TX_INTS) { pDrvCtrl->intErrorTX++; if (pDrvCtrl->inputFlags & EMAC_INPUT_TX_2_CHANNEL) isrClear = EMAC_ISR_TX_INTS | EMAC_ISR_DB0 | EMAC_ISR_DB1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -