⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ixethaccmac.c

📁 有关ARM开发板上的IXP400网络驱动程序的源码以。
💻 C
📖 第 1 页 / 共 5 页
字号:
        }        mBufPtr = mNextPtr;    }}PRIVATE IxEthAccStatus ixEthAccPortDisableTryReplenish(UINT32 portId){    int key;    IxEthAccStatus status = IX_ETH_ACC_SUCCESS;    volatile IxEthAccPortDisableState *rxState = &ixEthAccMacState[portId].rxState;    /* replenish with the special buffer again if it is received      * and update the rxState     * This section is protected because the portDisable context     * run an identical code, so the system keeps replenishing at the     * maximum rate.     */    key = ixOsalIrqLock();    if (*rxState == RECEIVE)    {	IX_OSAL_MBUF *mbufRxPtr = ixEthAccMacState[portId].portDisableRxMbufPtr;	*rxState = REPLENISH;	IX_OSAL_MBUF_MLEN(mbufRxPtr) = IX_ETHACC_RX_MBUF_MIN_SIZE;	status = ixEthAccPortRxFreeReplenish(portId, mbufRxPtr);    }    ixOsalIrqUnlock(key);    return status;}PRIVATE voidixEthAccPortDisableRxAndReplenish (IxEthAccPortId portId, 				   IX_OSAL_MBUF * mBufPtr,				   BOOL useMultiBufferCallback){    /* call the callback which forwards the traffic to the client */    ixEthAccPortDisableRx(portId, mBufPtr, useMultiBufferCallback);    /* try to replenish with the buffer used in portDisable     * if seen in Rx     */    ixEthAccPortDisableTryReplenish(portId);}PRIVATE voidixEthAccPortDisableRxCallback (UINT32 cbTag, 			       IX_OSAL_MBUF * mBufPtr,			       UINT32 learnedPortId){    IxEthAccPortId portId = (IxEthAccPortId)cbTag;    /* call the portDisable receive callback */   (ixEthAccPortDisableRxTable[portId])(portId, mBufPtr, FALSE);}PRIVATE voidixEthAccPortDisableMultiBufferRxCallback (UINT32 cbTag, 					  IX_OSAL_MBUF **mBufPtr){    IxEthAccPortId portId = (IxEthAccPortId)cbTag;    while (*mBufPtr)    {	/* call the portDisable receive callback with one buffer at a time */	(ixEthAccPortDisableRxTable[portId])(portId, *mBufPtr++, TRUE);    }}IxEthAccStatusixEthAccPortDisablePriv(IxEthAccPortId portId){    IxEthAccStatus status = IX_ETH_ACC_SUCCESS;    int key;    int retry, retryTimeout;    volatile IxEthAccPortDisableState *state = &ixEthAccMacState[portId].portDisableState;    volatile IxEthAccPortDisableState *rxState = &ixEthAccMacState[portId].rxState;    volatile IxEthAccPortDisableState *txState = &ixEthAccMacState[portId].txState;    IX_ETH_ACC_VALIDATE_PORT_ID(portId);    if (!IX_ETH_IS_PORT_INITIALIZED(portId))    {	return (IX_ETH_ACC_PORT_UNINITIALIZED);    }        /* if the state is being set to what it is already at, do nothing */    if (!ixEthAccMacState[portId].enabled)    {        return IX_ETH_ACC_SUCCESS;    }    *state = DISABLED;    /* disable MAC receive first */    ixEthAccPortRxDisablePriv(portId);    /* disable ethernet database for this port - It is done now to avoid     * issuing ELT maintenance after requesting 'port disable' in an NPE      */    if (ixEthDBPortDisable(portId) != IX_ETH_DB_SUCCESS)    {	status = IX_ETH_ACC_FAIL;        IX_ETH_ACC_FATAL_LOG("ixEthAccPortDisable: failed to disable EthDB for this port\n", 0, 0, 0, 0, 0, 0);    }    /* enter the critical section */    key = ixOsalIrqLock();    /* swap the Rx and TxDone callbacks */    ixEthAccPortDisableFn[portId]            = ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn;    ixEthAccPortDisableMultiBufferFn[portId] = ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn;    ixEthAccPortDisableCbTag[portId]         = ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag;    ixEthAccPortDisableMultiBufferCbTag[portId] = ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag;    ixEthAccPortDisableTxDoneFn[portId]      = ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn;    ixEthAccPortDisableTxDoneCbTag[portId]   = ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag;    ixEthAccPortDisableRxTable[portId]       =  ixEthAccPortDisableRx;    /* register temporary callbacks */    ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn            = ixEthAccPortDisableRxCallback;    ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag           = portId;    ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn = ixEthAccPortDisableMultiBufferRxCallback;    ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag = portId;    ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn  = ixEthAccPortDisableTxDone;    ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag           = portId;    /* initialise the Rx state and Tx states */    *txState = TRANSMIT_DONE;    *rxState = RECEIVE;    /* exit the critical section */    ixOsalIrqUnlock(key);    /* enable a NPE loopback */    if (ixEthAccNpeLoopbackEnablePriv(portId) != IX_ETH_ACC_SUCCESS)    {	status = IX_ETH_ACC_FAIL;    }    if (status == IX_ETH_ACC_SUCCESS)    {	retry = 0;	/* Step 1 : Drain Tx traffic and TxDone queues :	 *	 * Transmit and replenish at least once with the 	 * special buffers until both of them are seen 	 * in the callback hook	 *	 * (the receive callback keeps replenishing, so once we see	 * the special Tx buffer, we can be sure that Tx drain is complete)	 */	ixEthAccPortDisableRxTable[portId] 	    =  ixEthAccPortDisableRxAndReplenish;	ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn  	    = ixEthAccPortDisableTxDone;	do	{	    /* keep replenishing */	    status = ixEthAccPortDisableTryReplenish(portId);	    if (status == IX_ETH_ACC_SUCCESS)	    {		/* keep transmitting */				status = ixEthAccPortDisableTryTransmit(portId);	    }	    if (status == IX_ETH_ACC_SUCCESS)	    {		/* wait for some traffic being processed */		ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);	    }	}	while ((status == IX_ETH_ACC_SUCCESS)	       && (retry++ < IX_ETH_ACC_MAX_RETRY)	       && (*txState == TRANSMIT));	/* Step 2 : Drain Rx traffic, RxFree and Rx queues :	 *	 * Transmit and replenish at least once with the 	 * special buffers until both of them are seen 	 * in the callback hook	 * (the transmit callback keeps transmitting, and when we see	 * the special Rx buffer, we can be sure that rxFree drain 	 * is complete)	 *	 * The nested loop helps to retry if the user was keeping 	 * replenishing or transmitting during portDisable.	 *	 * The 2 nested loops ensure more retries if user traffic is 	 * seen during portDisable : the user should not replenish	 * or transmit while portDisable is running. However, because of	 * the queueing possibilities in ethAcc dataplane, it is possible	 * that a lot of traffic is left in the queues (e.g. when 	 * transmitting over a low speed link) and therefore, more	 * retries are allowed to help flushing the buffers out.	 */	ixEthAccPortDisableRxTable[portId] 	    =  ixEthAccPortDisableRx;	ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn  	    = ixEthAccPortDisableTxDoneAndSubmit;	do	{	    do	    {		ixEthAccPortDisableUserBufferCount[portId] = 0;		/* keep replenishing */		status = ixEthAccPortDisableTryReplenish(portId);		if (status == IX_ETH_ACC_SUCCESS)		{		    /* keep transmitting */				    status = ixEthAccPortDisableTryTransmit(portId);		}		if (status == IX_ETH_ACC_SUCCESS)		{		    /* wait for some traffic being processed */		    ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);		}	    }	    while ((status == IX_ETH_ACC_SUCCESS)		   && (retry++ < IX_ETH_ACC_MAX_RETRY)		   && ((ixEthAccPortDisableUserBufferCount[portId] != 0)		       || (*rxState == REPLENISH)));	    /* After the first iteration, change the receive callbacks, 	     * to process only 1 buffer at a time 	     */	    ixEthAccPortDisableRxTable[portId] 		= ixEthAccPortDisableRx;	    ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn  		= ixEthAccPortDisableTxDone;	    /* repeat the whole process while user traffic is seen in TxDone	     *	     * The conditions to stop the loop are	     * - Xscale has both Rx and Tx special buffers	     *   (txState = transmit, rxState = receive)	     * - any error in txSubmit or rxReplenish	     * - no user traffic seen 	     * - an excessive amount of retries	     */	}	while ((status == IX_ETH_ACC_SUCCESS)	       && (retry < IX_ETH_ACC_MAX_RETRY)	       && (*txState == TRANSMIT));	/* check the loop exit conditions. The NPE should not hold	 * the special buffers.	 */	if ((*rxState == REPLENISH) || (*txState == TRANSMIT))	{	    status = IX_ETH_ACC_FAIL;	}	if (status == IX_ETH_ACC_SUCCESS)	{	    /* Step 3 : Replenish without transmitting until a timeout 	     * occurs, in order to drain the internal NPE fifos	     *	     * we can expect a few frames srill held	     * in the NPE. 	     *	     * The 2 nested loops take care about the NPE dropping traffic	     * (including loopback traffic) when the Rx queue is full.	     *	     * The timeout value is very conservative 	     * since the loopback used keeps replenishhing.	     *	     */	    do	    {		ixEthAccPortDisableRxTable[portId] = ixEthAccPortDisableRxAndReplenish;		ixEthAccPortDisableUserBufferCount[portId] = 0;		retryTimeout = 0;		do		{		    /* keep replenishing */		    status = ixEthAccPortDisableTryReplenish(portId);		    if (status == IX_ETH_ACC_SUCCESS)		    {			/* wait for some traffic being processed */			ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);		    }		}		while ((status == IX_ETH_ACC_SUCCESS)		       && (retryTimeout++ < IX_ETH_ACC_MAX_RETRY_TIMEOUT));      		/* Step 4 : Transmit once. Stop replenish		 * 		 * After the Rx timeout, we are sure that the NPE does not		 * hold any frame in its internal NPE fifos.		 *		 * At this point, the NPE still holds the last rxFree buffer.		 * By transmitting a single frame, this should unblock the		 * last rxFree buffer. This code just transmit once and		 * wait for both frames seen in TxDone and in rxFree.		 *		 */		ixEthAccPortDisableRxTable[portId] =  ixEthAccPortDisableRx;		status = ixEthAccPortDisableTryTransmit(portId);		/* the NPE should immediatelyt release 		 * the last Rx buffer and the last transmitted buffer		 * unless the last Tx frame was dropped (rx queue full)		 */		if (status == IX_ETH_ACC_SUCCESS)		{		    retryTimeout = 0;		    do		    {			ixOsalSleep(IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS);		    }		    while ((*rxState == REPLENISH) 			   && (retryTimeout++ < IX_ETH_ACC_MAX_RETRY_TIMEOUT));		}		/* the NPE may have dropped the traffic because of Rx		 * queue being full. This code ensures that the last 		 * Tx and Rx frames are both received.		 */	    }	    while ((status == IX_ETH_ACC_SUCCESS)		   && (retry++ < IX_ETH_ACC_MAX_RETRY)		   && ((*txState == TRANSMIT) 		       || (*rxState == REPLENISH)		       || (ixEthAccPortDisableUserBufferCount[portId] != 0)));	    /* Step 5 : check the final states : the NPE has 	     * no buffer left, nor in Tx , nor in Rx directions.	     */	    if ((*rxState == REPLENISH) || (*txState == TRANSMIT))	    {		status = IX_ETH_ACC_FAIL;	    }	}        /* now all the buffers are drained, disable NPE loopback 	 * This is done regardless of the logic to drain the queues and	 * the internal buffers held by the NPE.	 */	if (ixEthAccNpeLoopbackDisablePriv(portId) != IX_ETH_ACC_SUCCESS)	{	    status = IX_ETH_ACC_FAIL;	}    }    /* disable MAC Tx and Rx services */    ixEthAccMacState[portId].enabled = FALSE;      ixEthAccMacStateUpdate(portId);    /* restore the Rx and TxDone callbacks (within a critical section) */    key = ixOsalIrqLock();    ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn            = ixEthAccPortDisableFn[portId];    ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag           = ixEthAccPortDisableCbTag[portId];    ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn = ixEthAccPortDisableMultiBufferFn[portId];    ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag = ixEthAccPortDisableMultiBufferCbTag[portId];    ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn  = ixEthAccPortDisableTxDoneFn[portId];    ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag           = ixEthAccPortDisableTxDoneCbTag[portId];        ixOsalIrqUnlock(key);    /* the MAC core rx/tx disable may left the MAC hardware in an     * unpredictable state. A hw reset is executed before resetting      * all the MAC parameters to a known value.     */    REG_WRITE(ixEthAccMacBase[portId], 	      IX_ETH_ACC_MAC_CORE_CNTRL,	      IX_ETH_ACC_CORE_RESET);    ixOsalSleep(IX_ETH_ACC_MAC_RESET_DELAY);    /* rewrite all parameters to their current value */    ixEthAccMacStateUpdate(portId);    REG_WRITE(ixEthAccMacBase[portId],	      IX_ETH_ACC_MAC_INT_CLK_THRESH,	      IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT);    REG_WRITE(ixEthAccMacBase[portId], 	      IX_ETH_ACC_MAC_CORE_CNTRL,	      IX_ETH_ACC_CORE_MDC_EN);        return status;}IxEthAccStatusixEthAccPortEnabledQueryPriv(IxEthAccPortId portId, BOOL *enabled){    IX_ETH_ACC_VALIDATE_PORT_ID(portId);      if (!IX_ETH_IS_PORT_INITIALIZED(portId))    {        /* Since Eth NPE is not available, port must be disabled */          *enabled = FALSE ;	return (IX_ETH_ACC_PORT_UNINITIALIZED);    }        *enabled = ixEthAccMacState[portId].enabled;        return IX_ETH_ACC_SUCCESS;}IxEthAccStatus ixEthAccPortMacResetPriv(IxEthAccPortId portId){    IX_ETH_ACC_VALIDATE_PORT_ID(portId);    if (!IX_ETH_IS_PORT_INITIALIZED(portId))    {	return (IX_ETH_ACC_PORT_UNINITIALIZED);    }        /* Reset MAC core */        REG_WRITE(ixEthAccMacBase[portId], 	      IX_ETH_ACC_MAC_CORE_CNTRL,	      IX_ETH_ACC_CORE_RESET);    ixOsalSleep(IX_ETH_ACC_MAC_RESET_DELAY);    REG_WRITE(ixEthAccMacBase[portId], 	      IX_ETH_ACC_MAC_CORE_CNTRL,	      IX_ETH_ACC_CORE_MDC_EN);    /* Reconfigure the MAC core registers */    REG_WRITE(ixEthAccMacBase[portId],	      IX_ETH_ACC_MAC_TX_CNTRL2,	      IX_ETH_ACC_TX_CNTRL2_RETRIES_MASK);    REG_WRITE(ixEthAccMacBase[portId],	      IX_ETH_ACC_MAC_RANDOM_SEED,	      IX_ETH_ACC_RANDOM_SEED_DEFAULT);    REG_WRITE(ixEthAccMacBase[portId],	      IX_ETH_ACC_MAC_THRESH_P_EMPTY,	      IX_ETH_ACC_MAC_THRESH_P_EMPTY_DEFAULT);    REG_WRITE(ixEthAccMacBase[portId],	      IX_ETH_ACC_MAC_THRESH_P_FULL,	      IX_ETH_ACC_MAC_THRESH_P_FULL_DEFAULT);    REG_WRITE(ixEthAccMacBase[portId],	      IX_ETH_ACC_MAC_TX_DEFER,	      IX_ETH_ACC_MAC_TX_DEFER_DEFAULT);    REG_WRITE(ixEthAccMacBase[portId],	      IX_ETH_ACC_MAC_TX_TWO_DEFER_1,	      IX_ETH_ACC_MAC_TX_TWO_DEFER_1_DEFAULT);    REG_WRITE(ixEthAccMacBase[portId],	      IX_ETH_ACC_MAC_TX_TWO_DEFER_2,	      IX_ETH_ACC_MAC_TX_TWO_DEFER_2_DEFAULT);    REG_WRITE(ixEthAccMacBase[portId],	      IX_ETH_ACC_MAC_SLOT_TIME,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -