📄 motfecend.c
字号:
} /**************************************************************************** motFecReset - reset the `motFec' interface** This routine resets the chip by setting the Reset bit in the Ethernet* Control Register. The ETHER_EN bit is cleared, and all the FEC registers * take their default values. In addition, any transmission/reception * currently in progress is abruptly aborted.** RETURNS: OK, always.*/LOCAL STATUS motFecReset ( DRV_CTRL * pDrvCtrl /* pointer to DRV_CTRL structure */ ) { /* issue a reset command to the FEC chip */ MOT_FEC_CSR_WR (MOT_FEC_CTRL_OFF, MOT_FEC_ETH_RES); /* wait at least 16 clock cycles */ taskDelay (1); return (OK); }/******************************************************************************** motFecInt - entry point for handling interrupts from the FEC** 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 motFecInt ( DRV_CTRL * pDrvCtrl /* pointer to DRV_CTRL structure */ ) { UINT32 event = 0; /* event intr register */ UINT32 mask = 0; /* holder for the mask intr register */ UINT32 status; /* status word */ CACHE_PIPE_FLUSH (); /* read and save the interrupt event register */ MOT_FEC_CSR_RD (MOT_FEC_EVENT_OFF, event); /* clear all interrupts */ MOT_FEC_CSR_WR (MOT_FEC_EVENT_OFF, (event & MOT_FEC_EVENT_MSK)); CACHE_PIPE_FLUSH (); /* read the interrupt mask register */ MOT_FEC_CSR_RD (MOT_FEC_MASK_OFF, mask); /* read CSR status word again */ MOT_FEC_CSR_RD (MOT_FEC_EVENT_OFF, status); MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: event 0x%x, status 0x%x\n"), (event & MOT_FEC_EVENT_MSK), status, 0, 0, 0, 0); /* handle bus error interrupts */ if ((event & MOT_FEC_EVENT_BERR) == MOT_FEC_EVENT_BERR) { MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: bus error, restart chip\n"), 0, 0, 0, 0, 0, 0); /* stop and restart the device */ (void) netJobAdd ((FUNCPTR) motFecStop, (int) pDrvCtrl, event, 0, 0, 0); (void) netJobAdd ((FUNCPTR) motFecStart, (int) pDrvCtrl, event, 0, 0, 0); } /* handle babbling transmit error interrupts */ if ((event & MOT_FEC_EVENT_BABT) == MOT_FEC_EVENT_BABT) { MOT_FEC_BAB_TX_ADD; MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: babbling tx error\n"), 0, 0, 0, 0, 0, 0); } /* handle babbling receive error interrupts */ if ((event & MOT_FEC_EVENT_BABR) == MOT_FEC_EVENT_BABR) { MOT_FEC_BAB_RX_ADD; MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: babbling rx error\n"), 0, 0, 0, 0, 0, 0); } /* handle transmit and receive interrupts */ if ((((event & MOT_FEC_EVENT_TXF) == MOT_FEC_EVENT_TXF) && ((mask & MOT_FEC_EVENT_TXF) == MOT_FEC_EVENT_TXF)) || (((event & MOT_FEC_EVENT_RXF) == MOT_FEC_EVENT_RXF) && ((mask & MOT_FEC_EVENT_RXF) == MOT_FEC_EVENT_RXF))) { /* disable tx/rx interrupts */ MOT_FEC_CSR_WR (MOT_FEC_MASK_OFF, (mask & (~(MOT_FEC_EVENT_TXF | MOT_FEC_EVENT_RXF)))); MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: tx/rx intr\n"), 0, 0, 0, 0, 0, 0); (void) netJobAdd ((FUNCPTR) motFecRxTxHandle, (int) pDrvCtrl, 0, 0, 0, 0); } /* handle heartbeat check fail interrupts */ if ((event & MOT_FEC_EVENT_HB) == MOT_FEC_EVENT_HB) { MOT_FEC_HB_FAIL_ADD; if (_func_motFecHbFail != NULL) (* _func_motFecHbFail) (pDrvCtrl); MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: heartbeat check fail\n"), 0, 0, 0, 0, 0, 0); } /* handle mii frame completion interrupts */ if ((event & MOT_FEC_EVENT_MII) == MOT_FEC_EVENT_MII) { MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: mii transfer\n"), 0, 0, 0, 0, 0, 0); /* let the PHY configuration task finish off its job */ MOT_FEC_MII_SEM_GIVE; } /* handle graceful transmit interrupts */ if ((event & MOT_FEC_EVENT_GRA) == MOT_FEC_EVENT_GRA) { MOT_FEC_LOG (MOT_FEC_DBG_INT, ("motFecInt: graceful transmit\n"), 0, 0, 0, 0, 0, 0); /* let the Stop task finish off its job */ MOT_FEC_GRA_SEM_GIVE; } }/******************************************************************************** motFecSend - 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: OK, or END_ERR_BLOCK, if no resources are available, or ERROR,* if the device is currently working in polling mode.*/LOCAL STATUS motFecSend ( DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */ M_BLK * pMblk /* pointer to the mBlk/cluster pair */ ) { UINT8 fragNum = 0; /* number of fragments in this mBlk */ UINT16 pktType = 0; /* packet type (unicast or multicast) */ MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend...\n"), 1, 2, 3, 4, 5, 6); END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER); /* check device mode */ if (MOT_FEC_FLAG_ISSET (MOT_FEC_POLLING)) { goto motFecSendError; } /* walk the mBlk */ if (motFecMblkWalk (pMblk, &fragNum, &pktType) == ERROR) { goto motFecSendError; } /* check we have enough resources */ if ((pDrvCtrl->cleanTbdNum) == 0) { goto motFecSendError; } if ((pDrvCtrl->cleanTbdNum) >= fragNum) { /* transmit the packet in zero-copy mode */ if (motFecPktTransmit (pDrvCtrl, pMblk, fragNum, pktType) == ERROR) { goto motFecSendError; } } else { /* transmit the packet in copy mode */ fragNum = 1; if (motFecPktCopyTransmit (pDrvCtrl, pMblk, fragNum, pktType) == ERROR) { goto motFecSendError; } } END_TX_SEM_GIVE (&pDrvCtrl->endObj); MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend...Done\n"), 1, 2, 3, 4, 5, 6); return (OK);motFecSendError: END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1); END_TX_SEM_GIVE (&pDrvCtrl->endObj); return (END_ERR_BLOCK); }/******************************************************************************** motFecPktTransmit - transmit a packet** This routine transmits the packet described by the given parameters* over the network, without copying the mBlk to the driver's buffer. * It also updates statistics.** RETURNS: OK, or ERROR if no resources were available.*/LOCAL STATUS motFecPktTransmit ( DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */ M_BLK * pMblk, /* pointer to the mBlk */ UINT8 fragNum, /* number of fragments */ UINT16 pktType /* packet type */ ) { int bufLen = 0; /* length of this fragment */ int pktLen = 0; /* length of this packet */ int totLen = 0; /* length of data to be sent */ char * pBuf = NULL; /* pointer to data to be sent */ MOT_FEC_TBD_ID pTbd = NULL; /* pointer to the current ready TBD */ MOT_FEC_TBD_LIST_ID pTbdList = NULL;/* pointer to the TBD list*/ UINT16 tbdStatus; /* holder for the TBD status */ M_BLK * pCurr = pMblk; /* holder for the current mBlk */ MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend...\n"), 1, 2, 3, 4, 5, 6); /* get the current free TBD */ pTbdList = motFecTbdListSet (pDrvCtrl, fragNum); if (pTbdList == (MOT_FEC_TBD_LIST_ID) NULL) { /* set to stall condition */ pDrvCtrl->txStall = TRUE; return (ERROR); } /* store the Mblk pointer */ pTbdList->pBuf = (UCHAR *) pMblk; pTbdList->bufType = BUF_TYPE_MBLK; /* store the packet type */ pTbdList->pktType = pktType; pCurr = pMblk; /* get the total packet lenght */ pktLen = pMblk->mBlkPktHdr.len; /* for each mBlk fragment, set up the related TBD */ for (; fragNum > 0; fragNum--) { pBuf = pCurr->mBlkHdr.mData; bufLen = pCurr->mBlkHdr.mLen; /* just in case we have to pad it */ totLen += bufLen; /* flush the cache, if necessary */ MOT_FEC_CACHE_FLUSH (pBuf, bufLen); /* get and set up the current TBD */ pTbd = pTbdList->pTbd; MOT_FEC_BD_LONG_WR (pTbd, MOT_FEC_BD_ADDR_OFF, (UINT32) pBuf); MOT_FEC_BD_WORD_RD (pTbd, MOT_FEC_BD_STAT_OFF, tbdStatus); pCurr = ((M_BLK *) pCurr->mBlkHdr.mNext); if (pCurr != NULL) { MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend more mblks \n"), 1, 2, 3, 4, 5, 6); MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_LEN_OFF, (UINT32) bufLen); MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_STAT_OFF, (tbdStatus | MOT_FEC_TBD_RDY)); } else { if (totLen < ETHERSMALL) bufLen = max (bufLen, (ETHERSMALL - totLen + bufLen)); MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend last len=0x%x\n"), bufLen, 2, 3, 4, 5, 6); MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_LEN_OFF, (UINT32) bufLen); MOT_FEC_BD_WORD_WR (pTbd, MOT_FEC_BD_STAT_OFF, (MOT_FEC_TBD_LAST | MOT_FEC_TBD_CRC | MOT_FEC_TBD_RDY | tbdStatus)); } /* move on to the next element */ pTbdList = pTbdList->pNext; } /* kick the transmitter */ MOT_FEC_TX_ACTIVATE; /* Flush the write pipe */ CACHE_PIPE_FLUSH (); /* up-date statistics */ if (pktType == PKT_TYPE_MULTI) { pDrvCtrl->endObj.mib2Tbl.ifOutNUcastPkts += 1; } else { END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1); } return (OK); }/******************************************************************************** motFecPktCopyTransmit - copy and transmit a packet** This routine transmits the packet described by the given parameters* over the network, after copying the mBlk to the driver's buffer. * It also updates statistics.** RETURNS: OK, or ERROR if no resources were available.*/LOCAL STATUS motFecPktCopyTransmit ( DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */ M_BLK * pMblk, /* pointer to the mBlk */ UINT8 fragNum, /* number of fragments */ UINT16 pktType /* packet type */ ) { int len = 0; /* length of data to be sent */ char * pBuf = NULL; /* pointer to data to be sent */ MOT_FEC_TBD_ID pTbd = NULL; /* pointer to the current ready TBD */ MOT_FEC_TBD_LIST_ID pTbdList = NULL;/* pointer to the TBD list*/ UINT16 tbdStatus; /* holder for the TBD status */ MOT_FEC_LOG (MOT_FEC_DBG_TX, ("motFecSend...\n"), 1, 2, 3, 4, 5, 6); /* get a cluster buffer from the pool */ pBuf = NET_BUF_ALLOC(); if (pBuf == NULL) { /* set t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -