| /** | 
 |  * @file IxEthAccMac.c | 
 |  * | 
 |  * @author Intel Corporation | 
 |  * @date | 
 |  * | 
 |  * @brief  MAC control functions | 
 |  * | 
 |  * Design Notes: | 
 |  * | 
 |  * @par | 
 |  * IXP400 SW Release version 2.0 | 
 |  * | 
 |  * -- Copyright Notice -- | 
 |  * | 
 |  * @par | 
 |  * Copyright 2001-2005, Intel Corporation. | 
 |  * All rights reserved. | 
 |  * | 
 |  * @par | 
 |  * Redistribution and use in source and binary forms, with or without | 
 |  * modification, are permitted provided that the following conditions | 
 |  * are met: | 
 |  * 1. Redistributions of source code must retain the above copyright | 
 |  *    notice, this list of conditions and the following disclaimer. | 
 |  * 2. Redistributions in binary form must reproduce the above copyright | 
 |  *    notice, this list of conditions and the following disclaimer in the | 
 |  *    documentation and/or other materials provided with the distribution. | 
 |  * 3. Neither the name of the Intel Corporation nor the names of its contributors | 
 |  *    may be used to endorse or promote products derived from this software | 
 |  *    without specific prior written permission. | 
 |  * | 
 |  * @par | 
 |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' | 
 |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
 |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE | 
 |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
 |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 
 |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
 |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 
 |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 
 |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 
 |  * SUCH DAMAGE. | 
 |  * | 
 |  * @par | 
 |  * -- End of Copyright Notice -- | 
 |  */ | 
 |  | 
 | #include "IxOsal.h" | 
 | #include "IxNpeMh.h" | 
 | #ifdef CONFIG_IXP425_COMPONENT_ETHDB | 
 | #include "IxEthDB.h" | 
 | #endif | 
 | #include "IxEthDBPortDefs.h" | 
 | #include "IxEthNpe.h" | 
 | #include "IxEthAcc.h" | 
 | #include "IxEthAccDataPlane_p.h" | 
 | #include "IxEthAcc_p.h" | 
 | #include "IxEthAccMac_p.h" | 
 |  | 
 | /* Maximum number of retries during ixEthAccPortDisable, which | 
 |  * is approximately 10 seconds | 
 | */ | 
 | #define IX_ETH_ACC_MAX_RETRY 500 | 
 |  | 
 | /* Maximum number of retries during ixEthAccPortDisable when expecting | 
 |  * timeout | 
 |  */ | 
 | #define IX_ETH_ACC_MAX_RETRY_TIMEOUT 5 | 
 |  | 
 | #define IX_ETH_ACC_VALIDATE_PORT_ID(portId) \ | 
 |     do                                                           \ | 
 |     {                                                            \ | 
 |         if(!IX_ETH_ACC_IS_PORT_VALID(portId))   \ | 
 |         {                                                        \ | 
 | 	    return IX_ETH_ACC_INVALID_PORT;                      \ | 
 |         }                                                        \ | 
 |     } while(0) | 
 |  | 
 | PUBLIC IxEthAccMacState ixEthAccMacState[IX_ETH_ACC_NUMBER_OF_PORTS]; | 
 |  | 
 | PRIVATE UINT32 ixEthAccMacBase[IX_ETH_ACC_NUMBER_OF_PORTS]; | 
 |  | 
 | /*Forward function declarations*/ | 
 | PRIVATE void | 
 | ixEthAccPortDisableRx (IxEthAccPortId portId, | 
 | 		       IX_OSAL_MBUF * mBufPtr, | 
 | 		       BOOL useMultiBufferCallback); | 
 |  | 
 | PRIVATE void | 
 | ixEthAccPortDisableRxAndReplenish (IxEthAccPortId portId, | 
 | 				   IX_OSAL_MBUF * mBufPtr, | 
 | 				   BOOL useMultiBufferCallback); | 
 |  | 
 | PRIVATE void | 
 | ixEthAccPortDisableTxDone (UINT32 cbTag, | 
 | 			   IX_OSAL_MBUF *mbuf); | 
 |  | 
 | PRIVATE void | 
 | ixEthAccPortDisableTxDoneAndSubmit (UINT32 cbTag, | 
 | 				    IX_OSAL_MBUF *mbuf); | 
 |  | 
 | PRIVATE void | 
 | ixEthAccPortDisableRxCallback (UINT32 cbTag, | 
 | 			       IX_OSAL_MBUF * mBufPtr, | 
 | 			       UINT32 learnedPortId); | 
 |  | 
 | PRIVATE void | 
 | ixEthAccPortDisableMultiBufferRxCallback (UINT32 cbTag, | 
 | 					  IX_OSAL_MBUF **mBufPtr); | 
 |  | 
 | PRIVATE IxEthAccStatus | 
 | ixEthAccPortDisableTryTransmit(UINT32 portId); | 
 |  | 
 | PRIVATE IxEthAccStatus | 
 | ixEthAccPortDisableTryReplenish(UINT32 portId); | 
 |  | 
 | PRIVATE IxEthAccStatus | 
 | ixEthAccPortMulticastMacAddressGet (IxEthAccPortId portId, | 
 | 				    IxEthAccMacAddr *macAddr); | 
 |  | 
 | PRIVATE IxEthAccStatus | 
 | ixEthAccPortMulticastMacFilterGet (IxEthAccPortId portId, | 
 | 				   IxEthAccMacAddr *macAddr); | 
 |  | 
 | PRIVATE void | 
 | ixEthAccMacNpeStatsMessageCallback (IxNpeMhNpeId npeId, | 
 | 				    IxNpeMhMessage msg); | 
 |  | 
 | PRIVATE void | 
 | ixEthAccMacNpeStatsResetMessageCallback (IxNpeMhNpeId npeId, | 
 | 					 IxNpeMhMessage msg); | 
 |  | 
 | PRIVATE void | 
 | ixEthAccNpeLoopbackMessageCallback (IxNpeMhNpeId npeId, | 
 | 				    IxNpeMhMessage msg); | 
 |  | 
 | PRIVATE void | 
 | ixEthAccMulticastAddressSet(IxEthAccPortId portId); | 
 |  | 
 | PRIVATE BOOL | 
 | ixEthAccMacEqual(IxEthAccMacAddr *macAddr1, | 
 | 		 IxEthAccMacAddr *macAddr2); | 
 |  | 
 | PRIVATE void | 
 | ixEthAccMacPrint(IxEthAccMacAddr *m); | 
 |  | 
 | PRIVATE void | 
 | ixEthAccMacStateUpdate(IxEthAccPortId portId); | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccMacMemInit(void) | 
 | { | 
 |     ixEthAccMacBase[IX_ETH_PORT_1] = | 
 | 	(UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_0_BASE, | 
 | 				 IX_OSAL_IXP400_ETHA_MAP_SIZE); | 
 |     ixEthAccMacBase[IX_ETH_PORT_2] = | 
 | 	(UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_1_BASE, | 
 | 				 IX_OSAL_IXP400_ETHB_MAP_SIZE); | 
 | #ifdef __ixp46X | 
 |     ixEthAccMacBase[IX_ETH_PORT_3] = | 
 | 	(UINT32) IX_OSAL_MEM_MAP(IX_ETH_ACC_MAC_2_BASE, | 
 | 				 IX_OSAL_IXP400_ETH_NPEA_MAP_SIZE); | 
 |     if (ixEthAccMacBase[IX_ETH_PORT_3] == 0) | 
 |     { | 
 | 	ixOsalLog(IX_OSAL_LOG_LVL_FATAL, | 
 | 		  IX_OSAL_LOG_DEV_STDOUT, | 
 | 		  "EthAcc: Could not map MAC I/O memory\n", | 
 | 		  0, 0, 0, 0, 0 ,0); | 
 |  | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 | #endif | 
 |  | 
 |     if (ixEthAccMacBase[IX_ETH_PORT_1] == 0 | 
 | 	|| ixEthAccMacBase[IX_ETH_PORT_2] == 0) | 
 |     { | 
 | 	ixOsalLog(IX_OSAL_LOG_LVL_FATAL, | 
 | 		  IX_OSAL_LOG_DEV_STDOUT, | 
 | 		  "EthAcc: Could not map MAC I/O memory\n", | 
 | 		  0, 0, 0, 0, 0 ,0); | 
 |  | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | void | 
 | ixEthAccMacUnload(void) | 
 | { | 
 |     IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_1]); | 
 |     IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_2]); | 
 | #ifdef __ixp46X | 
 |     IX_OSAL_MEM_UNMAP(ixEthAccMacBase[IX_ETH_PORT_3]); | 
 |     ixEthAccMacBase[IX_ETH_PORT_3] = 0; | 
 | #endif | 
 |     ixEthAccMacBase[IX_ETH_PORT_2] = 0; | 
 |     ixEthAccMacBase[IX_ETH_PORT_1] = 0; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortEnablePriv(IxEthAccPortId portId) | 
 | { | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable port.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 |         printf("EthAcc: (Mac) cannot enable port %d, port not initialized\n", portId); | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     if (ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn == NULL) | 
 |     { | 
 |         /* TxDone callback not registered */ | 
 |         printf("EthAcc: (Mac) cannot enable port %d, TxDone callback not registered\n", portId); | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     if ((ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn == NULL) | 
 | 	&& (ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn == NULL)) | 
 |     { | 
 |         /* Receive callback not registered */ | 
 |         printf("EthAcc: (Mac) cannot enable port %d, Rx callback not registered\n", portId); | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     if(!ixEthAccMacState[portId].initDone) | 
 |     { | 
 |         printf("EthAcc: (Mac) cannot enable port %d, MAC address not set\n", portId); | 
 | 	return (IX_ETH_ACC_MAC_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     /* if the state is being set to what it is already at, do nothing*/ | 
 |     if (ixEthAccMacState[portId].enabled) | 
 |     { | 
 |         return IX_ETH_ACC_SUCCESS; | 
 |     } | 
 |  | 
 | #ifdef CONFIG_IXP425_COMPONENT_ETHDB | 
 |     /* enable ethernet database for this port */ | 
 |     if (ixEthDBPortEnable(portId) != IX_ETH_DB_SUCCESS) | 
 |     { | 
 |         printf("EthAcc: (Mac) cannot enable port %d, EthDB failure\n", portId); | 
 |         return IX_ETH_ACC_FAIL; | 
 |     } | 
 | #endif | 
 |  | 
 |     /* set 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, | 
 | 	      IX_ETH_ACC_MAC_SLOT_TIME_DEFAULT); | 
 |  | 
 |     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_BUF_SIZE_TX, | 
 | 	      IX_ETH_ACC_MAC_BUF_SIZE_TX_DEFAULT); | 
 |  | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 	      IX_ETH_ACC_TX_CNTRL1_DEFAULT); | 
 |  | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	      IX_ETH_ACC_RX_CNTRL1_DEFAULT); | 
 |  | 
 |     /* set the global state */ | 
 |     ixEthAccMacState[portId].portDisableState = ACTIVE; | 
 |     ixEthAccMacState[portId].enabled = TRUE; | 
 |  | 
 |     /* rewrite the setup (including mac filtering) depending | 
 |      * on current options | 
 |      */ | 
 |     ixEthAccMacStateUpdate(portId); | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | /* | 
 |  * PortDisable local variables. They contain the intermediate steps | 
 |  * while the port is being disabled and the buffers being drained out | 
 |  * of the NPE. | 
 |  */ | 
 | typedef void (*IxEthAccPortDisableRx)(IxEthAccPortId portId, | 
 | 				      IX_OSAL_MBUF * mBufPtr, | 
 | 				      BOOL useMultiBufferCallback); | 
 | static IxEthAccPortRxCallback | 
 | ixEthAccPortDisableFn[IX_ETH_ACC_NUMBER_OF_PORTS]; | 
 | static IxEthAccPortMultiBufferRxCallback | 
 | ixEthAccPortDisableMultiBufferFn[IX_ETH_ACC_NUMBER_OF_PORTS]; | 
 | static IxEthAccPortDisableRx | 
 | ixEthAccPortDisableRxTable[IX_ETH_ACC_NUMBER_OF_PORTS]; | 
 | static UINT32 | 
 | ixEthAccPortDisableCbTag[IX_ETH_ACC_NUMBER_OF_PORTS]; | 
 | static UINT32 | 
 | ixEthAccPortDisableMultiBufferCbTag[IX_ETH_ACC_NUMBER_OF_PORTS]; | 
 |  | 
 | static IxEthAccPortTxDoneCallback | 
 | ixEthAccPortDisableTxDoneFn[IX_ETH_ACC_NUMBER_OF_PORTS]; | 
 | static UINT32 | 
 | ixEthAccPortDisableTxDoneCbTag[IX_ETH_ACC_NUMBER_OF_PORTS]; | 
 |  | 
 | static UINT32 | 
 | ixEthAccPortDisableUserBufferCount[IX_ETH_ACC_NUMBER_OF_PORTS]; | 
 |  | 
 | /* | 
 |  * PortDisable private callbacks functions. They handle the user | 
 |  * traffic, and the special buffers (one for tx, one for rx) used | 
 |  * in portDisable. | 
 |  */ | 
 | PRIVATE void | 
 | ixEthAccPortDisableTxDone(UINT32 cbTag, | 
 | 			  IX_OSAL_MBUF *mbuf) | 
 | { | 
 |     IxEthAccPortId portId = (IxEthAccPortId)cbTag; | 
 |     volatile IxEthAccPortDisableState *txState = &ixEthAccMacState[portId].txState; | 
 |  | 
 |     /* check for the special mbuf used in portDisable */ | 
 |     if (mbuf == ixEthAccMacState[portId].portDisableTxMbufPtr) | 
 |     { | 
 |         *txState = TRANSMIT_DONE; | 
 |     } | 
 |     else | 
 |     { | 
 | 	/* increment the count of user traffic during portDisable */ | 
 | 	ixEthAccPortDisableUserBufferCount[portId]++; | 
 |  | 
 |        /* call client TxDone function */ | 
 |         ixEthAccPortDisableTxDoneFn[portId](ixEthAccPortDisableTxDoneCbTag[portId], mbuf); | 
 |     } | 
 | } | 
 |  | 
 | PRIVATE IxEthAccStatus | 
 | ixEthAccPortDisableTryTransmit(UINT32 portId) | 
 | { | 
 |     int key; | 
 |     IxEthAccStatus status = IX_ETH_ACC_SUCCESS; | 
 |     volatile IxEthAccPortDisableState *txState = &ixEthAccMacState[portId].txState; | 
 |     /* transmit the special buffer again if it is transmitted | 
 |      * and update the txState | 
 |      * This section is protected because the portDisable context | 
 |      * run an identical code, so the system keeps transmitting at the | 
 |      * maximum rate. | 
 |      */ | 
 |     key = ixOsalIrqLock(); | 
 |     if (*txState == TRANSMIT_DONE) | 
 |     { | 
 | 	IX_OSAL_MBUF *mbufTxPtr = ixEthAccMacState[portId].portDisableTxMbufPtr; | 
 | 	*txState = TRANSMIT; | 
 | 	status = ixEthAccPortTxFrameSubmit(portId, | 
 | 					   mbufTxPtr, | 
 | 					   IX_ETH_ACC_TX_DEFAULT_PRIORITY); | 
 |     } | 
 |     ixOsalIrqUnlock(key); | 
 |  | 
 |     return status; | 
 | } | 
 |  | 
 | PRIVATE void | 
 | ixEthAccPortDisableTxDoneAndSubmit(UINT32 cbTag, | 
 | 				   IX_OSAL_MBUF *mbuf) | 
 | { | 
 |     IxEthAccPortId portId = (IxEthAccPortId)cbTag; | 
 |  | 
 |     /* call the callback which forwards the traffic to the client */ | 
 |     ixEthAccPortDisableTxDone(cbTag, mbuf); | 
 |  | 
 |     /* try to transmit the buffer used in portDisable | 
 |      * if seen in TxDone | 
 |      */ | 
 |     ixEthAccPortDisableTryTransmit(portId); | 
 | } | 
 |  | 
 | PRIVATE void | 
 | ixEthAccPortDisableRx (IxEthAccPortId portId, | 
 | 		       IX_OSAL_MBUF * mBufPtr, | 
 | 		       BOOL useMultiBufferCallback) | 
 | { | 
 |     volatile IxEthAccPortDisableState *rxState = &ixEthAccMacState[portId].rxState; | 
 |     IX_OSAL_MBUF *mNextPtr; | 
 |  | 
 |     while (mBufPtr) | 
 |     { | 
 | 	mNextPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mBufPtr); | 
 | 	IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mBufPtr) = NULL; | 
 |  | 
 | 	/* check for the special mbuf used in portDisable */ | 
 | 	if (mBufPtr == ixEthAccMacState[portId].portDisableRxMbufPtr) | 
 | 	{ | 
 |             *rxState = RECEIVE; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 	    /* increment the count of user traffic during portDisable */ | 
 | 	    ixEthAccPortDisableUserBufferCount[portId]++; | 
 |  | 
 | 	    /* reset the received payload length during portDisable */ | 
 | 	    IX_OSAL_MBUF_MLEN(mBufPtr)    = 0; | 
 | 	    IX_OSAL_MBUF_PKT_LEN(mBufPtr) = 0; | 
 |  | 
 | 	    if (useMultiBufferCallback) | 
 | 	    { | 
 | 		/* call the user callback with one unchained | 
 | 		 * buffer, without payload. A small array is built | 
 | 		 * to be used as a parameter (the user callback expects | 
 | 		 * to receive an array ended by a NULL pointer. | 
 | 		 */ | 
 | 		IX_OSAL_MBUF *mBufPtrArray[2]; | 
 |  | 
 | 		mBufPtrArray[0] = mBufPtr; | 
 | 		mBufPtrArray[1] = NULL; | 
 | 		ixEthAccPortDisableMultiBufferFn[portId]( | 
 | 			 ixEthAccPortDisableMultiBufferCbTag[portId], | 
 | 			 mBufPtrArray); | 
 | 	    } | 
 | 	    else | 
 | 	    { | 
 | 		/* call the user callback with a unchained | 
 | 		 * buffer, without payload and the destination port is | 
 | 		 * unknown. | 
 | 		 */ | 
 | 		ixEthAccPortDisableFn[portId]( | 
 | 		      ixEthAccPortDisableCbTag[portId], | 
 | 		      mBufPtr, | 
 | 		      IX_ETH_DB_UNKNOWN_PORT /* port not found */); | 
 | 	    } | 
 |         } | 
 |  | 
 |         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 void | 
 | ixEthAccPortDisableRxAndReplenish (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 void | 
 | ixEthAccPortDisableRxCallback (UINT32 cbTag, | 
 | 			       IX_OSAL_MBUF * mBufPtr, | 
 | 			       UINT32 learnedPortId) | 
 | { | 
 |     IxEthAccPortId portId = (IxEthAccPortId)cbTag; | 
 |  | 
 |     /* call the portDisable receive callback */ | 
 |    (ixEthAccPortDisableRxTable[portId])(portId, mBufPtr, FALSE); | 
 | } | 
 |  | 
 | PRIVATE void | 
 | ixEthAccPortDisableMultiBufferRxCallback (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); | 
 |     } | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortDisablePriv(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_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot disable port.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     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); | 
 |  | 
 | #ifdef CONFIG_IXP425_COMPONENT_ETHDB | 
 |     /* 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); | 
 |     } | 
 | #endif | 
 |  | 
 |     /* 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; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortEnabledQueryPriv(IxEthAccPortId portId, BOOL *enabled) | 
 | { | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable port.\n",(INT32)portId,0,0,0,0,0); | 
 |  | 
 |         /* Since Eth NPE is not available, port must be disabled */ | 
 |         *enabled = FALSE ; | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     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_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot reset Ethernet coprocessor.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     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 IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortLoopbackEnable(IxEthAccPortId portId) | 
 | { | 
 |     UINT32 regval; | 
 |  | 
 |     /* Turn off promiscuous mode */ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable loopback.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     /* read register */ | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	     regval); | 
 |  | 
 |     /* update register */ | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	      regval | IX_ETH_ACC_RX_CNTRL1_LOOP_EN); | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | PRIVATE void | 
 | ixEthAccNpeLoopbackMessageCallback (IxNpeMhNpeId npeId, | 
 | 				    IxNpeMhMessage msg) | 
 | { | 
 |     IxEthAccPortId portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId); | 
 |  | 
 | #ifndef NDEBUG | 
 |     /* Prudent to at least check the port is within range */ | 
 |     if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS) | 
 |     { | 
 | 	IX_ETH_ACC_FATAL_LOG("IXETHACC:ixEthAccPortDisableMessageCallback: Illegal port: %u\n", | 
 |             (UINT32) portId, 0, 0, 0, 0, 0); | 
 |  | 
 | 	return; | 
 |     } | 
 | #endif | 
 |  | 
 |     /* unlock message reception mutex */ | 
 |     ixOsalMutexUnlock(&ixEthAccMacState[portId].npeLoopbackMessageLock); | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccNpeLoopbackEnablePriv(IxEthAccPortId portId) | 
 | { | 
 |     IX_STATUS npeMhStatus; | 
 |     IxNpeMhMessage message; | 
 |     IxEthAccStatus status = IX_ETH_ACC_SUCCESS; | 
 |  | 
 |     /* Turn off promiscuous mode */ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable NPE loopback.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     /* enable NPE loopback (lsb of the message contains the value 1) */ | 
 |     message.data[0] = (IX_ETHNPE_SETLOOPBACK_MODE << IX_ETH_ACC_MAC_MSGID_SHL) | 
 | 	| 0x01; | 
 |     message.data[1] = 0; | 
 |  | 
 |     npeMhStatus = ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId), | 
 | 		message, | 
 | 		IX_ETHNPE_SETLOOPBACK_MODE_ACK, | 
 | 		ixEthAccNpeLoopbackMessageCallback, | 
 | 		IX_NPEMH_SEND_RETRIES_DEFAULT); | 
 |  | 
 |     if (npeMhStatus != IX_SUCCESS) | 
 |     { | 
 |         status = IX_ETH_ACC_FAIL; | 
 |     } | 
 |     else | 
 |     { | 
 | 	/* wait for NPE loopbackEnable response */ | 
 |         if (ixOsalMutexLock(&ixEthAccMacState[portId]. npeLoopbackMessageLock, | 
 | 			    IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS) | 
 | 	    != IX_SUCCESS) | 
 |         { | 
 |             status = IX_ETH_ACC_FAIL; | 
 |         } | 
 |     } | 
 |  | 
 |     return status; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortTxEnablePriv(IxEthAccPortId portId) | 
 | { | 
 |     UINT32 regval; | 
 |  | 
 |     /* Turn off promiscuous mode */ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable TX.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     /* read register */ | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 	     regval); | 
 |  | 
 |     /* update register */ | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 	      regval | IX_ETH_ACC_TX_CNTRL1_TX_EN); | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortRxEnablePriv(IxEthAccPortId portId) | 
 | { | 
 |     UINT32 regval; | 
 |  | 
 |     /* Turn off promiscuous mode */ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable RX.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     /* read register */ | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	     regval); | 
 |  | 
 |     /* update register */ | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	      regval | IX_ETH_ACC_RX_CNTRL1_RX_EN); | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortLoopbackDisable(IxEthAccPortId portId) | 
 | { | 
 |     UINT32 regval; | 
 |  | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot disable loopback.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     /*disable MAC loopabck */ | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	     regval); | 
 |  | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	      (regval & ~IX_ETH_ACC_RX_CNTRL1_LOOP_EN)); | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccNpeLoopbackDisablePriv(IxEthAccPortId portId) | 
 | { | 
 |     IX_STATUS npeMhStatus; | 
 |     IxNpeMhMessage message; | 
 |     IxEthAccStatus status = IX_ETH_ACC_SUCCESS; | 
 |  | 
 |     /* Turn off promiscuous mode */ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot enable NPE loopback.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     /* disable NPE loopback (lsb of the message contains the value 0) */ | 
 |     message.data[0] = (IX_ETHNPE_SETLOOPBACK_MODE << IX_ETH_ACC_MAC_MSGID_SHL); | 
 |     message.data[1] = 0; | 
 |  | 
 |     npeMhStatus = ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId), | 
 | 		message, | 
 | 		IX_ETHNPE_SETLOOPBACK_MODE_ACK, | 
 | 		ixEthAccNpeLoopbackMessageCallback, | 
 | 		IX_NPEMH_SEND_RETRIES_DEFAULT); | 
 |  | 
 |     if (npeMhStatus != IX_SUCCESS) | 
 |     { | 
 |         status = IX_ETH_ACC_FAIL; | 
 |     } | 
 |     else | 
 |     { | 
 | 	/* wait for NPE loopbackEnable response */ | 
 |         if (ixOsalMutexLock(&ixEthAccMacState[portId].npeLoopbackMessageLock, | 
 | 			    IX_ETH_ACC_PORT_DISABLE_DELAY_MSECS) | 
 | 	    != IX_SUCCESS) | 
 |         { | 
 |             status = IX_ETH_ACC_FAIL; | 
 |         } | 
 |     } | 
 |  | 
 |     return status; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortTxDisablePriv(IxEthAccPortId portId) | 
 | { | 
 |     UINT32 regval; | 
 |  | 
 |     /* Turn off promiscuous mode */ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot disable TX.\n", (INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     /* read register */ | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 	     regval); | 
 |  | 
 |     /* update register */ | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 	      (regval & ~IX_ETH_ACC_TX_CNTRL1_TX_EN)); | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortRxDisablePriv(IxEthAccPortId portId) | 
 | { | 
 |     UINT32 regval; | 
 |  | 
 |     /* Turn off promiscuous mode */ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Eth %d: Cannot disable RX.\n", (INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     /* read register */ | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	     regval); | 
 |  | 
 |     /* update register */ | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	      (regval & ~IX_ETH_ACC_RX_CNTRL1_RX_EN)); | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortPromiscuousModeClearPriv(IxEthAccPortId portId) | 
 | { | 
 |     UINT32 regval; | 
 |  | 
 |     /* Turn off promiscuous mode */ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot clear promiscuous mode.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     /*set bit 5 of Rx control 1 - enable address filtering*/ | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	     regval); | 
 |  | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	      regval | IX_ETH_ACC_RX_CNTRL1_ADDR_FLTR_EN); | 
 |  | 
 |     ixEthAccMacState[portId].promiscuous = FALSE; | 
 |  | 
 |     ixEthAccMulticastAddressSet(portId); | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortPromiscuousModeSetPriv(IxEthAccPortId portId) | 
 | { | 
 |     UINT32 regval; | 
 |  | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot set promiscuous mode.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     /* | 
 |      * Set bit 5 of Rx control 1 - We enable address filtering even in | 
 |      * promiscuous mode because we want the MAC to set the appropriate | 
 |      * bits in m_flags which doesn't happen if we turn off filtering. | 
 |      */ | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	     regval); | 
 |  | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	      regval | IX_ETH_ACC_RX_CNTRL1_ADDR_FLTR_EN); | 
 |  | 
 |     ixEthAccMacState[portId].promiscuous = TRUE; | 
 |  | 
 |     ixEthAccMulticastAddressSet(portId); | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortUnicastMacAddressSetPriv (IxEthAccPortId portId, | 
 | 				  IxEthAccMacAddr *macAddr) | 
 | { | 
 |     UINT32 i; | 
 |  | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot set Unicast Mac Address.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |  | 
 |     if (macAddr == NULL) | 
 |     { | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |     if ( macAddr->macAddress[0] & IX_ETH_ACC_ETH_MAC_BCAST_MCAST_BIT ) | 
 |     { | 
 | 	/* This is a multicast/broadcast address cant set it ! */ | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |     if ( macAddr->macAddress[0] == 0 && | 
 | 	 macAddr->macAddress[1] == 0 && | 
 | 	 macAddr->macAddress[2] == 0 && | 
 | 	 macAddr->macAddress[3] == 0 && | 
 | 	 macAddr->macAddress[4] == 0 && | 
 | 	 macAddr->macAddress[5] == 0  ) | 
 |     { | 
 | 	/* This is an invalid mac address cant set it ! */ | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 | #ifdef CONFIG_IXP425_COMPONENT_ETHDB | 
 |     /* update the MAC address in the ethernet database */ | 
 |     if (ixEthDBPortAddressSet(portId, (IxEthDBMacAddr *) macAddr) != IX_ETH_DB_SUCCESS) | 
 |     { | 
 |         return IX_ETH_ACC_FAIL; | 
 |     } | 
 | #endif | 
 |  | 
 |     /*Set the Unicast MAC to the specified value*/ | 
 |     for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++) | 
 |     { | 
 | 	REG_WRITE(ixEthAccMacBase[portId], | 
 | 		  IX_ETH_ACC_MAC_UNI_ADDR_1 + i*sizeof(UINT32), | 
 | 		  macAddr->macAddress[i]); | 
 |     } | 
 |     ixEthAccMacState[portId].initDone = TRUE; | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortUnicastMacAddressGetPriv (IxEthAccPortId portId, | 
 | 				  IxEthAccMacAddr *macAddr) | 
 | { | 
 |     /*Return the current value of the Unicast MAC from h/w | 
 |       for the specified port*/ | 
 |     UINT32 i; | 
 |  | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get Unicast Mac Address.\n",(INT32)portId,0,0,0,0,0); | 
 |         /* Since Eth Npe is unavailable, return invalid MAC Address = 00:00:00:00:00:00 */ | 
 |         for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++) | 
 |         { | 
 | 	    macAddr->macAddress[i] = 0; | 
 |         } | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if(!ixEthAccMacState[portId].initDone) | 
 |     { | 
 | 	return (IX_ETH_ACC_MAC_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     if (macAddr == NULL) | 
 |     { | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |  | 
 |     for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++) | 
 |     { | 
 | 	REG_READ(ixEthAccMacBase[portId], | 
 | 		 IX_ETH_ACC_MAC_UNI_ADDR_1 + i*sizeof(UINT32), | 
 | 		 macAddr->macAddress[i]); | 
 |     } | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | PRIVATE IxEthAccStatus | 
 | ixEthAccPortMulticastMacAddressGet (IxEthAccPortId portId, | 
 | 				    IxEthAccMacAddr *macAddr) | 
 | { | 
 |     /*Return the current value of the Multicast MAC from h/w | 
 |       for the specified port*/ | 
 |     UINT32 i; | 
 |  | 
 |     for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++) | 
 |     { | 
 |  | 
 | 	REG_READ(ixEthAccMacBase[portId], | 
 | 		 IX_ETH_ACC_MAC_ADDR_1 + i*sizeof(UINT32), | 
 | 		 macAddr->macAddress[i]); | 
 |     } | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | PRIVATE IxEthAccStatus | 
 | ixEthAccPortMulticastMacFilterGet (IxEthAccPortId portId, | 
 | 				   IxEthAccMacAddr *macAddr) | 
 | { | 
 |     /*Return the current value of the Multicast MAC from h/w | 
 |       for the specified port*/ | 
 |     UINT32 i; | 
 |  | 
 |     for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++) | 
 |     { | 
 |  | 
 | 	REG_READ(ixEthAccMacBase[portId], | 
 | 		 IX_ETH_ACC_MAC_ADDR_MASK_1 + i*sizeof(UINT32), | 
 | 		 macAddr->macAddress[i]); | 
 |     } | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortMulticastAddressJoinPriv (IxEthAccPortId portId, | 
 | 				  IxEthAccMacAddr *macAddr) | 
 | { | 
 |     UINT32 i; | 
 |     IxEthAccMacAddr broadcastAddr = {{0xff,0xff,0xff,0xff,0xff,0xff}}; | 
 |  | 
 |     /*Check that the port parameter is valid*/ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot join Multicast Mac Address.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     /*Check that the mac address is valid*/ | 
 |     if(macAddr == NULL) | 
 |     { | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |     /* Check that this is a multicast address */ | 
 |     if (!(macAddr->macAddress[0] & IX_ETH_ACC_ETH_MAC_BCAST_MCAST_BIT)) | 
 |     { | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |     /* We don't add the Broadcast address */ | 
 |     if(ixEthAccMacEqual(&broadcastAddr, macAddr)) | 
 |     { | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |     for (i = 0; | 
 | 	 i<ixEthAccMacState[portId].mcastAddrIndex; | 
 | 	 i++) | 
 |     { | 
 | 	/*Check if the current entry already match an existing matches*/ | 
 | 	if(ixEthAccMacEqual(&ixEthAccMacState[portId].mcastAddrsTable[i], macAddr)) | 
 | 	{ | 
 | 	    /* Address found in the list and already configured, | 
 | 	     * return a success status | 
 | 	     */ | 
 | 	    return IX_ETH_ACC_SUCCESS; | 
 | 	} | 
 |     } | 
 |  | 
 |     /* check for availability at the end of the current table */ | 
 |     if(ixEthAccMacState[portId].mcastAddrIndex >= IX_ETH_ACC_MAX_MULTICAST_ADDRESSES) | 
 |     { | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |     /*First add the address to the multicast table for the | 
 |       specified port*/ | 
 |     i=ixEthAccMacState[portId].mcastAddrIndex; | 
 |  | 
 |     memcpy(&ixEthAccMacState[portId].mcastAddrsTable[i], | 
 | 	   &macAddr->macAddress, | 
 | 	   IX_IEEE803_MAC_ADDRESS_SIZE); | 
 |  | 
 |     /*Increment the index into the table, this must be done here | 
 |      as MulticastAddressSet below needs to know about the latest | 
 |      entry. | 
 |     */ | 
 |     ixEthAccMacState[portId].mcastAddrIndex++; | 
 |  | 
 |     /*Then calculate the new value to be written to the address and | 
 |       address mask registers*/ | 
 |     ixEthAccMulticastAddressSet(portId); | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortMulticastAddressJoinAllPriv (IxEthAccPortId portId) | 
 | { | 
 |     IxEthAccMacAddr mcastMacAddr = {{0x1,0x0,0x0,0x0,0x0,0x0}}; | 
 |  | 
 |     /*Check that the port parameter is valid*/ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot join all Multicast Address.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     /* remove all entries from the database and | 
 |     *  insert a multicast entry | 
 |     */ | 
 |     memcpy(&ixEthAccMacState[portId].mcastAddrsTable[0], | 
 | 	   &mcastMacAddr.macAddress, | 
 | 	   IX_IEEE803_MAC_ADDRESS_SIZE); | 
 |  | 
 |     ixEthAccMacState[portId].mcastAddrIndex = 1; | 
 |     ixEthAccMacState[portId].joinAll = TRUE; | 
 |  | 
 |     ixEthAccMulticastAddressSet(portId); | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortMulticastAddressLeavePriv (IxEthAccPortId portId, | 
 | 				   IxEthAccMacAddr *macAddr) | 
 | { | 
 |     UINT32 i; | 
 |     IxEthAccMacAddr mcastMacAddr = {{0x1,0x0,0x0,0x0,0x0,0x0}}; | 
 |  | 
 |     /*Check that the port parameter is valid*/ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot leave Multicast Address.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     /*Check that the mac address is valid*/ | 
 |     if(macAddr == NULL) | 
 |     { | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |     /* Remove this mac address from the mask for the specified port | 
 |      * we copy down all entries above the blanked entry, and | 
 |      * decrement the index | 
 |      */ | 
 |     i=0; | 
 |  | 
 |     while(i<ixEthAccMacState[portId].mcastAddrIndex) | 
 |     { | 
 | 	/*Check if the current entry matches*/ | 
 | 	if(ixEthAccMacEqual(&ixEthAccMacState[portId].mcastAddrsTable[i], | 
 | 			    macAddr)) | 
 | 	{ | 
 | 	    if(ixEthAccMacEqual(macAddr, &mcastMacAddr)) | 
 | 	    { | 
 | 		ixEthAccMacState[portId].joinAll = FALSE; | 
 | 	    } | 
 | 	    /*Decrement the index into the multicast address table | 
 | 	      for the current port*/ | 
 | 	    ixEthAccMacState[portId].mcastAddrIndex--; | 
 |  | 
 | 	    /*Copy down all entries above the current entry*/ | 
 | 	    while(i<ixEthAccMacState[portId].mcastAddrIndex) | 
 | 	    { | 
 | 		memcpy(&ixEthAccMacState[portId].mcastAddrsTable[i], | 
 | 		       &ixEthAccMacState[portId].mcastAddrsTable[i+1], | 
 | 		       IX_IEEE803_MAC_ADDRESS_SIZE); | 
 |                 i++; | 
 | 	    } | 
 | 	    /*recalculate the mask and write it to the MAC*/ | 
 | 	    ixEthAccMulticastAddressSet(portId); | 
 |  | 
 | 	    return IX_ETH_ACC_SUCCESS; | 
 | 	} | 
 | 	/* search the next entry */ | 
 | 	i++; | 
 |     } | 
 |     /* no matching entry found */ | 
 |     return IX_ETH_ACC_NO_SUCH_ADDR; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortMulticastAddressLeaveAllPriv (IxEthAccPortId portId) | 
 | { | 
 |     /*Check that the port parameter is valid*/ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot leave all Multicast Address.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     ixEthAccMacState[portId].mcastAddrIndex = 0; | 
 |     ixEthAccMacState[portId].joinAll = FALSE; | 
 |  | 
 |     ixEthAccMulticastAddressSet(portId); | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortUnicastAddressShowPriv (IxEthAccPortId portId) | 
 | { | 
 |     IxEthAccMacAddr macAddr; | 
 |  | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot show Unicast Address.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     /*Get the MAC (UINICAST) address from hardware*/ | 
 |     if(ixEthAccPortUnicastMacAddressGetPriv(portId, &macAddr) != IX_ETH_ACC_SUCCESS) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: MAC address uninitialised port %u\n", | 
 | 			       (INT32)portId,0,0,0,0,0); | 
 | 	return IX_ETH_ACC_MAC_UNINITIALIZED; | 
 |     } | 
 |  | 
 |     /*print it out*/ | 
 |     ixEthAccMacPrint(&macAddr); | 
 |     printf("\n"); | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 |  | 
 |  | 
 | void | 
 | ixEthAccPortMulticastAddressShowPriv(IxEthAccPortId portId) | 
 | { | 
 |     IxEthAccMacAddr macAddr; | 
 |     UINT32 i; | 
 |  | 
 |     if(!IX_ETH_ACC_IS_PORT_VALID(portId)) | 
 |     { | 
 |         return; | 
 |     } | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot show Multicast Address.\n",(INT32)portId,0,0,0,0,0); | 
 |         return ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return; | 
 |     } | 
 |  | 
 |     printf("Multicast MAC: "); | 
 |     /*Get the MAC (MULTICAST) address from hardware*/ | 
 |     ixEthAccPortMulticastMacAddressGet(portId, &macAddr); | 
 |     /*print it out*/ | 
 |     ixEthAccMacPrint(&macAddr); | 
 |     /*Get the MAC (MULTICAST) filter from hardware*/ | 
 |     ixEthAccPortMulticastMacFilterGet(portId, &macAddr); | 
 |     /*print it out*/ | 
 |     printf(" ( "); | 
 |     ixEthAccMacPrint(&macAddr); | 
 |     printf(" )\n"); | 
 |     printf("Constituent Addresses:\n"); | 
 |     for(i=0;i<ixEthAccMacState[portId].mcastAddrIndex;i++) | 
 |     { | 
 | 	ixEthAccMacPrint(&ixEthAccMacState[portId].mcastAddrsTable[i]); | 
 | 	printf("\n"); | 
 |     } | 
 |     return; | 
 | } | 
 |  | 
 | /*Set the duplex mode*/ | 
 | IxEthAccStatus | 
 | ixEthAccPortDuplexModeSetPriv (IxEthAccPortId portId, | 
 | 			   IxEthAccDuplexMode mode) | 
 | { | 
 |     UINT32 txregval; | 
 |     UINT32 rxregval; | 
 |  | 
 |     /*This is bit 1 of the transmit control reg, set to 1 for half | 
 |       duplex, 0 for full duplex*/ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot set Duplex Mode.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 	     txregval); | 
 |  | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	     rxregval); | 
 |  | 
 |     if (mode ==  IX_ETH_ACC_FULL_DUPLEX) | 
 |     { | 
 | 	/*Clear half duplex bit in TX*/ | 
 | 	REG_WRITE(ixEthAccMacBase[portId], | 
 | 		  IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 		  txregval & ~IX_ETH_ACC_TX_CNTRL1_DUPLEX); | 
 |  | 
 | 	/*We must set the pause enable in the receive logic when in | 
 | 	  full duplex mode*/ | 
 | 	REG_WRITE(ixEthAccMacBase[portId], | 
 | 		  IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 		  rxregval | IX_ETH_ACC_RX_CNTRL1_PAUSE_EN); | 
 | 	ixEthAccMacState[portId].fullDuplex = TRUE; | 
 |  | 
 |     } | 
 |     else if (mode ==  IX_ETH_ACC_HALF_DUPLEX) | 
 |     { | 
 | 	/*Set half duplex bit in TX*/ | 
 | 	REG_WRITE(ixEthAccMacBase[portId], | 
 | 		  IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 		  txregval | IX_ETH_ACC_TX_CNTRL1_DUPLEX); | 
 |  | 
 | 	/*We must clear pause enable in the receive logic when in | 
 | 	  half duplex mode*/ | 
 | 	REG_WRITE(ixEthAccMacBase[portId], | 
 | 		  IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 		  rxregval & ~IX_ETH_ACC_RX_CNTRL1_PAUSE_EN); | 
 |  | 
 | 	ixEthAccMacState[portId].fullDuplex = FALSE; | 
 |     } | 
 |     else | 
 |     { | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 |  | 
 | } | 
 |  | 
 |  | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortDuplexModeGetPriv (IxEthAccPortId portId, | 
 | 			   IxEthAccDuplexMode *mode) | 
 | { | 
 |     /*Return the duplex mode for the specified port*/ | 
 |     UINT32 regval; | 
 |  | 
 |     /*This is bit 1 of the transmit control reg, set to 1 for half | 
 |       duplex, 0 for full duplex*/ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get Duplex Mode.\n",(INT32)portId,0,0,0,0,0); | 
 |         /* return hald duplex */ | 
 |         *mode = IX_ETH_ACC_HALF_DUPLEX ; | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     if (mode == NULL) | 
 |     { | 
 | 	return (IX_ETH_ACC_FAIL); | 
 |     } | 
 |  | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 	     regval); | 
 |  | 
 |     if( regval & IX_ETH_ACC_TX_CNTRL1_DUPLEX) | 
 |     { | 
 | 	*mode = IX_ETH_ACC_HALF_DUPLEX; | 
 |     } | 
 |     else | 
 |     { | 
 | 	*mode = IX_ETH_ACC_FULL_DUPLEX; | 
 |     } | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 |  | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortTxFrameAppendPaddingEnablePriv (IxEthAccPortId portId) | 
 | { | 
 |     UINT32 regval; | 
 |     /*Enable FCS computation by the MAC and appending to the | 
 |       frame*/ | 
 |  | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable Tx Frame Append Padding.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 	     regval); | 
 |  | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 	      regval | | 
 | 	      IX_ETH_ACC_TX_CNTRL1_PAD_EN); | 
 |  | 
 |     ixEthAccMacState[portId].txPADAppend = TRUE; | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortTxFrameAppendPaddingDisablePriv (IxEthAccPortId portId) | 
 | { | 
 |     UINT32 regval; | 
 |  | 
 |     /*disable FCS computation and appending*/ | 
 |     /*Set bit 4 of Tx control register one to zero*/ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot disble Tx Frame Append Padding.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 	     regval); | 
 |  | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 	      regval & ~IX_ETH_ACC_TX_CNTRL1_PAD_EN); | 
 |  | 
 |     ixEthAccMacState[portId].txPADAppend = FALSE; | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortTxFrameAppendFCSEnablePriv (IxEthAccPortId portId) | 
 | { | 
 |     UINT32 regval; | 
 |  | 
 |     /*Enable FCS computation by the MAC and appending to the | 
 |       frame*/ | 
 |  | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable Tx Frame Append FCS.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 	     regval); | 
 |  | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 	      regval | IX_ETH_ACC_TX_CNTRL1_FCS_EN); | 
 |  | 
 |     ixEthAccMacState[portId].txFCSAppend = TRUE; | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortTxFrameAppendFCSDisablePriv (IxEthAccPortId portId) | 
 | { | 
 |     UINT32 regval; | 
 |  | 
 |     /*disable FCS computation and appending*/ | 
 |     /*Set bit 4 of Tx control register one to zero*/ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot disable Tx Frame Append FCS.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 	     regval); | 
 |  | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 	      regval & ~IX_ETH_ACC_TX_CNTRL1_FCS_EN); | 
 |  | 
 |     ixEthAccMacState[portId].txFCSAppend = FALSE; | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortRxFrameAppendFCSEnablePriv (IxEthAccPortId portId) | 
 | { | 
 |     /*Set bit 2 of Rx control 1*/ | 
 |     UINT32 regval; | 
 |  | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot enable Rx Frame Append FCS.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	     regval); | 
 |  | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	      regval | IX_ETH_ACC_RX_CNTRL1_CRC_EN); | 
 |  | 
 |     ixEthAccMacState[portId].rxFCSAppend = TRUE; | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccPortRxFrameAppendFCSDisablePriv (IxEthAccPortId portId) | 
 | { | 
 |     UINT32 regval; | 
 |  | 
 |     /*Clear bit 2 of Rx control 1*/ | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot disable Rx Frame Append FCS.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     REG_READ(ixEthAccMacBase[portId], | 
 | 	     IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	     regval); | 
 |  | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 	      regval & ~IX_ETH_ACC_RX_CNTRL1_CRC_EN); | 
 |  | 
 |     ixEthAccMacState[portId].rxFCSAppend = FALSE; | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 |  | 
 |  | 
 | PRIVATE void | 
 | ixEthAccMacNpeStatsMessageCallback (IxNpeMhNpeId npeId, | 
 | 				    IxNpeMhMessage msg) | 
 | { | 
 |     IxEthAccPortId portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId); | 
 |  | 
 | #ifndef NDEBUG | 
 |     /* Prudent to at least check the port is within range */ | 
 |     if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS) | 
 |     { | 
 | 	IX_ETH_ACC_FATAL_LOG( | 
 |      "IXETHACC:ixEthAccMacNpeStatsMessageCallback: Illegal port: %u\n", | 
 |      (UINT32)portId, 0, 0, 0, 0, 0); | 
 | 	return; | 
 |     } | 
 | #endif | 
 |  | 
 |     /*Unblock Stats Get call*/ | 
 |     ixOsalMutexUnlock(&ixEthAccMacState[portId].ackMIBStatsLock); | 
 |  | 
 | } | 
 |  | 
 | PRIVATE void | 
 | ixEthAccMibIIStatsEndianConvert (IxEthEthObjStats *retStats) | 
 | { | 
 |     /* endianness conversion */ | 
 |  | 
 |     /* Rx stats */ | 
 |     retStats->dot3StatsAlignmentErrors = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsAlignmentErrors); | 
 |     retStats->dot3StatsFCSErrors = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsFCSErrors); | 
 |     retStats->dot3StatsInternalMacReceiveErrors = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsInternalMacReceiveErrors); | 
 |     retStats->RxOverrunDiscards = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxOverrunDiscards); | 
 |     retStats->RxLearnedEntryDiscards = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxLearnedEntryDiscards); | 
 |     retStats->RxLargeFramesDiscards = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxLargeFramesDiscards); | 
 |     retStats->RxSTPBlockedDiscards = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxSTPBlockedDiscards); | 
 |     retStats->RxVLANTypeFilterDiscards = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxVLANTypeFilterDiscards); | 
 |     retStats->RxVLANIdFilterDiscards = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxVLANIdFilterDiscards); | 
 |     retStats->RxInvalidSourceDiscards = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxInvalidSourceDiscards); | 
 |     retStats->RxBlackListDiscards = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxBlackListDiscards); | 
 |     retStats->RxWhiteListDiscards = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxWhiteListDiscards); | 
 |     retStats->RxUnderflowEntryDiscards = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->RxUnderflowEntryDiscards); | 
 |  | 
 |     /* Tx stats */ | 
 |     retStats->dot3StatsSingleCollisionFrames = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsSingleCollisionFrames); | 
 |     retStats->dot3StatsMultipleCollisionFrames = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsMultipleCollisionFrames); | 
 |     retStats->dot3StatsDeferredTransmissions = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsDeferredTransmissions); | 
 |     retStats->dot3StatsLateCollisions = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsLateCollisions); | 
 |     retStats->dot3StatsExcessiveCollsions = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsExcessiveCollsions); | 
 |     retStats->dot3StatsInternalMacTransmitErrors = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsInternalMacTransmitErrors); | 
 |     retStats->dot3StatsCarrierSenseErrors = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->dot3StatsCarrierSenseErrors); | 
 |     retStats->TxLargeFrameDiscards = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->TxLargeFrameDiscards); | 
 |     retStats->TxVLANIdFilterDiscards = | 
 | 	IX_OSAL_SWAP_BE_SHARED_LONG(retStats->TxVLANIdFilterDiscards); | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccMibIIStatsGet (IxEthAccPortId portId, | 
 | 		       IxEthEthObjStats *retStats ) | 
 | { | 
 |     IxNpeMhMessage message; | 
 |  | 
 |     if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) | 
 |     { | 
 |         printf("EthAcc: ixEthAccMibIIStatsGet (Mac) EthAcc service is not initialized\n"); | 
 | 	return (IX_ETH_ACC_FAIL); | 
 |     } | 
 |  | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (retStats == NULL) | 
 |     { | 
 |         printf("EthAcc: ixEthAccMibIIStatsGet (Mac) NULL argument\n"); | 
 | 	return (IX_ETH_ACC_FAIL); | 
 |     } | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         printf("EthAcc: ixEthAccMibIIStatsGet (Mac) NPE for port %d is not available\n", portId); | 
 |  | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get MIB II Stats.\n",(INT32)portId,0,0,0,0,0); | 
 |  | 
 |         /* Return all zero stats */ | 
 |         IX_ETH_ACC_MEMSET(retStats, 0, sizeof(IxEthEthObjStats)); | 
 |  | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 |         printf("EthAcc: ixEthAccMibIIStatsGet (Mac) port %d is not initialized\n", portId); | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     IX_OSAL_CACHE_INVALIDATE(retStats, sizeof(IxEthEthObjStats)); | 
 |  | 
 |     message.data[0] = IX_ETHNPE_GETSTATS << IX_ETH_ACC_MAC_MSGID_SHL; | 
 |     message.data[1] = (UINT32) IX_OSAL_MMU_VIRT_TO_PHYS(retStats); | 
 |  | 
 |     /* Permit only one task to request MIB statistics Get operation | 
 |        at a time */ | 
 |     ixOsalMutexLock(&ixEthAccMacState[portId].MIBStatsGetAccessLock, IX_OSAL_WAIT_FOREVER); | 
 |  | 
 |     if(ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId), | 
 | 				      message, | 
 | 				      IX_ETHNPE_GETSTATS, | 
 | 				      ixEthAccMacNpeStatsMessageCallback, | 
 | 				      IX_NPEMH_SEND_RETRIES_DEFAULT) | 
 |        != IX_SUCCESS) | 
 |     { | 
 | 	ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetAccessLock); | 
 |  | 
 |         printf("EthAcc: (Mac) StatsGet failed to send NPE message\n"); | 
 |  | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |     /* Wait for callback invocation indicating response to | 
 |        this request - we need this mutex in order to ensure | 
 |        that the return from this function is synchronous */ | 
 |     ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsLock, IX_ETH_ACC_MIB_STATS_DELAY_MSECS); | 
 |  | 
 |     /* Permit other tasks to perform MIB statistics Get operation */ | 
 |     ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetAccessLock); | 
 |  | 
 |     ixEthAccMibIIStatsEndianConvert (retStats); | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 |  | 
 | PRIVATE void | 
 | ixEthAccMacNpeStatsResetMessageCallback (IxNpeMhNpeId npeId, | 
 | 					 IxNpeMhMessage msg) | 
 | { | 
 |     IxEthAccPortId portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId); | 
 |  | 
 | #ifndef NDEBUG | 
 |     /* Prudent to at least check the port is within range */ | 
 |     if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS) | 
 |     { | 
 | 	IX_ETH_ACC_FATAL_LOG( | 
 |      "IXETHACC:ixEthAccMacNpeStatsResetMessageCallback: Illegal port: %u\n", | 
 |      (UINT32)portId, 0, 0, 0, 0, 0); | 
 | 	return; | 
 |     } | 
 | #endif | 
 |  | 
 |     /*Unblock Stats Get & reset call*/ | 
 |     ixOsalMutexUnlock(&ixEthAccMacState[portId].ackMIBStatsResetLock); | 
 |  | 
 | } | 
 |  | 
 |  | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccMibIIStatsGetClear (IxEthAccPortId portId, | 
 | 			    IxEthEthObjStats *retStats) | 
 | { | 
 |     IxNpeMhMessage message; | 
 |  | 
 |     if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) | 
 |     { | 
 |         printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) EthAcc service is not initialized\n"); | 
 | 	return (IX_ETH_ACC_FAIL); | 
 |     } | 
 |  | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (retStats == NULL) | 
 |     { | 
 |         printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) NULL argument\n"); | 
 | 	return (IX_ETH_ACC_FAIL); | 
 |     } | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) NPE for port %d is not available\n", portId); | 
 |  | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot get and clear MIB II Stats.\n", (INT32)portId, 0, 0, 0, 0, 0); | 
 |  | 
 |         /* Return all zero stats */ | 
 |         IX_ETH_ACC_MEMSET(retStats, 0, sizeof(IxEthEthObjStats)); | 
 |  | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if (!IX_ETH_IS_PORT_INITIALIZED(portId)) | 
 |     { | 
 |         printf("EthAcc: ixEthAccMibIIStatsGetClear (Mac) port %d is not initialized\n", portId); | 
 | 	return (IX_ETH_ACC_PORT_UNINITIALIZED); | 
 |     } | 
 |  | 
 |     IX_OSAL_CACHE_INVALIDATE(retStats, sizeof(IxEthEthObjStats)); | 
 |  | 
 |     message.data[0] = IX_ETHNPE_RESETSTATS << IX_ETH_ACC_MAC_MSGID_SHL; | 
 |     message.data[1] = (UINT32) IX_OSAL_MMU_VIRT_TO_PHYS(retStats); | 
 |  | 
 |     /* Permit only one task to request MIB statistics Get-Reset operation at a time */ | 
 |     ixOsalMutexLock(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock, IX_OSAL_WAIT_FOREVER); | 
 |  | 
 |     if(ixNpeMhMessageWithResponseSend(IX_ETH_ACC_PORT_TO_NPE_ID(portId), | 
 | 				      message, | 
 | 				      IX_ETHNPE_RESETSTATS, | 
 | 				      ixEthAccMacNpeStatsResetMessageCallback, | 
 | 				      IX_NPEMH_SEND_RETRIES_DEFAULT) | 
 |        != IX_SUCCESS) | 
 |     { | 
 | 	ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock); | 
 |  | 
 |         printf("EthAcc: (Mac) ixEthAccMibIIStatsGetClear failed to send NPE message\n"); | 
 |  | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |     /* Wait for callback invocation indicating response to this request */ | 
 |     ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsResetLock, IX_ETH_ACC_MIB_STATS_DELAY_MSECS); | 
 |  | 
 |     /* permit other tasks to get and reset MIB stats*/ | 
 |     ixOsalMutexUnlock(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock); | 
 |  | 
 |     ixEthAccMibIIStatsEndianConvert(retStats); | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | IxEthAccStatus | 
 | ixEthAccMibIIStatsClear (IxEthAccPortId portId) | 
 | { | 
 |     static IxEthEthObjStats retStats; | 
 |     IxEthAccStatus status; | 
 |  | 
 |     if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED()) | 
 |     { | 
 | 	return (IX_ETH_ACC_FAIL); | 
 |     } | 
 |  | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot clear MIB II Stats.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     /* there is no reset operation without a corresponding Get */ | 
 |     status = ixEthAccMibIIStatsGetClear(portId, &retStats); | 
 |  | 
 |     return status; | 
 | } | 
 |  | 
 | /* Initialize the ethernet MAC settings */ | 
 | IxEthAccStatus | 
 | ixEthAccMacInit(IxEthAccPortId portId) | 
 | { | 
 |     IX_OSAL_MBUF_POOL* portDisablePool; | 
 |     UINT8 *data; | 
 |  | 
 |     IX_ETH_ACC_VALIDATE_PORT_ID(portId); | 
 |  | 
 |     if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("EthAcc: Unavailable Eth %d: Cannot initialize Mac.\n",(INT32)portId,0,0,0,0,0); | 
 |         return IX_ETH_ACC_SUCCESS ; | 
 |     } | 
 |  | 
 |     if(ixEthAccMacState[portId].macInitialised == FALSE) | 
 |     { | 
 | 	ixEthAccMacState[portId].fullDuplex  = TRUE; | 
 | 	ixEthAccMacState[portId].rxFCSAppend = TRUE; | 
 | 	ixEthAccMacState[portId].txFCSAppend = TRUE; | 
 | 	ixEthAccMacState[portId].txPADAppend = TRUE; | 
 | 	ixEthAccMacState[portId].enabled     = FALSE; | 
 | 	ixEthAccMacState[portId].promiscuous = TRUE; | 
 | 	ixEthAccMacState[portId].joinAll     = FALSE; | 
 | 	ixEthAccMacState[portId].initDone    = FALSE; | 
 | 	ixEthAccMacState[portId].macInitialised = TRUE; | 
 |  | 
 |         /* initialize MIB stats mutexes */ | 
 |         ixOsalMutexInit(&ixEthAccMacState[portId].ackMIBStatsLock); | 
 |         ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsLock, IX_OSAL_WAIT_FOREVER); | 
 |  | 
 |         ixOsalMutexInit(&ixEthAccMacState[portId].ackMIBStatsResetLock); | 
 |         ixOsalMutexLock(&ixEthAccMacState[portId].ackMIBStatsResetLock, IX_OSAL_WAIT_FOREVER); | 
 |  | 
 |         ixOsalMutexInit(&ixEthAccMacState[portId].MIBStatsGetAccessLock); | 
 |  | 
 |         ixOsalMutexInit(&ixEthAccMacState[portId].MIBStatsGetResetAccessLock); | 
 |  | 
 |         ixOsalMutexInit(&ixEthAccMacState[portId].npeLoopbackMessageLock); | 
 |  | 
 | 	ixEthAccMacState[portId].portDisableRxMbufPtr = NULL; | 
 |         ixEthAccMacState[portId].portDisableTxMbufPtr = NULL; | 
 |  | 
 | 	portDisablePool = IX_OSAL_MBUF_POOL_INIT(2, | 
 | 			  IX_ETHACC_RX_MBUF_MIN_SIZE, | 
 | 			  "portDisable Pool"); | 
 |  | 
 |         IX_OSAL_ENSURE(portDisablePool != NULL, "Failed to initialize PortDisable pool"); | 
 |  | 
 | 	ixEthAccMacState[portId].portDisableRxMbufPtr = IX_OSAL_MBUF_POOL_GET(portDisablePool); | 
 |         ixEthAccMacState[portId].portDisableTxMbufPtr = IX_OSAL_MBUF_POOL_GET(portDisablePool); | 
 |  | 
 | 	IX_OSAL_ENSURE(ixEthAccMacState[portId].portDisableRxMbufPtr != NULL, | 
 | 		  "Pool allocation failed"); | 
 |         IX_OSAL_ENSURE(ixEthAccMacState[portId].portDisableTxMbufPtr != NULL, | 
 | 		  "Pool allocation failed"); | 
 | 	/* fill the payload of the Rx mbuf used in portDisable */ | 
 |         IX_OSAL_MBUF_MLEN(ixEthAccMacState[portId].portDisableRxMbufPtr) = IX_ETHACC_RX_MBUF_MIN_SIZE; | 
 |  | 
 |         memset(IX_OSAL_MBUF_MDATA(ixEthAccMacState[portId].portDisableRxMbufPtr), | 
 | 	       0xAA, | 
 | 	       IX_ETHACC_RX_MBUF_MIN_SIZE); | 
 |  | 
 | 	/* fill the payload of the Tx mbuf used in portDisable (64 bytes) */ | 
 |         IX_OSAL_MBUF_MLEN(ixEthAccMacState[portId].portDisableTxMbufPtr) = 64; | 
 |         IX_OSAL_MBUF_PKT_LEN(ixEthAccMacState[portId].portDisableTxMbufPtr) = 64; | 
 |  | 
 |         data = (UINT8 *) IX_OSAL_MBUF_MDATA(ixEthAccMacState[portId].portDisableTxMbufPtr); | 
 |         memset(data, 0xBB, 64); | 
 |         data[0] = 0x00; /* unicast destination MAC address */ | 
 |         data[6] = 0x00; /* unicast source MAC address */ | 
 |         data[12] = 0x08; /* typelength : IP frame */ | 
 |         data[13] = 0x00; /* typelength : IP frame */ | 
 |  | 
 | 	IX_OSAL_CACHE_FLUSH(data, 64); | 
 |     } | 
 |  | 
 |     IX_OSAL_ASSERT (ixEthAccMacBase[portId] != 0); | 
 |  | 
 |     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); | 
 |  | 
 |     REG_WRITE(ixEthAccMacBase[portId], | 
 | 	      IX_ETH_ACC_MAC_INT_CLK_THRESH, | 
 | 	      IX_ETH_ACC_MAC_INT_CLK_THRESH_DEFAULT); | 
 |  | 
 |     ixEthAccMacStateUpdate(portId); | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | /* PRIVATE Functions*/ | 
 |  | 
 | PRIVATE void | 
 | ixEthAccMacStateUpdate(IxEthAccPortId portId) | 
 | { | 
 |     UINT32 regval; | 
 |  | 
 |     if ( ixEthAccMacState[portId].enabled == FALSE ) | 
 |     { | 
 | 	/*  Just disable both the transmitter and reciver in the MAC.  */ | 
 |         REG_READ(ixEthAccMacBase[portId], | 
 | 		 IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 		 regval); | 
 |  	REG_WRITE(ixEthAccMacBase[portId], | 
 | 		  IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 		  regval & ~IX_ETH_ACC_RX_CNTRL1_RX_EN); | 
 |  | 
 |         REG_READ(ixEthAccMacBase[portId], | 
 | 		 IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 		 regval); | 
 |  	REG_WRITE(ixEthAccMacBase[portId], | 
 | 		  IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 		  regval & ~IX_ETH_ACC_TX_CNTRL1_TX_EN); | 
 |     } | 
 |  | 
 |     if(ixEthAccMacState[portId].fullDuplex) | 
 |     { | 
 | 	ixEthAccPortDuplexModeSetPriv (portId, IX_ETH_ACC_FULL_DUPLEX); | 
 |     } | 
 |     else | 
 |     { | 
 | 	ixEthAccPortDuplexModeSetPriv (portId, IX_ETH_ACC_HALF_DUPLEX); | 
 |     } | 
 |  | 
 |     if(ixEthAccMacState[portId].rxFCSAppend) | 
 |     { | 
 | 	ixEthAccPortRxFrameAppendFCSEnablePriv (portId); | 
 |     } | 
 |     else | 
 |     { | 
 | 	ixEthAccPortRxFrameAppendFCSDisablePriv (portId); | 
 |     } | 
 |  | 
 |     if(ixEthAccMacState[portId].txFCSAppend) | 
 |     { | 
 | 	ixEthAccPortTxFrameAppendFCSEnablePriv (portId); | 
 |     } | 
 |     else | 
 |     { | 
 | 	ixEthAccPortTxFrameAppendFCSDisablePriv (portId); | 
 |     } | 
 |  | 
 |     if(ixEthAccMacState[portId].txPADAppend) | 
 |     { | 
 | 	ixEthAccPortTxFrameAppendPaddingEnablePriv (portId); | 
 |     } | 
 |     else | 
 |     { | 
 | 	ixEthAccPortTxFrameAppendPaddingDisablePriv (portId); | 
 |     } | 
 |  | 
 |     if(ixEthAccMacState[portId].promiscuous) | 
 |     { | 
 | 	ixEthAccPortPromiscuousModeSetPriv(portId); | 
 |     } | 
 |     else | 
 |     { | 
 | 	ixEthAccPortPromiscuousModeClearPriv(portId); | 
 |     } | 
 |  | 
 |     if ( ixEthAccMacState[portId].enabled == TRUE ) | 
 |     { | 
 |         /*   Enable both the transmitter and reciver in the MAC.  */ | 
 |         REG_READ(ixEthAccMacBase[portId], | 
 | 		 IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 		 regval); | 
 |         REG_WRITE(ixEthAccMacBase[portId], | 
 | 		  IX_ETH_ACC_MAC_RX_CNTRL1, | 
 | 		  regval | IX_ETH_ACC_RX_CNTRL1_RX_EN); | 
 |  | 
 |         REG_READ(ixEthAccMacBase[portId], | 
 | 		 IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 		 regval); | 
 |  	REG_WRITE(ixEthAccMacBase[portId], | 
 | 		  IX_ETH_ACC_MAC_TX_CNTRL1, | 
 | 		  regval | IX_ETH_ACC_TX_CNTRL1_TX_EN); | 
 |     } | 
 | } | 
 |  | 
 |  | 
 | PRIVATE BOOL | 
 | ixEthAccMacEqual(IxEthAccMacAddr *macAddr1, | 
 | 		 IxEthAccMacAddr *macAddr2) | 
 | { | 
 |     UINT32 i; | 
 |     for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE; i++) | 
 |     { | 
 | 	if(macAddr1->macAddress[i] != macAddr2->macAddress[i]) | 
 | 	{ | 
 | 	    return FALSE; | 
 | 	} | 
 |     } | 
 |     return TRUE; | 
 | } | 
 |  | 
 | PRIVATE void | 
 | ixEthAccMacPrint(IxEthAccMacAddr *m) | 
 | { | 
 |     printf("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", | 
 | 	   m->macAddress[0], m->macAddress[1], | 
 | 	   m->macAddress[2], m->macAddress[3], | 
 | 	   m->macAddress[4], m->macAddress[5]); | 
 | } | 
 |  | 
 | /* Set the multicast address and address mask registers | 
 |  * | 
 |  * A bit in the address mask register must be set if | 
 |  * all multicast addresses always have that bit set, or if | 
 |  * all multicast addresses always have that bit cleared. | 
 |  * | 
 |  * A bit in the address register must be set if all multicast | 
 |  * addresses have that bit set, otherwise, it should be cleared | 
 |  */ | 
 |  | 
 | PRIVATE void | 
 | ixEthAccMulticastAddressSet(IxEthAccPortId portId) | 
 | { | 
 |     UINT32 i; | 
 |     UINT32 j; | 
 |     IxEthAccMacAddr addressMask; | 
 |     IxEthAccMacAddr address; | 
 |     IxEthAccMacAddr alwaysClearBits; | 
 |     IxEthAccMacAddr alwaysSetBits; | 
 |  | 
 |     /* calculate alwaysClearBits and alwaysSetBits: | 
 |      * alwaysClearBits is calculated by ORing all | 
 |      * multicast addresses, those bits that are always | 
 |      * clear are clear in the result | 
 |      * | 
 |      * alwaysSetBits is calculated by ANDing all | 
 |      * multicast addresses, those bits that are always set | 
 |      * are set in the result | 
 |      */ | 
 |  | 
 |     if (ixEthAccMacState[portId].promiscuous == TRUE) | 
 |     { | 
 | 	/* Promiscuous Mode is set, and filtering | 
 | 	 * allow all packets, and enable the mcast and | 
 | 	 * bcast detection. | 
 | 	 */ | 
 | 	memset(&addressMask.macAddress, | 
 | 	       0, | 
 | 	       IX_IEEE803_MAC_ADDRESS_SIZE); | 
 | 	memset(&address.macAddress, | 
 | 	       0, | 
 | 	       IX_IEEE803_MAC_ADDRESS_SIZE); | 
 |     } | 
 |     else | 
 |     { | 
 | 	if(ixEthAccMacState[portId].joinAll == TRUE) | 
 | 	{ | 
 | 	    /* Join all is set. The mask and address are | 
 | 	     * the multicast settings. | 
 | 	     */ | 
 | 	    IxEthAccMacAddr macAddr = {{0x1,0x0,0x0,0x0,0x0,0x0}}; | 
 |  | 
 | 	    memcpy(addressMask.macAddress, | 
 | 		   macAddr.macAddress, | 
 | 		   IX_IEEE803_MAC_ADDRESS_SIZE); | 
 | 	    memcpy(address.macAddress, | 
 | 		   macAddr.macAddress, | 
 | 		   IX_IEEE803_MAC_ADDRESS_SIZE); | 
 | 	} | 
 | 	else if(ixEthAccMacState[portId].mcastAddrIndex == 0) | 
 | 	{ | 
 | 	    /* No entry in the filtering database, | 
 | 	     * Promiscuous Mode is cleared, Broadcast filtering | 
 | 	     * is configured. | 
 | 	     */ | 
 | 	    memset(addressMask.macAddress, | 
 | 		   IX_ETH_ACC_MAC_ALL_BITS_SET, | 
 | 		   IX_IEEE803_MAC_ADDRESS_SIZE); | 
 | 	    memset(address.macAddress, | 
 | 		   IX_ETH_ACC_MAC_ALL_BITS_SET, | 
 | 		   IX_IEEE803_MAC_ADDRESS_SIZE); | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 	    /* build a mask and an address which mix all entreis | 
 | 	     * from the list of multicast addresses | 
 | 	     */ | 
 | 	    memset(alwaysClearBits.macAddress, | 
 | 		   0, | 
 | 		   IX_IEEE803_MAC_ADDRESS_SIZE); | 
 | 	    memset(alwaysSetBits.macAddress, | 
 | 		   IX_ETH_ACC_MAC_ALL_BITS_SET, | 
 | 		   IX_IEEE803_MAC_ADDRESS_SIZE); | 
 |  | 
 | 	    for(i=0;i<ixEthAccMacState[portId].mcastAddrIndex;i++) | 
 | 	    { | 
 | 		for(j=0;j<IX_IEEE803_MAC_ADDRESS_SIZE;j++) | 
 | 		{ | 
 | 		    alwaysClearBits.macAddress[j] |= | 
 | 			ixEthAccMacState[portId].mcastAddrsTable[i].macAddress[j]; | 
 | 		    alwaysSetBits.macAddress[j] &= | 
 | 			ixEthAccMacState[portId].mcastAddrsTable[i].macAddress[j]; | 
 | 		} | 
 | 	    } | 
 |  | 
 | 	    for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++) | 
 | 	    { | 
 | 		addressMask.macAddress[i] = alwaysSetBits.macAddress[i] | 
 | 		    | ~alwaysClearBits.macAddress[i]; | 
 | 		address.macAddress[i] = alwaysSetBits.macAddress[i]; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |     /*write the new addr filtering to h/w*/ | 
 |     for(i=0;i<IX_IEEE803_MAC_ADDRESS_SIZE;i++) | 
 |     { | 
 | 	REG_WRITE(ixEthAccMacBase[portId], | 
 | 		  IX_ETH_ACC_MAC_ADDR_MASK_1+i*sizeof(UINT32), | 
 | 		  addressMask.macAddress[i]); | 
 | 	REG_WRITE(ixEthAccMacBase[portId], | 
 | 		  IX_ETH_ACC_MAC_ADDR_1+i*sizeof(UINT32), | 
 | 		  address.macAddress[i]); | 
 |     } | 
 | } |