📄 bcm1250macend.c
字号:
/* disable mac hw */ ETH_MAC_REG_WRITE (pDrvCtrl->regMacEnable, 0); /* diasble VxW interrupt */ (void)bcm1250IntDisable (pDrvCtrl->intSource); /* disconnect interrupt handler */ (void)bcm1250IntDisconnect (pDrvCtrl->intSource); DRV_LOG (DRV_DEBUG_LOAD, "bcm1250MacStop done.\n", 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* bcm1250MacSend - 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, or is passed a bad M_BLK* pointer.*/LOCAL STATUS bcm1250MacSend ( DRV_CTRL * pDrvCtrl, /* driver control structure */ M_BLK * pMblk /* pointer to the mBlk/cluster pair */ ) { STATUS rtv = OK; /* function return value */ int fragNum = 0; /* number of fragments in this mBlk */ BOOL zeroCopyReady; /* able to transmit without buffer copy */ DRV_LOG (DRV_DEBUG_TX, "bcm1250MacSend...\n", 1, 2, 3, 4, 5, 6); /* * Obtain exclusive access to transmitter. This is necessary because * we might have more than one stack transmitting at once. */ END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER); /* check device mode */ if (DRV_FLAGS_ISSET (BCM1250_MAC_POLLING)) { netMblkClChainFree (pMblk); rtv = ERROR; errno = EINVAL; goto bcm1250MacSendError; } /* check for valid M_BLK */ if (pMblk == (M_BLK *)NULL) { DRV_LOG (DRV_DEBUG_TX, "Invalid pMblk\n", 1, 2, 3, 4, 5, 6); rtv = ERROR; errno = EINVAL; goto bcm1250MacSendError; } /* walk the mBlk */ bcm1250MacMblkWalk (pMblk, &fragNum, &zeroCopyReady); /* check we have enough resources */ if (zeroCopyReady && ((pDrvCtrl->txDma.maxDescr - pDrvCtrl->txDma.ringCount) >= fragNum)) { DRV_LOG (DRV_DEBUG_TX, "bcm1250MacSend fragNum = %d\n", fragNum, 2, 3, 4, 5, 6); /* transmit the packet in zero-copy mode */ rtv = bcm1250MacPktTransmit (pDrvCtrl, pMblk, fragNum); } else { /* transmit the packet in copy mode */ rtv = bcm1250MacPktCopyTransmit (pDrvCtrl, pMblk); }bcm1250MacSendError: END_TX_SEM_GIVE (&pDrvCtrl->endObj); DRV_LOG (DRV_DEBUG_TX, "bcm1250MacSend...Done\n", 1, 2, 3, 4, 5, 6); return (rtv); }/********************************************************************************* bcm1250MacPktCopyTransmit - 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 bcm1250MacPktCopyTransmit ( DRV_CTRL * pDrvCtrl, /* driver control structure */ M_BLK * pMblk /* pointer to the mBlk */ ) { int len = 0; /* length of data to be sent */ char * pBuf = (char *)NULL; /* pointer to data to be sent */ ETH_DMA_DSCR * pTxDscr; /* DMA buffer descriptor */ ETH_MAC_DMA * pTxDma; /* ethernet DMA structure */ UINT64 dscrCnt; /* buffer descriptor count */ DRV_LOG (DRV_DEBUG_TX, "bcm1250Mac CopyTx ...\n", 1, 2, 3, 4, 5, 6); pTxDma = &pDrvCtrl->txDma; /* get a cluster buffer from the pool */ pBuf = NET_BUF_ALLOC (); if (pBuf == (char *)NULL) { /* set to stall condition */ pDrvCtrl->txDma.txBlocked = TRUE; return (END_ERR_BLOCK); } /* Check for all DMA buffer descriptors in use. */ if (pTxDma->ringCount >= pTxDma->maxDescr) { DRV_LOG (DRV_DEBUG_TX, "No available TxBufs\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, 1); NET_BUF_FREE (pBuf); pDrvCtrl->txDma.txBlocked = TRUE; return (END_ERR_BLOCK); /* just return without freeing mBlk chain */ } len = netMblkToBufCopy (pMblk, (char *)pBuf, (FUNCPTR)NULL); netMblkClChainFree (pMblk); len = max (ETHERSMALL, len); DRV_LOG (DRV_DEBUG_TXD, "tx - *pBuf= 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", pBuf[0], pBuf[1], pBuf[2], pBuf[3], pBuf[4], pBuf[5]); DRV_LOG (DRV_DEBUG_TXD, "tx - *pBuf= 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", pBuf[6], pBuf[7], pBuf[8], pBuf[9], pBuf[10], pBuf[11]); DRV_LOG (DRV_DEBUG_TXD, "tx - *pBuf= 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x\n", pBuf[12], pBuf[13], pBuf[14], pBuf[15], pBuf[16], pBuf[17]); /* point to next buffer descriptor */ pTxDscr = &pTxDma->pDscrTable[pTxDma->tailIndex]; DRV_LOG (DRV_DEBUG_TXD, "pTxd->desc_a = 0x%08x\n", (UINT32)&pTxDscr->dscr_a, 2, 3, 4, 5, 6); DRV_LOG (DRV_DEBUG_TXD, "pTxd->desc_b = 0x%08x\n", (UINT32)&pTxDscr->dscr_b, 2, 3, 4, 5, 6); /* set buffer ptr, size in cache line, enable intr, mark as 1st pkt */ pTxDscr->dscr_a = (UINT64)((UINT32)KVTOPHYS (pBuf)) | V_DMA_DSCRA_A_SIZE (NUMCACHEBLKS (len)) | M_DMA_DSCRA_INTERRUPT | M_DMA_ETHTX_SOP; /* set pkt len and option */ pTxDscr->dscr_b = V_DMA_DSCRB_OPTIONS (K_DMA_ETHTX_APPENDCRC_APPENDPAD) | V_DMA_DSCRB_PKT_SIZE (len); DRV_LOG (DRV_DEBUG_TXD, "dscr_a = 0x%08x%08x\n", (pTxDscr->dscr_a) >> 32, pTxDscr->dscr_a, 3, 4, 5, 6); DRV_LOG (DRV_DEBUG_TXD, "dscr_b = 0x%08x%08x\n", (pTxDscr->dscr_b) >> 32, pTxDscr->dscr_b, 3, 4, 5, 6); /* save pointer to buffer and the buffer type. */ pTxDma->bufTable[pTxDma->tailIndex].pBuf = pBuf; pTxDma->bufTable[pTxDma->tailIndex].type = BUF_TYPE_CL; /* advance ring management variables */ pTxDma->tailIndex = (pTxDma->tailIndex + 1) % pTxDma->maxDescr; pTxDma->ringCount++; /* tell hw one more dscr to go */ ETH_DMA_REG_WRITE (pTxDma->regDscrCnt, 1); /* debug purpose */ dscrCnt = ETH_DMA_REG_READ (pTxDma->regDscrCnt); DRV_LOG (DRV_DEBUG_TX, "tx0 DMA dscrcnt=0x%08x%08x\n", (dscrCnt >> 32), dscrCnt, 3, 4, 5, 6); DRV_LOG (DRV_DEBUG_TX, "bcm1250Mac CopyTx Done.\n", 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* bcm1250MacMblkWalk - walk the mBlk** This routine walks the mBlk whose address is in <pMblk>, computes* the number of fragments it is made of, and returns it in the parameter* <pFragNum>. In addition, it finds out whether the specified packet* is unicast or multicast.** RETURNS: OK, or ERROR in case of invalid mBlk.*/LOCAL void bcm1250MacMblkWalk ( M_BLK * pMblk, /* pointer to the mBlk */ int * pFragNum, /* number of fragments in this mBlk */ BOOL * pZeroCopyReady /* no buffer copy flag */ ) { M_BLK * pCurr = pMblk; /* the current mBlk */ DRV_LOG (DRV_DEBUG_TX, "bcm1250MacMblkWalk: start\n", 1, 2, 3, 4, 5, 6); *pZeroCopyReady = TRUE; /* assume no buffer copy is required */ /* walk this mBlk */ do { /* if not first buffer in a packet, must start at cache line boundary */ if (pCurr != pMblk) { if (((UINT32)pCurr->mBlkHdr.mData & (CACHELINESIZE - 1)) != 0) { DRV_LOG (DRV_DEBUG_TX, "bcm1250MacMblkWalk: beginning align fail\n", 1, 2, 3, 4, 5, 6); *pZeroCopyReady = FALSE; /* buffer copy required */ } } /* if not last buffer in a pacet, must end at cache line boundary */ if (pCurr->mBlkHdr.mNext != (M_BLK *)NULL) { if ((((UINT32)pCurr->mBlkHdr.mData + pCurr->mBlkHdr.mLen) & (CACHELINESIZE - 1)) != 0) { DRV_LOG (DRV_DEBUG_TX, "bcm1250MacMblkWalk: ending align fail\n", 1, 2, 3, 4, 5, 6); *pZeroCopyReady = FALSE; /* buffer copy required */ } } /* keep track of the number of fragments in this mBlk */ (*pFragNum)++; pCurr = ((M_BLK *)pCurr->mBlkHdr.mNext); DRV_LOG (DRV_DEBUG_TX, "bcm1250MacMblkWalk: next\n", 1, 2, 3, 4, 5, 6); } while (pCurr != (M_BLK *)NULL); }/********************************************************************************* bcm1250MacPktTransmit - zero copy packet transmit** This routine transmits the packet described by the given parameters* over the network, zero mbuf copying** RETURNS: OK, or ERROR if no resources were available or condition* does not meet.*/LOCAL STATUS bcm1250MacPktTransmit ( DRV_CTRL * pDrvCtrl, /* driver control structure */ M_BLK * pMblk, /* pointer to the mBlk */ int fragNum /* number of fragments in this mBlk */ ) { int len = 0; /* length of data to be sent */ UINT32 offset; /* offset to cache line */ char * pBuf = (char *)NULL; /* pointer to data to be sent */ ETH_DMA_DSCR * pTxDscr; /* DMA buffer descriptor */ ETH_MAC_DMA * pTxDma; /* ethernet DMA structure */ M_BLK * pCurrentMblk; /* current mBlk pointer */ DRV_LOG (DRV_DEBUG_TX, "bcm1250Mac Zero-Copy Tx ...\n", 1, 2, 3, 4, 5, 6); pTxDma = &pDrvCtrl->txDma; pCurrentMblk = pMblk; while (pCurrentMblk != (M_BLK *)NULL) { /* point to next buffer descriptor */ pTxDscr = &pTxDma->pDscrTable[pTxDma->tailIndex]; pBuf = pCurrentMblk->mBlkHdr.mData; len = pCurrentMblk->mBlkHdr.mLen; offset = (UINT32)(pCurrentMblk->mBlkHdr.mData) & (CACHELINESIZE - 1); /* set buffer ptr, size in cache line */ pTxDscr->dscr_a = (UINT64)((UINT32)KVTOPHYS (pBuf)) | V_DMA_DSCRA_A_SIZE (NUMCACHEBLKS (offset + len)); pTxDscr->dscr_b = V_DMA_DSCRB_OPTIONS (K_DMA_ETHTX_APPENDCRC_APPENDPAD); if (pCurrentMblk == pMblk) { /* set pkt len and option */ pTxDscr->dscr_a |= M_DMA_ETHTX_SOP; pTxDscr->dscr_b |= V_DMA_DSCRB_PKT_SIZE( pCurrentMblk->mBlkPktHdr.len); } DRV_LOG (DRV_DEBUG_TXD, "dscr_a = 0x%08x%08x\n", (pTxDscr->dscr_a) >> 32, pTxDscr->dscr_a, 3, 4, 5, 6); DRV_LOG (DRV_DEBUG_TXD, "dscr_b = 0x%08x%08x\n", (pTxDscr->dscr_b) >> 32, pTxDscr->dscr_b, 3, 4, 5, 6); /* Is this the last one? */ if (pCurrentMblk->mBlkHdr.mNext == (M_BLK *)NULL) { pTxDscr->dscr_a |= M_DMA_DSCRA_INTERRUPT; /* save pointer to buffer and the buffer type. */ pTxDma->bufTable[pTxDma->tailIndex].pBuf = (char *)pMblk; pTxDma->bufTable[pTxDma->tailIndex].type = BUF_TYPE_MBLK; } else { /* * Save pointer to buffer and the buffer type for * the last descriptor. */ pTxDma->bufTable[pTxDma->tailIndex].pBuf = (char *)NULL; pTxDma->bufTable[pTxDma->tailIndex].type = BUF_TYPE_NONE; } /* advance ring management variables */ pTxDma->tailIndex = (pTxDma->tailIndex + 1) % pTxDma->maxDescr; pTxDma->ringCount++; pCurrentMblk = pCurrentMblk->mBlkHdr.mNext; } /* tell hw one more dscr to go */ ETH_DMA_REG_WRITE (pTxDma->regDscrCnt, fragNum); DRV_LOG (DRV_DEBUG_TX, "bcm1250Mac Zero-Copy Tx Done.\n", 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* bcm1250MacInt - entry point for handling interrupts** 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 bcm1250MacInt ( DRV_CTRL * pDrvCtrl /* driver control structure */ ) { UINT64 status; /* Interrupt status */ /* Get the interrupt status register value. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -