📄 fei82559end.c
字号:
CFD_BYTE_WR (pCFD, CFD_THRESH_OFFSET, pDrvCtrl->board.tcbTxThresh); /* bump to the next CFD */ pCFD = (CFD_ID) ((UINT32) pCFD + CFD_SIZE); } pCFD = (CFD_ID) ((UINT32) pCFD - CFD_SIZE); /* tie the last CFD to the first one */ CFD_NEXT_WR (pCFD, ((UINT32) pDrvCtrl->pFreeCFD)); /* set the used CFDs ring to the free one */ pDrvCtrl->pUsedCFD = pDrvCtrl->pFreeCFD; /* * N.B. * Use RFD_C_EL to tie the end of the RBD ring, and not RFD_C_SUSP * This is because we want the option of inserting a new RFD into * the ring on the fly (i.e., via an SCB_RUSTART command). Why would * we do this? Buffer loaning.... A suspend/resume reception model * will not allow us to do this, so we must use an idle/start model. */ /* initialize the RFD ring, some of the fields will be done * in fei82557Start */ for (ix = 0; ix < pDrvCtrl->nRFDs; ix++) { volatile RFD_ID pRFDOld; if ((pRFD = (RFD_ID) netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPoolId)) == NULL) return (ERROR); if (firstRFD) { /* first ready RFD pointer */ pDrvCtrl->pRFD = pRFD; firstRFD = FALSE; } else { /* tie the previous RFD to the current one */ RFD_NEXT_WR (pRFDOld, (UINT32) pRFD); RFD_LONG_WR (pRFD, RFD_PREV_OFFSET, (UINT32) pRFDOld); } /* no RBDs used */ RFD_RBD_WR (pRFD, (UINT32) RBD_NOT_USED); /* set the actual count field to zero */ RFD_WORD_WR (pRFD, RFD_COUNT_OFFSET, 0); /* set the size field for Ethernet packets */ RFD_WORD_WR (pRFD, RFD_SIZE_OFFSET, (UINT32) (ETHERMTU + EH_SIZE)); /* remember this RFD */ pRFDOld = pRFD; } /* tie the last RFD to the first one */ RFD_NEXT_WR ((UINT32) pRFD, (UINT32) pDrvCtrl->pRFD); /* link the first RFD to the last one */ RFD_LONG_WR (pDrvCtrl->pRFD, RFD_PREV_OFFSET, (UINT32) pRFD); /* Flush the write pipe */ CACHE_PIPE_FLUSH (); DRV_LOG (DRV_DEBUG_LOAD, ("fei82557InitMem... Done\n"), 0, 0, 0, 0, 0, 0); return OK; }/**************************************************************************** fei82557Start - start the device** This routine starts the 82557 device and brings it up to an operational* state. The driver must have already been attached with the fei82557Load()* routine.** RETURNS: OK, or ERROR if the device could not be initialized.*/LOCAL STATUS fei82557Start ( DRV_CTRL *pDrvCtrl /* pointer to DRV_CTRL structure */ ) { RFD_ID pRFD; UINT32 tempVar; int retVal; DRV_LOG (DRV_DEBUG_START, ("Starting end...\n"), 1, 2, 3, 4, 5, 6); /* must have been attached */ if (!pDrvCtrl->attached) return (ERROR); /* reset the chip */ if (fei82557Reset (pDrvCtrl) == ERROR) return (ERROR); /* connect the int handler */ SYS_INT_CONNECT (pDrvCtrl, fei82557Int, (int) pDrvCtrl, &retVal); if (retVal == ERROR) return (ERROR); /* acknowledge interrupts */ SYS_INT_ACK (pDrvCtrl); /* enable chip interrupts after fei82557Reset disabled them */ I82557_INT_ENABLE; /* enable system interrupts after fei82557Reset disabled them */ SYS_INT_ENABLE (pDrvCtrl); /* run diagnostics */ if (fei82557Diag (pDrvCtrl) == ERROR) return (ERROR); /* setup address */ if (fei82557IASetup (pDrvCtrl) == ERROR) return (ERROR); if (END_FLAGS_ISSET (IFF_MULTICAST)) FEI_FLAG_SET (FEI_MCAST); /* configure chip */ if (fei82557Config (pDrvCtrl) == ERROR) return (ERROR); /* set some flags to default values */ pDrvCtrl->rxHandle = FALSE; pDrvCtrl->txHandle = FALSE; pDrvCtrl->txStall = FALSE; /* get the current free RFD */ RFD_GET (pRFD); /* initiailize RFD ring */ do { /* set state and command for this RFD */ RFD_WORD_WR (pRFD, RFD_STAT_OFFSET, (UINT32) 0); RFD_WORD_WR (pRFD, RFD_COMM_OFFSET, (UINT32) 0); /* bump to the next RFD */ RFD_NEXT_RD (pRFD, tempVar); pRFD = (RFD_ID) tempVar; } while (pRFD != pDrvCtrl->pRFD); /* mark the last RFD for the chip to became idle */ RFD_LONG_RD (pRFD, RFD_PREV_OFFSET, tempVar); RFD_WORD_WR (tempVar, RFD_COMM_OFFSET, (UINT32) RFD_C_EL); /* Flush the write pipe */ CACHE_PIPE_FLUSH (); /* put CU into suspended state */ if (fei82557NOP (pDrvCtrl) == ERROR) return (ERROR); /* mark the interface as up */ END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING)); /* startup the receiver */ if (fei82557SCBCommand (pDrvCtrl, SCB_C_RUSTART, TRUE, pRFD) == ERROR) return (ERROR); DRV_LOG (DRV_DEBUG_START, ("Starting end... Done\n"), 1, 2, 3, 4, 5, 6); return (OK); }/******************************************************************************** fei82557Send - send an Ethernet packet** This routine() takes a M_BLK_ID and sends off the data in the M_BLK_ID.* The buffer must already have the addressing information properly installed* in it. This is done by a higher layer.** muxSend() calls this routine each time it wants to send a packet.** RETURNS: N/A*/LOCAL STATUS fei82557Send ( DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */ M_BLK * pMblk /* pointer to the mBlk/cluster pair */ ) { volatile CFD_ID pCFD; volatile CFD_ID pPrevCFD; int len = 0; volatile UINT16 command; volatile UINT16 status; char * pEnetHdr; volatile UINT16 scbStatus; DRV_LOG (DRV_DEBUG_TX, ("fei82557Send...\n"), 1, 2, 3, 4, 5, 6); /* check device mode */ if (FEI_FLAG_ISSET (FEI_POLLING)) { return (ERROR); } /* check for CFDs availability */ /* get the current free CFD */ FREE_CFD_GET (pCFD); /* Make cache consistent with memory */ FEI_CACHE_INVALIDATE (pCFD, 4); /* read the CFD status word */ CFD_WORD_RD (pCFD, CFD_STAT_OFFSET, status); if (!(FD_FLAG_ISSET (status, (CFD_S_COMPLETE | CFD_S_OK)))) { DRV_LOG (DRV_DEBUG_TX, ("fei82557Send...NO CFDS \n"), 1, 2, 3, 4, 5, 6);#ifdef INCLUDE_MIBII_RFC2233 if (pDrvCtrl->endObj.pMib2Tbl != NULL) { pDrvCtrl->endObj.pMib2Tbl->m2CtrUpdateRtn(pDrvCtrl->endObj.pMib2Tbl, M2_ctrId_ifOutErrors, 1); }#else END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);#endif /* INCLUDE_MIBII_RFC2233 */ /* set to stall condition */ END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER); pDrvCtrl->txStall = TRUE; END_TX_SEM_GIVE (&pDrvCtrl->endObj); return (END_ERR_BLOCK); } /* interlock with fei82557CFDFree */ END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER); pEnetHdr = (char *) (CFD_PKT_ADDR (pCFD)); len = netMblkToBufCopy (pMblk, (char *) pEnetHdr, NULL); netMblkClChainFree (pMblk); len = max (ETHERSMALL, len); #ifdef INCLUDE_MIBII_RFC2233 if (pDrvCtrl->endObj.pMib2Tbl != NULL) { pDrvCtrl->endObj.pMib2Tbl->m2PktCountRtn(pDrvCtrl->endObj.pMib2Tbl, M2_PACKET_OUT, (char *)pEnetHdr, len); }#endif /* INCLUDE_MIBII_RFC2233 */ /* set up the current CFD */ CFD_WORD_WR (pCFD, CFD_COUNT_OFFSET, ((len & 0x3fff) | TCB_CNT_EOF)); CFD_WORD_WR (pCFD, CFD_COMM_OFFSET, (CFD_C_XMIT | CFD_C_SUSP)); CFD_WORD_WR (pCFD, CFD_STAT_OFFSET, 0); /* set the thresh value */ CFD_BYTE_WR (pCFD, CFD_THRESH_OFFSET, pDrvCtrl->board.tcbTxThresh); /* no TBDs used */ CFD_BYTE_WR (pCFD, CFD_NUM_OFFSET, 0); /* this is a transmit command */ CFD_BYTE_WR (pCFD, CFD_ACTION_OFFSET, CFD_TX); /* tie to the previous CFD */ CFD_LONG_RD (pCFD, CFD_PREV_OFFSET, pPrevCFD); CFD_WORD_RD (pPrevCFD, CFD_COMM_OFFSET, command); CFD_WORD_WR (pPrevCFD, CFD_COMM_OFFSET, (command & (~CFD_C_SUSP))); /* Flush the write pipe */ CACHE_PIPE_FLUSH (); /* advance the current free CFD pointer */ fei82557FDUpdate (pDrvCtrl, CFD_FREE);#ifdef INCLUDE_MIBII_RFC2233#else END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);#endif /* INCLUDE_MIBII_RFC2233 */ /* kick the CU if needed */ /* read CSR status word */ CSR_WORD_RD (CSR_STAT_OFFSET, scbStatus); if ((scbStatus & SCB_S_CUMASK) == SCB_S_CUSUSP) { if (fei82557SCBCommand (pDrvCtrl, SCB_C_CURESUME, FALSE,(UINT32) 0) == ERROR) { DRV_LOG (DRV_DEBUG_TX, ("Could not send packet\n"), 1, 2, 3, 4, 5, 6); return (ERROR); } else { /* in the old driver ther was a second attempt * at transimitting the packet, but is it sensible? */ } } /* interlock with fei82557CFDFree */ END_TX_SEM_GIVE (&pDrvCtrl->endObj); DRV_LOG (DRV_DEBUG_TX, ("fei82557Send...Done\n"), 1, 2, 3, 4, 5, 6); return (OK); }/******************************************************************************** fei82557Int - entry point for handling interrupts from the 82557** The interrupting events are acknowledged to the device, so that the device* will de-assert its interrupt signal. The amount of work done here is kept* to a minimum; the bulk of the work is deferred to the netTask.** RETURNS: N/A*/LOCAL void fei82557Int ( DRV_CTRL * pDrvCtrl /* pointer to DRV_CTRL structure */ ) { UINT16 event; UINT16 scbStatus; UINT16 scbCommand; /* read and save CSR status word */ CSR_WORD_RD (CSR_STAT_OFFSET, event); if ((event & SCB_S_STATMASK) == 0) { /* This device was not the cause of the shared int */ return; } /* clear chip level interrupt pending, use byte access */ CSR_BYTE_WR (CSR_ACK_OFFSET, ((event & SCB_S_STATMASK) >> 8)); /* board level interrupt acknowledge */ SYS_INT_ACK (pDrvCtrl); /* read CSR status word again */ CSR_WORD_RD (CSR_STAT_OFFSET, scbStatus); DRV_LOG (DRV_DEBUG_INT, ("fei82557Int: event 0x%x, scbStatus 0x%x\n"), event, scbStatus, 0, 0, 0, 0); /* read CSR command word */ CSR_WORD_RD (CSR_COMM_OFFSET, scbCommand); /* handle transmit interrupts */ if ((event & SCB_S_CNA) && (!((UINT8) (scbCommand >> 8) & SCB_C_M)) && (!(pDrvCtrl->txHandle))) { I82557_INT_DISABLE; pDrvCtrl->txHandle = TRUE; (void) netJobAdd ((FUNCPTR) fei82557CFDFree, (int) pDrvCtrl, 0, 0, 0, 0); } /* handle receive interrupts only if fei82557Receive is not running */ if ((event & SCB_S_FR) && !((UINT8) (scbCommand >> 8) & SCB_C_M) && !(pDrvCtrl->rxHandle)) { I82557_INT_DISABLE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -