📄 ibmemacend.c
字号:
if (pNewCluster == NULL) { DRV_LOG (DRV_DEBUG_ERROR, "Recv netClusterGet failed\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); /* Toss the packet, but reuse the cluster */ goto cleanRXD; } /* Get a cluster block for the full cluster. */ if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL) { netClFree (pDrvCtrl->end.pNetPool, pNewCluster); DRV_LOG (DRV_DEBUG_ERROR, "Out of Cluster Blocks!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); pNewCluster = NULL; /* Toss the packet, but reuse the cluster */ goto cleanRXD; } /* * Get an mBlk for the full cluster */ if ((pMblk = mBlkGet(pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL) { netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk); netClFree (pDrvCtrl->end.pNetPool, pNewCluster); DRV_LOG (DRV_DEBUG_ERROR, "Out of M Blocks!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); pNewCluster = NULL; /* Toss the packet, but reuse the cluster */ goto cleanRXD; } END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); len = pRxDesc->dataLen; /* get packet length */ pCluster = pRxDesc->bufferAdrs; /* Pointer to the packet */ DRV_LOG (DRV_DEBUG_RX, "Packet @ 0x%X for %d bytes!\n", pCluster, len, 3, 4, 5, 6); /* * Join the full cluster from the RX descriptor ring to the cluster block * obtained above and then join the cluster block to the mBlk obtained * above. Complete the information in the mBlk. */ netClBlkJoin (pClBlk, pCluster, len, NULL, 0, 0, 0); netMblkClJoin (pMblk, pClBlk); pMblk->mBlkHdr.mLen = len; pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkPktHdr.len = len; /* * Invalidate the cluster so upper layers will see the packet data * in memory and not stale data in cache. */ EMAC_CACHE_INVALIDATE (pMblk->mBlkHdr.mData, len); DRV_LOG (DRV_DEBUG_RX, "Handing packet off to MUX\n", 1, 2, 3, 4, 5, 6); /* Call the upper layer's receive routine. */ END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);cleanRXD: /* * Prepare the RX descriptor to receive another packet now that the * packet just received has been handed off to the MUX layer. To do this * the address of the new cluster obtained above must be written to the * descriptor. If an error occurred above obtaining a new cluster or * mBlk, pNewCluster will be NULL. In this case bufferAdrs will not be * updated (the existing buffer will be used again). */ if (pNewCluster != NULL) pRxDesc->bufferAdrs = pNewCluster; /* * Re-initialize the rest of the RX descriptor to prepare it to * receive again. pRxDesc->bufferAdrs should already be filled * in at this point! */ pRxDesc->dataLen = 0; if (index == (pDrvCtrl->numRxD - 1)) pRxDesc->statusControl = EMAC_RX_DESC_INIT | MAL_RX_CTRL_WRAP; else pRxDesc->statusControl = EMAC_RX_DESC_INIT; DRV_LOG (DRV_DEBUG_RECV, "<-ibmEmacRecv \n", 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* ibmEmacSend - the driver send routine** This routine is called by muxSend. The packet to be sent is contained in the* mBlk. Hardware addessing information must already be present in the* packet data. ibmEmacSendCopy or ibmEmacSendNoCopy is called to actually* send out the packet (depending on the state of the inputFlags).** RETURNS: OK or ERROR.*/LOCAL STATUS ibmEmacSend ( EMAC_DRV_CTRL * pDrvCtrl, M_BLK_ID pMblk /* data to send */ ) { STATUS rc; DRV_LOG (DRV_DEBUG_SEND, "->ibmEmacSend \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. */ if (!(pDrvCtrl->localFlags & EMAC_POLLING_MODE)) END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER); /* * Depending on the input flag passed in to ibmEmacEndLoad, call the * appropriate send routine. Copy or zero copy. */ if (pDrvCtrl->inputFlags & EMAC_INPUT_TX_COPY) rc = ibmEmacSendCopy(pDrvCtrl, pMblk); else rc = ibmEmacSendNoCopy(pDrvCtrl, pMblk); /* * If both TX channels are being used, use the other channel for the * next packet. */ pDrvCtrl->txChannel = (pDrvCtrl->txChannel + 1) % pDrvCtrl->numTxChannels; /* Give up the semaphore */ if (!(pDrvCtrl->localFlags & EMAC_POLLING_MODE)) END_TX_SEM_GIVE (&pDrvCtrl->end); /* Bump the appropriate statistic counter */ if (rc == OK) END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1); else END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_ERRS, +1); DRV_LOG (DRV_DEBUG_SEND, "<-ibmEmacSend \n", 1, 2, 3, 4, 5, 6); return (rc); }/********************************************************************************* ibmEmacSendCopy - the driver send routine (with copy)** 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. This routine acquires a new* cluster and copies the packet data from the M_BLK_ID into the cluster.** RETURNS: OK or ERROR.*/LOCAL STATUS ibmEmacSendCopy ( EMAC_DRV_CTRL * pDrvCtrl, M_BLK_ID pMblk /* data to send */ ) { MAL_BD * pTxDesc; TX_INFO * pTxChn; char * pBuf; int level; int len = 0; DRV_LOG (DRV_DEBUG_SEND, "->ibmEmacSendCopy \n", 1, 2, 3, 4, 5, 6); pTxChn = pDrvCtrl->txInfo + pDrvCtrl->txChannel; pTxDesc = pTxChn->pTxDesc + pTxChn->indexTxD; DRV_LOG (DRV_DEBUG_TX, "Send : index %d TX desc = 0x%X channel = %d\n", pTxChn->indexTxD, (int)pTxDesc, pDrvCtrl->txChannel, 4, 5, 6); /* Make sure that an available TX descriptor exists. */ if (pTxDesc->statusControl & MAL_TX_CTRL_READY) { DRV_LOG (DRV_DEBUG_ERROR, "Out of TX descriptors.\n", 1, 2, 3, 4, 5, 6); level = intLock (); pDrvCtrl->localFlags |= EMAC_TX_BLOCKED; intUnlock (level); /* kick the wd to ensure we unblock the MUX again, 5sec delay */ wdStart(pDrvCtrl->wdRestart,5*sysClkRateGet(),(FUNCPTR)ibmEmacWdRestart,(int)pDrvCtrl); return (END_ERR_BLOCK); } /* * pMblk could contain multiple clusters. Get a new cluster that will * be used to combine the data in the clusters in pMblk. */ pBuf = netClusterGet(pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId); if (pBuf == NULL) { DRV_LOG (DRV_DEBUG_ERROR, "Send netClusterGet failed\n", 1 , 2, 3, 4, 5, 6); level = intLock (); pDrvCtrl->localFlags |= EMAC_TX_BLOCKED; intUnlock (level); /* kick the wd to ensure we unblock the MUX again, 5sec delay */ wdStart(pDrvCtrl->wdRestart,5*sysClkRateGet(),(FUNCPTR)ibmEmacWdRestart,(int)pDrvCtrl); return (END_ERR_BLOCK); } DRV_LOG (DRV_DEBUG_TX, "New cluster pBuf = 0x%x\n", (int)pBuf, 2, 3, 4, 5, 6); /* ready to send, so clear the watchdog */ wdCancel(pDrvCtrl->wdRestart); /* * Combine (copy) all of the data in pMblk into the newly acquired cluster. * Padding to the minimum length is not necessary because the EMAC will * take care of it before appending the FCS. */ len = netMblkToBufCopy (pMblk, pBuf, NULL); netMblkClChainFree(pMblk); /* Save the cluster address so that Send Cleanup can free it later. */ pTxChn->txFree[pTxChn->indexTxD].typeFree = EMAC_TX_FREE_CLUSTER; pTxChn->txFree[pTxChn->indexTxD].pFree = pBuf; /* Flush the buffer/cluster out to memory */ EMAC_CACHE_FLUSH (pBuf, len); /* Prepare the buffer descriptor for transmit */ pTxDesc->bufferAdrs = pBuf; pTxDesc->dataLen = len; pTxDesc->statusControl |= (MAL_TX_CTRL_READY | MAL_TX_CTRL_LAST | MAL_TX_CTRL_INTR); /* Make sure descriptor update gets out to memory before TX begins */ EIEIO_SYNC; /* Transmit the packet. Tell EMAC to Get the New Packet */ EMAC_REG_WRITE(pDrvCtrl, EMAC_TMR0, pTxChn->getNewPacketTX); DRV_LOG (DRV_DEBUG_TX, "Packet was transmitted\n", 1, 2, 3, 4, 5, 6); /* Bump the TX descriptor ring placeholder to the next position. */ pTxChn->indexTxD = (pTxChn->indexTxD + 1) % pTxChn->numTxD; return (OK); }/********************************************************************************* ibmEmacSendNoCopy - the driver send routine (zero copy)** 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. This transmits the data directly* from the M_BLK_ID (zero copy).** RETURNS: OK or ERROR.*/LOCAL STATUS ibmEmacSendNoCopy ( EMAC_DRV_CTRL * pDrvCtrl, M_BLK_ID pMblk /* data to send */ ) { M_BLK_ID pTempMblk; int numBuffers = 0; MAL_BD * pTxDesc; MAL_BD * pTxDescFirst = NULL; TX_INFO * pTxChn; int level; int i; int tempIndex; int firstIndex = 0; DRV_LOG (DRV_DEBUG_SEND, "->ibmEmacSendNoCopy \n", 1, 2, 3, 4, 5, 6); DRV_LOG (DRV_DEBUG_TX, "Total packet length = %d\n", pMblk->mBlkPktHdr.len,2,3,4,5,6); pTxChn = pDrvCtrl->txInfo + pDrvCtrl->txChannel; /* Count of the number of clusters associated with this Mblk */ pTempMblk = pMblk; while (pTempMblk != NULL) { numBuffers++; pTempMblk = pTempMblk->mBlkHdr.mNext; } /* * Check to be sure the number of buffers required for this packet * doesn't exceed the total number of descriptors for this TX channel. * If it does, let send with copy handle this packet. */ if (numBuffers > pTxChn->numTxD) { DRV_LOG (DRV_DEBUG_ERROR, "%d buffs req exceeds num of descriptors\n", numBuffers,2,3,4,5,6); return(ibmEmacSendCopy(pDrvCtrl, pMblk)); } /* Make sure that enough available TX descriptors exist. */ for (i=0; i < numBuffers; i++) { tempIndex = (pTxChn->indexTxD + i) % pTxChn->numTxD; pTxDesc = pTxChn->pTxDesc + tempIndex; if (pTxDesc->statusControl & MAL_TX_CTRL_READY) { DRV_LOG (DRV_DEBUG_ERROR, "Out of TX descriptors.\n", 1, 2, 3, 4, 5, 6); level = intLock (); pDrvCtrl->localFlags |= EMAC_TX_BLOCKED; intUnlock (level); return (END_ERR_BLOCK); } } /* Initialize the buffer descriptors */ pTempMblk = pMblk; while (pTempMblk != NULL) { pTxDesc = pTxChn->pTxDesc + pTxChn->indexTxD; /* Is this the last descriptor in the packet? */ if (pTempMblk->mBlkHdr.mNext == NULL) { /* Save the Mblk address so that Send Cleanup can free it later. */ pTxChn->txFree[pTxChn->indexTxD].typeFree = EMAC_TX_FREE_MBLK_LAST; pTxChn->txFree[pTxChn->indexTxD].pFree = (UCHAR *)pMblk; pTxDesc->statusControl |= (MAL_TX_CTRL_LAST | MAL_TX_CTRL_INTR); } else if (pTxDescFirst != NULL) { pTxChn->txFree[pTxChn->indexTxD].typeFree = EMAC_TX_FREE_MBLK; } /* Flush the buffer/cluster out to memory */ EMAC_CACHE_FLUSH (pTempMblk->mBlkHdr.mData, pTempMblk->mBlkHdr.mLen); /* Prepare the buffer descriptor for transmit */ pTxDesc->bufferAdrs = pTempMblk->mBlkHdr.mData; pTxDesc->dataLen = pTempMblk->mBlkHdr.mLen; DRV_LOG (DRV_DEBUG_TX, " buf addr = 0x%x len = %d
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -