📄 fei82557end.c
字号:
goto fei82557RecvError; if ((pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)) == NULL) goto fei82557RecvError; if ((pNewRFD = (RFD_ID) netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPoolId)) == NULL) goto fei82557RecvError; /* is the RFD to be given back?? */ if (netClBlkJoin (pClBlk, (char *) pRFD, RFD_SIZE, NULL, 0, 0, 0) == NULL) goto fei82557RecvError; if (netMblkClJoin (pMblk, pClBlk) == NULL) goto fei82557RecvError; END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1); /* get the actual received bytes number */ RFD_WORD_RD (pRFD, RFD_COUNT_OFFSET, count); pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkHdr.mData = (char *) (RFD_PKT_ADDR (pRFD)); pMblk->mBlkHdr.mLen = count & ~0xc000; pMblk->mBlkPktHdr.len = pMblk->mBlkHdr.mLen; /* put the new RFD on the RFD queue */ fei82557RFDReturn(pDrvCtrl, pNewRFD); END_RCV_RTN_CALL (&pDrvCtrl->endObj, pMblk); DRV_LOG (DRV_DEBUG_RX, ("fei82557Receive... Done, \n"), 0, 0, 0, 0, 0, 0); return;fei82557RecvError: if (pMblk != NULL) netMblkFree (pDrvCtrl->endObj.pNetPool, pMblk); if (pClBlk != NULL) netClBlkFree (pDrvCtrl->endObj.pNetPool, pClBlk); if (pNewRFD != NULL) netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *) pNewRFD); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); /* put the errored RFD on the RFD queue */ fei82557RFDReturn(pDrvCtrl, pRFD); }/**************************************************************************** fei82557RFDReturn - put a Receive Frame on the Receive Queue** This routine puts a Receive Frame on the Receive Queue.** RETURNS: N/A**/LOCAL void fei82557RFDReturn ( DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */ RFD_ID pNewRFD /* pointer to a RFD */ ) { volatile UINT32 tempVar; volatile RFD_ID pRFD; volatile UINT16 command; /* get the last used RFD */ RFD_GET (pRFD); /* link it to the RFD chain */ /* link the new RFD to the next one */ RFD_NEXT_RD (pRFD, (UINT32) tempVar); RFD_LONG_WR (tempVar, RFD_PREV_OFFSET, (UINT32) pNewRFD); RFD_NEXT_WR (pNewRFD, tempVar); /* link the new RFD to the previous one */ RFD_LONG_RD (pRFD, RFD_PREV_OFFSET, tempVar); RFD_NEXT_WR (tempVar, pNewRFD); RFD_LONG_WR (pNewRFD, RFD_PREV_OFFSET, tempVar); /* init the new RFD, mirrors fei82557Start */ /* set state and command for this RFD */ RFD_WORD_WR (pNewRFD, RFD_STAT_OFFSET, (UINT32) 0); RFD_WORD_WR (pNewRFD, RFD_COMM_OFFSET, (UINT32) RFD_C_EL); /* no RBDs used */ RFD_RBD_WR (pNewRFD, (UINT32) RBD_NOT_USED); /* set the actual count field to zero */ RFD_WORD_WR (pNewRFD, RFD_COUNT_OFFSET, 0); /* set the size field for Ethernet packets */ RFD_WORD_WR (pNewRFD, RFD_SIZE_OFFSET, (UINT32) (ETHERMTU + EH_SIZE)); /* chain the previous RFD */ RFD_LONG_RD (pNewRFD, RFD_PREV_OFFSET, tempVar); RFD_WORD_RD (tempVar, RFD_COMM_OFFSET, command); RFD_WORD_WR (tempVar, RFD_COMM_OFFSET, (command & (~RFD_C_EL))); /* bump to the next free RFD */ fei82557FDUpdate (pDrvCtrl, RFD_FREE); }/**************************************************************************** fei82557CFDFree - free all used command frames** This routine frees all used command frames and notifies upper protocols* that new resources are available.** RETURNS: N/A**/LOCAL void fei82557CFDFree ( DRV_CTRL * pDrvCtrl /* pointer to DRV_CTRL structure */ ) { volatile CFD_ID pUsedCFD = NULL; volatile UINT16 status; volatile UINT16 scbStatus; UINT8 action; if (!(FEI_FLAG_ISSET (FEI_POLLING))) { I82557_INT_ENABLE; /* interlock with fei82557Send */ END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER); /* read CSR status word */ CSR_WORD_RD (CSR_STAT_OFFSET, scbStatus); /* if CU is active, do not go on */ if ((scbStatus & SCB_S_CUMASK) != SCB_S_CUSUSP) { END_TX_SEM_GIVE (&pDrvCtrl->endObj); pDrvCtrl->txHandle = FALSE; return; } } /* process all the used CFDs until we find either: * a. a non-complete frame; * b. a frame with the SUSPEND bit set */ FOREVER { static BOOL first = TRUE; USED_CFD_GET (pUsedCFD); /* Make cache consistent with memory */ FEI_CACHE_INVALIDATE (pUsedCFD, 4); /* read the CFD status word */ CFD_WORD_RD (pUsedCFD, CFD_STAT_OFFSET, status); /* if it's not ready, don't touch it! */ if (!(FD_FLAG_ISSET (status, (CFD_S_COMPLETE | CFD_S_OK)))) { break; } /* put CFD back to a TxCB - mirrors fei82557InitMem() */ /* no TBDs used */ CFD_TBD_WR (pUsedCFD, (UINT32) TBD_NOT_USED); CFD_BYTE_WR (pUsedCFD, CFD_NUM_OFFSET, 0); /* set the thresh value */ CFD_BYTE_WR (pUsedCFD, CFD_THRESH_OFFSET, pDrvCtrl->board.tcbTxThresh); /* correct statistic only in case of non-action command */ CFD_BYTE_RD (pUsedCFD, CFD_ACTION_OFFSET, action); if ((action == CFD_TX) && !(FD_FLAG_ISSET (status, (CFD_S_COMPLETE | CFD_S_OK)))) { if (!(FEI_FLAG_ISSET (FEI_POLLING))) { DRV_LOG (DRV_DEBUG_INT, ("fei82557CFDFree: Errored Frame \n"), 0, 0, 0, 0, 0, 0); } END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, -1); /* make the errored CFD available */ CFD_WORD_WR (pUsedCFD, CFD_STAT_OFFSET, (CFD_S_OK | CFD_S_COMPLETE)); } if (!(FEI_FLAG_ISSET (FEI_POLLING))) { if (first) { /* soon notify upper protocols CFDs are available */ if (pDrvCtrl->txStall) { DRV_LOG (DRV_DEBUG_INT, ("fei82557CFDFree: Restart mux \n"), 0, 0, 0, 0, 0, 0); (void) netJobAdd ((FUNCPTR) muxTxRestart, (int) &pDrvCtrl->endObj, 0, 0, 0, 0); pDrvCtrl->txStall = FALSE; } first = FALSE; } } /* we have finished our work if this is a suspend CFD */ CFD_WORD_RD (pUsedCFD, CFD_COMM_OFFSET, status); if (FD_FLAG_ISSET (status, CFD_C_SUSP)) { /* advance pointer to the used CFDs even if we are exiting */ fei82557FDUpdate (pDrvCtrl, CFD_USED); break; } /* advance pointer to the used CFDs */ fei82557FDUpdate (pDrvCtrl, CFD_USED); } if (!(FEI_FLAG_ISSET (FEI_POLLING))) { pDrvCtrl->txHandle = FALSE; END_TX_SEM_GIVE (&pDrvCtrl->endObj); DRV_LOG (DRV_DEBUG_INT, ("fei82557CFDFree: Done \n"), 0, 0, 0, 0, 0, 0); } /* Flush the write pipe */ CACHE_PIPE_FLUSH (); }/**************************************************************************** fei82557FDUpdate - update the current frame descriptor** This routine updates the pointer to the appropriate frame descriptor * ring with the value stored in the link field of the current frame * descriptor. Frame descriptor here can be either an RFD or a CFD in the* free CFDs ring as well as in the used CFDs ring.** RETURNS: N/A**/LOCAL void fei82557FDUpdate ( DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */ UINT8 fdList /* FD list selector */ ) { volatile UINT32 fdAddr; volatile FD_ID pFD; switch (fdList) { case CFD_FREE: /* CFDs ready to be processed */ FREE_CFD_GET (pFD); /* get the next free CFD address */ CFD_NEXT_RD (pFD, fdAddr); /* bump to the next free CFD */ pDrvCtrl->pFreeCFD = (FD_ID) fdAddr; break; case CFD_USED: /* CFDs already processed */ USED_CFD_GET (pFD); /* get the next free CFD address */ CFD_NEXT_RD (pFD, fdAddr); /* bump to the next used CFD */ pDrvCtrl->pUsedCFD = (FD_ID) fdAddr; break; case RFD_FREE: /* RFDs ready to be processed */ RFD_GET (pFD); /* get the next free RFD address */ RFD_NEXT_RD (pFD, fdAddr); /* bump to the next free RFD */ pDrvCtrl->pRFD = (FD_ID) fdAddr; break; default: break; } }/**************************************************************************** fei82557Stop - stop the fei82557 interface** This routine marks the interface as inactive, disables interrupts and * resets the chip. It brings down the interface to a non-operational state. * To bring the interface back up, fei82557Start() must be called.** RETURNS: OK, always.*/LOCAL STATUS fei82557Stop ( DRV_CTRL * pDrvCtrl /* pointer to DRV_CTRL structure */ ) { int retVal; /* disable system interrupt */ SYS_INT_DISABLE (pDrvCtrl); /* disable chip interrupt */ I82557_INT_DISABLE; /* mark the interface as down */ END_FLAGS_CLR (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING)); /* reset the chip */ fei82557Reset (pDrvCtrl); /* disconnect the interrupt handler */ SYS_INT_DISCONNECT (pDrvCtrl, fei82557Int, (int)pDrvCtrl, &retVal); if (retVal == ERROR) return (ERROR); /* wait for the reset... */ taskDelay (2); return OK; } /**************************************************************************** fei82557Reset - reset the `fei82557' interface** This routine resets the chip by issuing a Port Selective Reset Command* to the chip. The Receiver And the Transmit Unit are in idle state after* this command is performed.** RETURNS: OK or ERROR, if the command was not successful.*/LOCAL STATUS fei82557Reset ( DRV_CTRL * pDrvCtrl /* pointer to DRV_CTRL structure */ ) { int ix; /* issue a selective reset to the 82557 chip */ CSR_LONG_WR (CSR_PORT_OFFSET, FEI_PORT_SELRESET); /* wait for the receive handler to catch up to the [reset] 557 */ for (ix = (FEI_INIT_TMO * fei82557ClkRate); --ix;) { if (!pDrvCtrl->rxHandle) break; taskDelay (1); } if (!ix) return (ERROR); return (OK); }/**************************************************************************** fei82557SCBCommand - deliver a command to the 82557 via the SCB** This function causes the device to execute a command. An error status is* returned if the command field does not return to zero, from a previous* command, in a reasonable amount of time.** RETURNS: OK, or ERROR if the command field appears to be frozen.*/LO
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -