📄 fei82557end.c
字号:
CACHE_PIPE_FLUSH (); /* kick receiver (if needed) */ CSR_WORD_RD (CSR_STAT_OFFSET, scbStatus); if ((scbStatus & SCB_S_RUMASK) != SCB_S_RURDY) { DRV_LOG (DRV_DEBUG_RX, ("HandleRecvInt: ********* RU NOT READY\n"), 0, 0, 0, 0, 0, 0); /* get the first used RFD */ RFD_GET (pRFD); if (fei82557SCBCommand (pDrvCtrl, SCB_C_RUSTART, TRUE, pRFD) == ERROR) { DRV_LOG (DRV_DEBUG_RX, "fei82557HandleRecvInt: command %d failed\n", SCB_C_RUSTART, 0, 0, 0, 0, 0); } else { /* read CSR command word */ CSR_WORD_RD (CSR_COMM_OFFSET, scbCommand); DRV_LOG (DRV_DEBUG_RX, "fei82557HandleRecvInt: CSR command word 0x%x\n", (int) scbCommand, 0, 0, 0, 0, 0); /* wait for RUSTART accept */ for (ix = (FEI_INIT_TMO * fei82557ClkRate); --ix;) { /* read CSR command word */ CSR_WORD_RD (CSR_COMM_OFFSET, scbCommand); if (!(scbCommand & SCB_C_RUMASK)) { DRV_LOG (DRV_DEBUG_RX, "fei82557HandleRecvInt: RUSTART accepted\n", 0, 0, 0, 0, 0, 0); break; } taskDelay (1); } if (!ix) { DRV_LOG (DRV_DEBUG_RX, "fei82557HandleRecvInt: RUSTART FAILED #######\n", 0, 0, 0, 0, 0, 0); } } } /* Final check to see how things are */ I82557_INT_DISABLE; CSR_WORD_RD (CSR_STAT_OFFSET, scbStatus); if (scbStatus & (SCB_S_FR | SCB_S_RNR)) { /* More stuff to do - re-queue ourselves */ netJobAdd ((FUNCPTR) fei82557HandleRecvInt, (int) pDrvCtrl, 0, 0, 0, 0); } else { pDrvCtrl->rxHandle = FALSE; } I82557_INT_ENABLE; DRV_LOG (DRV_DEBUG_RX, ("fei82557HandleRecvInt... Done, \n"), 0, 0, 0, 0, 0, 0); }/******************************************************************************** fei82557Receive - pass a received frame to the next layer up** RETURNS: N/A*/LOCAL void fei82557Receive ( DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */ RFD_ID pRFD /* pointer to a RFD */ ) { volatile RFD_ID pNewRFD; M_BLK_ID pMblk = NULL; CL_BLK_ID pClBlk = NULL; volatile UINT16 status; volatile UINT16 count; char * pData; /* pass the packet up only if reception was Ok */ RFD_WORD_RD (pRFD, RFD_STAT_OFFSET, status); if (!(FD_FLAG_ISSET (status, RFD_S_OK))) { DRV_LOG (DRV_DEBUG_RX, "fei82557Receive: NOT OK\n", 0,0,0,0,0,0); goto fei82557RecvError; } if ((pMblk = netMblkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT, MT_DATA)) == NULL) { DRV_LOG (DRV_DEBUG_RX, "fei82557Receive: netMblkGet failed\n", 0,0,0,0,0,0); goto fei82557RecvError; } if ((pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)) == NULL) { DRV_LOG (DRV_DEBUG_RX, "fei82557Receive: netClBlkGet failed\n", 0,0,0,0,0,0); goto fei82557RecvError; } if ((pNewRFD = (RFD_ID) netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPoolId)) == NULL) { DRV_LOG (DRV_DEBUG_RX, "fei82557Receive: netClusterGet failed\n", 0,0,0,0,0,0); goto fei82557RecvError; } /* is the RFD to be given back?? */ if (netClBlkJoin (pClBlk, (char *) pRFD, RFD_SIZE, NULL, 0, 0, 0) == NULL) { DRV_LOG (DRV_DEBUG_RX, "fei82557Receive: netClBlkJoin failed\n", 0,0,0,0,0,0); goto fei82557RecvError; } if (netMblkClJoin (pMblk, pClBlk) == NULL) { DRV_LOG (DRV_DEBUG_RX, "fei82557Receive: netMblkClJoin failed\n", 0,0,0,0,0,0); goto fei82557RecvError; } END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1); /* get the actual received bytes number */ DRV_LOG (DRV_DEBUG_RX, "pRFD = %p\n", pRFD, 0,0,0,0,0); RFD_WORD_RD (pRFD, RFD_COUNT_OFFSET, count); pData = (char *) (RFD_PKT_ADDR (pRFD)); if (pDrvCtrl->offset > 0) { bcopy (pData, pData+pDrvCtrl->offset, count & ~0xc000); pData += pDrvCtrl->offset; } pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkHdr.mData = pData; pMblk->mBlkHdr.mLen = count & ~0xc000; pMblk->mBlkPktHdr.len = pMblk->mBlkHdr.mLen; /* put the new RFD on the RFD queue */ fei82557RFDReturn(pDrvCtrl, pNewRFD); DRV_LOG (DRV_DEBUG_RX, "length %d\n", pMblk->mBlkHdr.mLen, 0,0,0,0,0); if (memcmp (pData, &pDrvCtrl->board.enetAddr, 6) == 0) { DRV_LOG (DRV_DEBUG_RX, ("fei82557Receive... Done - data @ %p\n"), pData, 0, 0, 0, 0, 0); DRV_LOG (DRV_DEBUG_RX, ("Sender IP %#x Receiver IP %#x\n"), *((int *)(pData+26)), *((int *)(pData+30)), 0, 0, 0, 0); } END_RCV_RTN_CALL (&pDrvCtrl->endObj, pMblk); 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))) { /* 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) { pDrvCtrl->txHandle = FALSE; END_TX_SEM_GIVE (&pDrvCtrl->endObj); return; } } /* process all the used CFDs until we find either: * a. a non-complete frame; * b. a frame with the SUSPEND bit set */ FOREVER { 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))) { /* 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); netJobAdd ((FUNCPTR) muxTxRestart, (int) &pDrvCtrl->endObj, 0, 0, 0, 0); pDrvCtrl->txStall = FALSE; } } /* we have finished our work if this is a suspend CFD */ CFD_WORD_RD (pUsedCFD, CFD_COMM_OFFSET, status); /* advance pointer to the used CFDs (even if we are exiting) */ fei82557FDUpdate (pDrvCtrl, CFD_USED); if (FD_FLAG_ISSET (status, CFD_C_SUSP)) { break; } } 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_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -