📄 ln7990end.c
字号:
break; } /* Turkey Carving * -------------- * * LOW MEMORY * * |-------------------------------------| * | The initialization block | * | (sizeof (ln_ib)) | * |-------------------------------------| * | The Rx descriptors | * | ((1 << lnRsize) + 1)*sizeof (ln_rmd)| * |-------------------------------------| * | The Tx descriptors | * | ((1 << lnTsize) + 1)*sizeof (ln_tmd)| * |-------------------------------------| */ /* align */ pDrvCtrl->pShMem = (char *) ( ( (int)pDrvCtrl->pShMem + 3) & ~3); /* Save some things */ pDrvCtrl->memBase = (char *)((ULONG)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); /* HELP: deal with memWidth */ /* 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. */ pDrvCtrl->pTring = (ln_tmd *) (int)(pDrvCtrl->pShMem + IB_SIZ + ((1 << lnRsize) + 1) * RMD_SIZ); 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 receive buffers from our own private pool. */ if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL) return (ERROR); lnMclConfig.mBlkNum = pDrvCtrl->rringSize * 2; lnClDescTbl[0].clNum = pDrvCtrl->rringSize *2; lnMclConfig.clBlkNum = lnClDescTbl[0].clNum; lnMclConfig.memSize = (lnMclConfig.mBlkNum * (MSIZE + sizeof (long))) + (lnMclConfig.clBlkNum * (CL_BLK_SZ + sizeof(long))); if ((lnMclConfig.memArea = (char *) memalign (sizeof(long), lnMclConfig.memSize)) == NULL) return (ERROR); lnClDescTbl[0].clNum = pDrvCtrl->rringSize *2; lnClDescTbl[0].memSize = (lnClDescTbl[0].clNum * (LN_BUFSIZ + 8)) + sizeof(int); if ((int) pDrvCtrl->memAdrs != NONE) /* Do we hand over our own memory? */ { lnClDescTbl[0].memArea = (char *)(pDrvCtrl->pTring + (((1 << lnTsize) + 1) * TMD_SIZ)); } else { lnClDescTbl[0].memArea = (char *) cacheDmaMalloc (lnClDescTbl[0].memSize); if ((int)lnClDescTbl[0].memArea == NULL) { DRV_LOG(DRV_DEBUG_LOAD, "system memory unavailable\n", 1, 2, 3, 4, 5, 6); return (ERROR); } } if (netPoolInit(pDrvCtrl->end.pNetPool, &lnMclConfig, &lnClDescTbl[0], lnClDescTblNumEnt, NULL) == ERROR) { DRV_LOG (DRV_DEBUG_LOAD, "Could not init buffering\n", 1, 2, 3, 4, 5, 6); return (ERROR); }#ifdef DRV_DEBUG ln7990NetPool = *pDrvCtrl->end.pNetPool;#endif /* Store the cluster pool id as others need it later. */ pDrvCtrl->pClPoolId = clPoolIdGet(pDrvCtrl->end.pNetPool, LN_BUFSIZ, FALSE); pRmd = pDrvCtrl->pRring; for (ix = 0; ix < pDrvCtrl->rringSize; ix++, pRmd++) { if ((pTempBuf = (char *)netClusterGet(pDrvCtrl->end.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; }/********************************************************************************* ln7990Start - 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 ln7990Start ( LN7990END_DEVICE *pDrvCtrl ) { STATUS result; pDrvCtrl->txCleaning = FALSE; pDrvCtrl->txBlocked = FALSE; SYS_INT_CONNECT (pDrvCtrl, ln7990Int, (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 (pDrvCtrl); DRV_LOG (DRV_DEBUG_LOAD, "interrupt enabled.\n", 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* ln7990HandleError - 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 ln7990HandleError ( LN7990END_DEVICE *pDrvCtrl ) { u_short stat; pDrvCtrl->errorHandling = FALSE; stat = pDrvCtrl->errorStat; pDrvCtrl->errorStat &= ~stat; if (stat & lncsr_MERR) { pDrvCtrl->lastError.errCode = END_ERR_RESET; pDrvCtrl->lastError.pMesg = "Memory error."; muxError (&pDrvCtrl->end, &pDrvCtrl->lastError); } if (stat & lncsr_BABL) { pDrvCtrl->lastError.errCode = END_ERR_WARN; pDrvCtrl->lastError.pMesg = "Babbling"; muxError (&pDrvCtrl->end, &pDrvCtrl->lastError); } if (stat & lncsr_MISS) { pDrvCtrl->lastError.errCode = END_ERR_WARN; pDrvCtrl->lastError.pMesg = "Missing"; muxError (&pDrvCtrl->end, &pDrvCtrl->lastError); } return; } /********************************************************************************* ln7990Int - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.** RETURNS: N/A.*/LOCAL void ln7990Int ( LN7990END_DEVICE *pDrvCtrl ) { u_short stat; ln_rmd *pRmd; /* Read the device status register */ stat = ln7990Csr0Read (pDrvCtrl); DRV_LOG (DRV_DEBUG_INT, "i=0x%x:\n", stat, 2, 3, 4, 5, 6); /* If false interrupt, return. */ if (!(stat & lncsr_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. */ ln7990CsrWrite (pDrvCtrl, 0, ((stat & (lncsr_BABL|lncsr_CERR|lncsr_MISS|lncsr_MERR| lncsr_RINT|lncsr_TINT|lncsr_IDON)) | lncsr_INEA)); /* Check for errors */ if (stat & (lncsr_BABL | lncsr_MISS | lncsr_MERR)) { ++pDrvCtrl->csr0Errs; END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); if (stat & lncsr_BABL) { pDrvCtrl->errorStat |= lncsr_BABL; if (!pDrvCtrl->errorHandling) { if (netJobAdd ((FUNCPTR) ln7990HandleError, (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 & lncsr_MISS) { pDrvCtrl->errorStat |= lncsr_MISS; if (!pDrvCtrl->errorHandling) { if (netJobAdd ((FUNCPTR) ln7990HandleError, (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 & lncsr_MERR) /* memory error */ { pDrvCtrl->errorStat |= lncsr_MERR; if (!pDrvCtrl->errorHandling) { if (netJobAdd ((FUNCPTR) ln7990HandleError, (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->end, (IFF_UP | IFF_RUNNING)); /* Only reset device if Restart will occur */ if (netJobAdd ((FUNCPTR) ln7990Restart , (int) pDrvCtrl, 2, 3, 4, 5) == OK) { ln7990Reset (pDrvCtrl); } return; } } /* Have netTask handle any input packets */ pRmd = pDrvCtrl->pRring + pDrvCtrl->rmdIndex; LN_CACHE_INVALIDATE (pRmd, RMD_SIZ); if (((stat & lncsr_RINT) && (stat & lncsr_RXON)) || LN_RMD_OWNED (pRmd) == 0) { DRV_LOG (DRV_DEBUG_INT, "r ", 1, 2, 3, 4, 5, 6); if (!(pDrvCtrl->flags & LS_RCV_HANDLING_FLAG)) { if (netJobAdd ((FUNCPTR)ln7990HandleRecvInt, (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 & lncsr_TINT)) { return; } DRV_LOG (DRV_DEBUG_INT, "t ", 1, 2, 3, 4, 5, 6); if (!pDrvCtrl->txCleaning) { pDrvCtrl->txCleaning = TRUE; netJobAdd ((FUNCPTR)ln7990ScrubTRing, (int) pDrvCtrl, 0, 0, 0, 0); } if (pDrvCtrl->txBlocked) /* cause a restart */ { netJobAdd ((FUNCPTR)muxTxRestart, (int) &pDrvCtrl->end, 0, 0, 0, 0); pDrvCtrl->txBlocked = FALSE; } /* Flush the write pipe */ CACHE_PIPE_FLUSH (); }/********************************************************************************* ln7990HandleRecvInt - 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.** RETURNS: N/A.*/LOCAL void ln7990HandleRecvInt ( LN7990END_DEVICE *pDrvCtrl ) { ln_rmd *pRmd; do { pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG; while ((pRmd = ln7990FullRMDGet (pDrvCtrl)) != NULL) ln7990Recv (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 (ln7990FullRMDGet (pDrvCtrl) != NULL); /* this double check solves the RACE */ }/********************************************************************************* ln7990FullRMDGet - get next received message RMD** Get next recevied message descriptor. Returns NULL if none are* ready.** RETURNS: ptr to next Rx desc to process, or NULL if none ready.*/LOCAL ln_rmd *ln7990FullRMDGet ( LN7990END_DEVICE *pDrvCtrl ) { ln_rmd *pRmd; pRmd = pDrvCtrl->pRring + pDrvCtrl->rmdIndex; /* form ptr to Rx desc */ LN_CACHE_INVALIDATE (pRmd, RMD_SIZ); if (LN_RMD_OWNED (pRmd) == 0) return (pRmd); else return ((ln_rmd *) NULL); }/********************************************************************************* ln7990Recv - process the next incoming packet** Handle one incoming packet. The packet is checked for errors.** RETURNS: N/A.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -