/**
 * ============================================================================
 * COPYRIGHT
 *              INTEL CORPORATION PROPRIETARY INFORMATION
 *   This software is supplied under the terms of a license agreement or
 *   nondisclosure agreement with Intel Corporation and may not be copied 
 *   or disclosed except in accordance with the terms in that agreement.
 *      Copyright (C) 2000-2002 Intel Corporation. All rights reserved.
 *
 * = PRODUCT
 *      Intel(r) IXA SDK 3.0 for the IXP2X00 Network Processor, Release 5
 *
 * = FILENAME
 *      ix_cc_eth_rx.c
 *
 * = DESCRIPTION
 *      This file contains ETH Rx CC interface APIs and internal 
 *      functions common to both level-0 and level-1 systems.
 * 
 * = CHANGE HISTORY
 *      11/20/2002 - Created.
 *
 * ============================================================================
 * $Id: ix_cc_eth_rx.c,v 1.18 2003/12/12 00:54:52 ktseng Exp $
 */
 
/**
 * System defined include files required.
 */

/**
 * User defined include files required.
 */
#include "ix_cc_error.h"

#include "ix_types.h"
#include "ix_error.h"
#include "ix_cc.h"
#include "bindings.h"
#include "ix_cc_properties.h"

#include "ix_rm.h"
#include "ix_ossl.h"

#ifndef IX_EXCLUDE_CCI
#include "ix_cci.h"
#endif

#include "cc/ix_cc_eth_rx.h"
#include "cc/internal/ix_cc_eth_rx_internal.h"



/**
 * Variable declarations global to this file only.  Extern are followed
 * by static variables.
 */



/**
 * Exported variable declarations global to this component only.
 */

ix_cc_eth_rx_ctl_blk *g_pCcEthRxCtlBlk = NULL; /* control block */

/**
 * Pre-processor symbols and macros used in this file.
 */



/**
 * Extern function prototypes
 */


/**
 * Static function prototypes
 */
PRIVATE ix_error _ix_cc_eth_rx_get_static_data(ix_cc_eth_rx_ctl_blk *);
PRIVATE void _ix_cc_eth_rx_free_ctl_blk(ix_cc_eth_rx_ctl_blk *);
PRIVATE ix_error _ix_cc_eth_rx_create_cb_ctx_tables(ix_cc_eth_rx_ctl_blk *);



/**
 * function definitions.
 */


/**
 * NAME: ix_cc_eth_rx_init
 * 
 * DESCRIPTION: This function initializes the Ethernet rx core component.This 
 *				primitive shall be called and returned successfully before 
 *				requesting any service from Ethernet Rx core component. 
 *				This primitive should be called only once to initialize 
 *              Ethernet Rx core component.This function performs allocation
 *				of memory for symbols to be patched, creation of 64 bit 
 *				counters, registration of packet and message handlers,
 *              and allocation and initialization of internal data structures
 *              
 * 
 * @Param: arg_hCc - IN -  handle to Ethernet Rx core component, created by
 *		core component infrastructure; 
 *		this shall be used later to get other services from core 
 *		component infrastructure.
 *
 * @Param: arg_ppContext - OUT  - We return this to CCI which uses this 
 *	 while calling our msg/pkt hdlr. This is a pointer to our (internal) CtrlBlk
 *   Upon successfull completion, it represents the location where the pointer
 *	 to the control block allocated by Ethernet Rx core component will be stored.
 *	 The control block is internal to Ethernet Rx core component and it contains
 *   information about Ethernet Rx internal data structures, allocated memory 
 *   and other relevant information. Later this pointer will be passed into  
 *   ix_cc_eth_rx_fini function for freeing memory when Ethernet Rx Core 
 *   Component is being destroyed.
 *  
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
ix_error ix_cc_eth_rx_init(
    ix_cc_handle arg_hCc, 
    void **arg_ppContext)
{

    ix_cc_eth_rx_ctl_blk *pCtlBlk = NULL;
    ix_imported_symbol symbol[L2_DECAP_NUM_SYMBOLS_PATCHED];
#ifdef MICROBLOCK_COUNTERS
    ix_imported_symbol ethRxSymbol;
#endif /* MICROBLOCK_COUNTERS */
    ix_uint32 i=0;
    ix_error err = IX_SUCCESS;
    
    ix_memory_type memType;
    ix_uint32 memCh;
    ix_uint32 memOffset;
    void *pPhyAddr;

    /* Variables used in retrieving static data from ix_cc_init_context */ 
    ix_cc_init_context *pInitCtx;
    ix_cc_properties_node *pPropNode;

 
    
	/* Check whether arg_ppContext is invalid */
    if (arg_ppContext == (void **)NULL)
    {
	
        return IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("Input parameter(arg_ppContext) is null"));
    }

 
    /* Get the generic init context */
    pInitCtx = (ix_cc_init_context *)*arg_ppContext;
	
	/* Allocate the control block structure */
    if ((pCtlBlk = (ix_cc_eth_rx_ctl_blk *)ix_ossl_malloc(sizeof(ix_cc_eth_rx_ctl_blk))) == NULL)
    {
		return IX_ERROR_WARNING(IX_CC_ERROR_OOM,
                    ("Failed to allocate memory for Ethernet Rx Control block"));

    }
    
    /* Initialize the structure */
    ix_ossl_memset((void *)pCtlBlk, 
                   0, 
                   (ix_ossl_size_t)sizeof(ix_cc_eth_rx_ctl_blk));

    
    /* Retrieve static configuration data */
   IX_ERROR_CG(_ix_cc_eth_rx_get_static_data(pCtlBlk), err, cleanup);

   /**
     * Retrieve the port id information of each channel from the 
     * init context (This will work for both level-1 and level-0 modes).
     */
    pPropNode = pInitCtx->pPropertyList;
    i=0;
    while (pPropNode != NULL)
    {
		pCtlBlk->portId[i] = pPropNode->pPropertyInfo->port_id;
		i++;
		/**
		* Store the local blade id. Assuming all nodes have same 
		* blade id so it's ok to keep overwriting. 
		*/
		pCtlBlk->bladeId = pPropNode->pPropertyInfo->blade_id;
		/*get the next node*/		
		pPropNode = pPropNode->pNextPropNode;
		
	}
	pCtlBlk->numChannels = i;
    if (pCtlBlk->numChannels > IX_CC_ETH_RX_MAX_NUM_ETH_PORTS)
	{
		return IX_ERROR_WARNING(IX_CC_ETH_RX_ERROR_INVALID_RANGE,
          ("Invalid total channel number\n"));
    }

    /* Set initial interface state of each port to UP */
    for (i = 0; i < pCtlBlk->numChannels; i++)
    {
        pCtlBlk->portState[i] = IX_CC_ETH_RX_IF_STATE_UP;
    }

    /* The shared memory between microblock and CC has to be allocated 
	** only when MICROBLOCK_COUNTERS flag is defined */
#ifdef MICROBLOCK_COUNTERS
    /* allocate memory for 32-bit counters */
   IX_ERROR_CGT(ix_rm_mem_alloc(IX_MEMORY_TYPE_SRAM,
                                  IX_CC_ETH_RX_DEFAULT_SRAM_CH_NUM,
                                  ETH_RX_SIZE_32BIT_COUNTER_BUF,                         
                                  (void **)&pCtlBlk->pCounterBase32Bit),
                  err,
                  IX_CC_ERROR_OOM_SRAM,
                  IX_ERROR_LEVEL_WARNING,
                  cleanup);

    /* Initialize the memory */
    ix_ossl_memset((void *)pCtlBlk->pCounterBase32Bit,
                   0, 
                   ETH_RX_SIZE_32BIT_COUNTER_BUF);


    /* allocate memory for 64-bit counter handler array */
    if ((pCtlBlk->pCounterHandlers64Bit = (ix_counter_64bit_handle *)ix_ossl_malloc(ETH_RX_SIZE_64BIT_COUNTER_HDL)) == NULL)
    {
        /* free all memories allocated earlier */
        _ix_cc_eth_rx_free_ctl_blk(pCtlBlk);

        return IX_ERROR_WARNING(IX_CC_ERROR_OOM_SYSTEM,
                                 ("Out of memory"));

    }
	
    /* allocate 64-bit counters from RM */ 
    IX_ERROR_CGT(ix_rm_counter_64bit_new(ETH_RX_TOTAL_NUM_COUNTERS,
	                          pCtlBlk->pCounterBase32Bit,
                                  CC_ETH_RX_32BIT_COUNTER_OVERFLOW_TIME,
                                  pCtlBlk->pCounterHandlers64Bit),
                  err,
                  IX_CC_ERROR_OOM_64BIT_COUNTER, 
                  IX_ERROR_LEVEL_WARNING,
                  cleanup);

#endif /* MICROBLOCK_COUNTERS */
    
#if (_IX_HARDWARE_TYPE_ == _IX_HW_2800_)

    /* Allocate memory for SRAM filter table */
    IX_ERROR_CGT(ix_rm_mem_alloc(IX_MEMORY_TYPE_SRAM,
                                  IX_CC_ETH_RX_DEFAULT_SRAM_CH_NUM_DECAP,
                                  pCtlBlk->filterTableSize, 
                                  (void **)&pCtlBlk->pFilterTableBase),
                  err,
                  IX_CC_ERROR_OOM_SRAM,
                  IX_ERROR_LEVEL_WARNING,
                  cleanup);

#else /* (_IX_HARDWARE_TYPE_ == _IX_HW_2800_) */

    IX_ERROR_CGT(ix_rm_mem_alloc(IX_MEMORY_TYPE_SRAM,
                                  IX_CC_ETH_RX_DEFAULT_SRAM_CH_NUM,
                                  pCtlBlk->filterTableSize,
                                  (void **)&pCtlBlk->pFilterTableBase),
                  err,
                  IX_CC_ERROR_OOM_SRAM,
                  IX_ERROR_LEVEL_WARNING,
                  cleanup);

#endif /* (_IX_HARDWARE_TYPE_ == _IX_HW_2800_) */

    /* Initialize the memory */
    ix_ossl_memset((void *)pCtlBlk->pFilterTableBase,
                   0, 
                   pCtlBlk->filterTableSize);    

    /**
     * Calculate the number of entries in the table.
     * (Assuming the base bucket size equals to the overflow bucket size.
     */
    pCtlBlk->filterTableTotalNumEntries = pCtlBlk->filterTableSize / sizeof(ix_cc_eth_rx_mac_filter_table_entry);
    pCtlBlk->filterTableNumEntriesBaseBucket = pCtlBlk->filterTableTotalNumEntries >> 1;
    pCtlBlk->filterTableNumEntriesOvBucket = pCtlBlk->filterTableNumEntriesBaseBucket;

#if (_IX_HARDWARE_TYPE_ == _IX_HW_2800_)

    /* allocate memory for Port mode bit map in SRAM */
    IX_ERROR_CGT(ix_rm_mem_alloc(IX_MEMORY_TYPE_SRAM,
                                  IX_CC_ETH_RX_DEFAULT_SRAM_CH_NUM_DECAP,
                                  ETH_RX_PORT_BIT_MAP_SIZE,
                                  (void **)&pCtlBlk->pPortMapBase),
                  err,
                  IX_CC_ERROR_OOM_SRAM,
                  IX_ERROR_LEVEL_WARNING,
                  cleanup);

#else /* (_IX_HARDWARE_TYPE_ == _IX_HW_2800_) */

    IX_ERROR_CGT(ix_rm_mem_alloc(IX_MEMORY_TYPE_SRAM,
                                  IX_CC_ETH_RX_DEFAULT_SRAM_CH_NUM,
                                  ETH_RX_PORT_BIT_MAP_SIZE,
                                  (void **)&pCtlBlk->pPortMapBase),
                  err,
                  IX_CC_ERROR_OOM_SRAM,
                  IX_ERROR_LEVEL_WARNING,
                  cleanup);

#endif /* (_IX_HARDWARE_TYPE_ == _IX_HW_2800_) */

    /* Initialize the memory such that all ports are 
     * working in promiscuous mode*/
   
#ifdef DISABLE_MAC_FILTERING
    *(pCtlBlk->pPortMapBase) = pCtlBlk->portMode;
#else
    ix_ossl_memset((void *)pCtlBlk->pPortMapBase,
		    0, 
		    ETH_RX_PORT_BIT_MAP_SIZE);
#endif

    /* 
     * patch various symbols and memory bases into Ethernet Rx microblock:
     * and L2 Decap microblock. The symbols to be patched for L2 Decap
	 * are:
     * 1. SRAM filter table base
     * 2. Port mode bit map base
	 * The symbol to be patched for Packet Rx microblock is 
     * 32-bit counter memory base. 
     */

    /* first obtain the base offset for pCtlBlk->pFilterTableBase. 
    Then we patch in the channel no*/

    IX_ERROR_CGT(ix_rm_get_phys_offset(pCtlBlk->pFilterTableBase,
                                       &memType,
                                       &memCh,
                                       &memOffset,
                                       &pPhyAddr),
                 err,
                 IX_CC_ETH_RX_ERROR_RM_GET_PHYS_OFFSET, 
                 IX_ERROR_LEVEL_WARNING,
                 cleanup);

	/* Pack the SRAM channel number into the offset */
     IX_CC_SET_SRAM_CHANNEL_INTO_OFFSET(memCh, memOffset);


    symbol[0].m_Value = memOffset; 
    symbol[0].m_Name = SYMBOL_ETH_RX_FLT_TABLE_BASE;

    /* first obtain the base offset for pCtlBlk->pPortMapBase. 
    Then we patch in the channel no*/

    IX_ERROR_CGT(ix_rm_get_phys_offset(pCtlBlk->pPortMapBase,
                                       &memType,
                                       &memCh,
                                       &memOffset,
                                       &pPhyAddr),
                 err,
                 IX_CC_ETH_RX_ERROR_RM_GET_PHYS_OFFSET, 
                 IX_ERROR_LEVEL_WARNING,
                 cleanup);

	/* Pack the SRAM channel number into the offset */
    IX_CC_SET_SRAM_CHANNEL_INTO_OFFSET(memCh, memOffset);


    symbol[1].m_Value = memOffset;
    symbol[1].m_Name = SYMBOL_ETH_RX_PORT_BIT_MAP_BASE;

	/* Patch symbols needed by L2 Decap microblock into each 
     microengine used by the L2 Decap microblock */
    for (i = 0; i < IX_CC_ETH_RX_MAX_ME_NUM; i++)
    {
        if (pCtlBlk->l2DecapMev2Num & (0x1 << i))
        {
            IX_ERROR_CT(ix_rm_ueng_patch_symbols(
                          g_aMicroengineNumberMapping[i],
                           L2_DECAP_NUM_SYMBOLS_PATCHED,
                           symbol),
                            err,
                            IX_CC_ETH_RX_ERROR_RM_PATCH_SYMBOL, 
                            IX_ERROR_LEVEL_WARNING);
			if (err != IX_SUCCESS)
			{
				/* free all memories allocated earlier */
				_ix_cc_eth_rx_free_ctl_blk(pCtlBlk);

				return(err);
			}
		}
	}

#ifdef MICROBLOCK_COUNTERS

     /* first obtain the base offsets for counter memory
     Then we patch in the channel number */

    IX_ERROR_CGT(ix_rm_get_phys_offset(pCtlBlk->pCounterBase32Bit,
                                       &memType,
                                       &memCh,
                                       &memOffset,
                                       &pPhyAddr),
                 err,
                 IX_CC_ETH_RX_ERROR_RM_GET_PHYS_OFFSET, 
                 IX_ERROR_LEVEL_WARNING,
                 cleanup);

	/* Pack the SRAM channel number into the offset */
     IX_CC_SET_SRAM_CHANNEL_INTO_OFFSET(memCh, memOffset);


    ethRxSymbol.m_Value = memOffset; /* gives warning-need typecasting*/
    ethRxSymbol.m_Name = SYMBOL_ETH_RX_COUNTERS_BASE;

	 /* Patch the symbol needed by Packet Rx microblock 
     into each microengine used by the microblock */
    for (i = 0; i < IX_CC_ETH_RX_MAX_ME_NUM; i++)
    {
		if (pCtlBlk->mev2Num & (0x1 << i))
		{
			IX_ERROR_CT(ix_rm_ueng_patch_symbols(
                  g_aMicroengineNumberMapping[i],
                  ETH_RX_NUM_SYMBOLS_PATCHED,
                            &ethRxSymbol),
                            err,
                            IX_CC_ETH_RX_ERROR_RM_PATCH_SYMBOL, 
                            IX_ERROR_LEVEL_WARNING);
			if (err != IX_SUCCESS)
			{
				/* free all memories allocated earlier */
				_ix_cc_eth_rx_free_ctl_blk(pCtlBlk);
				return(err);
			}
		}
	}

#endif /* MICROBLOCK_COUNTERS */
	
    /* 
     * Create mutex for critical section. 
     */
    IX_ERROR_CGT(ix_ossl_mutex_init(IX_OSSL_MUTEX_UNLOCK, 
                                    &(pCtlBlk->mid)),
                  err,
                  IX_CC_ETH_RX_ERROR_OSSL_MUTEX_INIT, 
                  IX_ERROR_LEVEL_WARNING,
                  cleanup);

	 /* 
     * Allocate free callback context entries for each async messaging
     * API function.
     */
    IX_ERROR_CG(_ix_cc_eth_rx_create_cb_ctx_tables(pCtlBlk), err, cleanup);
	
	
		
#ifndef IX_EXCLUDE_CCI
	/*Level 1*/ 
    /* Register message handler with CCI*/
	IX_ERROR_CGT(ix_cci_cc_add_message_handler(arg_hCc,
                                               IX_CC_ETH_RX_MSG_INPUT,
                                               ix_cc_eth_rx_msg_handler,
                                               IX_INPUT_TYPE_SINGLE_SRC),
                  err,
                  IX_CC_ETH_RX_ERROR_CCI_REG_HDLR, 
                  IX_ERROR_LEVEL_WARNING,
                  cleanup);
		
	
#else
    /*Level 0*/
	/* Register message handler with RM*/
    IX_ERROR_CGT(ix_rm_message_handler_register(IX_CC_ETH_RX_MSG_INPUT,
                                               ix_cc_eth_rx_msg_handler,
                                               pCtlBlk),
                  err,
                  IX_CC_ETH_RX_ERROR_RM_REG_HDLR, 
                  IX_ERROR_LEVEL_WARNING,
                  cleanup);
#endif	
	
    
	
#ifndef IX_EXCLUDE_CCI
	/*Level 1*/
    /* Register Low priority packet handler */
	IX_ERROR_CGT(ix_cci_cc_add_packet_handler(arg_hCc,
                                               IX_CC_ETH_MICROBLOCK_LOW_PRIORITY_PKT_INPUT,
                                               ix_cc_eth_rx_low_priority_pkt_handler,
                                               IX_INPUT_TYPE_SINGLE_SRC),
                  err,
                  IX_CC_ETH_RX_ERROR_CCI_REG_HDLR, 
                  IX_ERROR_LEVEL_WARNING,
                  cleanup);
    
	/* Register high priority packet handler */
        /* High priority packet handler needs to be registered 
	 * as a message handler */	
	IX_ERROR_CGT(ix_cci_cc_add_message_handler(arg_hCc,
                                              IX_CC_ETH_MICROBLOCK_HIGH_PRIORITY_PKT_INPUT,
                                               ix_cc_eth_rx_high_priority_pkt_handler,
                                               IX_INPUT_TYPE_SINGLE_SRC),
                  err,
                  IX_CC_ETH_RX_ERROR_CCI_REG_HDLR, 
                  IX_ERROR_LEVEL_WARNING,
                  cleanup);
#else
	/*Level 0*/
	IX_ERROR_CGT(ix_rm_packet_handler_register(IX_CC_ETH_MICROBLOCK_LOW_PRIORITY_PKT_INPUT,
                                               ix_cc_eth_rx_low_priority_pkt_handler,
                                               pCtlBlk),
                  err,
                  IX_CC_ETH_RX_ERROR_RM_REG_HDLR, 
                  IX_ERROR_LEVEL_WARNING,
                  cleanup);

	/* Register high priority packet handler as message handler */
    IX_ERROR_CGT(ix_rm_message_handler_register(IX_CC_ETH_MICROBLOCK_HIGH_PRIORITY_PKT_INPUT,
                                        ix_cc_eth_rx_high_priority_pkt_handler,
                                        pCtlBlk),
                  err,
                  IX_CC_ETH_RX_ERROR_RM_REG_HDLR, 
                  IX_ERROR_LEVEL_WARNING,
                  cleanup);
#endif

	

    /* assign output argument */
    *arg_ppContext = (void *)pCtlBlk;

    /*
     * Store the address of the control block structure to a global 
     * variable that can be used later in other functions.
     */
    g_pCcEthRxCtlBlk = pCtlBlk;

    return(IX_SUCCESS);

cleanup:

    /* free all memories allocated earlier */
    _ix_cc_eth_rx_free_ctl_blk(pCtlBlk);

#ifdef IX_CC_ETH_RX_DEBUG_ENABLE
	ix_error_dump(stderr, err);
#endif
    return(err);

} /* ix_cc_eth_rx_init */



/**
 * NAME: ix_cc_eth_rx_fini
 * 
 * DESCRIPTION: This function terminates the eth rx core component.
 * 
 * @Param: arg_hCc - IN - handle to Ethernet Rx core component, created by
 *		core component infrastructure
 * @Param: arg_pContext - IN - pointer to the control block memory allocated 
 * earlier in ix_cc_eth_rx_init function
 * 
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
ix_error ix_cc_eth_rx_fini(
    ix_cc_handle arg_hCc, 
    void *arg_pContext)
{
    
    /* Check whether arg_pContext is valid */
    if (arg_pContext == (void *)NULL)
    {
        return IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                               ("NULL argument"));

    }


	/*Currently we do not check for a valid arg_hCcHandle as we do not store it in
	the context in init. We use it only for reg pkt/msg hdlr*/


/*Removing message handlers*/

/*Level 1*/
#ifndef IX_EXCLUDE_CCI
	/* Remove message handler from CCI */
	IX_ERROR_CRT(ix_cci_cc_remove_message_handler(IX_CC_ETH_RX_MSG_INPUT),
                  IX_CC_ETH_RX_ERROR_CCI_REM_HDLR, 
                  IX_ERROR_LEVEL_WARNING);


#else
	/*Level 0*/
	/*Remove message handler from RM */
	IX_ERROR_CRT(ix_rm_message_handler_unregister(IX_CC_ETH_RX_MSG_INPUT),
					 IX_CC_ETH_RX_ERROR_RM_REM_HDLR,
                     IX_ERROR_LEVEL_WARNING);
	
#endif

		
		
		/*Removing high and low priority packet handlers*/
#ifndef IX_EXCLUDE_CCI
        
	     /* Remove low priority packet handler from CCI */		
		IX_ERROR_CRT(ix_cci_cc_remove_packet_handler(
                IX_CC_ETH_MICROBLOCK_LOW_PRIORITY_PKT_INPUT),
					 IX_CC_ETH_RX_ERROR_CCI_REM_HDLR,
                     IX_ERROR_LEVEL_WARNING);
		
         /* Remove high priority packet handler from CCI */		
		IX_ERROR_CRT(ix_cci_cc_remove_message_handler(
          IX_CC_ETH_MICROBLOCK_HIGH_PRIORITY_PKT_INPUT),
					 IX_CC_ETH_RX_ERROR_CCI_REM_HDLR,
                     IX_ERROR_LEVEL_WARNING);
		

#else
		/*Remove low priority packet handler from RM*/
		IX_ERROR_CRT(ix_rm_packet_handler_unregister(
          IX_CC_ETH_MICROBLOCK_LOW_PRIORITY_PKT_INPUT),
                     IX_CC_ETH_RX_ERROR_RM_REM_HDLR,
                     IX_ERROR_LEVEL_WARNING);
		
		/* Remove high priority packet handler */
		IX_ERROR_CRT(ix_rm_message_handler_unregister(
             IX_CC_ETH_MICROBLOCK_HIGH_PRIORITY_PKT_INPUT),
                     IX_CC_ETH_RX_ERROR_RM_REM_HDLR,
                     IX_ERROR_LEVEL_WARNING);
		
#endif


	
    /* Free all memories and resources indicated in the arg_pContext */
    _ix_cc_eth_rx_free_ctl_blk((ix_cc_eth_rx_ctl_blk *)arg_pContext);

    /* Reset the global pointer to the control block structure */
    g_pCcEthRxCtlBlk = NULL;

    return IX_SUCCESS;
} /* ix_cc_eth_rx_fini */





/**********************
 * Internal functions *
 **********************/


/**
 * NAME: _ix_cc_eth_rx_get_static_data
 * 
 * DESCRIPTION: This function retrieves all Ethernet Rx static data from 
 *              either system registry or ix_cc_eth_rx.h and store them 
 *              into the corresponding field in the control block 
 *              structure passed in.
 * 
 * @Param: arg_pCtlBlk - IN - Pointer to control block used for 
 *                    maintaining information about Ethernet Rx CC
 *                    internal data structures
 *  
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
PRIVATE ix_error _ix_cc_eth_rx_get_static_data(
    ix_cc_eth_rx_ctl_blk *arg_pCtlBlk)
{

#ifdef IX_INCLUDE_REGISTRY

    ix_configuration_property_handle hCoreRoot = IX_CP_CORE_PROPERTY_ROOT;
    ix_configuration_property_handle hProperty = 
            (ix_configuration_property_handle)NULL;

     
     /* open the property to get microengine number */
     IX_ERROR_CRT(ix_rm_cp_property_open(hCoreRoot,
                                         PROP_ETH_RX_MEV2_NUM_MASK,
                                         &hProperty),
                  IX_CC_ERROR_ENTRY_NOT_FOUND, 
                  IX_ERROR_LEVEL_REMOTE);
 
    /* read the property */
    IX_ERROR_CRT(ix_rm_cp_property_get_value_uint32(hProperty, 
                                                     &arg_pCtlBlk->mev2Num),
                  IX_CC_ERROR_ENTRY_NOT_FOUND, 
                  IX_ERROR_LEVEL_REMOTE);
    
	 /* open the property to get SRAM Filter Table Size */
     IX_ERROR_CRT(ix_rm_cp_property_open(hCoreRoot,
                                         PROP_ETH_RX_FLT_TABLE_BASE,
                                         &hProperty),
                  IX_CC_ERROR_ENTRY_NOT_FOUND, 
                  IX_ERROR_LEVEL_REMOTE);
 
     /* read the property */
     IX_ERROR_CRT(ix_rm_cp_property_get_value_uint32(hProperty, 
                    &arg_pCtlBlk->filterTableSize),
                  IX_CC_ERROR_ENTRY_NOT_FOUND, 
                  IX_ERROR_LEVEL_REMOTE);    

	/* open the property to get L2 Decap Microengine number */
     IX_ERROR_CRT(ix_rm_cp_property_open(hCoreRoot,
                                         PROP_L2_DECAP_MEV2_NUM_MASK,
                                         &hProperty),
                  IX_CC_ERROR_ENTRY_NOT_FOUND, 
                  IX_ERROR_LEVEL_REMOTE);
 
     /* read the property */
     IX_ERROR_CRT(ix_rm_cp_property_get_value_uint32(hProperty, 
                    &arg_pCtlBlk->l2DecapMev2Num),
                  IX_CC_ERROR_ENTRY_NOT_FOUND, 
                  IX_ERROR_LEVEL_REMOTE);    

	/* open the property to get L2 Decap Port mode bit map */
	IX_ERROR_CRT(ix_rm_cp_property_open(hCoreRoot,
                                   PROP_L2_DECAP_PORT_MODE_BIT_MAP,
                                   &hProperty),
                  IX_CC_ERROR_ENTRY_NOT_FOUND, 
                  IX_ERROR_LEVEL_REMOTE);
 
	/* read the property */
	IX_ERROR_CRT(ix_rm_cp_property_get_value_uint32(hProperty, 
                    &arg_pCtlBlk->portMode),
                  IX_CC_ERROR_ENTRY_NOT_FOUND, 
                  IX_ERROR_LEVEL_REMOTE);    
 
 
#else  /* IX_INCLUDE_REGISTRY */
 
	arg_pCtlBlk->mev2Num = ETH_RX_MEV2_NUM_MASK;
	arg_pCtlBlk->filterTableSize = ETH_RX_SIZE_SRAM_FILTER_TBL;
	arg_pCtlBlk->l2DecapMev2Num = L2_DECAP_MEV2_NUM_MASK;
	arg_pCtlBlk->portMode = L2_DECAP_PORT_MODE_BIT_MAP;

#endif /* IX_INCLUDE_REGISTRY */

    return IX_SUCCESS;

} /* _ix_cc_eth_rx_get_static_data */






/**
 * NAME: _ix_cc_eth_rx_create_cb_ctx_tables
 * 
 * DESCRIPTION: This function creates callback context tables that 
 *              contain free callback context entry structure for 
 *              being used by each invocation of helper API 
 *              that has callback defined.
 * 
 * @Param: arg_pCtlBlk - IN: pointer to the component context allocated
 *                           in the component's init function. 
 * 
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
PRIVATE ix_error _ix_cc_eth_rx_create_cb_ctx_tables(
    ix_cc_eth_rx_ctl_blk *arg_pCtlBlk)
{

    /**
     * Create table for ix_cc_eth_rx_async_get_statistics_info().
     */

    /* Allocate cb_ctx_table structure first */
    if ((arg_pCtlBlk->pCbCtxTblGetStatInfo = (ix_cc_eth_rx_cb_ctx_tbl *)ix_ossl_malloc(sizeof(ix_cc_eth_rx_cb_ctx_tbl))) == NULL)
    {
        return(IX_ERROR_REMOTE(IX_CC_ERROR_OOM_SYSTEM,
                               ("Out of memory")));
    } 
    
    /* Initialize the structure */
    ix_ossl_memset((void *)arg_pCtlBlk->pCbCtxTblGetStatInfo, 
                   0, 
                   (ix_ossl_size_t)sizeof(ix_cc_eth_rx_cb_ctx_tbl));

    /* Allocate the callback context entries and put them in the table structure */
    if ((arg_pCtlBlk->pCbCtxTblGetStatInfo->pTable = (ix_cc_eth_rx_cb_ctx_entry *)ix_ossl_malloc(ETH_RX_SIZE_CB_CTX_TBL_GET_STAT)) == NULL)
    {
        ix_ossl_free(arg_pCtlBlk->pCbCtxTblGetStatInfo);
        return(IX_ERROR_REMOTE(IX_CC_ERROR_OOM_SYSTEM,
                               ("Out of memory")));
    }

    /**
     * Create table for ix_cc_eth_rx_async_get_interface_state().
     */

    /* Allocate cb_ctx_table structure first */
    if ((arg_pCtlBlk->pCbCtxTblGetIfState = (ix_cc_eth_rx_cb_ctx_tbl *)ix_ossl_malloc(sizeof(ix_cc_eth_rx_cb_ctx_tbl))) == NULL)
    {
        return(IX_ERROR_REMOTE(IX_CC_ERROR_OOM_SYSTEM,
                               ("Out of memory")));
    } 
    
    /* Initialize the structure */
    ix_ossl_memset((void *)arg_pCtlBlk->pCbCtxTblGetIfState, 
                   0, 
                   (ix_ossl_size_t)sizeof(ix_cc_eth_rx_cb_ctx_tbl));

    /* Allocate the callback context entries and put them in the table structure */
    if ((arg_pCtlBlk->pCbCtxTblGetIfState->pTable = (ix_cc_eth_rx_cb_ctx_entry *)ix_ossl_malloc(ETH_RX_SIZE_CB_CTX_TBL_GET_IF)) == NULL)
    {
        ix_ossl_free(arg_pCtlBlk->pCbCtxTblGetStatInfo);
        return(IX_ERROR_REMOTE(IX_CC_ERROR_OOM_SYSTEM,
                               ("Out of memory")));
    }

    return(IX_SUCCESS);

} /* _ix_cc_eth_rx_create_cb_ctx_tables */





/**
 * NAME: _ix_cc_eth_rx_free_ctl_blk
 * 
 * DESCRIPTION: This function frees all memories and resources specified 
 *              by each pointer member of the control block structure.
 *              Finally, it frees the control block structure.
 * 
 * @Param: arg_pCtlBlk - IN - pointer to control block maintained by
 *                    Ethernet Rx Core Component
 * 
 * @Return: None
 */
PRIVATE void _ix_cc_eth_rx_free_ctl_blk(
    ix_cc_eth_rx_ctl_blk *arg_pCtlBlk)
{
#ifdef MICROBLOCK_COUNTERS    
    ix_uint32 i;

    /* Free 64-bit counter handle array */
    if (arg_pCtlBlk->pCounterHandlers64Bit != NULL)
    {
        /* First delete each 64-bit counter from Resource Manager */
        for (i = 0; i < ETH_RX_TOTAL_NUM_COUNTERS; i++)
        {
            if(ix_rm_counter_64bit_delete(*(arg_pCtlBlk->pCounterHandlers64Bit + i)) != IX_SUCCESS)
				 ix_ossl_message_log("Warning: Resource Manager 64 bit counter delete failed.\n");
        }

        /* Then free the counter handler array */
        ix_ossl_free(arg_pCtlBlk->pCounterHandlers64Bit);
    }

    /* Free 32-bit counter memory */
    if (arg_pCtlBlk->pCounterBase32Bit != NULL)
    {
       if (ix_rm_mem_free(arg_pCtlBlk->pCounterBase32Bit) != IX_SUCCESS)
			ix_ossl_message_log("Warning: Resource manager memory free failed.\n");
    }
#endif /* MICROBLOCK_COUNTERS */

	/* Free filter table memory */
    if (arg_pCtlBlk->pFilterTableBase != NULL)
    {
		if (ix_rm_mem_free(arg_pCtlBlk->pFilterTableBase) != IX_SUCCESS)
			ix_ossl_message_log("Warning: Resource manager memory free failed.\n");
    }

    /* Free Port bit map memory */
    if (arg_pCtlBlk->pPortMapBase != NULL)
    {
		if (ix_rm_mem_free(arg_pCtlBlk->pPortMapBase) != IX_SUCCESS)
			ix_ossl_message_log("Warning: Resource manager memory free failed.\n");
    }

    /* Free async callback context table and entries for getStat */
    if (arg_pCtlBlk->pCbCtxTblGetStatInfo != NULL)
    {
        /* Free the entries first */
        if (arg_pCtlBlk->pCbCtxTblGetStatInfo->pTable != NULL);
        {
            ix_ossl_free(arg_pCtlBlk->pCbCtxTblGetStatInfo->pTable);
        }

        /* Free the table structure */
        ix_ossl_free(arg_pCtlBlk->pCbCtxTblGetStatInfo);
    }

	/* Free async callback context table and entries for get interface state */
    if (arg_pCtlBlk->pCbCtxTblGetIfState != NULL)
    {
        /* Free the entries first */
        if (arg_pCtlBlk->pCbCtxTblGetIfState->pTable != NULL)
        {
            ix_ossl_free(arg_pCtlBlk->pCbCtxTblGetIfState->pTable);
        }

        /* Free the table structure */
        ix_ossl_free(arg_pCtlBlk->pCbCtxTblGetIfState);
    }
	

    /* Destroy the critical section mutex */
    if (arg_pCtlBlk->mid != NULL)
    {
        if (ix_ossl_mutex_fini(arg_pCtlBlk->mid) != IX_SUCCESS)
        {
            ix_ossl_message_log("Warning: OSSL mutex fini failed.\n");
        } 
    }

    /* free the control block structure itself */
    ix_ossl_free((void *)arg_pCtlBlk);

} /*_ix_cc_eth_rx_free_ctl_blk */


