| /** | 
 |  * @file IxEthAccCommon.c | 
 |  * | 
 |  * @author Intel Corporation | 
 |  * @date 12-Feb-2002 | 
 |  * | 
 |  * @brief This file contains the implementation common support routines for the component | 
 |  * | 
 |  * 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 -- | 
 |  */ | 
 |  | 
 | /* | 
 |  * Component header files | 
 |  */ | 
 |  | 
 | #include "IxOsal.h" | 
 | #include "IxEthAcc.h" | 
 | #include "IxEthDB.h" | 
 | #include "IxNpeMh.h" | 
 | #include "IxEthDBPortDefs.h" | 
 | #include "IxFeatureCtrl.h" | 
 | #include "IxEthAcc_p.h" | 
 | #include "IxEthAccQueueAssign_p.h" | 
 |  | 
 | #include "IxEthAccDataPlane_p.h" | 
 | #include "IxEthAccMii_p.h" | 
 |  | 
 | /** | 
 |  * @addtogroup IxEthAccPri | 
 |  *@{ | 
 |  */ | 
 |  | 
 | extern IxEthAccInfo   ixEthAccDataInfo; | 
 |  | 
 | /** | 
 |  * | 
 |  * @brief Maximum number of RX queues set to be the maximum number | 
 |  * of traffic calsses. | 
 |  * | 
 |  */ | 
 | #define IX_ETHACC_MAX_RX_QUEUES \ | 
 |       (IX_ETH_DB_QOS_TRAFFIC_CLASS_7_RX_QUEUE_PROPERTY \ | 
 |       - IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY \ | 
 |       + 1) | 
 |  | 
 | /** | 
 |  * | 
 |  * @brief Maximum number of 128 entry RX queues | 
 |  * | 
 |  */ | 
 | #define IX_ETHACC_MAX_LARGE_RX_QUEUES 4 | 
 |  | 
 | /** | 
 |  * | 
 |  * @brief Data structure template for Default RX Queues | 
 |  * | 
 |  */ | 
 | IX_ETH_ACC_PRIVATE | 
 | IxEthAccQregInfo ixEthAccQmgrRxDefaultTemplate = | 
 |   { | 
 |     IX_ETH_ACC_RX_FRAME_ETH_Q,	     /**< Queue ID */ | 
 |     "Eth Rx Q", | 
 |     ixEthRxFrameQMCallback,          /**< Functional callback */ | 
 |     (IxQMgrCallbackId) 0,	     /**< Callback tag	      */ | 
 |     IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ | 
 |     IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ | 
 |     TRUE,			     /**< Enable Q notification at startup */ | 
 |     IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback   */ | 
 |     IX_QMGR_Q_WM_LEVEL0,	     /**< Q Low water mark */ | 
 |     IX_QMGR_Q_WM_LEVEL1,	     /**< Q High water mark - needed by NPE */ | 
 |   }; | 
 |  | 
 | /** | 
 |  * | 
 |  * @brief Data structure template for Small RX Queues | 
 |  * | 
 |  */ | 
 | IX_ETH_ACC_PRIVATE | 
 | IxEthAccQregInfo ixEthAccQmgrRxSmallTemplate = | 
 |   { | 
 |     IX_ETH_ACC_RX_FRAME_ETH_Q,	     /**< Queue ID */ | 
 |     "Eth Rx Q", | 
 |     ixEthRxFrameQMCallback,          /**< Functional callback */ | 
 |     (IxQMgrCallbackId) 0,	     /**< Callback tag	      */ | 
 |     IX_QMGR_Q_SIZE64,		     /**< Allocate Smaller Q */ | 
 |     IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ | 
 |     TRUE,			     /**< Enable Q notification at startup */ | 
 |     IX_ETH_ACC_RX_FRAME_ETH_Q_SOURCE,/**< Q Condition to drive callback   */ | 
 |     IX_QMGR_Q_WM_LEVEL0,	     /**< Q Low water mark */ | 
 |     IX_QMGR_Q_WM_LEVEL1,	     /**< Q High water mark - needed by NPE */ | 
 |   }; | 
 |  | 
 |  | 
 | /** | 
 |  * | 
 |  * @brief Data structure used to register & initialize the Queues | 
 |  * | 
 |  */ | 
 | IX_ETH_ACC_PRIVATE | 
 | IxEthAccQregInfo ixEthAccQmgrStaticInfo[]= | 
 | { | 
 |   { | 
 |     IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q, | 
 |     "Eth Rx Fr Q 1", | 
 |     ixEthRxFreeQMCallback, | 
 |     (IxQMgrCallbackId) IX_ETH_PORT_1, | 
 |     IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ | 
 |     IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ | 
 |     FALSE,			     /**< Disable Q notification at startup */ | 
 |     IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q_SOURCE, /**< Q Condition to drive callback  */ | 
 |     IX_QMGR_Q_WM_LEVEL0,	     /***< Q Low water mark */ | 
 |     IX_QMGR_Q_WM_LEVEL64,	     /**< Q High water mark */ | 
 |   }, | 
 |  | 
 |   { | 
 |     IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q, | 
 |     "Eth Rx Fr Q 2", | 
 |     ixEthRxFreeQMCallback, | 
 |     (IxQMgrCallbackId) IX_ETH_PORT_2, | 
 |     IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ | 
 |     IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ | 
 |     FALSE,			     /**< Disable Q notification at startup */ | 
 |     IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q_SOURCE,  /**< Q Condition to drive callback  */ | 
 |     IX_QMGR_Q_WM_LEVEL0,	     /**< Q Low water mark */ | 
 |     IX_QMGR_Q_WM_LEVEL64,	     /**< Q High water mark */ | 
 |   }, | 
 | #ifdef __ixp46X | 
 |   { | 
 |     IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q, | 
 |     "Eth Rx Fr Q 3", | 
 |     ixEthRxFreeQMCallback, | 
 |     (IxQMgrCallbackId) IX_ETH_PORT_3, | 
 |     IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ | 
 |     IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ | 
 |     FALSE,			     /**< Disable Q notification at startup */ | 
 |     IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q_SOURCE,  /**< Q Condition to drive callback  */ | 
 |     IX_QMGR_Q_WM_LEVEL0,	     /**< Q Low water mark */ | 
 |     IX_QMGR_Q_WM_LEVEL64,	     /**< Q High water mark */ | 
 |   }, | 
 | #endif | 
 |   { | 
 |      IX_ETH_ACC_TX_FRAME_ENET0_Q, | 
 |     "Eth Tx Q 1", | 
 |      ixEthTxFrameQMCallback, | 
 |      (IxQMgrCallbackId) IX_ETH_PORT_1, | 
 |     IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ | 
 |     IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ | 
 |     FALSE,			     /**< Disable Q notification at startup */ | 
 |     IX_ETH_ACC_TX_FRAME_ENET0_Q_SOURCE,	 /**< Q Condition to drive callback  */ | 
 |     IX_QMGR_Q_WM_LEVEL0,	     /**< Q Low water mark */ | 
 |     IX_QMGR_Q_WM_LEVEL64,	     /**< Q High water mark */ | 
 |   }, | 
 |  | 
 |   { | 
 |      IX_ETH_ACC_TX_FRAME_ENET1_Q, | 
 |     "Eth Tx Q 2", | 
 |      ixEthTxFrameQMCallback, | 
 |      (IxQMgrCallbackId) IX_ETH_PORT_2, | 
 |     IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ | 
 |     IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ | 
 |     FALSE,			     /**< Disable Q notification at startup */ | 
 |     IX_ETH_ACC_TX_FRAME_ENET1_Q_SOURCE,	     /**< Q Condition to drive callback  */ | 
 |     IX_QMGR_Q_WM_LEVEL0,	     /**< Q Low water mark */ | 
 |     IX_QMGR_Q_WM_LEVEL64,	     /**< Q High water mark */ | 
 |   }, | 
 | #ifdef __ixp46X | 
 |   { | 
 |      IX_ETH_ACC_TX_FRAME_ENET2_Q, | 
 |     "Eth Tx Q 3", | 
 |      ixEthTxFrameQMCallback, | 
 |      (IxQMgrCallbackId) IX_ETH_PORT_3, | 
 |     IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ | 
 |     IX_QMGR_Q_ENTRY_SIZE1,	     /** Queue Entry Sizes - all Q entries are single ord entries   */ | 
 |     FALSE,			     /** Disable Q notification at startup */ | 
 |     IX_ETH_ACC_TX_FRAME_ENET2_Q_SOURCE,	     /** Q Condition to drive callback  */ | 
 |     IX_QMGR_Q_WM_LEVEL0,	     /* No queues use almost empty */ | 
 |     IX_QMGR_Q_WM_LEVEL64,	      /** Q High water mark - needed used  */ | 
 |   }, | 
 | #endif | 
 |   { | 
 |      IX_ETH_ACC_TX_FRAME_DONE_ETH_Q, | 
 |     "Eth Tx Done Q", | 
 |      ixEthTxFrameDoneQMCallback, | 
 |      (IxQMgrCallbackId) 0, | 
 |     IX_QMGR_Q_SIZE128,		     /**< Allocate Max Size Q */ | 
 |     IX_QMGR_Q_ENTRY_SIZE1,	     /**< Queue Entry Sizes - all Q entries are single word entries   */ | 
 |     TRUE,			     /**< Enable Q notification at startup */ | 
 |     IX_ETH_ACC_TX_FRAME_DONE_ETH_Q_SOURCE, /**< Q Condition to drive callback  */ | 
 |     IX_QMGR_Q_WM_LEVEL0,	     /**< Q Low water mark */ | 
 |     IX_QMGR_Q_WM_LEVEL2,	     /**< Q High water mark - needed by NPE */ | 
 |   }, | 
 |  | 
 |   {  /* Null Termination entry | 
 |       */ | 
 |      (IxQMgrQId)0, | 
 |      (char *) NULL, | 
 |      (IxQMgrCallback) NULL, | 
 |      (IxQMgrCallbackId) 0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0 | 
 |   } | 
 |  | 
 | }; | 
 |  | 
 | /** | 
 |  * | 
 |  * @brief Data structure used to register & initialize the Queues | 
 |  * | 
 |  * The structure will be filled at run time depending on the NPE | 
 |  * image already loaded and the QoS configured in ethDB. | 
 |  * | 
 |  */ | 
 | IX_ETH_ACC_PRIVATE | 
 | IxEthAccQregInfo ixEthAccQmgrRxQueuesInfo[IX_ETHACC_MAX_RX_QUEUES+1]= | 
 | { | 
 |   {  /* PlaceHolder for rx queues | 
 |       * depending on the QoS configured | 
 |       */ | 
 |      (IxQMgrQId)0, | 
 |      (char *) NULL, | 
 |      (IxQMgrCallback) NULL, | 
 |      (IxQMgrCallbackId) 0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0 | 
 |   }, | 
 |  | 
 |   {  /* PlaceHolder for rx queues | 
 |       * depending on the QoS configured | 
 |       */ | 
 |      (IxQMgrQId)0, | 
 |      (char *) NULL, | 
 |      (IxQMgrCallback) NULL, | 
 |      (IxQMgrCallbackId) 0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0 | 
 |   }, | 
 |  | 
 |   {  /* PlaceHolder for rx queues | 
 |       * depending on the QoS configured | 
 |       */ | 
 |      (IxQMgrQId)0, | 
 |      (char *) NULL, | 
 |      (IxQMgrCallback) NULL, | 
 |      (IxQMgrCallbackId) 0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0 | 
 |   }, | 
 |  | 
 |   {  /* PlaceHolder for rx queues | 
 |       * depending on the QoS configured | 
 |       */ | 
 |      (IxQMgrQId)0, | 
 |      (char *) NULL, | 
 |      (IxQMgrCallback) NULL, | 
 |      (IxQMgrCallbackId) 0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0 | 
 |   }, | 
 |  | 
 |   {  /* PlaceHolder for rx queues | 
 |       * depending on the QoS configured | 
 |       */ | 
 |      (IxQMgrQId)0, | 
 |      (char *) NULL, | 
 |      (IxQMgrCallback) NULL, | 
 |      (IxQMgrCallbackId) 0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0 | 
 |   }, | 
 |  | 
 |   {  /* PlaceHolder for rx queues | 
 |       * depending on the QoS configured | 
 |       */ | 
 |       (IxQMgrQId)0, | 
 |      (char *) NULL, | 
 |      (IxQMgrCallback) NULL, | 
 |      (IxQMgrCallbackId) 0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0 | 
 |   }, | 
 |  | 
 |   {  /* PlaceHolder for rx queues | 
 |       * depending on the QoS configured | 
 |       */ | 
 |      (IxQMgrQId)0, | 
 |      (char *) NULL, | 
 |      (IxQMgrCallback) NULL, | 
 |      (IxQMgrCallbackId) 0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0 | 
 |   }, | 
 |  | 
 |   {  /* PlaceHolder for rx queues | 
 |       * depending on the QoS configured | 
 |       */ | 
 |      (IxQMgrQId)0, | 
 |      (char *) NULL, | 
 |      (IxQMgrCallback) NULL, | 
 |      (IxQMgrCallbackId) 0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0 | 
 |   }, | 
 |  | 
 |   {  /* Null Termination entry | 
 |       */ | 
 |      (IxQMgrQId)0, | 
 |      (char *) NULL, | 
 |      (IxQMgrCallback) NULL, | 
 |      (IxQMgrCallbackId) 0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0, | 
 |      0 | 
 |   } | 
 |  | 
 | }; | 
 |  | 
 | /* forward declarations */ | 
 | IX_ETH_ACC_PRIVATE IxEthAccStatus | 
 | ixEthAccQMgrQueueSetup(IxEthAccQregInfo *qInfoDes); | 
 |  | 
 | /** | 
 |  * @fn ixEthAccQMgrQueueSetup(void) | 
 |  * | 
 |  * @brief Setup one queue and its event, and register the callback required | 
 |  * by this component to the QMgr | 
 |  * | 
 |  * @internal | 
 |  */ | 
 | IX_ETH_ACC_PRIVATE IxEthAccStatus | 
 | ixEthAccQMgrQueueSetup(IxEthAccQregInfo *qInfoDes) | 
 | { | 
 |     /* | 
 |      * Configure each Q. | 
 |      */ | 
 |     if ( ixQMgrQConfig( qInfoDes->qName, | 
 | 			qInfoDes->qId, | 
 | 			qInfoDes->qSize, | 
 | 			qInfoDes->qWords) != IX_SUCCESS) | 
 |     { | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |     if ( ixQMgrWatermarkSet( qInfoDes->qId, | 
 | 			     qInfoDes->AlmostEmptyThreshold, | 
 | 			     qInfoDes->AlmostFullThreshold | 
 | 			     ) != IX_SUCCESS) | 
 |     { | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |     /* | 
 |      * Set dispatcher priority. | 
 |      */ | 
 |     if ( ixQMgrDispatcherPrioritySet( qInfoDes->qId, | 
 | 				      IX_ETH_ACC_QM_QUEUE_DISPATCH_PRIORITY) | 
 | 	 != IX_SUCCESS) | 
 |     { | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |     /* | 
 |      * Register callbacks for each Q. | 
 |      */ | 
 |     if ( ixQMgrNotificationCallbackSet(qInfoDes->qId, | 
 | 				       qInfoDes->qCallback, | 
 | 				       qInfoDes->callbackTag) | 
 | 	 != IX_SUCCESS ) | 
 |     { | 
 | 	return IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |     /* | 
 |      * Set notification condition for Q | 
 |      */ | 
 |     if ( qInfoDes->qNotificationEnableAtStartup == TRUE ) | 
 |     { | 
 | 	if (   ixQMgrNotificationEnable(qInfoDes->qId, | 
 | 					qInfoDes->qConditionSource) | 
 | 	       != IX_SUCCESS ) | 
 | 	{ | 
 | 	    return IX_ETH_ACC_FAIL; | 
 | 	} | 
 |     } | 
 |  | 
 |     return(IX_ETH_ACC_SUCCESS); | 
 | } | 
 |  | 
 | /** | 
 |  * @fn ixEthAccQMgrQueuesConfig(void) | 
 |  * | 
 |  * @brief Setup all the queues and register all callbacks required | 
 |  * by this component to the QMgr | 
 |  * | 
 |  * The RxFree queues, tx queues, rx queues are configured statically | 
 |  * | 
 |  * Rx queues configuration is driven by QoS setup. | 
 |  * Many Rx queues may be required when QoS is enabled (this depends | 
 |  * on IxEthDB setup and the images being downloaded). The configuration | 
 |  * of the rxQueues is done in many steps as follows: | 
 |  * | 
 |  * @li select all Rx queues as configured by ethDB for all ports | 
 |  * @li sort the queues by traffic class | 
 |  * @li build the priority dependency for all queues | 
 |  * @li fill the configuration for all rx queues | 
 |  * @li configure all statically configured queues | 
 |  * @li configure all dynamically configured queues | 
 |  * | 
 |  * @param none | 
 |  * | 
 |  * @return IxEthAccStatus | 
 |  * | 
 |  * @internal | 
 |  */ | 
 | IX_ETH_ACC_PUBLIC | 
 | IxEthAccStatus ixEthAccQMgrQueuesConfig(void) | 
 | { | 
 |     struct | 
 |     { | 
 | 	int npeCount; | 
 | 	UINT32 npeId; | 
 | 	IxQMgrQId qId; | 
 | 	IxEthDBProperty trafficClass; | 
 |     } rxQueues[IX_ETHACC_MAX_RX_QUEUES]; | 
 |  | 
 |     UINT32 rxQueue = 0; | 
 |     UINT32 rxQueueCount = 0; | 
 |     IxQMgrQId ixQId =IX_QMGR_MAX_NUM_QUEUES; | 
 |     IxEthDBStatus ixEthDBStatus = IX_ETH_DB_SUCCESS; | 
 |     IxEthDBPortId ixEthDbPortId = 0; | 
 |     IxEthAccPortId ixEthAccPortId = 0; | 
 |     UINT32 ixNpeId = 0; | 
 |     UINT32 ixHighestNpeId = 0; | 
 |     UINT32 sortIterations = 0; | 
 |     IxEthAccStatus ret = IX_ETH_ACC_SUCCESS; | 
 |     IxEthAccQregInfo *qInfoDes = NULL; | 
 |     IxEthDBProperty ixEthDBTrafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY; | 
 |     IxEthDBPropertyType ixEthDBPropertyType = IX_ETH_DB_INTEGER_PROPERTY; | 
 |     UINT32 ixEthDBParameter = 0; | 
 |     BOOL completelySorted = FALSE; | 
 |  | 
 |     /* Fill the corspondance between ports and queues | 
 |      * This defines the mapping from port to queue Ids. | 
 |      */ | 
 |  | 
 |     ixEthAccPortData[IX_ETH_PORT_1].ixEthAccRxData.rxFreeQueue | 
 | 	= IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q; | 
 |     ixEthAccPortData[IX_ETH_PORT_2].ixEthAccRxData.rxFreeQueue | 
 | 	= IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q; | 
 | #ifdef __ixp46X | 
 |     ixEthAccPortData[IX_ETH_PORT_3].ixEthAccRxData.rxFreeQueue | 
 | 	= IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q; | 
 | #endif | 
 |     ixEthAccPortData[IX_ETH_PORT_1].ixEthAccTxData.txQueue | 
 | 	= IX_ETH_ACC_TX_FRAME_ENET0_Q; | 
 |     ixEthAccPortData[IX_ETH_PORT_2].ixEthAccTxData.txQueue | 
 | 	= IX_ETH_ACC_TX_FRAME_ENET1_Q; | 
 | #ifdef __ixp46X | 
 |     ixEthAccPortData[IX_ETH_PORT_3].ixEthAccTxData.txQueue | 
 | 	= IX_ETH_ACC_TX_FRAME_ENET2_Q; | 
 | #endif | 
 |     /* Fill the corspondance between ports and NPEs | 
 |      * This defines the mapping from port to npeIds. | 
 |      */ | 
 |  | 
 |     ixEthAccPortData[IX_ETH_PORT_1].npeId = IX_NPEMH_NPEID_NPEB; | 
 |     ixEthAccPortData[IX_ETH_PORT_2].npeId = IX_NPEMH_NPEID_NPEC; | 
 | #ifdef __ixp46X | 
 |     ixEthAccPortData[IX_ETH_PORT_3].npeId = IX_NPEMH_NPEID_NPEA; | 
 | #endif | 
 |     /* set the default rx scheduling discipline */ | 
 |     ixEthAccDataInfo.schDiscipline = FIFO_NO_PRIORITY; | 
 |  | 
 |     /* | 
 |      * Queue Selection step: | 
 |      * | 
 |      * The following code selects all the queues and build | 
 |      * a temporary array which contains for each queue | 
 |      * - the queue Id, | 
 |      * - the highest traffic class (in case of many | 
 |      * priorities configured for the same queue on different | 
 |      * ports) | 
 |      * - the number of different Npes which are | 
 |      * configured to write to this queue. | 
 |      * | 
 |      * The output of this loop is a temporary array of RX queues | 
 |      * in any order. | 
 |      * | 
 |      */ | 
 | #ifdef CONFIG_IXP425_COMPONENT_ETHDB | 
 |     for (ixEthAccPortId = 0; | 
 | 	 (ixEthAccPortId < IX_ETH_ACC_NUMBER_OF_PORTS) | 
 | 	     && (ret == IX_ETH_ACC_SUCCESS); | 
 | 	 ixEthAccPortId++) | 
 |     { | 
 | 	/* map between ethDb and ethAcc port Ids */ | 
 | 	ixEthDbPortId = (IxEthDBPortId)ixEthAccPortId; | 
 |  | 
 | 	/* map between npeId and ethAcc port Ids */ | 
 | 	ixNpeId = IX_ETH_ACC_PORT_TO_NPE_ID(ixEthAccPortId); | 
 |  | 
 | 	/* Iterate thru the different priorities */ | 
 | 	for (ixEthDBTrafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY; | 
 | 	     ixEthDBTrafficClass <= IX_ETH_DB_QOS_TRAFFIC_CLASS_7_RX_QUEUE_PROPERTY; | 
 | 	     ixEthDBTrafficClass++) | 
 | 	{ | 
 | 	    ixEthDBStatus = ixEthDBFeaturePropertyGet( | 
 | 	      ixEthDbPortId, | 
 | 	      IX_ETH_DB_VLAN_QOS, | 
 | 	      ixEthDBTrafficClass, | 
 | 	      &ixEthDBPropertyType, | 
 | 	      (void *)&ixEthDBParameter); | 
 |  | 
 | 	    if (ixEthDBStatus == IX_ETH_DB_SUCCESS) | 
 | 	    { | 
 | 		/* This port and QoS class are mapped to | 
 | 		 * a RX queue. | 
 | 		 */ | 
 | 		if (ixEthDBPropertyType == IX_ETH_DB_INTEGER_PROPERTY) | 
 | 		{ | 
 | 		    /* remember the highest npe Id supporting ethernet */ | 
 | 		    if (ixNpeId > ixHighestNpeId) | 
 | 		    { | 
 | 			ixHighestNpeId = ixNpeId; | 
 | 		    } | 
 |  | 
 | 		    /* search the queue in the list of queues | 
 | 		     * already used by an other port or QoS | 
 | 		     */ | 
 | 		    for (rxQueue = 0; | 
 | 			 rxQueue < rxQueueCount; | 
 | 			 rxQueue++) | 
 | 		    { | 
 | 			if (rxQueues[rxQueue].qId == (IxQMgrQId)ixEthDBParameter) | 
 | 			{ | 
 | 			    /* found an existing setup, update the number of ports | 
 | 			     * for this queue if the port maps to | 
 | 			     * a different NPE. | 
 | 			     */ | 
 | 			    if (rxQueues[rxQueue].npeId != ixNpeId) | 
 | 			    { | 
 | 				rxQueues[rxQueue].npeCount++; | 
 | 				rxQueues[rxQueue].npeId = ixNpeId; | 
 | 			    } | 
 | 			    /* get the highest traffic class for this queue */ | 
 | 			    if (rxQueues[rxQueue].trafficClass > ixEthDBTrafficClass) | 
 | 			    { | 
 | 				rxQueues[rxQueue].trafficClass = ixEthDBTrafficClass; | 
 | 			    } | 
 | 			    break; | 
 | 			} | 
 | 		    } | 
 | 		    if (rxQueue == rxQueueCount) | 
 | 		    { | 
 | 			/* new queue not found in the current list, | 
 | 			 * add a new entry. | 
 | 			 */ | 
 | 			IX_OSAL_ASSERT(rxQueueCount < IX_ETHACC_MAX_RX_QUEUES); | 
 | 			rxQueues[rxQueueCount].qId = ixEthDBParameter; | 
 | 			rxQueues[rxQueueCount].npeCount = 1; | 
 | 			rxQueues[rxQueueCount].npeId = ixNpeId; | 
 | 			rxQueues[rxQueueCount].trafficClass = ixEthDBTrafficClass; | 
 | 			rxQueueCount++; | 
 | 		    } | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 		    /* unexpected property type (not Integer) */ | 
 | 		    ret = IX_ETH_ACC_FAIL; | 
 |  | 
 |                     IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: unexpected property type returned by EthDB\n", 0, 0, 0, 0, 0, 0); | 
 |  | 
 | 		    /* no point to continue to iterate */ | 
 | 		    break; | 
 | 		} | 
 | 	    } | 
 | 	    else | 
 | 	    { | 
 | 		/* No Rx queue configured for this port | 
 | 		 * and this traffic class. Do nothing. | 
 | 		 */ | 
 | 	    } | 
 | 	} | 
 |  | 
 |         /* notify EthDB that queue initialization is complete and traffic class allocation is frozen */ | 
 |         ixEthDBFeaturePropertySet(ixEthDbPortId, | 
 |             IX_ETH_DB_VLAN_QOS, | 
 |             IX_ETH_DB_QOS_QUEUE_CONFIGURATION_COMPLETE, | 
 |             NULL /* ignored */); | 
 |     } | 
 |  | 
 | #else | 
 |  | 
 |     ixNpeId = IX_ETH_ACC_PORT_TO_NPE_ID(ixEthAccPortId); | 
 |     rxQueues[0].qId = 4; | 
 |     rxQueues[0].npeCount = 1; | 
 |     rxQueues[0].npeId = ixNpeId; | 
 |     rxQueues[0].trafficClass = IX_ETH_DB_QOS_TRAFFIC_CLASS_0_RX_QUEUE_PROPERTY; | 
 |     rxQueueCount++; | 
 |  | 
 | #endif | 
 |  | 
 |     /* check there is at least 1 rx queue : there is no point | 
 |      * to continue if there is no rx queue configured | 
 |      */ | 
 |     if ((rxQueueCount == 0) || (ret == IX_ETH_ACC_FAIL)) | 
 |     { | 
 |         IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: no queues configured, bailing out\n", 0, 0, 0, 0, 0, 0); | 
 | 	return (IX_ETH_ACC_FAIL); | 
 |     } | 
 |  | 
 |     /* Queue sort step: | 
 |      * | 
 |      * Re-order the array of queues by decreasing traffic class | 
 |      * using a bubble sort. (trafficClass 0 is the lowest | 
 |      * priority traffic, trafficClass 7 is the highest priority traffic) | 
 |      * | 
 |      * Primary sort order is traffic class | 
 |      * Secondary sort order is npeId | 
 |      * | 
 |      * Note that a bubble sort algorithm is not very efficient when | 
 |      * the number of queues grows . However, this is not a very bad choice | 
 |      * considering the very small number of entries to sort. Also, bubble | 
 |      * sort is extremely fast when the list is already sorted. | 
 |      * | 
 |      * The output of this loop is a sorted array of queues. | 
 |      * | 
 |      */ | 
 |     sortIterations = 0; | 
 |     do | 
 |     { | 
 | 	sortIterations++; | 
 | 	completelySorted = TRUE; | 
 | 	for (rxQueue = 0; | 
 | 	     rxQueue < rxQueueCount - sortIterations; | 
 | 	     rxQueue++) | 
 | 	{ | 
 | 	    /* compare adjacent elements */ | 
 | 	    if ((rxQueues[rxQueue].trafficClass < | 
 | 		rxQueues[rxQueue+1].trafficClass) | 
 | 		|| ((rxQueues[rxQueue].trafficClass == | 
 | 		     rxQueues[rxQueue+1].trafficClass) | 
 | 		    &&(rxQueues[rxQueue].npeId < | 
 | 		       rxQueues[rxQueue+1].npeId))) | 
 | 	    { | 
 | 		/* swap adjacent elements */ | 
 | 		int npeCount = rxQueues[rxQueue].npeCount; | 
 | 		UINT32 npeId = rxQueues[rxQueue].npeId; | 
 | 		IxQMgrQId qId = rxQueues[rxQueue].qId; | 
 | 		IxEthDBProperty trafficClass = rxQueues[rxQueue].trafficClass; | 
 | 		rxQueues[rxQueue].npeCount = rxQueues[rxQueue+1].npeCount; | 
 | 		rxQueues[rxQueue].npeId = rxQueues[rxQueue+1].npeId; | 
 | 		rxQueues[rxQueue].qId = rxQueues[rxQueue+1].qId; | 
 | 		rxQueues[rxQueue].trafficClass = rxQueues[rxQueue+1].trafficClass; | 
 | 		rxQueues[rxQueue+1].npeCount = npeCount; | 
 | 		rxQueues[rxQueue+1].npeId = npeId; | 
 | 		rxQueues[rxQueue+1].qId = qId; | 
 | 		rxQueues[rxQueue+1].trafficClass = trafficClass; | 
 | 		completelySorted = FALSE; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     while (!completelySorted); | 
 |  | 
 |     /* Queue traffic class list: | 
 |      * | 
 |      * Fill an array of rx queues linked by ascending traffic classes. | 
 |      * | 
 |      * If the queues are configured as follows | 
 |      *   qId 6 -> traffic class 0 (lowest) | 
 |      *   qId 7 -> traffic class 0 | 
 |      *   qId 8 -> traffic class 6 | 
 |      *   qId 12 -> traffic class 7 (highest) | 
 |      * | 
 |      * Then the output of this loop will be | 
 |      * | 
 |      * higherPriorityQueue[6] = 8 | 
 |      * higherPriorityQueue[7] = 8 | 
 |      * higherPriorityQueue[8] = 12 | 
 |      * higherPriorityQueue[12] = Invalid queueId | 
 |      * higherPriorityQueue[...] = Invalid queueId | 
 |      * | 
 |      * Note that this queue ordering does not handle all possibilities | 
 |      * that could result from different rules associated with different | 
 |      * ports, and inconsistencies in the rules. In all cases, the | 
 |      * output of this  algorithm is a simple linked list of queues, | 
 |      * without closed circuit. | 
 |  | 
 |      * This list is implemented as an array with invalid values initialized | 
 |      * with an "invalid" queue id which is the maximum number of queues. | 
 |      * | 
 |      */ | 
 |  | 
 |     /* | 
 |      * Initialise the rx queue list. | 
 |      */ | 
 |     for (rxQueue = 0; rxQueue < IX_QMGR_MAX_NUM_QUEUES; rxQueue++) | 
 |     { | 
 | 	ixEthAccDataInfo.higherPriorityQueue[rxQueue] = IX_QMGR_MAX_NUM_QUEUES; | 
 |     } | 
 |  | 
 |     /* build the linked list for this NPE. | 
 |      */ | 
 |     for (ixNpeId = 0; | 
 | 	 ixNpeId <= ixHighestNpeId; | 
 | 	 ixNpeId++) | 
 |     { | 
 | 	/* iterate thru the sorted list of queues | 
 | 	 */ | 
 | 	ixQId = IX_QMGR_MAX_NUM_QUEUES; | 
 | 	for (rxQueue = 0; | 
 | 	     rxQueue < rxQueueCount; | 
 | 	     rxQueue++) | 
 | 	{ | 
 | 	    if (rxQueues[rxQueue].npeId == ixNpeId) | 
 | 	    { | 
 | 		ixEthAccDataInfo.higherPriorityQueue[rxQueues[rxQueue].qId] = ixQId; | 
 | 		/* iterate thru queues with the same traffic class | 
 | 		 * than the current queue. (queues are ordered by descending | 
 | 		 * traffic classes and npeIds). | 
 | 		 */ | 
 | 		while ((rxQueue < rxQueueCount - 1) | 
 | 		       && (rxQueues[rxQueue].trafficClass | 
 | 			   == rxQueues[rxQueue+1].trafficClass) | 
 | 		       && (ixNpeId == rxQueues[rxQueue].npeId)) | 
 | 		{ | 
 | 		    rxQueue++; | 
 | 		    ixEthAccDataInfo.higherPriorityQueue[rxQueues[rxQueue].qId] = ixQId; | 
 | 		} | 
 | 		ixQId = rxQueues[rxQueue].qId; | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |     /* point on the first dynamic queue description */ | 
 |     qInfoDes = ixEthAccQmgrRxQueuesInfo; | 
 |  | 
 |     /* update the list of queues with the rx queues */ | 
 |     for (rxQueue = 0; | 
 | 	 (rxQueue < rxQueueCount) && (ret == IX_ETH_ACC_SUCCESS); | 
 | 	 rxQueue++) | 
 |     { | 
 | 	/* Don't utilize more than IX_ETHACC_MAX_LARGE_RX_QUEUES queues | 
 | 	 * with the full 128 entries.  For the lower priority queues, use | 
 | 	 * a smaller number of entries.  This ensures queue resources | 
 | 	 * remain available for other components. | 
 | 	 */ | 
 | 	if( (rxQueueCount > IX_ETHACC_MAX_LARGE_RX_QUEUES) && | 
 | 	    (rxQueue < rxQueueCount - IX_ETHACC_MAX_LARGE_RX_QUEUES) ) | 
 | 	{ | 
 | 	    /* add the small RX Queue setup template to the list of queues */ | 
 | 	    memcpy(qInfoDes, &ixEthAccQmgrRxSmallTemplate, sizeof(*qInfoDes)); | 
 | 	} else { | 
 | 	    /* add the default RX Queue setup template to the list of queues */ | 
 | 	    memcpy(qInfoDes, &ixEthAccQmgrRxDefaultTemplate, sizeof(*qInfoDes)); | 
 | 	} | 
 |  | 
 | 	/* setup the RxQueue ID */ | 
 | 	qInfoDes->qId = rxQueues[rxQueue].qId; | 
 |  | 
 | 	/* setup the RxQueue watermark level | 
 | 	 * | 
 | 	 * Each queue can be filled by many NPEs. To avoid the | 
 | 	 * NPEs to write to a full queue, need to set the | 
 | 	 * high watermark level for nearly full condition. | 
 | 	 * (the high watermark level are a power of 2 | 
 | 	 * starting from the top of the queue) | 
 | 	 * | 
 | 	 * Number of     watermark | 
 |          *   ports        level | 
 |          *    1             0 | 
 | 	 *    2             1 | 
 | 	 *    3             2 | 
 | 	 *    4             4 | 
 | 	 *    5             4 | 
 | 	 *    6             8 | 
 | 	 *    n          approx. 2**ceil(log2(n)) | 
 | 	 */ | 
 | 	if (rxQueues[rxQueue].npeCount == 1) | 
 | 	{ | 
 | 	    qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL0; | 
 | 	} | 
 | 	else if (rxQueues[rxQueue].npeCount == 2) | 
 | 	{ | 
 | 	    qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL1; | 
 | 	} | 
 | 	else if (rxQueues[rxQueue].npeCount == 3) | 
 | 	{ | 
 | 	    qInfoDes->AlmostFullThreshold = IX_QMGR_Q_WM_LEVEL2; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 	    /* reach the maximum number for CSR 2.0 */ | 
 |             IX_ETH_ACC_WARNING_LOG("ixEthAccQMgrQueuesConfig: maximum number of NPEs per queue reached, bailing out\n", 0, 0, 0, 0, 0, 0); | 
 | 	    ret = IX_ETH_ACC_FAIL; | 
 | 	    break; | 
 | 	} | 
 |  | 
 | 	/* move to next queue entry */ | 
 | 	++qInfoDes; | 
 |     } | 
 |  | 
 |     /* configure the static list (RxFree, Tx and TxDone queues) */ | 
 |     for (qInfoDes = ixEthAccQmgrStaticInfo; | 
 | 	 (qInfoDes->qCallback != (IxQMgrCallback) NULL ) | 
 | 	     && (ret == IX_ETH_ACC_SUCCESS); | 
 | 	 ++qInfoDes) | 
 |     { | 
 | 	ret = ixEthAccQMgrQueueSetup(qInfoDes); | 
 |     } | 
 |  | 
 |     /* configure the dynamic list (Rx queues) */ | 
 |     for (qInfoDes = ixEthAccQmgrRxQueuesInfo; | 
 | 	 (qInfoDes->qCallback != (IxQMgrCallback) NULL ) | 
 | 	     && (ret == IX_ETH_ACC_SUCCESS); | 
 | 	 ++qInfoDes) | 
 |     { | 
 | 	ret = ixEthAccQMgrQueueSetup(qInfoDes); | 
 |     } | 
 |  | 
 |     return(ret); | 
 | } | 
 |  | 
 | /** | 
 |  * @fn ixEthAccQMgrRxQEntryGet(UINT32 *rxQueueEntries) | 
 |  * | 
 |  * @brief Add and return the total number of entries in all Rx queues | 
 |  * | 
 |  * @param UINT32 rxQueueEntries[in] number of entries in all queues | 
 |  * | 
 |  * @return void | 
 |  * | 
 |  * @note Rx queues configuration is driven by Qos Setup. There is a | 
 |  * variable number of rx queues which are set at initialisation. | 
 |  * | 
 |  * @internal | 
 |  */ | 
 | IX_ETH_ACC_PUBLIC | 
 | void ixEthAccQMgrRxQEntryGet(UINT32 *numRxQueueEntries) | 
 | { | 
 |     UINT32 rxQueueLevel; | 
 |     IxEthAccQregInfo *qInfoDes;; | 
 |  | 
 |     *numRxQueueEntries = 0; | 
 |  | 
 |     /* iterate thru rx queues */ | 
 |     for (qInfoDes = ixEthAccQmgrRxQueuesInfo; | 
 | 	 qInfoDes->qCallback != (IxQMgrCallback)NULL; | 
 | 	 ++qInfoDes) | 
 |     { | 
 | 	/* retrieve the rx queue level */ | 
 | 	rxQueueLevel = 0; | 
 | 	ixQMgrQNumEntriesGet(qInfoDes->qId, &rxQueueLevel); | 
 | 	(*numRxQueueEntries) += rxQueueLevel; | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * @fn ixEthAccQMgrRxCallbacksRegister(IxQMgrCallback ixQMgrCallback) | 
 |  * | 
 |  * @brief Change the callback registered to all rx queues. | 
 |  * | 
 |  * @param IxQMgrCallback ixQMgrCallback[in] QMgr callback to register | 
 |  * | 
 |  * @return IxEthAccStatus | 
 |  * | 
 |  * @note The user may decide to use different Rx mechanisms | 
 |  * (e.g. receive many frames at the same time , or receive | 
 |  *  one frame at a time, depending on the overall application | 
 |  *  performances). A different QMgr callback is registered. This | 
 |  *  way, there is no excessive pointer checks in the datapath. | 
 |  * | 
 |  * @internal | 
 |  */ | 
 | IX_ETH_ACC_PUBLIC | 
 | IxEthAccStatus ixEthAccQMgrRxCallbacksRegister(IxQMgrCallback ixQMgrCallback) | 
 | { | 
 |     IxEthAccQregInfo *qInfoDes; | 
 |     IxEthAccStatus ret = IX_ETH_ACC_SUCCESS; | 
 |  | 
 |     /* parameter check */ | 
 |     if (NULL == ixQMgrCallback) | 
 |     { | 
 | 	ret = IX_ETH_ACC_FAIL; | 
 |     } | 
 |  | 
 |     /* iterate thru rx queues */ | 
 |     for (qInfoDes = ixEthAccQmgrRxQueuesInfo; | 
 | 	 (qInfoDes->qCallback != (IxQMgrCallback) NULL ) | 
 | 	     && (ret == IX_ETH_ACC_SUCCESS); | 
 | 	 ++qInfoDes) | 
 |     { | 
 | 	/* register the rx callback for all queues */ | 
 | 	if (ixQMgrNotificationCallbackSet(qInfoDes->qId, | 
 | 					     ixQMgrCallback, | 
 | 					     qInfoDes->callbackTag | 
 | 					     ) != IX_SUCCESS) | 
 | 	{ | 
 | 	    ret = IX_ETH_ACC_FAIL; | 
 | 	} | 
 |     } | 
 |     return(ret); | 
 | } | 
 |  | 
 | /** | 
 |  * @fn ixEthAccSingleEthNpeCheck(IxEthAccPortId portId) | 
 |  * | 
 |  * @brief Check the npe exists for this port | 
 |  * | 
 |  * @param IxEthAccPortId portId[in] port | 
 |  * | 
 |  * @return IxEthAccStatus | 
 |  * | 
 |  * @internal | 
 |  */ | 
 | IX_ETH_ACC_PUBLIC | 
 | IxEthAccStatus ixEthAccSingleEthNpeCheck(IxEthAccPortId portId) | 
 | { | 
 |  | 
 |     /* If not IXP42X A0 stepping, proceed to check for existence of coprocessors */ | 
 |     if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 != | 
 |         (ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK)) | 
 |         || (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ())) | 
 |       { | 
 |             if ((IX_ETH_PORT_1 == portId) && | 
 |                 (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) == | 
 |                  IX_FEATURE_CTRL_COMPONENT_ENABLED)) | 
 |             { | 
 |                 return IX_ETH_ACC_SUCCESS; | 
 |             } | 
 |  | 
 |             if ((IX_ETH_PORT_2 == portId) && | 
 |                 (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) == | 
 |                  IX_FEATURE_CTRL_COMPONENT_ENABLED)) | 
 |             { | 
 |                 return IX_ETH_ACC_SUCCESS; | 
 |             } | 
 |  | 
 |             if ((IX_ETH_PORT_3 == portId) && | 
 |                 (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA_ETH) == | 
 |                  IX_FEATURE_CTRL_COMPONENT_ENABLED)) | 
 |             { | 
 |                 return IX_ETH_ACC_SUCCESS; | 
 |             } | 
 |  | 
 |             return IX_ETH_ACC_FAIL; | 
 |       } | 
 |  | 
 |     return IX_ETH_ACC_SUCCESS; | 
 | } | 
 |  | 
 | /** | 
 |  * @fn ixEthAccStatsShow(void) | 
 |  * | 
 |  * @brief Displays all EthAcc stats | 
 |  * | 
 |  * @return void | 
 |  * | 
 |  */ | 
 | void ixEthAccStatsShow(IxEthAccPortId portId) | 
 | { | 
 |     ixEthAccMdioShow(); | 
 |  | 
 |     printf("\nPort %u\nUnicast MAC : ", portId); | 
 |     ixEthAccPortUnicastAddressShow(portId); | 
 |     ixEthAccPortMulticastAddressShow(portId); | 
 |     printf("\n"); | 
 |  | 
 |     ixEthAccDataPlaneShow(); | 
 | } | 
 |  | 
 |  | 
 |  |