📄 at91eth.c
字号:
/* Allocate cluster buffer. */ pBuf = netClusterGet(dev->endObj.pNetPool, dev->endObj.pNetPool->clTbl[0]); if (!pBuf) {#ifdef DEBUG_TRACE printf("eth%d Error: Failed to allocate cluster buffer\n", dev->unit);#endif /* DEBUG_TRACE */ return NULL; } /* pBuf =(pBuf + (SIZE_ETH_FB_HDR - 4));*/ } return (pBuf);}/********************************************************************************* at91EthTbdFree - free TBD** RETURNS: N/A.*/void at91EthTbdFree( ETH_DRV_CTRL *dev, /* pointer to driver structure */ unsigned char* pBuf /* pointer to the TBD to be freed */ ){#ifdef DEBUG_TRACE printf("eth%d TbdFree\n", dev->unit);#endif /* DEBUG_TRACE */ /* Free cluster buffer if necessary. */ /* if (dev->pClPool)*/ { /*netClFree(dev->endObj.pNetPool, (UCHAR *)(pBuf - (SIZE_ETH_FB_HDR - 4)));*/ netClFree(dev->endObj.pNetPool, (UCHAR *)(pBuf)); } /* Free the used TBD. */ /* Advance to next RBD. *//* dev->tbdIndex++; if (dev->tbdIndex == NUM_TBD_ETH) { dev->tbdIndex = 0; }*/}/********************************************************************************* at91EthTbdStart - start transmit** RETURNS: N/A.*/void at91EthTbdStart( ETH_DRV_CTRL *dev, /* pointer to driver structure */ unsigned char* data , /* pointer to the TBD to be freed */ ULONG length /* length of data */ ){ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; struct at91_private *lp = (struct at91_private *) dev->priv; if(regs->EMAC_TSR & AT91C_EMAC_BNQ){ /* Store packet information (to free when Tx completed) */ lp->skb = data; lp->skb_length = length; cacheFlush(DATA_CACHE,data, length); /* clean_dcache_range(data, length);*/ lp->skb_physaddr = (unsigned long) data ; /*cacheDrvVirtToPhys( )*/ lp->stats.tx_bytes += length; /* Set address of the data in the Transmit Address register */ regs->EMAC_TSR |= AT91C_EMAC_COMP; regs->EMAC_TAR = lp->skb_physaddr ; /* Set length of the packet in the Transmit Control register */ regs->EMAC_TCR = length; }}/********************************************************************************* at91EthTbdCheck - check TBD** RETURNS: OK, or ERROR.*/STATUS at91EthTbdCheck( ETH_DRV_CTRL *dev, /* pointer to driver structure */ unsigned char* pTbd /* pointer to the TBD to be checked */ ){ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; struct at91_private *lp = (struct at91_private *) dev->priv; int timeout = TX_WAIT_MAX; int retry = 3;#ifdef DEBUG_TRACE printf("eth%d TbdCheck\n", dev->unit);#endif /* DEBUG_TRACE */ /* Check if completed. */ while ( !(regs->EMAC_TSR & AT91C_EMAC_BNQ)) { if (--timeout == 0) { if (--retry == 0) { printf("eth%d Error: Tx timeout\n", dev->unit); return ERROR; } timeout = TX_WAIT_MAX; } } return ERROR;}/********************************************************************************* at91EthSend - send packet in interrupt mode** RETURNS: OK, or END_ERR_BLOCK.*/STATUS at91EthSend( ETH_DRV_CTRL *dev, /* pointer to driver structure */ M_BLK_ID pMblk /* pointer to the mBlk/cluster pair */ ){ ULONG length; unsigned char* pBuf=0; AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; if (!(regs->EMAC_TSR & AT91C_EMAC_BNQ)) return ERROR;#ifdef DEBUG_TRACE printf("eth%d Send, 0x%08X\n", unit, (UINT32)pMblk->mBlkHdr.mData);#endif /* DEBUG_TRACE */ if (dev->bTxBlocked) { /* Retry later. */ return END_ERR_BLOCK; } if (dev->bPolling) { return ERROR; } length = pMblk->mBlkPktHdr.len; /* Check frame length. */ if ((length <= SIZE_ETH_HDR) || (length > SIZE_ETH_MFLR)) { /* Up-date statistics. */ dev->MIB2TBL.ifOutErrors++; return ERROR; } pBuf = at91EthTbdGet(dev);#if 0 if ((pMblk->mBlkHdr.mData >= (char *)SYS_MEM_TOP) && (pMblk->mBlkHdr.mNext == NULL)) { char *pBuf1 = pMblk->pClBlk->clNode.pClBuf; length = pMblk->mBlkPktHdr.len; /* Swap buffer. */ pMblk->pClBlk->clNode.pClBuf = (char *)(pBuf - (SIZE_ETH_FB_HDR - 4)); pBuf = (pBuf1 + (SIZE_ETH_FB_HDR - 4)); pMblk->mBlkHdr.mData = (char *)(pBuf + SIZE_ETH_WA); } else#endif { /* Copy data. */ length = netMblkToBufCopy(pMblk, (char *)(pBuf + SIZE_ETH_WA), NULL); } /* Bump the statistic counter. */ END_ERR_ADD (&dev->endObj, MIB2_OUT_UCAST, +1); /* Free the Mblk. */ netMblkClChainFree(pMblk);#ifdef DEBUG_TRACE at91EthHexDump((UCHAR *)(pBuf + SIZE_ETH_WA), length);#endif /* DEBUG_TRACE */ /* Start transmit. */ at91EthTbdStart(dev, pBuf, length); return OK;}/********************************************************************************* at91EthPollReceive - receive packet in polled mode** RETURNS: OK, or EAGAIN.*/STATUS at91EthPollReceive( ETH_DRV_CTRL *dev, /* pointer to driver structure */ M_BLK_ID pMblk /* pointer to the mBlk/cluster pair */ ){ struct at91_private *lp = (struct at91_private *) dev->priv; PETHRBD pRbd = lp->dlist; AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; int index = lp->rxBuffIndex; char* pBuf =(char*)( pRbd->descriptors[index].addr&0xfffffffc); /* Get the first available RBD. */ /*pRbd = at91EthRbdGet(dev);*/ /* If no RBD is available, retry it later. */ if (pRbd == NULL) { return EAGAIN; } do { ULONG length = pRbd->descriptors[index].size & 0x7ff; if (length == 0) { break; } /* If buffer is not large enough, we do not copy the received buffer. */ if ((ULONG)pMblk->mBlkHdr.mLen < length) { printf("eth%d Error: Too small Rx mBlk, %d\n", dev->unit, pMblk->mBlkHdr.mLen); break; }#ifdef DEBUG_TRACE at91EthHexDump((UCHAR *)(pBuf + SIZE_ETH_WA), length);#endif /* DEBUG_TRACE */ /* Up-date statistics. */ dev->MIB2TBL.ifInOctets += length; if (((UINT8 *)(pBuf + SIZE_ETH_WA))[0] & 0x01) { dev->MIB2TBL.ifInNUcastPkts += 1; } else { dev->MIB2TBL.ifInUcastPkts += 1; } /* Set up the mBlk properly. */ pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkHdr.mLen = length; pMblk->mBlkPktHdr.len = length; /* Copy data. */ bcopy((char *)(pBuf + SIZE_ETH_WA), (char *)pMblk->mBlkHdr.mData, length); /* Free the used RBD. */ at91EthRbdFree(dev, pRbd); return OK; } while (FALSE); /* Up-date statistics. */ dev->MIB2TBL.ifInErrors++; /* Free the used RBD. */ at91EthRbdFree(dev, pRbd); return EAGAIN;}/********************************************************************************* at91EthPollSend - send packet in polled mode** RETURNS: OK, or EAGAIN.*/STATUS at91EthPollSend( ETH_DRV_CTRL *dev, /* pointer to driver structure */ M_BLK_ID pMblk /* pointer to the mBlk/cluster pair */ ){ ULONG length; unsigned char* pBuf = 0; AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; struct at91_private *lp = (struct at91_private *) dev->priv; if (!(regs->EMAC_TSR & AT91C_EMAC_BNQ)) return ERROR; #ifdef DEBUG_TRACE printf("eth%d PollSend, 0x%08X\n", unit, (UINT32)pMblk->mBlkHdr.mData);#endif /* DEBUG_TRACE */ length = pMblk->mBlkPktHdr.len; /* Check frame length. */ if ((length <= SIZE_ETH_HDR) || (length > SIZE_ETH_MFLR)) { /* Up-date statistics. */ dev->MIB2TBL.ifOutErrors++; return ERROR; } pBuf = at91EthTbdGet(dev); do { /* Copy data but do not free the Mblk. */ length = (ULONG)netMblkToBufCopy(pMblk, (char *)(pBuf + SIZE_ETH_WA), NULL);#ifdef DEBUG_TRACE at91EthHexDump((UCHAR *)(pBuf + SIZE_ETH_WA), length);#endif /* DEBUG_TRACE */ /* Start transmit. */ at91EthTbdStart(dev, pBuf, length); /* Check if completed. */ if (at91EthTbdCheck(dev, pBuf) == OK) { /* Up-date statistics. */ dev->MIB2TBL.ifOutOctets += (ULONG)length; if (((UINT8 *)(pBuf + SIZE_ETH_WA))[0] & 0x01) { dev->MIB2TBL.ifOutNUcastPkts += 1; } else { dev->MIB2TBL.ifOutUcastPkts += 1; } /* Free the used TBD. */ at91EthTbdFree(dev, pBuf); return OK; } } while (FALSE); /* Up-date statistics. */ dev->MIB2TBL.ifOutErrors++; /* Free the used TBD. */ at91EthTbdFree(dev, pBuf); return EAGAIN;}/********************************************************************************* at91EthRbdProcess - porcess a RBD** RETURNS : N/A*/void at91EthRbdProcess( ETH_DRV_CTRL *dev, /* pointer to driver structure */ PETHRBD pRbd /* pointer to the RBD */ ){ M_BLK_ID pMblk = NULL; char *pNewCluster = NULL; int index = dev->priv->rxBuffIndex; CL_BLK_ID pClBlk = NULL; char *pData ; UINT32 len ; while ( (pRbd->descriptors[index].addr & EMAC_DESC_DONE)) {#ifdef DEBUG_TRACE printf(" RxHandler, index = %d, addr=%x \n", index,pRbd->descriptors[index].addr);#endif /* DEBUG_TRACE */ pData = (char*)(pRbd->descriptors[index].addr&0xfffffffc); len = (pRbd->descriptors[index].size & 0x7ff);#ifdef DEBUG_TRACE at91EthHexDump((UCHAR *)(pData + SIZE_ETH_WA), len);#endif if (dev->endObj.pNetPool == NULL) { DEBUG_LOG (DRV_DEBUG_RX, "at91EndRecv: Illegal pNetPool on entry!\n", 0,0,0,0,0,0); END_ERR_ADD (&dev->endObj, MIB2_IN_ERRS, +1); goto cleanRXD; } /* Add one to our unicast data. */ END_ERR_ADD (&dev->endObj, MIB2_IN_UCAST, +1); if ((pMblk = mBlkGet (dev->endObj.pNetPool, M_DONTWAIT, MT_DATA)) == NULL) { DEBUG_LOG (DRV_DEBUG_RX, "at91EndRecv: Out of M Blocks!\n", 0,0,0,0,0,0); END_ERR_ADD (&dev->endObj, MIB2_IN_ERRS, +1); goto cleanRXD; } pNewCluster = netClusterGet (dev->endObj.pNetPool, dev->endObj.pNetPool->clTbl[0]); if (pNewCluster == NULL) { DEBUG_LOG (DRV_DEBUG_RX, "sngks32cEndRecv: Cannot loan!\n", 0,0,0,0,0,0); dev->lastError.errCode = END_ERR_NO_BUF; muxError(&dev->endObj, &dev->lastError); goto cleanRXD; } memcpy(pNewCluster+2,pData,len); /* Grab a cluster block to marry to the cluster we received. */ if ((pClBlk = netClBlkGet (dev->endObj.pNetPool, M_DONTWAIT)) == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -