/**
 * ============================================================================
 * = 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-2001 Intel Corporation. All rights reserved.
 *
 * = PRODUCT
 *      Intel(r) IXA SDK 3.0 for the IXP2000 Network Processor
 *
 * = LIBRARY
 *      
 *
 * = MODULE
 *      ATM TM4.1 Core Component - CCI - init function
 *
 * = FILENAME
 *      ix_cc_atmtm41_init.c
 *
 * = DESCRIPTION
 *      The file defines for init interface and internal functions.
 *
 * = AUTHOR
 *       Adam Dzieciatkowski
 *       adam.dzieciatkowski@intel.com
 *       Jaroslaw Kogut
 *       jaroslaw.kogut@intel.com
 *
 * = AKNOWLEDGEMENTS
 *      
 *
 * = CREATION TIME
 *      11/07/2002
 *
 * = CHANGE HISTORY
 *
 * ============================================================================
 */
#define IX_ERROR_FILE_IDENT "$Id: ix_cc_atmtm41_init.c,v 1.9 2003/12/12 20:30:40 adziecia Exp $";



/**
 * System defined include files
 */
#include "ix_cc_error.h"
#include "ix_rm.h"
#include "ix_ossl.h"
#include "ix_cc.h"
#include "ix_cc_macros.h"
#include "ix_config.h"
#include "bindings.h"
#include "cc/ix_cc_atmsar.h"
#include "cc/ix_cc_atmsar_plugin.h"

#if (_IX_OS_TYPE_ == _IX_OS_LINUX_KERNEL_) 
#include "cc/ix_cc_reg_util.h"
#endif

/**
 * User defined include files
 */
#include "cc/ix_cc_atmtm41_cci.h"
#include "cc/internal/ix_cc_atmtm41_private.h"

/**
 * Preprocessor symbols and Macros used in this file
 */

/* TBD: Temporaty solution - during redesing SAR in multinstaces solution.
 * Instead of the definition should be mechanism of multiinstaces */
#define _IX_CC_ATMTM41_INSTANCE_SAR_0 0


/**
 * Type definitions whose scope is limited to this file
 */

#define _IX_CC_ATMTM41_SCHEDULER_SYMBOL 0x1
#define _IX_CC_ATMTM41_SHAPER_SYMBOL    0x2

/**
 * TYPENAME: _ix_cc_atmtm41_symbol_table_t
 * 
 * DESCRIPTION:
 *    This data structure describes the SRAM memory to be allocated,
 *    initialized and patched into corresponding symbol
 */
typedef struct ix_s_atmtm41_symbol_table
{
    ix_uint8     *registryName;
    ix_uint8     *symbol;
    ix_uint32    elementSize;
    ix_int8      symbolType;    
    ix_uint8     initValue;
    ix_uint8     type;
    _ix_cc_atmtm41_symbol_id_t symbolId;
    ix_uint32    valueToPatch;
}_ix_cc_atmtm41_symbol_table_t;


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


/**
 * VARNAME: g_atmTm41DebugMask
 *
 * DESCRIPTION:
 *    The global variable contains mask of bits that define what debugging
 *    traces has to be show.
 */
ix_uint32 g_atmTm41DebugMask=0x0FFFFFFFF; /* all traces are activ */


static _ix_cc_atmtm41_symbol_table_t s_atmTm41SymbolTable[] =
{        									 
    {   /* Allocate SRAM memory for GCRA_PARAM_TABLE */          		 
        "GCRA_PARAM_SRAM_BASE",
        "GCRA_PARAM_SRAM_BASE",
        GCRA_ENTRY_SIZE,
        _IX_CC_ATMTM41_AAL5_VC_SYMBOL_TYPE,
        0,
        _IX_CC_ATMTM41_SHAPER_SYMBOL,
        _IX_CC_ATMTM41_GCRA_PARAM_TABLE_SYMBOL_ID,
        0
    },          								 
    {   /* Allocate SRAM memory for the image of the HBR queue       */	 
        /* (HBR_TQ_SRAM_BASE)  in the local memory.Each byte in the  */       	 
        /* LM of the TQ represents a VCQ.     		              */	 
        /* The size of the array is MAX_NUBER_OF_HIGH_RATE_VCC.      */       	 
        "HBR_TQ_SRAM_BASE",
        "HBR_TQ_SRAM_BASE",
        HBR_TQ_SRAM_SIZE,
        _IX_CC_ATMTM41_AAL5_SINGLE_SYMBOL_TYPE,
        0x0,
        _IX_CC_ATMTM41_SCHEDULER_SYMBOL,
        _IX_CC_ATMTM41_HBR_TQ_SRAM_BASE_SYMBOL_ID,
        0
    },          								 
    {   /* Allocate one long word of SRAM to be used as HBR_TQ_SRAM_INDICATOR, */   
        /* which will be set when the context of the image         */               
        /* is modified by the TM4.1 manager due to setting up a new connection */   
        /* or removing an existing one.  */            				 
        "HBR_TQ_SRAM_INDICATOR",
        "HBR_TQ_SRAM_INDICATOR",
        HBR_TQ_INDICATOR_SIZE,
        _IX_CC_ATMTM41_AAL5_SINGLE_SYMBOL_TYPE,
        0,
        _IX_CC_ATMTM41_SCHEDULER_SYMBOL,
        _IX_CC_ATMTM41_HBR_TQ_SRAM_INDICATOR_SYMBOL_ID,
        0
    },          								 
    {   /* Allocate SRAM memory for RTQ_SRAM_BASE Real Time Queues for */        
        /* ATM TM scheduler. The size (in bytes) is           	       */	 
        /* RTQ_SRAM_SIZE = AGGREGATION*RT_FRAC*(MAXTQ+1)*16            */     	 
        "RTQ_SRAM_BASE",
        "RTQ_SRAM_BASE",
        TQ_SIZE,
        _IX_CC_ATMTM41_AAL5_TQTOT_SYMBOL_TYPE,
        0,
        _IX_CC_ATMTM41_SCHEDULER_SYMBOL,
        _IX_CC_ATMTM41_RTQ_SRAM_BASE_SYMBOL_ID,
        0
    },          								 
    {   /* Allocate SRAM memory for RTQLEN_SRAM_BASE Real Time Queue length */	 
        /* for ATM TM scheduler. The size (in bytes) is  */			 
        /* RTQLEN_SIZE = (MAXTQ + 1) * 4. */				         
        "RTQLEN_SRAM_BASE",
        "RTQLEN_SRAM_BASE",
        TQLEN_ENTRY_SIZE,
        _IX_CC_ATMTM41_AAL5_TQTOT_SYMBOL_TYPE,
        0,
        _IX_CC_ATMTM41_SCHEDULER_SYMBOL,
        _IX_CC_ATMTM41_RTQLEN_SRAM_BASE_SYMBOL_ID,
        0
    },          								 
    {   /* Allocate SRAM memory for NRTQ_SRAM_BASE Non Real Time Queues  */      
        /* for ATM TM scheduler. The size (in bytes) is                  */	 
        /* NRTQ_SRAM_SIZE = AGGREGATION * NRT_FRAC *(MAXTQ+1) * 16       */      
        "NRTQ_SRAM_BASE",
        "NRTQ_SRAM_BASE",
        TQ_SIZE,
        _IX_CC_ATMTM41_AAL5_TQTOT_SYMBOL_TYPE,
        0,
        _IX_CC_ATMTM41_SCHEDULER_SYMBOL,
        _IX_CC_ATMTM41_NRTQ_SRAM_BASE_SYMBOL_ID,
        0
    },          								 
    {   /* Allocate SRAM memory for NRTQLEN_SRAM_BASE Non Real Time Queue  */   
        /* lenght for ATM TM scheduler.         			    */	 
        /* The size (in bytes) is NRTQLEN_SIZE = (MAXTQ + 1) *  4          */   
        "NRTQLEN_SRAM_BASE",
        "NRTQLEN_SRAM_BASE",
        TQLEN_ENTRY_SIZE,
        _IX_CC_ATMTM41_AAL5_TQTOT_SYMBOL_TYPE,        
        0,
        _IX_CC_ATMTM41_SCHEDULER_SYMBOL,
        _IX_CC_ATMTM41_NRTQLEN_SRAM_BASE_SYMBOL_ID,
        0
    },          								 
    {   /* Allocate SRAM memory for UBRTQ_SRAM_BASE UBR Time Queues      */      
        /* for ATM TM scheduler. The size (in bytes) is                  */	 
        /* UBRTQ_SRAM_SIZE = AGGREGATION * ??? *(MAXTQ+1) * 16       */      
        "UBRTQ_SRAM_BASE",
        "UBRTQ_SRAM_BASE",
        TQ_SIZE,
        _IX_CC_ATMTM41_AAL5_TQTOT_SYMBOL_TYPE,        
        0,
        _IX_CC_ATMTM41_SCHEDULER_SYMBOL,
        _IX_CC_ATMTM41_UBRTQ_SRAM_BASE_SYMBOL_ID,
        0
    },          								 
    {   /* Allocate SRAM memory for UBRTQLEN_SRAM_BASE UBR Time Queue     */
        /* lenght for ATM TM scheduler.         			    */	 
        /* The size (in bytes) is UBRTQLEN_SIZE = (MAXTQ + 1) *  4        */   
        "UBRTQLEN_SRAM_BASE",
        "UBRTQLEN_SRAM_BASE",
        TQLEN_ENTRY_SIZE,
        _IX_CC_ATMTM41_AAL5_TQTOT_SYMBOL_TYPE,        
        0,
        _IX_CC_ATMTM41_SCHEDULER_SYMBOL,
        _IX_CC_ATMTM41_UBRTQLEN_SRAM_BASE_SYMBOL_ID,
        0
    },          								 
    {   /* Allocate SRAM memory for PORTINFO_SRAM_BASE - Port info in  */    
        /* SRAM for ATM TM scheduler.   				   */    
        /* The size (in bytes) is MAX_ATM_PORTS */
#ifndef PORTINFO_IN_SDRAM
        "PORTINFO_SRAM_BASE",
        "PORTINFO_SRAM_BASE",
	1<<PORTDATA_SRAM_ENTRY_SIZE_LOG2,
#else
        "PORTINFO_SDRAM_BASE",
        "PORTINFO_SDRAM_BASE",
        1<<PORTDATA_SDRAM_ENTRY_SIZE_LOG2,
#endif
        _IX_CC_ATMTM41_AAL5_PORT_SYMBOL_TYPE,
        0x00,
        _IX_CC_ATMTM41_SCHEDULER_SYMBOL,
        _IX_CC_ATMTM41_PORTINFO_SRAM_BASE_SYMBOL_ID,
        0
    },
    {   /* Allocate SRAM memory for PORTSHAPING_SRAM_BASE - Port shapping in  */    
        /* SRAM for ATM TM scheduler.   				   */    
        /* The size (in bytes) is MAX_ATM_PORTS*4 */
        "PORTSHAPING_SRAM_BASE",
        "PORTSHAPING_SRAM_BASE",
        PORTSHAPING_ENTRY_SIZE,
        _IX_CC_ATMTM41_AAL5_PORT_SYMBOL_TYPE,
        0xff,
        _IX_CC_ATMTM41_SCHEDULER_SYMBOL,
        _IX_CC_ATMTM41_PORTSHAPING_SRAM_BASE_SYMBOL_ID,
        0
    },
    {   /* Allocate SRAM memory for DQ_SRAM_BASE - Port shapping in  */
        /* SRAM for ATM TM scheduler.   				   */    
        /* The size (in bytes) is DQ_ELEMENT_SIZE * MAX_ATM_PORTS */
        "DQ_SRAM_BASE",
        "DQ_SRAM_BASE",
        DQ_ELEMENT_SIZE,
        _IX_CC_ATMTM41_AAL5_PORT_SYMBOL_TYPE,
        0,
        _IX_CC_ATMTM41_SCHEDULER_SYMBOL,
        _IX_CC_ATMTM41_DQ_SRAM_BASE_SYMBOL_ID,
        0
    },
    {   /* Terminator */          						 
        NULL,
        0,
        0,
        0
    },
};       


/** 
 * Extern function prototypes.
 */

/** 
 * Static function prototypes.
 */

#if (_IX_OS_TYPE_ == _IX_OS_LINUX_KERNEL_) 

/*
 * TBD: Workaround for the Linux Kernel Mode - ATM TM4.1 needs _ix_sa_prop_is_present
 * function. ATM TM4.1 is installed in kernel before System Application and
 * because of that to avoid undefined references this function must be defined here. 
 */
static int _ix_sa_prop_is_present(char* arg_parent_path, char* arg_prop)
{
    ix_configuration_property_handle prop,subprop;
    ix_uint32 idx = 0;
    ix_cp_property_info prop_info;
    
    if(ix_cc_reg_get_prop_from_path(arg_parent_path, &prop) != IX_SUCCESS)
    {
        return 0;
    }
    
    ix_rm_cp_property_get_subproperty(prop, idx,
                                      &subprop);
    while(subprop != 0)
    {
        if(ix_rm_cp_property_get_info(subprop, &prop_info) != IX_SUCCESS)
        {
            return 0;
        }
        
        if (strcmp(prop_info.m_aName, arg_prop) == 0)
        {
            return 1;
        }
        
        idx++;
        ix_rm_cp_property_get_subproperty(prop, idx, &subprop);
    }
    return 0;
} 

#else
extern int _ix_sa_prop_is_present(char* arg_parent_path, char* arg_prop);
#endif

/** 
 * Function definitions.
 */


/******************************************************************************
 *                            SHUTDOWN FUNCTIONS
 *****************************************************************************/

/**
 * NAME: _ix_cc_atmtm41_free_symbols
 *
 * DESCRIPTION:
 *    This primitive will be used to free memory for symbols  allocated for
 *    patching.
 * 
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ERROR_OOM - failed to free memory for symbols.
 */
static ix_error
_ix_cc_atmtm41_free_symbols(
_ix_cc_atmtm41_context_t* arg_pContext)
{
    return IX_SUCCESS;
}/* end _ix_cc_atmtm41_free_symbols */


/**
 * NAME: _ix_cc_atmtm41_delete_64bit_counters
 *
 * DESCRIPTION:
 *    This primitive will be used to delete 64 bit counters. 
 * 
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ERROR_OOM_64BIT_COUNTER - failed to delete 64 bit counter.
 */
static ix_error
_ix_cc_atmtm41_delete_64bit_counters(
_ix_cc_atmtm41_context_t* arg_pContext)
{
    return IX_SUCCESS;
}/* end _ix_cc_atmtm41_delete_64bit_counters */


/**
 * NAME: _ix_cc_atmtm41_unregister_message_handler
 *
 * DESCRIPTION:
 *    This primitive will be used to unregister message handler. It calls CCI
 *    services in level 1 system and resore manager services in level 0 system.
 *
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ATMTM41_ERROR_CCI - error from CCI
 */
static ix_error
_ix_cc_atmtm41_unregister_message_handler(
_ix_cc_atmtm41_context_t* arg_pContext)
{
    /* Call CCI if CCI is enabled */
#if defined(IX_EXCLUDE_CCI)
    IX_ERROR_CRT(ix_rm_message_handler_unregister(IX_CC_ATMTM41_MSG_INPUT),
                 IX_CC_ATMTM41_ERROR_CCI,
                 IX_ERROR_LEVEL_WARNING);
#else
    IX_ERROR_CRT(ix_cci_cc_remove_message_handler(IX_CC_ATMTM41_MSG_INPUT),
                 IX_CC_ATMTM41_ERROR_CCI,
                 IX_ERROR_LEVEL_WARNING);
#endif
    return IX_SUCCESS;
}/* end _ix_cc_atmtm41_unregister_message_handler */


/**
 * NAME: _ix_cc_atmtm41_unregister_cci_packet_handlers
 *
 * DESCRIPTION:
 *    This primitive will be used to unregister packet handler with CCI. 
 * 
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ATMTM41_ERROR_CCI - error from CCI
 */
static ix_error
_ix_cc_atmtm41_unregister_cci_packet_handlers(
_ix_cc_atmtm41_context_t* arg_pContext)
{
#if 0
    /*#if !defined(IX_EXCLUDE_CCI)*/
    IX_ERROR_CRT(ix_cci_cc_remove_message_handler(IX_CC_ATMTM41_PKT_INPUT),
                 IX_CC_ATMTM41_ERROR_CCI,
                 IX_ERROR_LEVEL_WARNING);
#endif
    return IX_SUCCESS;
}/* end _ix_cc_atmtm41_unregister_cci_packet_handlers */


/**
 * NAME: _ix_cc_atmtm41_unregister_rm_packet_handlers
 *
 * DESCRIPTION:
 *    This primitive will be used to unregister packet handler with 
 *    resource manager
 * 
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ATMTM41_ERROR_CCI - error from RM
 */
#if 0
/*#if defined(IX_EXCLUDE_CCI)*/
static ix_error
_ix_cc_atmtm41_unregister_rm_packet_handlers(
_ix_cc_atmtm41_context_t* arg_pContext)
{
    IX_ERROR_CRT(ix_rm_message_handler_unregister(IX_CC_ATMTM41_PKT_INPUT),
                 IX_CC_ATMTM41_ERROR_CCI,
                 IX_ERROR_LEVEL_WARNING);
    return IX_SUCCESS;
}/* end _ix_cc_atmtm41_unregister_rm_packet_handlers */
#endif


/**
 * NAME: _ix_cc_atmtm41_unregister_packet_handlers
 *
 * DESCRIPTION: This primitive will be used to unregister packet handler 
 * with CCI/Resource manager
 *
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ATMTM41_ERROR_CCI - error from CCI/RM
 */
static ix_error
_ix_cc_atmtm41_unregister_packet_handlers(
_ix_cc_atmtm41_context_t* arg_pContext)
{
    /* Call CCI if CCI is enabled */
#if defined(IX_EXCLUDE_CCI)
    IX_ERROR_CR(_ix_cc_atmtm41_unregister_rm_packet_handlers(arg_pContext));
#else
    IX_ERROR_CR(_ix_cc_atmtm41_unregister_cci_packet_handlers(arg_pContext));
#endif
    return IX_SUCCESS;
}/* end _ix_cc_atmtm41_unregister_packet_handlers */


/******************************************************************************
 *                            INITIALIZATION FUNCTIONS
 *****************************************************************************/


/**
 * NAME: _ix_cc_atmtm41_registry
 *
 * DESCRIPTION:
 *    This primitive will be used to retreive data from registry for all the
 *    core component static data.
 *           .
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - OUT  none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ATMTM41_ERROR_REGISTRY  - not able to access registry.
 */
static ix_error
_ix_cc_atmtm41_registry(
_ix_cc_atmtm41_context_t* arg_pContext)
{
#if defined (IX_INCLUDE_REGISTRY)
    char propertyName[256];
    ix_configuration_property_handle hCoreRoot = IX_CP_CORE_PROPERTY_ROOT;
    ix_configuration_property_handle hProperty;
    ix_cp_property_info propertyInfo;
    
    ix_int32 i;

    /* read SAR general configuration from registry */
    IX_ERROR_CR(ix_cc_atmsar_plugin_get_cfg_params(arg_pContext->instance,
                                                   &(arg_pContext->pluginCfg)));
    
    sprintf(propertyName,"ATM_SCHEDULER_%d%cTQ_TOT",
            arg_pContext->instance,
            IX_CP_PATH_NAME_DELIMITER);

    IX_ERROR_CR(ix_rm_cp_property_open(hCoreRoot, propertyName, &hProperty));
    
    IX_ERROR_CR(ix_rm_cp_property_get_value_uint32(hProperty, &(arg_pContext->tq_tot)));

    sprintf(propertyName,"ATM_SCHEDULER_%d%cATM_SCHEDULER_MEV2_NUM_MASK",
            arg_pContext->instance,
            IX_CP_PATH_NAME_DELIMITER);

    IX_ERROR_CR(ix_rm_cp_property_open(hCoreRoot, propertyName, &hProperty));
    
    IX_ERROR_CR(ix_rm_cp_property_get_value_uint32(hProperty, &(arg_pContext->schedulerMEMask)));    

    sprintf(propertyName,"ATM_SCHEDULER_%d%cSCHEDULER_COUNTERS",
            arg_pContext->instance,
            IX_CP_PATH_NAME_DELIMITER);

    IX_ERROR_CR(ix_rm_cp_property_open(hCoreRoot, propertyName, &hProperty));
    
    IX_ERROR_CR(ix_rm_cp_property_get_value_uint32(hProperty, &(arg_pContext->counters)));        
    
    sprintf(propertyName,"ATM_SHAPER_%d%cATM_SHAPER_MEV2_NUM_MASK",
            arg_pContext->instance,
            IX_CP_PATH_NAME_DELIMITER);

    IX_ERROR_CR(ix_rm_cp_property_open(hCoreRoot, propertyName, &hProperty));
    
    IX_ERROR_CR(ix_rm_cp_property_get_value_uint32(hProperty, &(arg_pContext->shaperMEMask)));    



    for (i=0; s_atmTm41SymbolTable[i].symbol != NULL; i++)
    {

        sprintf(propertyName,"ATM_%s_%d%c%s%cCHANNEL",
                (s_atmTm41SymbolTable[i].type == _IX_CC_ATMTM41_SCHEDULER_SYMBOL)?"SCHEDULER":"SHAPER",
                arg_pContext->instance,
                IX_CP_PATH_NAME_DELIMITER,
                s_atmTm41SymbolTable[i].registryName,
                IX_CP_PATH_NAME_DELIMITER);

        IX_ERROR_CR(ix_rm_cp_property_open(hCoreRoot, propertyName, &hProperty));
        
        IX_ERROR_CR(ix_rm_cp_property_get_value_uint32(hProperty, &(arg_pContext->symbolDescr[i].channel)));

        _IX_CC_ATMTM41_DBG_INIT(("SYMBOL: %s CHANNEL: %ld\n",
                                 s_atmTm41SymbolTable[i].symbol,
                                 arg_pContext->symbolDescr[i].channel));
        
        sprintf(propertyName,"ATM_%s_%d%c%s%cMEM_TYPE",
                (s_atmTm41SymbolTable[i].type == _IX_CC_ATMTM41_SCHEDULER_SYMBOL)?"SCHEDULER":"SHAPER",
                arg_pContext->instance,
                IX_CP_PATH_NAME_DELIMITER,
                s_atmTm41SymbolTable[i].registryName      ,
                IX_CP_PATH_NAME_DELIMITER);

        IX_ERROR_CR(ix_rm_cp_property_open(hCoreRoot, propertyName, &hProperty));
        
        IX_ERROR_CR(ix_rm_cp_property_get_value_uint32(hProperty, &(arg_pContext->symbolDescr[i].memType)));

        _IX_CC_ATMTM41_DBG_INIT(("SYMBOL: %s MEMTYPE: %ld\n",
                                 s_atmTm41SymbolTable[i].symbol,
                                 arg_pContext->symbolDescr[i].memType));        

        /* calculate the memory size*/
        switch(s_atmTm41SymbolTable[i].symbolType)
        {        
        case _IX_CC_ATMTM41_AAL5_PORT_SYMBOL_TYPE:
            arg_pContext->symbolDescr[i].memSize = s_atmTm41SymbolTable[i].elementSize * arg_pContext->pluginCfg.numberOfPorts;
            break;
        case _IX_CC_ATMTM41_AAL5_VC_SYMBOL_TYPE:
            arg_pContext->symbolDescr[i].memSize = s_atmTm41SymbolTable[i].elementSize * arg_pContext->pluginCfg.numberOfVcs;
            break;
        case _IX_CC_ATMTM41_AAL5_TQTOT_SYMBOL_TYPE:
            arg_pContext->symbolDescr[i].memSize = s_atmTm41SymbolTable[i].elementSize * arg_pContext->tq_tot;
            break;
        case _IX_CC_ATMTM41_AAL5_SINGLE_SYMBOL_TYPE:
            arg_pContext->symbolDescr[i].memSize = s_atmTm41SymbolTable[i].elementSize;
            break;
        default:
            IX_ERROR_GLOBAL(IX_CC_ATMTM41_ERROR_REGISTRY,
                            ("Symbol type (%d) is invalid for %s.\n",
                             s_atmTm41SymbolTable[i].symbol));
            break;
        } /* switch */
        
        sprintf(propertyName,"ATM_%s_%d%c%s",
                (s_atmTm41SymbolTable[i].type == _IX_CC_ATMTM41_SCHEDULER_SYMBOL)?"SCHEDULER":"SHAPER",
                arg_pContext->instance,
                IX_CP_PATH_NAME_DELIMITER,
                s_atmTm41SymbolTable[i].registryName);
        
        if(_ix_sa_prop_is_present(propertyName, "PATCH_MEV2_NUM_MASK")) 
        {
            sprintf(propertyName,"ATM_%s_%d%c%s%cPATCH_MEV2_NUM_MASK",
                	(s_atmTm41SymbolTable[i].type == _IX_CC_ATMTM41_SCHEDULER_SYMBOL)?"SCHEDULER":"SHAPER",
                	arg_pContext->instance,
                	IX_CP_PATH_NAME_DELIMITER,
                 	s_atmTm41SymbolTable[i].registryName,
                	IX_CP_PATH_NAME_DELIMITER);
            
            ix_rm_cp_property_open(hCoreRoot, propertyName, &hProperty);
           	IX_ERROR_CR(ix_rm_cp_property_get_value_uint32(hProperty, &(arg_pContext->symbolDescr[i].patchMask)));
           	_IX_CC_ATMTM41_DBG_INIT(("SYMBOL: %s PATCH_MEV2_NUM_MASK: %ld\n",
                                     s_atmTm41SymbolTable[i].symbol,
                                     arg_pContext->symbolDescr[i].patchMask));
            
        }
        else
        {
            
	        if (s_atmTm41SymbolTable[i].type == _IX_CC_ATMTM41_SCHEDULER_SYMBOL)
        	{
                arg_pContext->symbolDescr[i].patchMask = arg_pContext->schedulerMEMask;
        	}
        	else
        	{
                arg_pContext->symbolDescr[i].patchMask = arg_pContext->shaperMEMask;
        	}
            
            
        }
        
    }
    
    /* property SYMBOL_PREFIX */
    sprintf(propertyName,"ATM_SCHEDULER_%d%cSYMBOL_PREFIX",
            arg_pContext->instance,
            IX_CP_PATH_NAME_DELIMITER);
    
    IX_ERROR_CR(ix_rm_cp_property_open(hCoreRoot, propertyName, &hProperty));
    
    IX_ERROR_CR(ix_rm_cp_property_get_info(hProperty, &propertyInfo));
    
    if (propertyInfo.m_DataSize > _IX_CC_ATMTM41_SYMBOL_PREFIX_SIZE)
    {
        return IX_ERROR_WARNING(IX_CC_ATMTM41_ERROR_REGISTRY,
                                ("The prefix symbol size (%d) is too long.\n",
                                 propertyInfo.m_DataSize));
    }
    IX_ERROR_CR(ix_rm_cp_property_get_value(hProperty, &propertyInfo.m_DataSize, 
                                            arg_pContext->symbolPrefix));

    
#else

    ix_int32 i;

    for (i=0; s_atmTm41SymbolTable[i].symbol != NULL; i++)
    {
        arg_pContext->symbolDescr[i].channel = _IX_CC_ATMTM41_DEFAULT_CHANNEL(arg_pContext->instance);
        arg_pContext->symbolDescr[i].memType = _IX_CC_ATMTM41_DEFAULT_MEMTYPE(arg_pContext->instance);        
    }
    
    arg_pContext->schedulerMEMask = _IX_CC_ATMTM41_SCHEDULER_DEFAULT_MASK(arg_pContext->instance);
    arg_pContext->shaperMEMask =    _IX_CC_ATMTM41_SHAPER_DEFAULT_MASK(arg_pContext->instance);
    arg_pContext->counters =        _IX_CC_ATMTM41_SCHEDULER(arg_pContext->instance);
    strcpy(arg_pContext->symbolPrefix, _IX_CC_ATMTM41_SYMBOL_PREFIX(arg_pContext->instance));
#endif
    
    return IX_SUCCESS;
}/* end _ix_cc_atmtm41_registry */

/**
 * NAME: _ix_cc_atmtm41_read_port_cfg
 *
 * DESCRIPTION:
 *    This primitive will be used to retreive data from registry for all the
 *    core component static data.
 *           .
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ATMTM41_ERROR_REGISTRY  - not able to access registry.
 */
static ix_error
_ix_cc_atmtm41_read_port_cfg(
_ix_cc_atmtm41_context_t* arg_pContext)
{
    ix_uint32 j, linkRate;
    ix_uint16 i;
    ix_cc_atmsar_plugin_cfg_port_descr_t *pPortCfgTab;
    ix_error err=IX_SUCCESS;

    _IX_CC_ATMTM41_DBG_INIT(("ATM TM41 READ PORT STATIC CONFIGURATION\n"));

    pPortCfgTab = ix_ossl_malloc(sizeof(*pPortCfgTab)*arg_pContext->pluginCfg.numberOfPorts);
    if (pPortCfgTab == NULL)
    {
        return IX_ERROR_GLOBAL(IX_CC_ERROR_NULL, ("Pointer for Port configuration table is NULL"));
    }
    
    IX_ERROR_CG(ix_cc_atmsar_plugin_get_cfg_ports_params(arg_pContext->instance,
                                                         arg_pContext->pluginCfg.numberOfPorts,
                                                         pPortCfgTab),
                err,
                end_of_processing);

    /* prepare/initialize a port table */
    for (i = 0; i<arg_pContext->pluginCfg.numberOfPorts; i++)
    {
        arg_pContext->portsTab[i].n=_IX_CC_ATMTM41_INVALID_PORT_RATE_EXP;
        
        if (pPortCfgTab[i].linkRate == 0)
        {
            continue;
        }
        
        if((pPortCfgTab[i].linkRate > _IX_CC_ATMTM41_LINE_RATE) || (pPortCfgTab[i].linkRate<(_IX_CC_ATMTM41_LINE_RATE/arg_pContext->pluginCfg.numberOfPorts)))
        {
            err = IX_ERROR_GLOBAL(IX_CC_ERROR_ENTRY_NOT_FOUND, 
                                  ("Speed of ATM PORT %d has to be in range <%d..%d>",
                                   i,
                                   (ix_uint32)(_IX_CC_ATMTM41_LINE_RATE/arg_pContext->pluginCfg.numberOfPorts),
                                   (ix_uint32)(_IX_CC_ATMTM41_LINE_RATE)));
            goto end_of_processing;
        }

        /*
         * Find exponent for 
         */
        for(j=0, linkRate=_IX_CC_ATMTM41_LINE_RATE; (j<=arg_pContext->log2MaxAtmPort) && (linkRate != pPortCfgTab[i].linkRate);
            j++, linkRate>>=1)
        {
        }

        if(j>arg_pContext->log2MaxAtmPort)
        {
            err = IX_ERROR_REMOTE(IX_CC_ERROR_ENTRY_NOT_FOUND,
                                  ("Wrong Link speed %d for port %d",
                                   pPortCfgTab[i].linkRate, i));
            goto end_of_processing;
        }

        if(arg_pContext->portsTab[i].n !=_IX_CC_ATMTM41_INVALID_PORT_RATE_EXP)
        {
            err = IX_ERROR_REMOTE(IX_CC_ERROR_ENTRY_NOT_FOUND, 
                                  ("Port ID %d duplicated.", i));
            goto end_of_processing;
        }
        arg_pContext->portsTab[i].n=j;
        arg_pContext->portsTab[i].lrCfg=pPortCfgTab[i].linkRate;
        arg_pContext->portsTab[i].lrUsed=0;
        _IX_CC_ATMTM41_DBG_INIT(("ATM PORT(%04d):  speed=%-10ld, n=%ld, name= %s\n",
                                 i, pPortCfgTab[i].linkRate, j, pPortCfgTab[i].linkName));
    }

    for (i=0, j=0; i<arg_pContext->pluginCfg.numberOfPorts; i++)
    {
        if (arg_pContext->portsTab[i].n !=_IX_CC_ATMTM41_INVALID_PORT_RATE_EXP)
        {
            j++;
        }
    }
    arg_pContext->portCount=j;

  end_of_processing:

    ix_ossl_free(pPortCfgTab);
    
    return err;
}/* end _ix_cc_atmtm41_read_port_cfg */


/**
 * NAME: _ix_cc_atmtm41_port_shapping_tbl_show
 *
 * DESCRIPTION:
 *    The function show portShaperTab.
 * 
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 *
 * @Return: none
 */
void
_ix_cc_atmtm41_port_shapping_tbl_show(
_ix_cc_atmtm41_context_t* arg_pContext)
{
	ix_uint16 i;
    ix_uint32 *pTab;

    if(arg_pContext==NULL)
    {
        _IX_CC_ATMTM41_DBG_INIT(("_ix_cc_atmtm41_port_shapping_init_show() pointer to context is NULL\n"));
        return;
    }
    pTab=arg_pContext->pSymbolTable[_IX_CC_ATMTM41_PORTSHAPING_SRAM_BASE_SYMBOL_ID];
    if(pTab==NULL)
    {
        _IX_CC_ATMTM41_DBG_INIT(("_ix_cc_atmtm41_port_shapping_init_show() pointer to port shaping table is NULL\n"));
        return;
    }
    for(i=0; i<arg_pContext->pluginCfg.numberOfPorts; i++)
    {
		if((i%64)==0)
		{
			_IX_CC_ATMTM41_DBG_INIT(("\n%4d: ",i));
		}
		if(pTab[i] != _IX_CC_ATMTM41_PORT_SHAPPING_EMPTY_ENTRY)
		{
			_IX_CC_ATMTM41_DBG_INIT(("x"));
		}
		else
		{
			_IX_CC_ATMTM41_DBG_INIT(("_"));
		}
    }
    _IX_CC_ATMTM41_DBG_INIT(("\n"));
} /* end _ix_cc_atmtm41_port_shapping_tbl_show */


/**
 * NAME: _ix_cc_atmtm41_port_hbr_init
 *
 * DESCRIPTION:
 *    The function configures correlation between HBR VC table and ports.
 * 
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ATMTM41_ERROR_INVALID_PARAM
 */
static ix_error
_ix_cc_atmtm41_port_hbr_init(
_ix_cc_atmtm41_context_t* arg_pContext)
{
    ix_uint32 *pTab;
    ix_uint16 i, hbrDesc;
    ix_uint32 portId, step;
    _ix_cc_atmtm41_port_t *pPort;
    _ix_cc_atmtm41_hbr_descr_t *pHbr;
    
    /*
     * First _IX_CC_ATMTM41_VC_HBR_MAX entries in port shapping table
     * contains Id of ports that are candidates to ports servicing HBR VC.
     */


    hbrDesc=1; /* 'hbrDesc' contains hbr descriptior ID. 0 - means invalid */
    
    pTab=arg_pContext->pSymbolTable[_IX_CC_ATMTM41_PORTSHAPING_SRAM_BASE_SYMBOL_ID];

    for(i=0; (i<_IX_CC_ATMTM41_VC_HBR_MAX) && (i<arg_pContext->pluginCfg.numberOfPorts); i++)
    {
        portId=pTab[i];
        if(portId != _IX_CC_ATMTM41_PORT_SHAPPING_EMPTY_ENTRY)
        {
            pPort=&(arg_pContext->portsTab[portId]);
            step=1<<pPort->n;
            if(step>_IX_CC_ATMTM41_VC_HBR_MAX)
            {
                /* the port does not service hbr traffic, skip it */
                continue;
            }
            /* entry of port shapping table contains port id */
            if(pPort->hbrDescr==0)
            {
                /* allocate hbr descr and insert it into port description */
                pPort->hbrDescr=hbrDesc++;
                arg_pContext->hbrDescrForPort[pPort->hbrDescr].first=i;
                arg_pContext->hbrDescrForPort[pPort->hbrDescr].step=step;
                _IX_CC_ATMTM41_DBG_INIT(("HBR DESCR[%-3d] port:%-4ld, first:%-3d, step:%-3ld: New entry\n",
                                         pPort->hbrDescr, portId, i, step));
            }
            else
            {
                /*
                 * Hbr descriptor already set for the port, verify it
                 * Find multipierc for 'step' and 'first'
                 */
                pHbr=&(arg_pContext->hbrDescrForPort[pPort->hbrDescr]);
                if( ((i - pHbr->first) % pHbr->step) != 0)
                {
                    return IX_ERROR_GLOBAL(IX_CC_ATMTM41_ERROR_INVALID_PARAM,
                                           ("Port shapping entry %d is not match to "
                                            "hbr_descr (first:%d, step:%d)\n",
                                            i, pHbr->first, pHbr->step));;
                }
                _IX_CC_ATMTM41_DBG_INIT(("HBR DESCR[%-3d] port:%-4ld, first:%-3d, step:%-3ld: Verified\n",
                                         pPort->hbrDescr, portId, i, step));
            }
            
        }
    }
	return IX_SUCCESS;
} /* end _ix_cc_atmtm41_port_hbr_init */


/**
 * NAME: _ix_cc_atmtm41_port_shapping_init
 *
 * DESCRIPTION:
 *    The function fills portShaperTab with defined port in a list.
 * 
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    TBD
 */
static ix_error
_ix_cc_atmtm41_port_shapping_init(
_ix_cc_atmtm41_context_t* arg_pContext)
{
	ix_uint16 i, j, k, pos, entriesCount, entries, exp;
    ix_uint32 *pTab;
    ix_uint16 *pPortList;

    if(PORTSHAPING_ENTRY_SIZE != sizeof(ix_uint32))
    {
        return IX_ERROR_GLOBAL(IX_CC_ATMTM41_ERROR_INVALID_PARAM,
                               ("Size of entry in port shapping table is "
                                "inconsist with used type\n"));;
    }

    exp = arg_pContext->log2MaxAtmPort;
    
    /* Sort ports for inserting into port shapping table */
    pPortList= ix_ossl_malloc(sizeof(ix_uint16) * arg_pContext->portCount);
    if(pPortList == NULL)
    {
        return IX_ERROR_GLOBAL(IX_CC_ERROR_NULL,
                               ("Cannot allocate memory for port list\n"));;
    }

    for(i=0, k=0; i<=exp; i++)
    {
        for(j=0; j<arg_pContext->pluginCfg.numberOfPorts; j++)
        {
            if(arg_pContext->portsTab[j].n == i)
            {
                pPortList[k++]=j;
            }
        }
    }

    /* Prepare port shapping table. */
    pTab=arg_pContext->pSymbolTable[_IX_CC_ATMTM41_PORTSHAPING_SRAM_BASE_SYMBOL_ID];
    entriesCount=0;
	for(i=0; i<arg_pContext->portCount; i++)
	{
		entries=1<<(exp-arg_pContext->portsTab[pPortList[i]].n);

		/* 
         * odwaracamy liczbe juz wykorzystanych elementow,
         * to jest sprytny mechanizm na znalezienie pierwszej wolnej pozycji
         */
		k=entriesCount ;
		pos = 0;
		for(j=exp; j>0; j--)
		{
			pos <<=1;
			if((k & 1) !=0)
			{
				pos++;
			}
			k>>=1;
		}

		k= arg_pContext->pluginCfg.numberOfPorts/entries;  /* krok co jaki wstawic element */

		/*_IX_CC_ATMTM41_DBG_INIT(("Port: %4d, entries:%4d, entriesCount:%4d (%04X) pos:%4d (%04X)\n", 
          i, entries, entriesCount, entriesCount, pos, pos));
        */
		for(j=0; j<entries; j++, pos+=k)
		{
			pos%=arg_pContext->pluginCfg.numberOfPorts;
			if(pTab[pos] != _IX_CC_ATMTM41_PORT_SHAPPING_EMPTY_ENTRY)
			{
				_ix_cc_atmtm41_port_shapping_tbl_show(arg_pContext);
                ix_ossl_free(pPortList);
				return IX_ERROR_GLOBAL(IX_CC_ERROR_NULL,
                                       ("Error for position %d and port %d\n",
                                        pos, i+1));;
			}
			pTab[pos]=pPortList[i];
		}
		entriesCount+=entries;
	}

    ix_ossl_free(pPortList);
	return IX_SUCCESS;
} /* end _ix_cc_atmtm41_port_shapping_init */


/**
 * NAME: _ix_cc_atmtm41_alloc_symbols
 *
 * DESCRIPTION:
 *    This primitive will be used to allocate memory for symbols to be patched.
 * 
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - OUT  - none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ERROR_OOM  - not able to allocate memory
 */
static ix_error
_ix_cc_atmtm41_alloc_symbols(
_ix_cc_atmtm41_context_t* arg_pContext)
{
    ix_error  err = IX_SUCCESS;
    ix_uint32 i;
    ix_uint32 **pTable;
    ix_uint32 *pAddr;
    ix_uint32 *pPtr;

    ix_memory_type memType;
    ix_uint32 channel = 0;
    ix_uint32 zboffset = 0;
    void *pPhysicalAddress = NULL;
    ix_uint32 **pPhyAddress;
    ix_uint32 **pCoreAddress;
    char* pMemTypeName;
    
    /* Allocate SRAM memory to be used by the microblock */
    for (i=0; s_atmTm41SymbolTable[i].symbol != NULL; i++)
    {
        pTable = &arg_pContext->pSymbolTable[s_atmTm41SymbolTable[i].symbolId];
        /* Allocate memory for a table */   
        err = ix_rm_mem_alloc(arg_pContext->symbolDescr[i].memType,
                              arg_pContext->symbolDescr[i].channel,
                              arg_pContext->symbolDescr[i].memSize,
                              (void **)pTable);
        if( err )
        {
            err=IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                 ("Unable to allocate %d memory for symbol %s \n",
                                  arg_pContext->symbolDescr[i].memSize,
                                  s_atmTm41SymbolTable[i].symbol));
            return err;
        }

        IX_ERROR_CT(ix_rm_get_phys_offset((void *)(*pTable),
                                          &memType,
                                          &channel,
                                          &zboffset,
                                          &pPhysicalAddress),
                    err,
                    IX_CC_ERROR_OOM_64BIT_COUNTER, 
                    IX_ERROR_LEVEL_REMOTE);
        if (err != IX_SUCCESS)
        {
            return(err);
        }

        /* Pack the SRAM channel number into the offset */
        if (memType == IX_MEMORY_TYPE_SRAM)
        {
            IX_CC_SET_SRAM_CHANNEL_INTO_OFFSET(channel, zboffset);
        }

        arg_pContext->pPhyAddress[s_atmTm41SymbolTable[i].symbolId] = (ix_uint32*)zboffset;

        switch (memType)
        {
        case IX_MEMORY_TYPE_DRAM:
            pMemTypeName="DRAM";
            break;
        case IX_MEMORY_TYPE_SRAM:
            pMemTypeName="SRAM";
            break;
        case IX_MEMORY_TYPE_SCRATCH:
            pMemTypeName="SCRATCH";
            break;
        case IX_MEMORY_TYPE_LOCAL:
            pMemTypeName="LOCAL";
            break;
        default:
            pMemTypeName="UNKNOWN";
            break;
        }
        
        _IX_CC_ATMTM41_DBG_INIT(("NAME: %s ADDR: %08lX PHY_ADDR:%08lX from %s defined:%ld read:%d\n",
                                 s_atmTm41SymbolTable[i].symbol,
                                 (ix_uint32)arg_pContext->pSymbolTable[s_atmTm41SymbolTable[i].symbolId],
                                 (ix_uint32)arg_pContext->pPhyAddress[s_atmTm41SymbolTable[i].symbolId],
                                 pMemTypeName,
                                 arg_pContext->symbolDescr[i].memType, memType));
        
        /* Initialize table  */
        ix_ossl_memset((ix_uint8 *)(*pTable),
                       (ix_uint8)s_atmTm41SymbolTable[i].initValue,
                       (ix_uint32)arg_pContext->symbolDescr[i].memSize);

        _IX_CC_ATMTM41_DBG_INIT(("Successfuly allocated %ld bytes for symbol %s\n",
                                 arg_pContext->symbolDescr[i].memSize, s_atmTm41SymbolTable[i].symbol));
    }
    
    /* Additional initialization: */

    /* Initialize RTQLEN SRAM table : */
    pPhyAddress = arg_pContext->pPhyAddress;
    pCoreAddress = arg_pContext->pSymbolTable;
    pAddr = pPhyAddress[_IX_CC_ATMTM41_RTQ_SRAM_BASE_SYMBOL_ID];       /* RTQ_SRAM_BASE    */
    pPtr = pCoreAddress[_IX_CC_ATMTM41_RTQLEN_SRAM_BASE_SYMBOL_ID];     /* RTQLEN_SRAM_BASE */


    ix_ossl_memset((ix_uint8 *)(*pTable),
                   (ix_uint8)s_atmTm41SymbolTable[i].initValue,
                   (ix_uint32)arg_pContext->symbolDescr[i].memSize);


    _IX_CC_ATMTM41_DBG_INIT(("Successfuly init memory for IPQ_QDESC_SRAM_BASE \n"));

    /* Fill port shaping table with static configuration */
    IX_ERROR_CRT(_ix_cc_atmtm41_port_shapping_init(arg_pContext),
                 IX_CC_ERROR_NULL, IX_ERROR_LEVEL_GLOBAL);

    _IX_CC_ATMTM41_DBG_INIT(("Successfuly init memory for PORTSHAPING_SRAM_BASE\n"));
    
    /* Fill port shaping table with static configuration */
    IX_ERROR_CRT(_ix_cc_atmtm41_port_info_init(arg_pContext),
                 IX_CC_ERROR_NULL, IX_ERROR_LEVEL_GLOBAL);

    _IX_CC_ATMTM41_DBG_INIT(("Successfuly init memory for PORTINFO_SRAM_BASE\n"));

    /* Prepare structures for HBR VCs management */
    IX_ERROR_CRT(_ix_cc_atmtm41_port_hbr_init(arg_pContext),
                 IX_CC_ERROR_NULL, IX_ERROR_LEVEL_GLOBAL);

    _IX_CC_ATMTM41_DBG_INIT(("Successfuly init HBR VCs management subsystem\n"));
    
    return IX_SUCCESS;
}/* end _ix_cc_atmtm41_alloc_symbols */


/**
 * NAME: _ix_ccatmtm41_patch_symbols
 *
 * DESCRIPTION:
 *    This primitive will be used to patch symbols to L2 Bridge microblocks.
 * 
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ATMTM41_ERROR_FAILED_PATCHING - failed patching by calling resource
 *        manager function
 */
static ix_error _ix_ccatmtm41_patch_symbols(
_ix_cc_atmtm41_context_t* arg_pContext)
{
    /* ATM RX */
    ix_imported_symbol aImportSymbol;
    ix_uint32 i,j;
    ix_memory_type memType;
    ix_uint32 channel = 0;
    ix_uint32 zboffset = 0;
    void *pPhysicalAddress = NULL;
    char symbol[_IX_CC_ATMTM41_SYMBOL_PREFIX_SIZE + _IX_CC_ATMTM41_SYMBOL_SIZE + 1];
    
    ix_error err;

    _IX_CC_ATMTM41_DBG_INIT(("_ix_ccatmtm41_patch_symbols() !!! MICROENGINE NUMBER HARD CODED !!!\n"));

    for (i=0; s_atmTm41SymbolTable[i].symbol != NULL; i++)
    {
        IX_ERROR_CT(ix_rm_get_phys_offset((void *)(arg_pContext->pSymbolTable[s_atmTm41SymbolTable[i].symbolId]),
                                          &memType,
                                          &channel,
                                          &zboffset,
                                          &pPhysicalAddress),
                    err,
                    IX_CC_ERROR_OOM_64BIT_COUNTER, 
                    IX_ERROR_LEVEL_REMOTE);
        if (err != IX_SUCCESS)
        {

            return(err);
        }

        /* Pack the SRAM channel number into the offset */
        if (memType == IX_MEMORY_TYPE_SRAM)
        {
            IX_CC_SET_SRAM_CHANNEL_INTO_OFFSET(channel, zboffset);
        }


        /** 
         * Prepare the symbol array.  For now only single mode is used 
         * so skip the memOffsetNextAvailTBufElem.
         */   
        aImportSymbol.m_Value = (ix_uint32)zboffset;
        sprintf(symbol, "%s%s", arg_pContext->symbolPrefix, s_atmTm41SymbolTable[i].symbol);
        aImportSymbol.m_Name  = symbol;

        for (j=0;j<IX_MAX_MICROENGINE_NUMBER;j++)
        {
            if (arg_pContext->symbolDescr[i].patchMask & (0x1 << j))
                IX_ERROR_CR(ix_rm_ueng_patch_symbols(g_aMicroengineNumberMapping[j], 1, &aImportSymbol));
        }
    }

    return IX_SUCCESS;
}/* end _ix_ccatmtm41_patch_symbols */


/**
 * NAME: _ix_cc_atmtm41_create_64bit_counters
 *
 * DESCRIPTION:
 *    This primitive will be used to create 64 bit counters.   .
 * 
 * @Param:  - IN none
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ERROR_OOM_64BIT_COUNTER - error in creating 64 bit counter
 */
static ix_error
_ix_cc_atmtm41_create_64bit_counters(void)
{
    return IX_SUCCESS;
}/* end _ix_cc_atmtm41_create_64bit_counters */


/**
 * NAME: _ix_cc_atmtm41_register_message_handler
 *
 * DESCRIPTION:
 *    This primitive will be used to register message handler. 
 * 
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - OUT  none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ATMTM41_ERROR_CCI - Error from CCI
 */
static ix_error
_ix_cc_atmtm41_register_message_handler(
_ix_cc_atmtm41_context_t* arg_pContext)
{
    /* Call CCI message handler if CCI is enabled */
#if 0
#if defined(IX_EXCLUDE_CCI) 
    IX_ERROR_CRT(ix_rm_message_handler_register(IX_CC_ATMTM41_MSG_INPUT,
                                                ix_cc_atmtm41_msg_handler,
                                                arg_pContext),
                 IX_CC_ATMTM41_ERROR_CCI,
                 IX_ERROR_LEVEL_WARNING);
#else
    IX_ERROR_CRT(ix_cci_cc_add_message_handler(arg_pContext->hAtmtm41Handle,
                                               IX_CC_ATMTM41_MSG_INPUT,
                                               ix_cc_atmtm41_msg_handler,
                                               IX_INPUT_TYPE_MULTI_SRC),
                 IX_CC_ATMTM41_ERROR_CCI,
                 IX_ERROR_LEVEL_WARNING);

#endif
#endif
    return IX_SUCCESS;
}/* end _ix_cc_atmtm41_register_message_handler */


/**
 * NAME: _ix_cc_atmtm41_register_cci_packet_handlers
 *
 * DESCRIPTION:
 *    This primitive will be used to register packet handler with CCI.
 *
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ATMTM41_ERROR_CCI - error from CCI
 */
static ix_error
_ix_cc_atmtm41_register_cci_packet_handlers(
_ix_cc_atmtm41_context_t* arg_pContext)
{
#if 0
    /*#if !defined(IX_EXCLUDE_CCI)*/
    /* High priority packet handler needs to be registered as a message handler */
    IX_ERROR_CRT(ix_cci_cc_add_message_handler(arg_pContext->hAtmtm41Handle,
                                               IX_CC_ATMTM41_PKT_INPUT,
                                               ix_cc_atmtm41_pkt_handler,
                                               IX_INPUT_TYPE_SINGLE_SRC),
                 IX_CC_ATMTM41_ERROR_CCI,
                 IX_ERROR_LEVEL_WARNING);
    
#endif
    return IX_SUCCESS;
}/* end _ix_cc_atmtm41_register_cci_packet_handlers */


/**
 * NAME: _ix_cc_atmtm41_register_rm_packet_handlers
 *
 * DESCRIPTION:
 *    This primitive will be used to register packet handler with resource
 *    manager
 *
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ATMTM41_ERROR_CCI - error from resource manager
 */
#if defined(IX_EXCLUDE_CCI)
static ix_error
_ix_cc_atmtm41_register_rm_packet_handlers(
_ix_cc_atmtm41_context_t* arg_pContext)
{
    IX_ERROR_CRT(ix_rm_message_handler_register(IX_CC_ATMTM41_PKT_INPUT,
                                                ix_cc_atmtm41_pkt_handler,
                                                arg_pContext),
                 IX_CC_ATMTM41_ERROR_CCI,
                 IX_ERROR_LEVEL_WARNING);

    return IX_SUCCESS;
}/* end _ix_cc_atmtm41_register_rm_packet_handlers */
#endif

/**
 * NAME: _ix_cc_atmtm41_register_packet_handlers
 *
 * DESCRIPTION:
 *    This primitive will be used to register packet handlers. It registers with
 *    CCI in level 1 system and register with RM in level 0 system.
 * 
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ATMTM41_ERROR_CCI - error from CCI/resource manager
 */
static ix_error
_ix_cc_atmtm41_register_packet_handlers(
_ix_cc_atmtm41_context_t* arg_pContext)
{
    /* Call CCI packet handler if CCI is enabled */
#if defined(IX_EXCLUDE_CCI)
    IX_ERROR_CR(_ix_cc_atmtm41_register_rm_packet_handlers(arg_pContext));
#else
    IX_ERROR_CR(_ix_cc_atmtm41_register_cci_packet_handlers(arg_pContext));
#endif
    return IX_SUCCESS;
}/* end _ix_cc_atmtm41_register_packet_handlers */


/******************************************************************************
 *                            CCI API FUNCTIONS
 *****************************************************************************/


/**
 * NAME: _ix_cc_atmtm41_vc_list_get_entry
 * 
 * DESCRIPTION:
 *    The callback function returns pointer to stucture with
 *    vc description.
 *
 * @Param:  - IN arg_pUserData - pointer to structure that descrige storage
 *                   of entries
 * @Param:  - IN arg_handle - ID of entry
 *
 * @Return:
 *     Pointer if success otherwise NULL.
 */
void*
_ix_cc_atmtm41_vc_list_get_entry(
void *arg_pUserData,
ix_uint16 arg_handle)
{
    _ix_cc_atmtm41_context_t* pCtx=arg_pUserData;
    return &(pCtx->vc[arg_handle]);
} /* end _ix_cc_atmtm41_vc_list_get_entry*/



/**
 * NAME: ix_cc_atmtm41_init
 *
 * DESCRIPTION:
 *    This primitive shall be called and returned successfully before requesting
 *    any service from the core component. This primitive should be called
 *    only once to initialize the core component. This function performs
 *    allocation of memory for symbols to be patched, Creation of 64 bit
 *    counters, registration of packet and message handlers, allocation and
 *    initialization of internal data structures.
 *              
 * 
 * @Param:  IN arg_hCcHandle - handle to the core component, created by CCI; 
 *                 this shall be used later to get other (to add event handler)
 *                 services from core component infrastructure.
 *
 * @Param:  IN-OUT arg_ppContext - Buffer free list and dynamic property data
 *                 will be given during by system APPs during initialization.
 *                 Upon successfull completion, it represents the location where
 *                 the pointer to the control block allocated by the core
 *                 component will be stored. The control block is internal to
 *                 the core component and it contains information about internal
 *                 data structures, allocated memory and other relevant
 *                 information. Later this pointer to be passed into fini()
 *                 function for freeing memory and other house keeping
 *                 operations when the core component is being destroyed.  
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ERROR_NULL - input parameter arg_ppContext is null
 *    IX_CC_ERROR_OOM   - memory allocation failure      
 *    IX_CC_ATMTM41_ERROR_FAILED_PATCHING   - patching failures                      
 *    IX_CC_ERROR_OOM_64BIT_COUNTER - 64 bit counter creation failure
 *    IX_CC_ATMTM41_ERROR_REGISTRY  - registry access failures
 *    IX_CC_ATMTM41_ERROR_RTM - failure from RTM core component
 *    IX_CC_ATMTM41_ERROR_CCI - failure from CCI 
 */
ix_error ix_cc_atmtm41_init(
ix_cc_handle arg_hCcHandle,
void** arg_ppContext)
{
    ix_int32 i;
    ix_error err = IX_SUCCESS;
    _ix_cc_atmtm41_context_t* pContext;
    ix_uint32 memSize;
    
    /* Variables used in retrieving static data from arg_ppContext */
    ix_cc_init_context *pInitCtx;

    _IX_CC_ATMTM41_DBG_INIT(("ix_cc_atmtm41_init...START\n" ));

    /* Check for argument validity */
    if(arg_ppContext == NULL)
    {
        return IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("Input parameter(arg_ppContext) is null"));
    }/* end if (arg_ppContext == NULL) */

    /* Get the generic init context */
    pInitCtx = (ix_cc_init_context *)*arg_ppContext;

    if(pInitCtx == NULL)
    {
        return IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("pInitCtx is null"));
    }/* end if (arg_ppContext == NULL) */
    
    /* Allocate memory for L2 Bridge Context */
    pContext = (_ix_cc_atmtm41_context_t*)ix_ossl_malloc(sizeof(_ix_cc_atmtm41_context_t));
    if(pContext == NULL)
    {
        return IX_ERROR_WARNING(IX_CC_ERROR_OOM,
                                ("Failed to allocate memory for ATM TM4.1 context"));
    }/* end if (pContext == NULL) */

    /* initialize the structure */
    ix_ossl_memset(pContext, 0, sizeof(_ix_cc_atmtm41_context_t));
    
    /* store ATM TM41 component handle in _ix_cc_atmtm41_context_t */
    pContext->hAtmtm41Handle = arg_hCcHandle;

#ifdef CCI_MULTIINSTANCE
    /* use multiinstance CC ID if applicable */
    pContext->instance = IX_HANDLE_TO_INSTANCE(arg_hCcHandle);
#else
    /* if not, use default instance number */
    pContext->instance = _IX_CC_ATMTM41_INSTANCE_SAR_0;
#endif /* CCI_MULTIINSTANCE */

    
    /* Retrieve static configuration from registry. If there is no registry, 
     * then the data structure 
     * will be filled with data from header file. */
    IX_ERROR_CG(_ix_cc_atmtm41_registry(pContext),err,cleanupContext);
    
    
    /* Allocate context tables and structures. */
    memSize = pContext->pluginCfg.numberOfPorts * sizeof(_ix_cc_atmtm41_port_t);
    pContext->portsTab = (_ix_cc_atmtm41_port_t*) ix_ossl_malloc(memSize);
    if(pContext->portsTab == NULL)
    {
        return IX_ERROR_WARNING(IX_CC_ERROR_OOM_64BIT_COUNTER,
                                ("Memory allocation failed for TM4.1 port table"));
    }    
    ix_ossl_memset(pContext->portsTab,0,memSize);

    memSize = pContext->pluginCfg.numberOfVcs * sizeof(ix_uint16);
    pContext->vcId = (ix_uint16*) ix_ossl_malloc(memSize);
    if(pContext->vcId == NULL)
    {
        return IX_ERROR_WARNING(IX_CC_ERROR_OOM_64BIT_COUNTER,
                                ("Memory allocation failed for TM4.1 vcId table"));
    }    
    ix_ossl_memset(pContext->vcId,0,memSize);

    memSize = pContext->pluginCfg.numberOfVcs * sizeof(_ix_cc_atmtm41_vc_entry_t);
    pContext->vc = (_ix_cc_atmtm41_vc_entry_t*) ix_ossl_malloc(memSize);
    if(pContext->vc == NULL)
    {
        return IX_ERROR_WARNING(IX_CC_ERROR_OOM_64BIT_COUNTER,
                                ("Memory allocation failed for TM4.1 vc table"));
    }    
    ix_ossl_memset(pContext->vc,0,memSize);


    /*
     * Now we try find the value of exponent for MAX_ATM_PORTS and verify it.
     * The values is used for initialization of the rest of ATM TM core
     * component.
     */
    for(i=pContext->pluginCfg.numberOfPorts, pContext->log2MaxAtmPort=0;
        i>1;
        i>>=1, pContext->log2MaxAtmPort++) {}
    /* verification of MAX_ATM_PORTS value */
    i=1<<pContext->log2MaxAtmPort;
    if(pContext->pluginCfg.numberOfPorts != i)
    {
        return IX_ERROR_GLOBAL(IX_CC_ATMTM41_ERROR_INVALID_PARAM,
                               ("MAX_ATM_PORTS has a wrong value %d, callcolated exp is %d and portCount %d\n",
                                (ix_uint16)pContext->pluginCfg.numberOfPorts, pContext->log2MaxAtmPort, i));
    }

    /* Now we try find the value of exponent of 2 for TQ_TOT and verify it. */
    for(i=pContext->tq_tot, pContext->log2TqTot=0; i>1; i>>=1, pContext->log2TqTot++) {}
    /* verification of TQ_TOT value */
    i=1<<pContext->log2TqTot;
    if(pContext->tq_tot != i)
    {
        return IX_ERROR_GLOBAL(IX_CC_ATMTM41_ERROR_INVALID_PARAM,
                               ("TQ_TOT has a wrong value %d, callcolated exp is %d and portCount %d\n",
                                (ix_uint16)pContext->tq_tot, pContext->log2TqTot, i));
    }

    /* Now we try find the value of exponent of 2 for TQ_TOT and verify it. */
    for(i=AGGREGATION, pContext->log2Aggregation=0; i>1; i>>=1, pContext->log2Aggregation++) {}
    /* verification of TQ_TOT value */
    i=1<<pContext->log2Aggregation;
    if(AGGREGATION != i)
    {
        return IX_ERROR_GLOBAL(IX_CC_ATMTM41_ERROR_INVALID_PARAM,
                               ("AGGREGATION has a wrong value %d, callcolated exp is %d and portCount %d\n",
                                (ix_uint16)AGGREGATION, pContext->log2Aggregation, i));
    }
    
    _IX_CC_ATMTM41_DBG_INIT(("Log2(MAX_ATM_PORTS)=%d, Log2(TQ_TOT)=%d, Log2(AGGREGATION)=%d\n",
                             pContext->log2MaxAtmPort,
                             pContext->log2TqTot,
                             pContext->log2Aggregation));

    /* initialize heads of list for VCs serviced by particular port */
    for(i=0; i < pContext->pluginCfg.numberOfPorts; i++)
    {
        pContext->portsTab[i].vcList=IX_CC_ATM_LIST_INVALID_HANDLE;
    }

    /* initialize VC list */
    pContext->listVc.count=pContext->pluginCfg.numberOfVcs-1;
    pContext->listVc.getEntry=_ix_cc_atmtm41_vc_list_get_entry;
    pContext->listVc.pUserData=pContext;
    
    if(ix_cc_atm_list_init(&(pContext->listVc),
                           IX_CC_ATM_LIST_INIT_NO_LINK) == IX_CC_ATM_LIST_ERROR)
    {
        err = IX_ERROR_GLOBAL(IX_CC_ERROR_OOM,
                              ("Failed VC list initialization for ATM TM41 context"));
        goto cleanupContext;
    }
    
    for(i=0; i < pContext->listVc.count; i++)
    {
        pContext->vc[i].port=IX_CC_ATMSAR_PORTID_INVALID;
    }

    /* Prepare free list for the high part of GCRA_PARAM_TABLE to keep track
     * on entries available for high rate VCCs.  */
    pContext->freeHbrVcs=IX_CC_ATM_LIST_INVALID_HANDLE;
    pContext->freeLbrVcs=IX_CC_ATM_LIST_INVALID_HANDLE;

    for(i=(((pContext->listVc.count<_IX_CC_ATMTM41_VC_HBR_MAX)?pContext->listVc.count:_IX_CC_ATMTM41_VC_HBR_MAX)-1); i>=1 ; i--) 
    {
        if(ix_cc_atm_list_insert(i, 0, &pContext->freeHbrVcs, &pContext->listVc) != IX_CC_ATM_LIST_OK)
        {
            err = IX_ERROR_GLOBAL(IX_CC_ERROR_OOM,
                                  ("Failed HBR VC list initialization for ATM TM41 context"));
            goto cleanupContext;
        }
    }

    
    /* Prepare free list for the low part of GCRA_PARAM_TABLE to keep track
     * on entries available for low rate VCCs.  */
    for(i=(pContext->listVc.count-1); i >_IX_CC_ATMTM41_LBR_MIN_HANDLE ; i--) 
    {
        if(ix_cc_atm_list_insert(i, 0, &pContext->freeLbrVcs, &pContext->listVc) != IX_CC_ATM_LIST_OK)
        {
            err = IX_ERROR_GLOBAL(IX_CC_ERROR_OOM,
                                  ("Failed HBR VC list initialization for ATM TM41 context"));
            goto cleanupContext;
        }
    }
    
    /* initialize copy of VC HBR table. The table is in DRAM and it is used for
     * calculation entries in real HBR VC table in SRAM. The copy is used*/
    for(i=0; i < _IX_CC_ATMTM41_VC_HBR_MAX; i++) 
    {
        pContext->hbrVc[i]=_IX_CC_ATMTM41_HBR_VC_EMPTY;
    }

    /*
     * Retrieve the port id information of each channel from the 
     * init context (This will work for both level-1 and level-0 modes).
     */
    IX_ERROR_CG(_ix_cc_atmtm41_read_port_cfg(pContext), err, cleanupContext);
   
    /* Allocate memory for symbols to be patched */
    IX_ERROR_CG(_ix_cc_atmtm41_alloc_symbols(pContext), err, cleanupContext);

    /* Patch symbols */
    IX_ERROR_CG(_ix_ccatmtm41_patch_symbols(pContext), err, cleanupMemory);

    /* 64 bit counter creation */
    if (pContext->counters)
    {        
        IX_ERROR_CG(_ix_cc_atmtm41_create_64bit_counters(), err, cleanupMemory);
    }

    /* Register Message Handler */
    IX_ERROR_CG(_ix_cc_atmtm41_register_message_handler(pContext), err, cleanupCounter);

    /* Register Packet Handler */
    IX_ERROR_CG(_ix_cc_atmtm41_register_packet_handlers(pContext), err, cleanupMessageHandler);


    IX_ERROR_CG(ix_cc_atmsar_plugin_reg_port_handle_service(pContext->instance,
                                                            pContext,
                                                            _ix_cc_atmtm41_plugin_port_alloc,
                                                            _ix_cc_atmtm41_plugin_port_free),
                err,
                cleanupPacketHandlers);

    IX_ERROR_CG(ix_cc_atmsar_plugin_reg_vc_handle_service(pContext->instance,
                                                          pContext,
                                                          _ix_cc_atmtm41_plugin_vc_alloc,
                                                          _ix_cc_atmtm41_plugin_vc_free),
                err,
                cleanupPacketHandlers);

    /* Register the core component into SAR CONTROL */
    IX_ERROR_CG(ix_cc_atmsar_plugin_reg_vc_service(IX_CC_ATMTM41,
                                                   pContext->instance,
                                                   _ix_cc_atmtm41_plugin_vc_create,
                                                   _ix_cc_atmtm41_plugin_vc_update,
                                                   _ix_cc_atmtm41_plugin_vc_remove,
                                                   NULL), /* the CC does not support stats for VC */
                err,
                cleanupPacketHandlers);

    IX_ERROR_CG(ix_cc_atmsar_plugin_reg_port_service(IX_CC_ATMTM41,
                                                     pContext->instance,
                                                     _ix_cc_atmtm41_plugin_port_create,
                                                     _ix_cc_atmtm41_plugin_port_remove,
                                                     NULL), /* the CC does not support stats for port */
                err,
                cleanupPacketHandlers);
    
    IX_ERROR_CG(ix_cc_atmsar_plugin_reg_done(IX_CC_ATMTM41,
                                             pContext->instance,
                                             pContext),
                err,
                cleanupPacketHandlers);
    
    *arg_ppContext = (void *)pContext;
    _IX_CC_ATMTM41_DBG_INIT(("ix_error ix_cc_atmtm41_init...SUCCESS\n"));
    return IX_SUCCESS;

  cleanupPacketHandlers:
    _ix_cc_atmtm41_unregister_packet_handlers(pContext);
  cleanupMessageHandler:
    _ix_cc_atmtm41_unregister_message_handler(pContext);
  cleanupCounter:
    if (pContext->counters)
    {
        _ix_cc_atmtm41_delete_64bit_counters(pContext);
    }
  cleanupMemory:
    _ix_cc_atmtm41_free_symbols(pContext);
  cleanupContext:
    ix_ossl_free(pContext);
    return err;
} /* end ix_cc_atmtm41_init */


/**
 * NAME: ix_cc_atmtm41_fini
 *
 * DESCRIPTION:
 *    This primitive shall be called to terminate services from this core
 *    component. This primitive frees memory allocated during initialization,
 *    free all the created resources: delete 64 bit counter. If client claims
 *    for any services from this core component after calling this function,
 *    then the behavior is undefined.
 * 
 * @Param:  IN arg_hCcHandle - handle to this core component
 * @Param:  IN arg_pContext - pointer to the control block memory allocated 
 *                 earlier in ix_cc_atmtm41_init function. 
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ATMTM41_ERROR_INVALID_INPUT_PARAM - invalid input parameter(s)
 *    IX_CC_ERROR _OOM - failure of memory deletion                
 *    IX_CC_ERROR_OOM_64BIT_COUNTER - failure of  64 bit counter deletion 
 *    IX_CC_ATMTM41_ERROR _RTM - failure from RTM
 *    IX_CC_ATMTM41_ERROR_CCI - failure from CCI
 */
ix_error ix_cc_atmtm41_fini(
ix_cc_handle arg_hCcHandle,
void* arg_pContext)
{
    _ix_cc_atmtm41_context_t* pCtx=arg_pContext;
    /* Validate Parameters */
    if(pCtx == NULL)
    {
        return IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("Pointer to context is null"));

    }/* if(arg_pContext == NULL)  */ 

    if((arg_hCcHandle != pCtx->hAtmtm41Handle))
    {
        return IX_ERROR_WARNING(IX_CC_ATMTM41_ERROR_INVALID_INPUT_PARAM,
                                ("Invalid input Parameters"));
    }
  
    /* Free memory for symbols */
    IX_ERROR_CR(_ix_cc_atmtm41_free_symbols(pCtx));

    /* Delete 64 bit counter */
    if (pCtx->counters)
    {
        IX_ERROR_CR(_ix_cc_atmtm41_delete_64bit_counters(pCtx));
    }
    
    /* Unregister Message Handler */
    IX_ERROR_CR(_ix_cc_atmtm41_unregister_message_handler(pCtx));
  
    /* Unregister Packet Handler */
    IX_ERROR_CR(_ix_cc_atmtm41_unregister_packet_handlers(pCtx));
    
    /* Free Atmtm41 Context */ 
    ix_ossl_free(pCtx);
        
    return IX_SUCCESS;
} /* end ix_cc_atmtm41_fini */

