/**
 * ============================================================================
 * = 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
 *      IPv4 Forwarder Core Component - fini
 *
 * = FILENAME
 *      ix_cc_ipv4_fini.c
 *
 * = DESCRIPTION
 *      The file defines fini interface and internal functions.
 *
 * = AUTHOR
 *       Govindan Nair
 *       govindan.nair@intel.com
 *
 * = AKNOWLEDGEMENTS
 *      
 *
 * = CREATION TIME
 *      06/28/2002
 *
 * = CHANGE HISTORY
 *
 * ============================================================================
 */

#define IX_ERROR_FILE_IDENT "$Id: ix_cc_ipv4_fini.c,v 1.19 2003/11/01 03:20:12 rranjeet Exp $";


/**
 * System defined include files
 */


/**
 * User defined include files
 */

#include "ix_cc_error.h"

#include "ix_rm.h"
#include "ix_ossl.h"
#include "cc/ix_cc_rtmv4.h"

#include "ix_cc.h"
#include "bindings.h"
#include "cc/ix_cc_ipv4.h"
#include "cc/ipv4/internal/ix_cc_ipv4_init.h"
#include "cc/ipv4/internal/ix_cc_ipv4_fini.h"







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



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


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


/** 
 * Extern function prototypes.
 */

extern ix_cc_ipv4_context* g_pIpv4Context;


/** 
 * Static function prototypes.
 */


/** 
 * Function definitions.
 */



/**
 * NAME: _ix_cc_ipv4_free_symbols
 *
 * DESCRIPTION: This primitive will be used to free memory for symbols 
 * allocated for patching.         .
 * 
 * @Param:  - IN none
 *
 * @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.
 * 
 */

ix_error _ix_cc_ipv4_free_symbols()
{
    /* Free memory for microblock symbols */
    IX_ERROR_CRT(ix_rm_mem_free(g_pIpv4Context->pMbBase),IX_CC_ERROR_OOM,IX_ERROR_LEVEL_LOCAL);
    IX_ERROR_CRT(ix_rm_mem_free(g_pIpv4Context->pMbStatsBase),IX_CC_ERROR_OOM,IX_ERROR_LEVEL_LOCAL);           
    /*
     * Function successfully freed memory for control block, 
     * directed broadcast table and statistics.
     */

    g_pIpv4Context->pMbBase = NULL;
    g_pIpv4Context->pMbCbBase = NULL;
    g_pIpv4Context->pMbStatsBase = NULL;
    g_pIpv4Context->pMbDbBase = NULL;

    return IX_SUCCESS;

}/* end _ix_cc_ipv4_free_symbols */


/**
 * NAME: _ix_cc_ipv4_delete_64bit_counters
 *
 * DESCRIPTION: This primitive will be used to delete 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 - failed to delete 64 bit counter.
 * 
 */

ix_error _ix_cc_ipv4_delete_64bit_counters()
{

    ix_uint32 ipv4Index;

  
   /*  In uCode we have ipv4 statistics per port
   we have to change it in Core Components so that no iligal use of 
   SCRATCH is done. This may be a temporary solution */

    ix_uint32 portIndex;
    for (portIndex = 0; portIndex < MAX_NUMBER_OF_PORTS_PER_BLADE; portIndex++)
    {

    	for(ipv4Index =0; ipv4Index < IX_CC_IPV4_NUMBER_OF_MB_COUNTERS;ipv4Index++)
    	{
     	   IX_ERROR_CRT(ix_rm_counter_64bit_delete(
			g_pIpv4Context->counter64BitHandle[portIndex].ahCounter64BitHandle[ipv4Index]),
      	               	IX_CC_ERROR_OOM_64BIT_COUNTER,IX_ERROR_LEVEL_WARNING);

	}/* end for(ipv4Index =0; ipv4Index < IX_CC_IPV4_NUMBER_OF_MB_COUNTERS;ipv4Index++) */
    }/* end for (portIndex = 0; portIndex < MAX_NUMBER_OF_PORTS_PER_BLADE; portIndex++) */


    return IX_SUCCESS;

}/* end _ix_cc_ipv4_create_64bit_counters */





/**
 * NAME: _ix_cc_ipv4_terminate_rtm_services
 *
 * DESCRIPTION: This primitive will be used to terminate RTM services: 
 * 1. remove all the next hops and routes from RTM
 * 3. Terminate RTM by calling fini function of RTM
 * 
 * @Param:  - IN none
 *
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 * 
 * IX_CC_IPV4_ERROR_RTM - error from RTM
 * 
 */

ix_error _ix_cc_ipv4_terminate_rtm_services()
{
    /* Call RTM purge to delete all routes and next hops from RTM */
    IX_ERROR_CRT( ix_cc_rtmv4_purge(g_pIpv4Context->hRtm),
                 IX_CC_IPV4_ERROR_RTM,IX_ERROR_LEVEL_WARNING);

    /* Call RTM fini */
    IX_ERROR_CRT(ix_cc_rtmv4_fini(g_pIpv4Context->hRtm),
                 IX_CC_IPV4_ERROR_RTM,IX_ERROR_LEVEL_WARNING);

    return IX_SUCCESS;
}/* end _ix_cc_ipv4_terminate_rtm_services */



/**
 * NAME: _ix_cc_ipv4_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 none
 *
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 * 
 * IX_CC_IPV4_ERROR_CCI - error from CCI
 * 
 */

ix_error _ix_cc_ipv4_unregister_message_handler()
{
    /* Call CCI if CCI is enabled */

    #if defined(IX_EXCLUDE_CCI)
        IX_ERROR_CRT(ix_rm_message_handler_unregister(IX_CC_IPV4_MSG_INPUT),
                     IX_CC_IPV4_ERROR_CCI,
                     IX_ERROR_LEVEL_WARNING);
    #else
        IX_ERROR_CRT(ix_cci_cc_remove_message_handler(IX_CC_IPV4_MSG_INPUT),
                     IX_CC_IPV4_ERROR_CCI,
                     IX_ERROR_LEVEL_WARNING);
    #endif

    return IX_SUCCESS;
}/* end _ix_cc_ipv4_unregister_message_handler */



/**
 * NAME: _ix_cc_ipv4_unregister_cci_packet_handlers
 *
 * DESCRIPTION: This primitive will be used to unregister packet handler with CCI. 
 * 
 * @Param:  - IN none
 *
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 * 
 * IX_CC_IPV4_ERROR_CCI - error from CCI
 * 
 */

ix_error _ix_cc_ipv4_unregister_cci_packet_handlers()
{

#if !defined(IX_EXCLUDE_CCI)
    IX_ERROR_CRT(ix_cci_cc_remove_message_handler(IX_CC_IPV4_PKT_MICROBLOCK_HIGH_PRIORITY_INPUT),
                     IX_CC_IPV4_ERROR_CCI,
                     IX_ERROR_LEVEL_WARNING);
    

    IX_ERROR_CRT(ix_cci_cc_remove_packet_handler(IX_CC_IPV4_PKT_MICROBLOCK_LOW_PRIORITY_INPUT),
                     IX_CC_IPV4_ERROR_CCI,
                     IX_ERROR_LEVEL_WARNING);

    IX_ERROR_CRT(ix_cci_cc_remove_packet_handler(IX_CC_IPV4_PKT_STKDRV_INPUT),
                     IX_CC_IPV4_ERROR_CCI,
                     IX_ERROR_LEVEL_WARNING);

    IX_ERROR_CRT(ix_cci_cc_remove_packet_handler(IX_CC_IPV4_PKT_COMMON_INPUT),
                     IX_CC_IPV4_ERROR_CCI,
                     IX_ERROR_LEVEL_WARNING);
#endif

    return IX_SUCCESS;

}/* end _ix_cc_ipv4_unregister_cci_packet_handlers */


/**
 * NAME: _ix_cc_ipv4_unregister_rm_packet_handlers
 *
 * DESCRIPTION: This primitive will be used to unregister packet handler with 
 * resource manager
 * 
 * @Param:  - IN none
 *
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 * 
 * IX_CC_IPV4_ERROR_CCI - error from RM
 * 
 */

ix_error _ix_cc_ipv4_unregister_rm_packet_handlers()
{

    IX_ERROR_CRT(ix_rm_message_handler_unregister(IX_CC_IPV4_PKT_MICROBLOCK_HIGH_PRIORITY_INPUT),
                     IX_CC_IPV4_ERROR_CCI,
                     IX_ERROR_LEVEL_WARNING);

    IX_ERROR_CRT(ix_rm_packet_handler_unregister(IX_CC_IPV4_PKT_MICROBLOCK_LOW_PRIORITY_INPUT),
                     IX_CC_IPV4_ERROR_CCI,
                     IX_ERROR_LEVEL_WARNING);

    IX_ERROR_CRT(ix_rm_packet_handler_unregister(IX_CC_IPV4_PKT_STKDRV_INPUT),
                     IX_CC_IPV4_ERROR_CCI,
                     IX_ERROR_LEVEL_WARNING);


    IX_ERROR_CRT(ix_rm_packet_handler_unregister(IX_CC_IPV4_PKT_COMMON_INPUT),
                     IX_CC_IPV4_ERROR_CCI,
                     IX_ERROR_LEVEL_WARNING);
    return IX_SUCCESS;

}/* end _ix_cc_ipv4_unregister_rm_packet_handlers */



/**
 * NAME: _ix_cc_ipv4_unregister_packet_handlers
 *
 * DESCRIPTION: This primitive will be used to unregister packet handler 
 * with CCI/Resource manager
 *
 * @Param:  - IN none
 *
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 * 
 * IX_CC_IPV4_ERROR_CCI - error from CCI/RM
 * 
 */

ix_error _ix_cc_ipv4_unregister_packet_handlers()
{
 
    /* Call CCI if CCI is enabled */
    #if defined(IX_EXCLUDE_CCI)
        IX_ERROR_CR(_ix_cc_ipv4_unregister_rm_packet_handlers());
    #else
        IX_ERROR_CR(_ix_cc_ipv4_unregister_cci_packet_handlers());
    #endif

    return IX_SUCCESS;

}/* end _ix_cc_ipv4_unregister_packet_handlers */


/**
 * NAME: _ix_cc_ipv4_delete_event_handler
 *
 * DESCRIPTION: This primitive will be used to delete event handler.
 * User needs to implement this function in level0 system.
 *
 * @Param:  - IN arg_pEventId - id of ICMP event hanlder
 *
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 * 
 * IX_CC_ERROR_UNIMPL - not implemented.
 * 
 */

ix_error _ix_cc_ipv4_delete_event_handler(ix_ossl_thread_t arg_pEventId)
{


    return IX_ERROR_WARNING(IX_CC_ERROR_UNIMPL,("No Event Handler for Icmp\n"));
}/* end _ix_cc_ipv4_delete_event_handler */


/**
 * NAME: _ix_cc_ipv4_delete_icmp_event_handler
 *
 * DESCRIPTION: This primitive will be used to delete icmp event handler. 
 * It calls CCI delete event handler function to delete an event handler in level1
 * system and calls _ix_cc_ipv4_delete_event_handler in level 0 system
 * 
 * @Param:  - IN none
 *
 * @Param:  - OUT none
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 * 
 * IX_CC_IPV4_ERROR_CCI - error from delete event hanler
 * 
 */

ix_error _ix_cc_ipv4_delete_icmp_event_handler()
{
        
    #if defined(IX_EXCLUDE_CCI) /* compile time flag */
        IX_ERROR_CR(_ix_cc_ipv4_delete_event_handler(g_pIpv4Context->icmpThreadId));
    #else 
         IX_ERROR_CRT(ix_cci_cc_remove_event_handler(g_pIpv4Context->hIpv4Handle,
                                             g_pIpv4Context->hEventHandle),
                      IX_CC_IPV4_ERROR_CCI,
                      IX_ERROR_LEVEL_WARNING);
    #endif


    return IX_SUCCESS;
}/* end _ix_cc_ipv4_delete_icmp_event_handler */


/**
 * NAME: ix_cc_ipv4_fini
 *
 * DESCRIPTION: This primitive shall be called to terminate services from IPv4 forwarder 
 * component. This primitive frees memory allocated during initialization, shut down RTM, 
 * free all the created resources: delete 64 bit counter. If client claims for any services 
 * from IPv4 after calling this function, then the behavior is undefined.
 * 
 * @Param:  - IN arg_hCcHandle - handle to IPv4 Forwader core component
 *
 * @Param:  - IN arg_pContext - pointer to the control block memory allocated 
 * earlier in ix_cc_ipv4_init function. 
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 * 
 * IX_CC_IPV4_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_IPV4_ERROR _RTM - failure from RTM
 * IX_CC_IPV4_ERROR_CCI - failure from CCI
 * 
 */

ix_error ix_cc_ipv4_fini(ix_cc_handle arg_hCcHandle,
                         void* arg_pContext)
{

    /* Validate Parameters */
    if(arg_pContext == NULL)
    {
        return IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                            ("arg_pContext is null"));

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


    if((arg_hCcHandle != g_pIpv4Context->hIpv4Handle) ||
       (ix_cc_ipv4_context *)arg_pContext != g_pIpv4Context)
    {
        return IX_ERROR_WARNING(IX_CC_IPV4_ERROR_INVALID_INPUT_PARAM,
                            ("Invalid input Parameters"));
    }/* if(arg_hCcHandle != g_pIpv4Context->hIpv4Handle ||
       (ix_cc_ipv4_context *)arg_pContext != g_pIpv4Context) */ 
  
    /* Terminate RTM services*/
    IX_ERROR_CR(_ix_cc_ipv4_terminate_rtm_services());  

    /* Free memory for symbols */
    IX_ERROR_CR(_ix_cc_ipv4_free_symbols());   

    /* Delete 64 bit counter */
    IX_ERROR_CR(_ix_cc_ipv4_delete_64bit_counters());
    
    /* Unregister Message Handler */
    IX_ERROR_CR(_ix_cc_ipv4_unregister_message_handler());
  
    /* Unregister Packet Handler */
    IX_ERROR_CR(_ix_cc_ipv4_unregister_packet_handlers());
   
    /* Remove ICMP event handler */
    IX_ERROR_CR(_ix_cc_ipv4_delete_icmp_event_handler());
    
    /* Free mutex */
    IX_ERROR_CR(ix_ossl_mutex_fini(g_pIpv4Context->ipv4Mutex));

    /* Free IPv4 Context */ 
    ix_ossl_free(g_pIpv4Context);
        
    return IX_SUCCESS;

} /* end ix_cc_ipv4_fini */
