/*****************************************************************************
 *                            Intel Proprietary
 *
 * Copyright (c) 1998-2002 By Intel Corporation.  All rights reserved.  
 * No part of this program or publication may be reproduced, transmitted,
 * transcribed, stored in a retrieval system, or translated into any language
 * or computer language in any form or by any means, electronic, mechanical,
 * magnetic, optical, chemical, manual, or otherwise, without the prior
 * written permission of:
 *                        Intel Corporation
 *                        2200 Mission College Blvd.
 *                        Santa Clara, CA  95052-8119
 *****************************************************************************/

/**
 *****************************************************************************
 * @ingroup LlcSnapEncap
 *
 * File:  ix_cc_llc_snap_encap_init.c
 *
 * @description
 *      This file defines the initialization functions for the LLC Snap
 *      Encapsulation Core Component.
 *
 *****************************************************************************/

/*****************************************************************************
 *
 * Contents:
 *        Definitions of following exported data:
 *
 *        Definitions of following exported functions:
 *            ix_cc_llc_snap_encap_init
 *
 *        Definitions of following local data:
 *            pLlcSnapEncapContext
 *            llcSnapEncapRegistryData
 *
 *        Definitions of following local functions:
 *            ix_cc_llc_snap_encap_retrieve_registry_data
 *            ix_cc_llc_snap_encap_registry
 *            ix_cc_llc_snap_encap_alloc_symbols
 *            ix_cc_llc_snap_encap_patch_symbols
 *            ix_cc_llc_snap_encap_register_message_handler
 *            ix_cc_llc_snap_encap_register_packet_handlers
 *
 *****************************************************************************/


/*
 * User defined include files
 */
#include "ix_cc_llc_snap_encap.h"
#include "ix_cc_llc_snap_encap_private.h"


/*
 * Global variables for the LLC Snap Encap CC
 */
ix_cc_llc_snap_encap_context_t*      pLlcSnapEncapContext = NULL;
ix_cc_llc_snap_encap_registry_data_t llcSnapEncapRegistryData;


/**
 * Function definitions.
 */



/*****************************************************************************
 * Abstract:
 *    This primitive will be used to retrieve data from the registry 
 *    for a given property type. If there is no registry, then the data
 *    structure will be filled with the defaults from the header file.
 *
 * Parameters:
 *    pPropertyName  - IN:  pointer to the property name string
 *    pPropertyValue - OUT: pointer to the property value
 *
 * Return values:
 *    IX_SUCCESS - data retrieved successfully
 *    IX_CC_LLC_SNAP_ENCAP_ERROR_REGISTRY - failed to access the registry
 *
 *****************************************************************************/
ix_error
ix_cc_llc_snap_encap_retrieve_registry_data(const char* pPropertyName,
                                            ix_uint32* pPropertyValue)
{
    ix_configuration_property_handle hLlcSnapEncapPropertyHandle; 

    /* Get static data from registry */    
    IX_ERROR_CRT(ix_rm_cp_property_open(IX_CP_CORE_PROPERTY_ROOT,
                                        pPropertyName,
                                        &hLlcSnapEncapPropertyHandle),
                 IX_CC_LLC_SNAP_ENCAP_ERROR_REGISTRY,
                 IX_ERROR_LEVEL_WARNING);
    
    IX_ERROR_CRT(ix_rm_cp_property_get_value_uint32(hLlcSnapEncapPropertyHandle,
                                                    pPropertyValue),
                 IX_CC_LLC_SNAP_ENCAP_ERROR_REGISTRY,
                 IX_ERROR_LEVEL_WARNING);
    
    IX_ERROR_CRT(ix_rm_cp_property_close(hLlcSnapEncapPropertyHandle),
                 IX_CC_LLC_SNAP_ENCAP_ERROR_REGISTRY,
                 IX_ERROR_LEVEL_WARNING);
    
    return IX_SUCCESS;

} /* ix_cc_llc_snap_encap_retrieve_registry_data */


/*****************************************************************************
 * Abstract:
 *    This primitive will be used to retrieve data from the registry for
 *    all LLC Snap Encapsulation static data stored in an
 *    ix_cc_llc_snap_encap_registry_data_t type data structure.
 *
 * Parameters:
 *    None
 *
 * Return values:
 *    IX_SUCCESS - data retrieved successfully
 *    IX_CC_LLC_SNAP_ENCAP_ERROR_REGISTRY - failed to access the registry
 *
 *****************************************************************************/
ix_error
ix_cc_llc_snap_encap_registry(void)
{
    /* retrieve all configuration data from the registry */
    IX_ERROR_CRT(ix_cc_llc_snap_encap_retrieve_registry_data(
                 LLC_SNAP_ENCAP_REGNAME_SRAM_CHANNEL,
                 &llcSnapEncapRegistryData.sramChannel),
                 IX_CC_LLC_SNAP_ENCAP_ERROR_REGISTRY,
                 IX_ERROR_LEVEL_WARNING);

    IX_ERROR_CRT(ix_cc_llc_snap_encap_retrieve_registry_data(
                 LLC_SNAP_ENCAP_REGNAME_NUMBER_OF_NEXT_HOP_ENTRIES,
                 &llcSnapEncapRegistryData.numberOfNextHopEntries),
                 IX_CC_LLC_SNAP_ENCAP_ERROR_REGISTRY,
                 IX_ERROR_LEVEL_WARNING);
    
    IX_ERROR_CRT(ix_cc_llc_snap_encap_retrieve_registry_data(
                 LLC_SNAP_ENCAP_REGNAME_MEV2_NUM_MASK,
                 &llcSnapEncapRegistryData.mev2NumMask),
                 IX_CC_LLC_SNAP_ENCAP_ERROR_REGISTRY,
                 IX_ERROR_LEVEL_WARNING);

    return IX_SUCCESS;

} /* ix_cc_llc_snap_encap_registry */


/*****************************************************************************
 * Abstract:
 *    This primitive will be used to allocate SRAM memory for the table
 *    which base address is to be patched into microcode.
 *
 * Parameters:
 *    None
 *
 * Return values:
 *    IX_SUCCESS - memory allocated successfully
 *    IX_CC_ERROR_OOM - unable to allocate memory
 *
 *****************************************************************************/
ix_error
ix_cc_llc_snap_encap_alloc_symbols(void)
{
    ix_error err = IX_SUCCESS;
    ix_uint32 memSize;

    /* calculate size of the Next Hop table */
    memSize = (sizeof(llc_snap_encap_next_hop_entry_t) *
               llcSnapEncapRegistryData.numberOfNextHopEntries);

    /* Allocation of memory for the Next Hop Table */
    err = ix_rm_mem_alloc(IX_MEMORY_TYPE_SRAM,
                          llcSnapEncapRegistryData.sramChannel,
                          memSize,
                          (void**)&pLlcSnapEncapContext->pNextHopTableSramBase);
    
    if (err != IX_SUCCESS)
    {
        return IX_ERROR_WARNING(
        IX_CC_ERROR_OOM,
        ("LLC Snap Encap: Memory allocation for the Next Hop Table failed"));   
    }

    /* clear the allocated memory */
    ix_ossl_memset(pLlcSnapEncapContext->pNextHopTableSramBase, 0, memSize);

    return IX_SUCCESS;

} /* ix_cc_llc_snap_encap_alloc_symbols */


/*****************************************************************************
 * Abstract:
 *    This primitive will be used to actually patch the symbols into
 *    the LLC Snap Encap microcode.
 *
 * Parameters:
 *    None
 *
 * Return values:
 *    IX_SUCCESS - symbol patching ended successfully
 *    IX_CC_LLC_SNAP_ENCAP_ERROR_FAILED_PATCHING - patching failed
 *
 *****************************************************************************/
ix_error
ix_cc_llc_snap_encap_patch_symbols(void)
{
    ix_imported_symbol \
        llcSnapEncapSymbols[IX_CC_LLC_SNAP_ENCAP_NUMBER_OF_SYMBOLS];
    ix_uint16 llcSnapEncapIndex = 0;
    ix_memory_type memType;
    ix_uint32 memChannel;
    ix_uint32 memOffset;
    void* pPhysAddr;
    
    /* get the physical offset for the Next Hop table */
    IX_ERROR_CRT(ix_rm_get_phys_offset(
                 pLlcSnapEncapContext->pNextHopTableSramBase,
                 &memType,
                 &memChannel,
                 &memOffset,
                 &pPhysAddr),
                 IX_CC_LLC_SNAP_ENCAP_ERROR_FAILED_PATCHING,
                 IX_ERROR_LEVEL_WARNING);
    
    if (memType == IX_MEMORY_TYPE_SRAM)
    {
        IX_CC_SET_SRAM_CHANNEL_INTO_OFFSET(memChannel, memOffset);
    }
    
    llcSnapEncapSymbols[0].m_Value = memOffset; 
    llcSnapEncapSymbols[0].m_Name  = LLC_SNAP_ENCAP_PATCHNAME_NEXT_HOP_TABLE;

    
    /* actually patch the symbols */
    for (llcSnapEncapIndex = 0; llcSnapEncapIndex < 8; llcSnapEncapIndex++)
    {   
        if (((llcSnapEncapRegistryData.mev2NumMask) &
             (1 << llcSnapEncapIndex)) != 0)
        {
            IX_ERROR_CRT(ix_rm_ueng_patch_symbols(
                         g_aMicroengineNumberMapping[llcSnapEncapIndex],
                         IX_CC_LLC_SNAP_ENCAP_NUMBER_OF_SYMBOLS, 
                         llcSnapEncapSymbols),
                         IX_CC_LLC_SNAP_ENCAP_ERROR_FAILED_PATCHING,
                         IX_ERROR_LEVEL_WARNING);
        }
    }

    return IX_SUCCESS;

} /* ix_cc_llc_snap_encap_patch_symbols */


/*****************************************************************************
 * Abstract:
 *    This primitive will be used to register the message handler for the
 *    LLC Snap Encapsulation Core Component.
 *
 * Parameters:
 *    None
 *
 * Return values:
 *    IX_SUCCESS - message handler registered successfully
 *    IX_CC_LLC_SNAP_ENCAP_ERROR_CCI - error from CCI
 *
 *****************************************************************************/
ix_error
ix_cc_llc_snap_encap_register_message_handler(void)
{
    
    /* Call CCI message handler if CCI is enabled */
#if defined(IX_EXCLUDE_CCI)
    
    IX_ERROR_CRT(ix_rm_message_handler_register(IX_CC_LLC_SNAP_ENCAP_MSG_INPUT,
                                                ix_cc_llc_snap_encap_msg_handler,
                                                pLlcSnapEncapContext),
                 IX_CC_LLC_SNAP_ENCAP_ERROR_CCI,
                 IX_ERROR_LEVEL_WARNING);
#else
    
    IX_ERROR_CRT(ix_cci_cc_add_message_handler(
                 pLlcSnapEncapContext->hLlcSnapEncapHandle,
                 IX_CC_LLC_SNAP_ENCAP_MSG_INPUT,
                 ix_cc_llc_snap_encap_msg_handler,
                 IX_INPUT_TYPE_MULTI_SRC),
                 IX_CC_LLC_SNAP_ENCAP_ERROR_CCI,
                 IX_ERROR_LEVEL_WARNING);
#endif

    return IX_SUCCESS;

} /* ix_cc_llc_snap_encap_register_message_handler */


/*****************************************************************************
 * Abstract:
 *    This primitive will be used to register the packet handlers for the
 *    LLC Snap Encapsulation Core Component.
 *
 * Parameters:
 *    None
 *
 * Return values:
 *    IX_SUCCESS - packet handlers registered successfully
 *    IX_CC_LLC_SNAP_ENCAP_ERROR_CCI - error from CCI
 *
 *****************************************************************************/
ix_error
ix_cc_llc_snap_encap_register_packet_handlers(void)
{
    /* Call CCI packet handler if CCI is enabled */
#if defined(IX_EXCLUDE_CCI)
    
    IX_ERROR_CRT(ix_rm_message_handler_register(IX_CC_LLC_SNAP_ENCAP_PKT_INPUT,
                                                ix_cc_llc_snap_encap_pkt_handler,
                                                pLlcSnapEncapContext),
                 IX_CC_LLC_SNAP_ENCAP_ERROR_CCI,
                 IX_ERROR_LEVEL_WARNING);

#else
    IX_ERROR_CRT(ix_cci_cc_add_message_handler(
                 pLlcSnapEncapContext->hLlcSnapEncapHandle,
                 IX_CC_LLC_SNAP_ENCAP_PKT_INPUT,
                 ix_cc_llc_snap_encap_pkt_handler,
                 IX_INPUT_TYPE_SINGLE_SRC),
                 IX_CC_LLC_SNAP_ENCAP_ERROR_CCI,
                 IX_ERROR_LEVEL_WARNING);
#endif

    return IX_SUCCESS;

} /* ix_cc_llc_snap_encap_register_packet_handlers */


/**
 ****************************************************************************
 * @ingroup LlcSnapEncap
 * LLC Snap CC main initializaton function
 * @description
 *    This routine is the main initialization function for the LLC Snap
 *    Encapsulation Core Component. It performs memory allocations,
 *    handlers registration and all other activities necessary to start
 *    the Core Component's regular activity.
 *
 * @param hCcHandle - IN: handle to the core component, created by the core
 *                    component infrastructure; this should be used later to
 *                    get other services from the core component infrastructure.
 * @param ppContext - OUT: location where the pointer to the control block
 *                    allocated by the core component will be stored. The
 *                    control block is internal to the CC and contains
 *                    information about LLC Snap Encap internal data structures,
 *                    allocated memory and other relevant information. Later
 *                    this pointer is to be passed into the
 *                    ix_cc_llc_snap_encap_fini function for freeing memory and
 *                    other housekeeping operations when the core component
 *                    is being destroyed.  
 *
 * @retval IX_SUCCESS - initialization successful
 * @retval IX_CC_ERROR_NULL - input parameter arg_ppContext is null
 * @retval IX_CC_ERROR_OOM - memory allocation failure      
 * @retval IX_CC_LLC_SNAP_ENCAP_ERROR_REGISTRY - registry access failure
 * @retval IX_CC_LLC_SNAP_ENCAP_ERROR_CCI - failure from CCI 
 * @retval IX_CC_LLC_SNAP_ENCAP_ERROR_FAILED_PATCHING - patching failure
 *
 *****************************************************************************/
ix_error
ix_cc_llc_snap_encap_init(ix_cc_handle hCcHandle,
                          void** ppContext)
{
    ix_error err = IX_SUCCESS;
    
    /* variable used in retrieving static data from arg_ppContext */
    ix_cc_init_context* pInitCtx;

    ix_ossl_message_log("LLC Snap Encap init: 01\n");

    /* check for input arguments validity */
    if(ppContext == NULL)
    {
        return IX_ERROR_WARNING(
        IX_CC_ERROR_NULL,
        ("LLC Snap Encap init: Input parameter ppContext is NULL"));

    }
    
    /* Allocate memory for the LLC Snap Encap CC context */
    pLlcSnapEncapContext = (ix_cc_llc_snap_encap_context_t*) \
        ix_ossl_malloc(sizeof(ix_cc_llc_snap_encap_context_t));

    if(pLlcSnapEncapContext == NULL)
    {
        return IX_ERROR_WARNING(
        IX_CC_ERROR_OOM,
        ("LLC Snap Encap init: Failed to allocate memory for the context"));
    }

    ix_ossl_message_log("LLC Snap Encap init: 02\n");

    /* initialize the structure */
    ix_ossl_memset(pLlcSnapEncapContext,
                   0,
                   sizeof(ix_cc_llc_snap_encap_context_t));

    pLlcSnapEncapContext->initialized = FALSE; /* CC not initialized yet */

    /* store the core component handle in the context */
    pLlcSnapEncapContext->hLlcSnapEncapHandle = hCcHandle;

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

    /*
     * Retrieve static configuration from the registry. If there is no registry,
     * then the data structure will be filled with data from header file.
     */
#if defined (IX_INCLUDE_REGISTRY)
    
    IX_ERROR_CG(ix_cc_llc_snap_encap_registry(),
                err,
                cleanupContext);
#else
    
    /* Fill the registry data structure manually */
	llcSnapEncapRegistryData.numberOfNextHopEntries = NUMBER_OF_NEXT_HOP_ENTRIES;
    llcSnapEncapRegistryData.mev2NumMask = IX_CC_LLC_SNAP_ENCAP_MEV2_NUM_MASK;
    llcSnapEncapRegistryData.sramChannel = IX_CC_LLC_SNAP_ENCAP_SRAM_CHANNEL;
#endif

    ix_ossl_message_log("LLC Snap Encap init: 03\n");

    /* Allocate memory for symbols to be patched */
    IX_ERROR_CG(ix_cc_llc_snap_encap_alloc_symbols(),
                err,
                cleanupContext);

    ix_ossl_message_log("LLC Snap Encap init: 04\n");

    /* Patch symbols */
    IX_ERROR_CG(ix_cc_llc_snap_encap_patch_symbols(),
                err,
                cleanupMemory);

    ix_ossl_message_log("LLC Snap Encap init: 05\n");
   
    /* Register Message Handler */
    IX_ERROR_CG(ix_cc_llc_snap_encap_register_message_handler(),
                err,
                cleanupMemory);

    ix_ossl_message_log("LLC Snap Encap init: 06\n");

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

    ix_ossl_message_log("LLC Snap Encap init: 07\n");

    *ppContext = (void*)pLlcSnapEncapContext;

    ix_ossl_message_log("LLC Snap Encap init: 08\n");
    
    pLlcSnapEncapContext->initialized = TRUE; /* CC initialized successfully */

    ix_ossl_message_log("LLC Snap Encap init: 09\n");

    return IX_SUCCESS;

  cleanupMessageHandler:
    ix_cc_llc_snap_encap_unregister_message_handler();
  cleanupMemory:
    ix_cc_llc_snap_encap_free_symbols();
  cleanupContext:
    ix_ossl_free(pLlcSnapEncapContext);

    return err;

} /* ix_cc_llc_snap_encap_init */

