📄 sh7615end.c
字号:
/* * We implicitly are loaning here, if copying is necessary this * step may be skipped, but the data must be copied before being * passed up to the protocols. */ pNewCluster = NET_BUF_ALLOC (); if (pNewCluster == NULL) { pDrvCtrl->lastError.errCode = END_ERR_NO_BUF; muxError (&pDrvCtrl->end, &pDrvCtrl->lastError); DRV_LOG (DRV_DEBUG_RX, "Cannot loan!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); goto cleanRxD; } /* Grab a cluster block to marry to the cluster we received. */ if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL) { pDrvCtrl->lastError.errCode = END_ERR_NO_BUF; muxError (&pDrvCtrl->end, &pDrvCtrl->lastError); NET_BUF_FREE (pNewCluster); DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); goto cleanRxD; } /* * OK we've got a spare, let's get an M_BLK_ID and marry it to the * one in the ring. */ if ((pMblk = mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL) { netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk); NET_BUF_FREE (pNewCluster); DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); goto cleanRxD; } END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); len = SH7615END_FRAME_LEN_GET (pRxD->rDesc1); /* * Invalidate cache and copy to ensure 4 byte alignment of IP header. * This is required by the IP network stack. */ SH7615END_CACHE_INVALIDATE ((char *) (pRxD->rDesc2), len); len = (len + 1) & 0xfffffffe; bcopy((char*)pRxD->rDesc2,(char*)pRxD->rDesc2+2,len); /* Join the cluster to the MBlock */ netClBlkJoin (pClBlk, (char *) (pRxD->rDesc3), SH7615END_BUFSIZ, NULL, 0, 0, 0); netMblkClJoin (pMblk, pClBlk); pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkHdr.mLen = len; pMblk->mBlkHdr.mData = (char *) (pRxD->rDesc2 + 2); pMblk->mBlkPktHdr.len = pMblk->mBlkHdr.mLen; /* save the new True data buffer address for freeing later */ pRxD->rDesc3 = (UINT32) pNewCluster; /* Install new data buffer - force 16 byte alignment */ pRxD->rDesc2 = NET_TO_SH7615END_BUF (pNewCluster); /* mark the descriptor ready to receive, preserve the RDL bit */ pRxD->rDesc0 = (pRxD->rDesc0 & RD0_RDL) | RD0_OWN; /* advance management index */ pDrvCtrl->rxIndex = (pDrvCtrl->rxIndex + 1) % pDrvCtrl->numRds; /* Call the upper layer's receive routine. */ DRV_LOG (DRV_DEBUG_RX, "Calling upper layer!\n", 1, 2, 3, 4, 5, 6); END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk); return (OK);cleanRxD: /* mark the descriptor ready to receive - make sure to preserve the RDL bit */ pRxD->rDesc0 = (pRxD->rDesc0 & RD0_RDL) | RD0_OWN; /* advance management index */ pDrvCtrl->rxIndex = (pDrvCtrl->rxIndex + 1) % pDrvCtrl->numRds; return (OK); }/********************************************************************************* sh7615EndRcvIntHandle - 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 sh7615EndRcvIntHandle ( DRV_CTRL *pDrvCtrl /* interrupting device */ ) { SH7615_RD *pRxD; pDrvCtrl->rxHandling = TRUE; /* interlock with sh7615EndInt() */ while ((pRxD = sh7615EndRxDGet (pDrvCtrl)) != NULL) sh7615EndRecv (pDrvCtrl, pRxD); pDrvCtrl->rxHandling = FALSE; /* interlock with sh7615EndInt() */ /* Make sure the Receive Request is still ON */ SH7615END_REG_WRITE(E_DMAC_EDRRR, EDRRR_RR); /* enable receive interrupt */ SH7615END_BIT_SET (E_DMAC_EESIPR, EESIPR_FRIP); }/********************************************************************************* sh7615EndSend - transmit an ethernet packet** This routine takes a M_BLK_ID 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. The last arguments are a free* routine to be called when the device is done with the buffer and a pointer* to the argument to pass to the free routine.** RETURNS: OK on success; and ERROR otherwise.*/ LOCAL STATUS sh7615EndSend ( DRV_CTRL * pDrvCtrl, M_BLK * pMblk ) { SH7615_TD * pTxD; char * pBuf; int len; DRV_LOG (DRV_DEBUG_TX, "EndSend\n", 1, 2, 3, 4, 5, 6); /* Gain exclusive access to transmit */ END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER); /* Get the next TXD */ pTxD = sh7615EndTxDGet (pDrvCtrl); if (pTxD == NULL) { DRV_LOG (DRV_DEBUG_TX, "No available TxD-s \n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_ERRS, +1); END_TX_SEM_GIVE (&pDrvCtrl->end); if (!pDrvCtrl->txCleaning && !pDrvCtrl->txBlocked) sh7615EndTxRingClean (pDrvCtrl); pDrvCtrl->txBlocked = TRUE; /* transmitter not ready */ return (END_ERR_BLOCK); /* just return without freeing mBlk chain */ } pBuf = NET_BUF_ALLOC(); if (pBuf == NULL) { pDrvCtrl->lastError.errCode = END_ERR_NO_BUF; muxError (&pDrvCtrl->end, &pDrvCtrl->lastError); DRV_LOG (DRV_DEBUG_TX, "No available TxBufs \n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_ERRS, +1); END_TX_SEM_GIVE (&pDrvCtrl->end); if (!pDrvCtrl->txCleaning && !pDrvCtrl->txBlocked) sh7615EndTxRingClean (pDrvCtrl); pDrvCtrl->txBlocked = TRUE; /* transmitter not ready */ return (END_ERR_BLOCK); /* just return without freeing mBlk chain */ } /* * Store the buf info. Do this before adjusting alignment below * so that the netBufFree will work correctly later. */ pDrvCtrl->freeBuf[pDrvCtrl->txIndex].pClBuf = pBuf; /* force 16 byte alignment of send buffer */ (UINT32) pBuf = NET_TO_SH7615END_BUF (pBuf); /* Now copy data to 16 byte aligned location in pBuf and free Mblk */ len = netMblkToBufCopy (pMblk, pBuf, NULL); len = max (ETHERSMALL, len); netMblkClChainFree (pMblk); /* flush the cache, if necessary */ SH7615END_CACHE_FLUSH (pBuf, len); /* initialize the transmit descriptor -- preserve TD0_TDL bit */ pTxD->tDesc0 = ((pTxD->tDesc0 & TD0_TDL) | (TD0_OWN | TD0_TFP)); pTxD->tDesc1 = SH7615END_TBS_PUT(len); pTxD->tDesc2 = (UINT32) pBuf; pTxD->tDesc3 = 0; /* Advance our management index */ pDrvCtrl->txIndex = (pDrvCtrl->txIndex + 1) % pDrvCtrl->numTds; SH7615END_REG_WRITE(E_DMAC_EDTRR, EDTRR_TR); /* Transmit request */ END_TX_SEM_GIVE (&pDrvCtrl->end); /* update statistics */ END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1); return (OK); }/********************************************************************************* sh7615EndPollStart - starting polling mode** This routine starts polling mode by disabling ethernet interrupts and* setting the polling flag in the END_CTRL stucture.** RETURNS: OK, always.*/ LOCAL STATUS sh7615EndPollStart ( DRV_CTRL * pDrvCtrl ) { int intLevel; DRV_LOG (DRV_DEBUG_POLL, "PollStart\n", 1, 2, 3, 4, 5, 6); intLevel = intLock(); /* Disable system interrupts */ SYS_INT_DISABLE (pDrvCtrl); /* mask interrupts */ SH7615END_BIT_CLR(E_DMAC_EESIPR, pDrvCtrl->intrMask); DRV_FLAGS_SET (SH7615END_POLLING); intUnlock (intLevel); return (OK); }/********************************************************************************* sh7615EndPollStop - stop polling mode** This function terminates polled mode operation. The device returns to* interrupt mode.** The device interrupts are enabled, the current mode flag is switched* to indicate interrupt mode and the device is then reconfigured for* interrupt operation.** RETURNS: OK, always.*/ LOCAL STATUS sh7615EndPollStop ( DRV_CTRL * pDrvCtrl ) { int intLevel; DRV_LOG (DRV_DEBUG_POLL, "PollStop\n", 1, 2, 3, 4, 5, 6); intLevel = intLock(); DRV_FLAGS_CLR (SH7615END_POLLING); /* Enable chip interrupts */ SH7615END_REG_WRITE(E_DMAC_EESIPR, pDrvCtrl->intrMask); /* Enable system interrupts */ SYS_INT_ENABLE (pDrvCtrl); intUnlock (intLevel); DRV_LOG (DRV_DEBUG_POLL, "s\n", 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* sh7615EndPollSend - send a packet in polled mode** This routine is called by a user to try and send a packet on the* device.** RETURNS: OK on success, EAGAIN on failure*/ LOCAL STATUS sh7615EndPollSend ( DRV_CTRL * pDrvCtrl, M_BLK * pMblk ) { SH7615_TD * pTxD; char * pBuf; char * pBufAligned; int len; DRV_LOG (DRV_DEBUG_POLL, "PollSend\n", 1, 2, 3, 4, 5, 6); pTxD = sh7615EndTxDGet (pDrvCtrl); pBuf = NET_BUF_ALLOC (); if ((pTxD == NULL) || (pBuf == NULL)) { pDrvCtrl->lastError.errCode = END_ERR_NO_BUF; muxError (&pDrvCtrl->end, &pDrvCtrl->lastError); sh7615EndTxRingClean (pDrvCtrl); if (pBuf) NET_BUF_FREE (pBuf); return (EAGAIN); } /* force 16 byte alignment of send buffer */ (UINT32) pBufAligned = NET_TO_SH7615END_BUF (pBuf); /* copy the MBLK */ len = netMblkToBufCopy (pMblk, pBufAligned, NULL); len = max (ETHERSMALL, len); /* flush the cache, if necessary */ SH7615END_CACHE_FLUSH (pBufAligned, len); pTxD->tDesc0 = ((pTxD->tDesc0 & TD0_TDL) | (TD0_OWN | TD0_TFP)); pTxD->tDesc1 = SH7615END_TBS_PUT(len); pTxD->tDesc2 = (UINT32) pBufAligned; pTxD->tDesc3 = 0; /* Advance our management index */ pDrvCtrl->txIndex = (pDrvCtrl->txIndex + 1) % pDrvCtrl->numTds; /* Transmit request */ SH7615END_REG_WRITE(E_DMAC_EDTRR, EDTRR_TR); /* The buffer does not belong to us; Spin until it can be freed */ while (pTxD->tDesc0 & TD0_OWN) ; NET_BUF_FREE (pBuf); /* Try again on transmit errors */ if (pTxD->tDesc0 & TD0_TFE) return (EAGAIN); return (EAGAIN); }/********************************************************************************* sh7615EndPollReceive - get a packet in polled mode** This routine is called by a user to try and get a packet from the* device.** RETURNS: OK on success, EAGAIN on failure.*/ LOCAL STATUS sh7615EndPollReceive ( DRV_CTRL *pDrvCtrl, M_BLK *pMblk ) { SH7615_RD *pRxD; char *pRxBuf; int len; BOOL gotOne=FALSE; DRV_LOG (DRV_DEBUG_POLL, "PollReceive\n", 1, 2, 3, 4, 5, 6); if ((pMblk->mBlkHdr.mFlags & M_EXT) != M_EXT) return (EAGAIN); while (((pRxD = sh7615EndRxDGet (pDrvCtrl)) != NULL) && !gotOne) { /* Check if the packet was received OK */ if ((pRxD->rDesc0 & RD0_RFE) && !((pRxD->rDesc0 & RD0_RFS7) && (DRV_FLAGS_GET() & SH7615END_MCAST))) { /* Update the error statistics and discard the packet */ END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); } else { len = SH7615END_FRAME_LEN_GET (pRxD->rDesc1); if ((len <= pMblk->mBlkHdr.mLen) && (len >= ETHERSMALL)) { gotOne = TRUE; END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* set the packet header */ pMblk->mBlkHdr.mLen = len; /* set the data len */ pMblk->mBlkPktHdr.len = len; /* set the total len */ /* cache invalidate to prepare for the copy */ pRxBuf = (char *) pRxD->rDesc2; SH7615END_CACHE_INVALIDATE (pRxBuf, len); /* bump the buffer mData by 2 to ensure alignment */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -