📄 ln97xend.c
字号:
/* Add it all up */ sz = (((1 << lnRsize) + 1) * RMD_SIZ) + (((1 << lnTsize) + 1) * TMD_SIZ) + IB_SIZ + 0x10; /***** Establish a region of shared memory *****/ /* OK. We now know how much shared memory we need. If the caller * provides a specific memory region, we check to see if the provided * region is large enough for our needs. If the caller did not * provide a specific region, then we attempt to allocate the memory * from the system, using the cache aware allocation system call. */ switch ((int) pDrvCtrl->memAdrs) { default : /* caller provided memory */ if (pDrvCtrl->memSize < sz) /* not enough space */ { DRV_LOG (DRV_DEBUG_LOAD, "ln97x: not enough memory provided\n" "ln97x: need %ul got %d\n", sz, pDrvCtrl->memSize, 3, 4, 5, 6); return (ERROR); } /* set the beginning of pool */ pDrvCtrl->pShMem = pDrvCtrl->memAdrs; /* assume pool is cache coherent, copy null structure */ pDrvCtrl->cacheFuncs = cacheNullFuncs; DRV_LOG (DRV_DEBUG_LOAD, "Memory checks out\n", 1, 2, 3, 4, 5, 6); break; case NONE : /* get our own memory */ /* Because the structures that are shared between the device * and the driver may share cache lines, the possibility exists * that the driver could flush a cache line for a structure and * wipe out an asynchronous change by the device to a neighboring * structure. Therefore, this driver cannot operate with memory * that is not write coherent. We check for the availability of * such memory here, and abort if the system did not give us what * we need. */ if (!CACHE_DMA_IS_WRITE_COHERENT ()) { printf ( "ln97x: device requires cache coherent memory\n" ); return (ERROR); } pDrvCtrl->pShMem = (char *) cacheDmaMalloc (sz); if (pDrvCtrl->pShMem == NULL) { printf ( "ln97x: system memory unavailable\n" ); return (ERROR); } /* copy the DMA structure */ pDrvCtrl->cacheFuncs = cacheDmaFuncs; break; } /* Turkey Carving * -------------- * * LOW MEMORY * * |-------------------------------------| * | The initialization block | * | (sizeof (LN_IB)) | * |-------------------------------------| * | The Rx descriptors | * | (1 << lnRsize) * sizeof (LN_RMD) | * |-------------------------------------| * | The Tx descriptors | * | (1 << lnTsize) * sizeof (LN_TMD) | * |-------------------------------------| */ /* Save some things */ pDrvCtrl->memBase = (char *)((UINT32)pDrvCtrl->pShMem & 0xff000000); if ((int) pDrvCtrl->memAdrs == NONE) pDrvCtrl->flags |= LS_MEM_ALLOC_FLAG; /* first let's clear memory */ bzero ( (char *) pDrvCtrl->pShMem, (int) sz ); /* setup Rx memory pointers */ pDrvCtrl->pRring = (LN_RMD *) ((int)pDrvCtrl->pShMem + IB_SIZ); pDrvCtrl->rringLen = lnRsize; pDrvCtrl->rringSize = 1 << lnRsize; pDrvCtrl->rmdIndex = 0; /* setup Tx memory pointers. */ /* Note: +2 is to round up to alignment. */ pDrvCtrl->pTring = (LN_TMD *) (int)(pDrvCtrl->pShMem + IB_SIZ + ((1 << lnRsize) + 1) * RMD_SIZ + 0xf); pDrvCtrl->pTring = (LN_TMD *) (((int)pDrvCtrl->pTring + 0xf) & ~0xf); pDrvCtrl->tringSize = 1 << lnTsize; pDrvCtrl->tringLen = lnTsize; pDrvCtrl->tmdIndex = 0; pDrvCtrl->tmdIndexC = 0; /* allocate pool structure for mblks, clBlk, and clusters */ if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof(NET_POOL))) == NULL) return (ERROR);#ifdef DRV_DEBUG pLan97xNetPool = pDrvCtrl->endObj.pNetPool;#endif pDrvCtrl->clDesc.clNum = pDrvCtrl->rringSize * 2; pDrvCtrl->mClCfg.clBlkNum = pDrvCtrl->clDesc.clNum; pDrvCtrl->mClCfg.mBlkNum = pDrvCtrl->mClCfg.clBlkNum * 2; /* total memory size for mBlks and clBlks */ pDrvCtrl->mClCfg.memSize = (pDrvCtrl->mClCfg.mBlkNum * (MSIZE + sizeof (long))) + (pDrvCtrl->mClCfg.clBlkNum * (CL_BLK_SZ + sizeof (long))); /* total memory for mBlks and clBlks */ if ((pDrvCtrl->mClCfg.memArea = (char *) memalign (sizeof(long), pDrvCtrl->mClCfg.memSize)) == NULL) return (ERROR); /* total memory size for all clusters */ pDrvCtrl->clDesc.clSize = LN_BUFSIZ; pDrvCtrl->clDesc.memSize = (pDrvCtrl->clDesc.clNum * (pDrvCtrl->clDesc.clSize + 8)) + sizeof(int); /* Do we hand over our own memory? */ if (pDrvCtrl->memAdrs != (char *)NONE) { pDrvCtrl->clDesc.memArea = (char *)(pDrvCtrl->pTring + pDrvCtrl->tringSize); } else { pDrvCtrl->clDesc.memArea = cacheDmaMalloc (pDrvCtrl->clDesc.memSize); if (pDrvCtrl->clDesc.memArea == NULL) { DRV_LOG(DRV_DEBUG_LOAD, "system memory unavailable\n", 1, 2, 3, 4, 5, 6); return (ERROR); } } /* initialize the device net pool */ if (netPoolInit (pDrvCtrl->endObj.pNetPool, &pDrvCtrl->mClCfg, &pDrvCtrl->clDesc, 1, NULL) == ERROR) { DRV_LOG (DRV_DEBUG_LOAD, "Could not init buffering\n", 1, 2, 3, 4, 5, 6); return (ERROR); } /* Store the cluster pool id as others need it later. */ pDrvCtrl->pClPoolId = clPoolIdGet (pDrvCtrl->endObj.pNetPool, LN_BUFSIZ, FALSE); /* Longword align rmd ring */ pDrvCtrl->pRring = (LN_RMD *) (((int)pDrvCtrl->pRring + 0xf) & ~0xf); pDrvCtrl->pRring = (LN_RMD *) (((int)pDrvCtrl->pRring + 0xf) & ~0xf); pRmd = pDrvCtrl->pRring; DRV_LOG (DRV_DEBUG_LOAD, "Using %d RX buffers from 0x%X\n", pDrvCtrl->rringSize, (int)pRmd, 3, 4, 5, 6); for (ix = 0; ix < pDrvCtrl->rringSize; ix++, pRmd++) { if ((pTempBuf = (char *)netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPoolId)) == NULL) { DRV_LOG (DRV_DEBUG_LOAD, "Could not get a buffer\n", 1, 2, 3, 4, 5, 6); return (ERROR); } pTempBuf += pDrvCtrl->offset; LN_RMD_BUF_TO_ADDR (pRmd, pTemp, pTempBuf); } return OK; }/********************************************************************************* ln97xStart - 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 ln97xStart ( LN_97X_DRV_CTRL * pDrvCtrl /* device to be initialized */ ) { STATUS result; pDrvCtrl->txCleaning = FALSE; pDrvCtrl->txBlocked = FALSE; SYS_INT_CONNECT (pDrvCtrl, ln97xInt, (int)pDrvCtrl, &result); if (result == ERROR) return ERROR; /* mark the interface as up */ END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING)); DRV_LOG (DRV_DEBUG_LOAD, "Interrupt connected.\n", 1, 2, 3, 4, 5, 6); SYS_INT_ENABLE (); DRV_LOG (DRV_DEBUG_LOAD, "interrupt enabled.\n", 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* ln97xHandleError - handle controller interrupt errors** This routine is called to process controller errors at a task level that * were detecected in interrupt context.** RETURNS: N/A.*/LOCAL void ln97xHandleError ( LN_97X_DRV_CTRL *pDrvCtrl ) { u_short stat; pDrvCtrl->errorHandling = FALSE; stat = pDrvCtrl->errorStat; pDrvCtrl->errorStat &= ~stat; if (stat & CSR0_MERR) { pDrvCtrl->lastError.errCode = END_ERR_RESET; pDrvCtrl->lastError.pMesg = "Memory error."; muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError); } if (stat & CSR0_BABL) { pDrvCtrl->lastError.errCode = END_ERR_WARN; pDrvCtrl->lastError.pMesg = "Babbling"; muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError); } if (stat & CSR0_MISS) { pDrvCtrl->lastError.errCode = END_ERR_WARN; pDrvCtrl->lastError.pMesg = "Missing"; muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError); } return; }/********************************************************************************* ln97xInt - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.*/LOCAL void ln97xInt ( LN_97X_DRV_CTRL * pDrvCtrl /* device to be initialized */ ) { UINT32 stat; /* Read the device status register */ stat = ln97xCsrRead (pDrvCtrl, 0); DRV_LOG (DRV_DEBUG_INT, "i=0x%x:\n", stat, 2, 3, 4, 5, 6); /* If false interrupt, return. */ if (! (stat & CSR0_INTR)) { DRV_LOG (DRV_DEBUG_INT, "False interrupt.\n", 1, 2, 3, 4, 5, 6); return; } /* * enable interrupts, clear receive and/or transmit interrupts, and clear * any errors that may be set. * Writing back what was read clears all interrupts */ ln97xCsrWrite (pDrvCtrl, 0, stat); /* Check for errors */ if (stat & (CSR0_BABL | CSR0_MISS | CSR0_MERR)) { END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); if (stat & CSR0_BABL) { pDrvCtrl->errorStat |= CSR0_BABL; if (!pDrvCtrl->errorHandling) { if (netJobAdd ((FUNCPTR) ln97xHandleError, (int) pDrvCtrl , 2, 3, 4, 5) == OK) { pDrvCtrl->errorHandling = TRUE; } } DRV_LOG (DRV_DEBUG_INT, "Babbling\n", 1, 2, 3, 4, 5, 6); } if (stat & CSR0_MISS) { pDrvCtrl->errorStat |= CSR0_MISS; if (!pDrvCtrl->errorHandling) { if (netJobAdd ((FUNCPTR) ln97xHandleError, (int) pDrvCtrl , 2, 3, 4, 5) == OK) { pDrvCtrl->errorHandling = TRUE; } } DRV_LOG (DRV_DEBUG_INT, "Missing\n", 1, 2, 3, 4, 5, 6); } /* restart chip on fatal error */ if (stat & CSR0_MERR) /* memory error */ { pDrvCtrl->errorStat |= CSR0_MERR; if (!pDrvCtrl->errorHandling) { if (netJobAdd ((FUNCPTR) ln97xHandleError, (int) pDrvCtrl , 2, 3, 4, 5) == OK) { pDrvCtrl->errorHandling = TRUE; } } DRV_LOG (DRV_DEBUG_INT, "Memory error, restarting.\n", 1, 2, 3, 4, 5, 6); END_FLAGS_CLR (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING)); /* Only reset device if Restart will occur */ if (netJobAdd ((FUNCPTR) ln97xRestart, (int) pDrvCtrl , 2, 3, 4, 5) == OK) { ln97xReset (pDrvCtrl); } return; } } /* Have netTask handle any input packets */ if ((stat & CSR0_RINT) && (stat & CSR0_RXON) && !(pDrvCtrl->flags & LS_RCV_HANDLING_FLAG) ) { if (netJobAdd ((FUNCPTR)ln97xHandleRecvInt, (int)pDrvCtrl , 0,0,0,0) == OK) { pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG; } } /* * Did LANCE update any of the TMD's? * If not then don't bother continuing with transmitter stuff */ if ((stat & CSR0_TINT) && (!pDrvCtrl->txCleaning)) { pDrvCtrl->txCleaning = TRUE; netJobAdd ((FUNCPTR)ln97xTRingScrub, (int) pDrvCtrl, 0, 0, 0, 0); } if (pDrvCtrl->txBlocked) /* cause a restart */ { pDrvCtrl->txBlocked = FALSE; netJobAdd ((FUNCPTR)muxTxRestart, (int) &pDrvCtrl->endObj, 0, 0, 0, 0); } /* Flush the write pipe */ CACHE_PIPE_FLUSH (); return; }/********************************************************************************* ln97xHandleRecvInt - task level interrupt service for input packets** This routine is called at task level indirectly by the interrupt* service routine to do any message received processing.*/LOCAL void ln97xHandleRecvInt ( LN_97X_DRV_CTRL * pDrvCtrl /* device to be initialized */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -