📄 ln97xend.c
字号:
if (!CACHE_DMA_IS_WRITE_COHERENT ()) { printf ( "ln97x: device requires cache coherent memory\n" ); return (ERROR); } pDrvCtrl->pShMem = (char *) cacheDmaMalloc (sz); if ((int)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; /* Set up the structures to allow us to free data after sending it. */ for (ix = 0; ix < pDrvCtrl->rringSize; ix++) { pDrvCtrl->freeRtn[ix] = NULL; pDrvCtrl->freeData[ix].arg1 = NULL; pDrvCtrl->freeData[ix].arg2 = NULL; } /* 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 ((int)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; 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); }/********************************************************************************* 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->lastError.errCode = END_ERR_WARN; pDrvCtrl->lastError.pMesg = "Babbling"; netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj, (int) &pDrvCtrl->lastError, 0, 0, 0); DRV_LOG (DRV_DEBUG_INT, "Babbling\n", 1, 2, 3, 4, 5, 6); } if (stat & CSR0_MISS) { pDrvCtrl->lastError.errCode = END_ERR_WARN; pDrvCtrl->lastError.pMesg = "Missing"; netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj, (int) &pDrvCtrl->lastError, 0, 0, 0); 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->lastError.errCode = END_ERR_RESET; pDrvCtrl->lastError.pMesg = "Memory error."; netJobAdd ((FUNCPTR)muxError, (int) &pDrvCtrl->endObj, (int)&pDrvCtrl->lastError, 0, 0, 0); DRV_LOG (DRV_DEBUG_INT, "Memory error, restarting.\n", 1, 2, 3, 4, 5, 6); END_FLAGS_CLR (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING)); ln97xRestart (pDrvCtrl); return; } } /* Have netTask handle any input packets */ if ((stat & CSR0_RINT) && (stat & CSR0_RXON)) { if (!(pDrvCtrl->flags & LS_RCV_HANDLING_FLAG)) { pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG; (void) netJobAdd ((FUNCPTR)ln97xHandleRecvInt, (int)pDrvCtrl, 0,0,0,0); } } /* * Did LANCE update any of the TMD's? * If not then don't bother continuing with transmitter stuff */ if (!(stat & CSR0_TINT)) return; DRV_LOG (DRV_DEBUG_INT, "t ", 1, 2, 3, 4, 5, 6); if (!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 */ ) { LN_RMD * pRmd = (LN_RMD *)NULL; do { pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG; while ((pRmd = ln97xFullRMDGet (pDrvCtrl)) != (LN_RMD *)NULL) { LN_CACHE_INVALIDATE (pRmd, RMD_SIZ); ln97xRecv (pDrvCtrl, pRmd); }; /* * There is a RACE right here. The ISR could add a receive packet * and check the boolean below, and decide to exit. Thus the * packet could be dropped if we don't double check before we * return. */ pDrvCtrl->flags &= ~LS_RCV_HANDLING_FLAG; } while (ln97xFullRMDGet (pDrvCtrl) != NULL); /* this double check solves the RACE */ }/********************************************************************************* ln97xFullRMDGet - get next received message RMD** Returns ptr to next Rx desc to process, or NULL if none ready.*/LOCAL LN_RMD * ln97xFullRMDGet ( LN_97X_DRV_CTRL * pDrvCtrl /* device to be initialized */ ) { LN_RMD * pRmd; pRmd = pDrvCtrl->pRring + pDrvCtrl->rmdIndex; /* form ptr to Rx desc */ /* If receive buffer has been released to us, return it */ if ((PCI_SWAP (pRmd->rBufRmd1) & RMD1_OWN) == 0) return (pRmd); else return ((LN_RMD *) NULL); }/********************************************************************************* ln97xRecv - process the next incoming packet** RETURNS: OK/ERROR*/LOCAL STATUS ln97xRecv ( LN_97X_DRV_CTRL * pDrvCtrl, /* device to be initialized */ LN_RMD * pRmd ) { int len; M_BLK_ID pMblk; char * pCluster; char * pNewCluster; char * pTemp; CL_BLK_ID pClBlk; UINT32 rmd1Tmp; /* Packet must be checked for errors, Read rmd1 once only */ rmd1Tmp = PCI_SWAP (pRmd->rBufRmd1); DRV_LOG (DRV_DEBUG_TX, "Recv : rmd1 = %X index = %d\n", rmd1Tmp, pDrvCtrl->rmdIndex, 3, 4, 5, 6); /* If error flag OR if packet is not completely in one buffer */ if ((rmd1Tmp & RMD1_ERR) || (rmd1Tmp & (RMD1_STP | RMD1_ENP)) != (RMD1_STP | RMD1_ENP)) { DRV_LOG (DRV_DEBUG_RX, "RMD error!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); goto cleanRXD; /* skip to clean up */ } /* If we cannot get a buffer to loan then bail out. */ pNewCluster = netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPoolId); if (pNewCluster == NULL) { DRV_LOG (DRV_DEBUG_RX, "Cannot loan!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); goto cleanRXD; } if ((pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)) == NULL) { netClFree (pDrvCtrl->endObj.pNetPool, pNewCluster); DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); goto cleanRXD; } /* * OK we've got a spare, let's get an M_BLK_ID and marry it to the * one in the ring.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -