📄 ixethaccend.c
字号:
* ixEthAccEndMCastDel - delete a multicast address for the device** This routine removes a multicast address from whatever the driver* is listening for. It then resets the address filter.** RETURNS: OK or ERROR.*/LOCAL STATUS ixEthAccEndMCastDel(END_DEVICE *pDrvCtrl, /* device pointer */char* pAddress /* address to be deleted */){ int error; if ((error = etherMultiDel (&pDrvCtrl->end.multiList, (char *)pAddress)) == ENETRESET) ixEthAccEndConfig (pDrvCtrl); return(OK);}/******************************************************************************* ixEthAccEndMCastGet - get the multicast address list for the device** This routine gets the multicast list of whatever the driver* is already listening for.** RETURNS: OK or ERROR.*/LOCAL STATUS ixEthAccEndMCastGet(END_DEVICE *pDrvCtrl, /* device pointer */MULTI_TABLE* pTable /* address table to be filled in */){ return(etherMultiGet (&pDrvCtrl->end.multiList, pTable));}/********************************************************************************* ixEthAccEndStop - stop the device** This function calls BSP functions to disconnect interrupts and stop* the device from operating in interrupt mode.** RETURNS: OK or ERROR.*/LOCAL STATUS ixEthAccEndStop(END_DEVICE *pDrvCtrl /* device to be stopped */){ STATUS result = OK; /* If that port doesn't exist then just return */ if ( ixEthAccPhyAddresses[ pDrvCtrl->unit ] == 0xffffffff ) return OK; SYS_INT_DISCONNECT (pDrvCtrl, IxEthAccEndInt, (int)pDrvCtrl, &result); if (result == ERROR) { IXP_DRV_LOG (IXP_DRV_DEBUG_ERROR, "ixEthAccEndStop: Could not disconnect interrupt!\n", 1, 2, 3, 4, 5, 6); } /* register callbacks which discard the traffic */ result = ixEthAccPortTxDoneCallbackRegister( pDrvCtrl->unit, ixEthAccEndTxDoneCallbackShutdown, (UINT32) pDrvCtrl); if ( result != IX_ETH_ACC_SUCCESS) { IXP_DRV_LOG((IXP_DRV_DEBUG_ERROR | IXP_DRV_DEBUG_LOAD), "Error:Registering IxEthAcc Tx Callbacks for shutdown Port[%d]\n", pDrvCtrl->unit,2,3,4,5,6); return(ERROR); } result = ixEthAccPortRxCallbackRegister( pDrvCtrl->unit, ixEthAccEndRxCallbackShutdown, (UINT32) pDrvCtrl); if ( result != IX_ETH_ACC_SUCCESS) { IXP_DRV_LOG((IXP_DRV_DEBUG_ERROR | IXP_DRV_DEBUG_LOAD), "Error:Registering IxEthAcc Rx Callbacks for shutdown Port[%d]\n", pDrvCtrl->unit,2,3,4,5,6); return(ERROR); } /* now, shutdown the hw level */ result = ixdp425EthLibStop(pDrvCtrl->unit); if ( result != IX_SUCCESS) { IXP_DRV_LOG((IXP_DRV_DEBUG_ERROR | IXP_DRV_DEBUG_LOAD), "ixdp425EthLibStop Failed Port[%d]\n", pDrvCtrl->unit,2,3,4,5,6); return ERROR; } /* Wait aprox 1/2 sec for spin down */ taskDelay(sysClkRateGet()/2); END_FLAGS_CLR (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING)); return(result);}/******************************************************************************** ixEthAccEndUnload - unload a driver from the system** This function first brings down the device, and then frees any* stuff that was allocated by the driver in the load function.** RETURNS: OK or ERROR.*/LOCAL STATUS ixEthAccEndUnload(END_DEVICE* pDrvCtrl /* device to be unloaded */){ /* now, shutdown the hw level */ IX_STATUS result = ixdp425EthLibUnload(pDrvCtrl->unit); if ( result != IX_SUCCESS) { logMsg("ixdp425EthLibUnload Failed Port %d\n", pDrvCtrl->unit,2,3,4,5,6); return ERROR; } END_OBJECT_UNLOAD (&pDrvCtrl->end); /* TODO - Free any shared DMA memory */ return(OK);}/********************************************************************************* ixEthAccEndPollStart - start polled mode operations** RETURNS: OK or ERROR.*/LOCAL STATUS ixEthAccEndPollStart(END_DEVICE * pDrvCtrl /* device to be polled */){ int oldLevel; oldLevel = intLock (); /* disable ints during update */ pDrvCtrl->flags |= IxEthAccEnd_POLLING; intUnlock (oldLevel); /* now IxEthAccEndInt won't get confused */ IXP_DRV_LOG (IXP_DRV_DEBUG_POLL, "STARTED\n", 1, 2, 3, 4, 5, 6); ixEthAccEndConfig (pDrvCtrl); /* reconfigure device */ return(OK);}/********************************************************************************* ixEthAccEndPollStop - stop polled mode operations** 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 or ERROR.*/LOCAL STATUS ixEthAccEndPollStop(END_DEVICE * pDrvCtrl /* device to be polled */){ int oldLevel; oldLevel = intLock (); /* disable ints during register updates */ pDrvCtrl->flags &= ~IxEthAccEnd_POLLING; intUnlock (oldLevel); ixEthAccEndConfig (pDrvCtrl); IXP_DRV_LOG (IXP_DRV_DEBUG_POLL, "STOPPED\n", 1, 2, 3, 4, 5, 6); return(OK);}/********************************************************************************* ixEthAccEndReset - reset device** RETURNS: N/A.*/LOCAL void ixEthAccEndReset(END_DEVICE *pDrvCtrl){ /* TODO - reset the controller */}#ifdef IXE_ETHACC_POLL_ENABLE/********************************************************************************* ixEthAccEndStatusRead - get current device state/status** RETURNS: status bits.*/LOCAL UINT ixEthAccEndStatusRead(END_DEVICE *pDrvCtrl){ /* TODO - read and return status bits/register */ return(0);}#endif /* IXE_ETHACC_POLL_ENABLE */LOCAL void ixEthAccEndTxDoneCallbackShutdown(UINT32 callbackTag, M_BLK *pMblk){ /* Free the buffer back to the pool */ netMblkClChainFree (pMblk);}/********************************************************************************* ixEthAccEndTxDoneReplenishFast - replenish a mbuf to its pool* Attempt to return a mbuf to its pool. If this is not possible* then the buffer is stored in a fast 1R1W queue which is drained inside * the tnetTask context.** RETURNS: none*/LOCAL __inline__ void ixEthAccEndTxDoneReplenishFast(END_DEVICE *pDrvCtrl, M_BLK *pMblk){ /* check on the fly that it is possible to replenish * and check the buffer can be used for immediate replenish * (not chained nor shared) */#if 0 UINT32 rxBufsActive = pDrvCtrl->rxBufsReplenish - pDrvCtrl->rxBufsRecv; if (rxBufsActive < pDrvCtrl->rxBufsAlloc) { if ((pMblk->pClBlk->clRefCnt == 1) && (pMblk->m_next == NULL)) { /* check nobody else is running a replenish at the same time */ if (ixOsServFastMutexTryLock(&(pDrvCtrl->fastReplMutex)) == IX_SUCCESS) { /* replenish */ if (ixEthAccPortRxFreeReplenish(pDrvCtrl->unit, pMblk) != IX_ETH_ACC_SUCCESS) { pDrvCtrl->rxBufsReplenish++; /* The number of mblk sent to NPE */ /* release the lock */ ixOsServFastMutexUnlock(&(pDrvCtrl->fastReplMutex)); /* done */ return; } /* release the lock */ ixOsServFastMutexUnlock(&(pDrvCtrl->fastReplMutex)); } } }#endif /* the bufffer cannot yet be used for replenish, * Free the buffer back to the fast pool */ pDrvCtrl->replBufList[pDrvCtrl->replWr++ & RECBUF_MASK] = pMblk; /* pDrvCtrl points to the driver structure which got a * mbuf to replenish. If this queue is getting overloaded * it is necessary to wake up the tnetTask */ if (((pDrvCtrl->replWr - pDrvCtrl->replRd) == IXETHACC_REPL_NEARLY_FULL_THRESHOLD) && (pDrvCtrl->netJobAddIn - pDrvCtrl->netJobAddOut <= IXETHACC_NETJOBADD_THRESHOLD)) { IXP_DRV_LOG ((IXP_DRV_DEBUG_INT | IXP_DRV_DEBUG_RX), "NetJobAdd required for Replenish\n", 1, 2, 3, 4, 5, 6); if (netJobAdd ((FUNCPTR)ixEthAccEndHandleRcvInt, (int)pDrvCtrl, 0,0,0,0) == ERROR) {#ifdef IXP_DRV_DEBUG_MBUFS pDrvCtrl->tnetJobAddFail++;#endif DO_EVENT(IXE_EVT_XMT_REPLENISH_NETJOBADDFAIL); IXP_DRV_LOG ((IXP_DRV_DEBUG_ERROR), "NetJobAdd failed for TX Replenish\n", 1, 2, 3, 4, 5, 6); } else { pDrvCtrl->netJobAddIn++; DO_EVENT(IXE_EVT_XMT_REPLENISH_NETJOBADD); } } return;}LOCAL void ixEthAccEndTxDoneCallback(UINT32 callbackTag, M_BLK *pMblk){ END_DEVICE *pDrvCtrl = (END_DEVICE *)callbackTag; NET_POOL_ID netPoolId;#ifdef IXP_DRV_DEBUG M_BLK *mbufPtr;#endif DO_EVENT(IXE_EVT_XMT_DONECALLBACK_ENTRY);#ifdef IXP_DRV_DEBUG for ( mbufPtr = pMblk; mbufPtr; mbufPtr = mbufPtr->m_next ) { IXP_DRV_LOG (IXP_DRV_DEBUG_INT, "Tx ixe[%d] Callback Hdr: 0x%08X Buff: 0x%08X Size: 0x%08X\n" , pDrvCtrl->unit , (int)mbufPtr , (int)mbufPtr->m_data , mbufPtr->m_pkthdr.len , 5, 6); }#endif /* IXP_DRV_DEBUG */#ifdef IXP_DRV_DEBUG_MBUFS elogHook(pMblk, 5, pDrvCtrl->rxBufsRecv, pDrvCtrl->rxBufsReplenish);#endif /* attempt to release to the fastreplenish pool * associated with each driver */ netPoolId = MBLK_TO_NET_POOL(pMblk); /* check the current driver */ if (netPoolId == pDrvCtrl->end.pNetPool) { ixEthAccEndTxDoneReplenishFast(pDrvCtrl, pMblk); DO_EVENT(IXE_EVT_XMT_DONECALLBACK_EXIT); return; } else { /* check the other ixe driver (safe even if the driver is not * initialized, because the structure is initialized with * a dummy structure) */ pDrvCtrl = ixEthAccpDrvCtrl[1 - pDrvCtrl->unit]; if (netPoolId == pDrvCtrl->end.pNetPool) { ixEthAccEndTxDoneReplenishFast(pDrvCtrl, pMblk); DO_EVENT(IXE_EVT_XMT_DONECALLBACK_EXIT); return; } } /* this mbuf is from an 'unknown' origin, probably the system pool. * Free the buffer back to its pool */ netMblkClChainFree (pMblk); DO_EVENT(IXE_EVT_XMT_DONECALLBACK_EXIT);}LOCAL void ixEthAccEndRxCallbackShutdown(UINT32 callbackTag, M_BLK *pMblk, IxEthAccPortId portId){ END_DEVICE *pDrvCtrl = (END_DEVICE *)callbackTag; pDrvCtrl->rxBufsRecv++; netMblkClChainFree (pMblk);}LOCAL void ixEthAccEndRxCallback(UINT32 callbackTag, M_BLK *pMblk, IxEthAccPortId portId){ END_DEVICE *pDrvCtrl = (END_DEVICE *)callbackTag; BOOL netJobAddNeeded; DO_EVENT(IXE_EVT_RCV_CALLBACK_ENTRY); pDrvCtrl->rxBufsRecv++; DO_EVENT(IXE_EVT_RCV_CALLBACK_CACHEOPS); /* Now start a prefetch on the packet header */ PREFETCH(pMblk); IXP_DRV_LOG ((IXP_DRV_DEBUG_INT | IXP_DRV_DEBUG_RX), "Rx ixe[%d] Callback Hdr: 0x%08X Buff: 0x%08X Size: 0x%08X\n" , pDrvCtrl->unit , (int)pMblk , (int)pMblk->m_data , pMblk->m_pkthdr.len , 5, 6); /* 3 possibilities before the queue update * a - no entry in the queue : need to wake up the tnetTask * b - between 1 and 120 entries : the tnettask is already running * and there is no need for netjobadd * c - more than 120 entries : impossible by design, there are * only 120 mbufs in the rx pool. No check for overflow is * necessary. */ netJobAddNeeded = (pDrvCtrl->recWr == pDrvCtrl->recRd); /* Store to the top of the 1R1W queue */ pDrvCtrl->recBufList[pDrvCtrl->recWr++ & RECBUF_MASK] = pMblk; DO_EVENT(IXE_EVT_RCV_CALLBACK_RINGADD); /* 4 possibilities after the queue update * a - no entry in the queue : a ctxt switch occured * and the entry is already processed. No need for netjobadd * (this may occur when QMgr is running from a task) * b - 1 entry in the queue : the queue was empty before this cb * and a netjobadd is necessary to wake up the tnettask * c - between 2 and 120 entries : the tnettask is already running * and there is no need for netjobadd * d - more than 120 entries : impossible by design, there are * only 120 mbufs in the rx pool. No check for overflow is * necessary. */ /* if there are already NetJobAdd pending, it is unnecesary * to add more netJobAdd requests (1 netJobAdd will drain all * the sw queue) * In case of traffic burst, WRS strongly advice to not * overflow the tnetTask message queue. */ netJobAddNeeded = netJobAddNeeded &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -