/**
 * ============================================================================
 * = 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, Release 6
 *
 * = FILENAME
 *      ix_cc_stkdrv.h
 *
 * = DESCRIPTION
 *      Header file for the Stack Driver CC Module.
 *
 * = AUTHOR
 *      Aaron Luk
 *      aaron.luk@intel.com
 *
 * = CHANGE HISTORY
 *       6/19/2002 - initial revision
 *
 * ============================================================================
 * $Id: ix_cc_stkdrv.h,v 1.47 2003/11/20 16:42:45 ktseng Exp $
 */
#if !defined(__IX_CC_STKDRV_H__)
#define __IX_CC_STKDRV_H__

#if defined(IX_PLATFORM_2401) || defined(IX_PLATFORM_2801)
/* Improvement
 * Cleanup in headers - don't include user space stdio.h, use <> when including
 * headers from global include paths.
 */
#include <ix_ossl.h>
#include <ix_rm.h>

#include <ix_cc_error.h>
#include <ix_cc.h>
#include <ix_cc_properties.h>
#include <cc/ix_cc_stkdrv_common.h>
#include <cc/ix_cc_stkdrv_pktclass.h>

#else /* IX_PLATFORM_2x01 */

#include "ix_cc_error.h"
#include <stdio.h>
#include "ix_ossl.h"
#include "ix_rm.h"
#include "ix_cc.h"
#include "ix_cc_properties.h"
#include "cc/ix_cc_stkdrv_common.h"
#include "cc/ix_cc_stkdrv_pktclass.h"

#endif /* IX_PLATFORM_2x01 */

#if defined(__cplusplus)
extern "C"
{
#endif /* end defined(__cplusplus) */

/**
 * Pre-processor symbol and macro definitions.
 */

/**
 * Special port ID that can be passed into ix_cc_stkdrv_async_get_property
 * to get properties for all ports.
 */
#define IX_CC_GET_ALL_PORTS -1


/* Property IDs used to get properties. */

/**
 * Used to get IPv4 or IPv6 address, subnet
 * mask, gateway, and broadcast for a
 * given port.
 */
#define IX_CC_GET_PROPERTY_INTERFACE_IPV4       0x00000001
#define IX_CC_GET_PROPERTY_INTERFACE_IPV6       0x00000002

/* Used to get MTU for a given port. */
#define IX_CC_GET_PROPERTY_MTU                  0x00000004

/**
 * Used to get physical interface status (up/down)
 * for a given port.
 */
#define IX_CC_GET_PROPERTY_PHYSICAL_IF_STATUS   0x00000008

/**
 * Used to get physical interface status (up/down)
 * for a given port.
 */
#define IX_CC_GET_PROPERTY_LINK_STATUS          0x00000010

/* Used to get MAC address for a given port. */
#define IX_CC_GET_PROPERTY_MAC_ADDR             0x00000020

/**
 * Used to get link speed, in megabits-per-second,
 * for a given port.
 */
#define IX_CC_GET_PROPERTY_LINK_SPEED           0x00000040

/**
 * Used to get media type (Fast Ethernet,
 * 1GB Ethernet, ATM, POS) for a given port.
 */
#define IX_CC_GET_PROPERTY_MEDIA_TYPE           0x00000080


#if defined(IX_INCLUDE_REGISTRY)
    #define REPOSITORY_PATH_REMOTE_SUPPORT_FLAG "System_Properties/REMOTE_STACK_FLAG"
#else
    /* local stack support by default. */
    #define IX_CC_STKDRV_REMOTE_SUPPORT_FLAG 0
#endif /* defined(IX_INCLUDE_REGISTRY) */

/**
 * MACRO NAME: _IX_CC_STKDRV_VIDD_CHECK_DUPLICATE_IPV4_ADDR
 *
 * DESCRIPTION: Checks if the IPv4 address is already added
 *
 * @Param:  - IN arg_pPhysicalIf - pointer to the port information
 *            on whose list the search is needed.
 * @Param:  - IN arg_ipv4Addr - The IPv4 address to be searched.
 * @Param:  - OUT arg_flag - 0 indicates that the IPv4 address
 *            is not present, 1 indicates that it is present.
 *
 * @Return:
 */
#define _IX_CC_STKDRV_VIDD_CHECK_DUPLICATE_IPV4_ADDR(                       \
                                          arg_pPhysicalIf,                  \
                                          arg_ipv4Addr,                     \
                                          arg_flag                          \
                                          )                                 \
{                                                                           \
    ix_cc_stkdrv_virtual_if* pTempVirtualIf;                                \
    do                                                                      \
    {                                                                       \
        flag = 0;                                                           \
        pTempVirtualIf = arg_pPhysicalIf->pPhysicalIfInfo->pVirtualIfs;     \
        /* Traverse the list of virtual IFs to find the virtual IF with the \
         * given IPv4 address */                                            \
        while(pTempVirtualIf != NULL)                                       \
        {                                                                   \
            if(pTempVirtualIf->ipProp.protocol.ipv4_prop.ipv4_address       \
                == arg_ipv4Addr)                                            \
            {                                                               \
                flag = 1;                                                   \
                break;                                                      \
            }                                                               \
            pTempVirtualIf = pTempVirtualIf->pNextVirtualIf;                \
        }                                                                   \
    }                                                                       \
    while(0);                                                               \
}

#if defined(IX_IPV6_SUPPORT)
/**
 * MACRO NAME: _IX_CC_STKDRV_VIDD_CHECK_DUPLICATE_IPV6_ADDR
 *
 * DESCRIPTION: Checks if the IPv6 address is already added
 *
 * @Param:  - IN arg_pPhysicalIf - pointer to the port information
 *            on whose list the search is needed.
 * @Param:  - IN arg_ipv6Addr - The IPv6 address to be searched.
 * @Param:  - OUT arg_flag - 0 indicates that the IPv6 address
 *            is not present, 1 indicates that it is present.
 *
 * @Return:
 */
#define _IX_CC_STKDRV_VIDD_CHECK_DUPLICATE_IPV6_ADDR(                       \
                                          arg_pPhysicalIf,                  \
                                          arg_ipv6Addr,                     \
                                          arg_flag                          \
                                          )                                 \
{                                                                           \
    ix_cc_stkdrv_virtual_if* pTempVirtualIf;                                \
    do                                                                      \
    {                                                                       \
        flag = 0;                                                           \
        pTempVirtualIf = arg_pPhysicalIf->pPhysicalIfInfo->pVirtualIfs;     \
        /* Traverse the list of virtual IFs to find the virtual IF with the \
         * given IPv6 address */                                            \
        while(pTempVirtualIf != NULL)                                       \
        {                                                                   \
            if (IX_128_BIT_BINARY_OPERATION_EQ                              \
                    (pTempVirtualIf->ipProp.protocol.ipv6_prop.ipv6_address.\
                     addr, arg_ipv6Addr))                                   \
            {                                                               \
                flag = 1;                                                   \
                break;                                                      \
            }                                                               \
            pTempVirtualIf = pTempVirtualIf->pNextVirtualIf;                \
        }                                                                   \
    }                                                                       \
    while(0);                                                               \
}
#endif

/**
 * Type definitions.
 */

/**
 * TYPENAME: ix_cc_stkdrv_ctrl
 * 
 * DESCRIPTION: The is the control block for the CC Module, which used as a context
 * in the Core Component Infrastructure APIs.
 *
 */
typedef struct ix_s_cc_stkdrv_ctrl
{
    /* list of all handlers */
    ix_cc_stkdrv_handler_module* pHandlerList;
    
    /* list of all FPs */
    ix_cc_stkdrv_fp_node* pFPList;

    /* control structure for filters */
    ix_cc_stkdrv_filter_ctrl* pFilterCtrl;
    
    /* handle to freelist of ix_buffers used to contain packets. */
    ix_buffer_free_list_handle hFreeList;

    /* flag indicating whether the stack driver interfaces to the remote stack. */
    ix_uint8 remoteSupportFlag;
} ix_cc_stkdrv_ctrl;


/**
 * TYPENAME: ix_cc_stkdrv_cb_get_num_ports
 * 
 * DESCRIPTION: Callback function for getting number of ports
 *              asynchronously.
 *
 * @Param:  - IN ix_error arg_Result - error code returned from the
 *          messaging operation.
 * @Param:  - IN void *arg_pContext - pointer to user context.
 * @Param:  - OUT ix_uint32* arg_pNumPorts - pointer to where the
 *          number of ports is returned.
 *
 * @Return: IX_SUCCESS, or an appropriate error code.
 *
 */
typedef ix_error (*ix_cc_stkdrv_cb_get_num_ports)(
                                                  ix_error arg_Result,
                                                  void *arg_pContext,
                                                  ix_uint32* arg_pNumPorts
                                                  );

/**
 * TYPENAME: ix_cc_stkdrv_cb_get_property
 * 
 * DESCRIPTION: Callback function for getting interface properties
 *              asynchronously.
 *
 * @Param:  - IN ix_error arg_Result - error code returned from the
 *          messaging operation.
 * @Param:  - IN void *arg_pContext - pointer to user context.
 * @Param:  - OUT ix_cc_properties* arg_pProperty - pointer to where the
 *          interface properties structures are returned, or a pointer
 *			to a contiguous block of memory containing an array
 *			of property structures if the client requested
 *			properties for all ports.
 *          This memory is only valid during this routine and
 *          must be copied into local memory.
 *
 * @Return: IX_SUCCESS, or an appropriate error code.
 *
 */
typedef ix_error (*ix_cc_stkdrv_cb_get_property)(
                                                 ix_error arg_Result,
                                                 void *arg_pContext,
                                                 ix_cc_properties* arg_pProperty
                                                 );

/**
 * TYPENAME: ix_cc_stkdrv_cb_register_comm_handler
 * 
 * DESCRIPTION: Callback function for getting interface properties
 *              asynchronously.
 *
 * @Param:  - IN ix_error arg_Result - error code returned from the
 *          messaging operation.
 * @Param:  - IN void* arg_pContext - pointer to user context.
 *
 * @Return: IX_SUCCESS, or an appropriate error code.
 *
 */
typedef ix_error (*ix_cc_stkdrv_cb_register_comm_handler)(
                                                          ix_error arg_Result,
                                                          void *arg_pContext
                                                          );

/**
 * TYPENAME: ix_cc_stkdrv_msg_id
 * 
 * DESCRIPTION: Message IDs used for sending messages to the Stack Driver.
 *
 */
typedef enum ix_e_cc_stkdrv_msg_id
{
    IX_CC_STKDRV_MSG_ID_FIRST = IX_CC_COMMON_MSG_ID_LAST,
    IX_CC_STKDRV_MSG_ID_GET_NUM_PORTS = IX_CC_STKDRV_MSG_ID_FIRST,
    IX_CC_STKDRV_MSG_ID_GET_PROPERTY,
    IX_CC_STKDRV_MSG_ID_SEND_HANDLER_MSG,
    IX_CC_STKDRV_MSG_ID_REGISTER_HANDLER,

    /* Message IDs specific to packet classification. */
    #if defined(IX_CC_STKDRV_PKT_CLASS)
        IX_CC_STKDRV_MSG_ID_ADD_FILTER,
        IX_CC_STKDRV_MSG_ID_REMOVE_FILTER,
        IX_CC_STKDRV_MSG_ID_REMOVE_ALL_FILTERS,
        IX_CC_STKDRV_MSG_ID_MODIFY_FILTER,
        IX_CC_STKDRV_MSG_ID_REGISTER_FILTER_TYPE,
        IX_CC_STKDRV_MSG_ID_UNREGISTER_FILTER_TYPE,
    #endif /* defined(IX_CC_STKDRV_PKT_CLASS) */

    IX_CC_STKDRV_MSG_ID_LAST,
} ix_cc_stkdrv_msg_id;

/**
 * Prototypes for interface functions.
 */

/**
 * NAME: ix_cc_stkdrv_init
 *
 * DESCRIPTION: Initializes the core component - creates stack driver CC
 * control structure, and makes function calls to initialize and register
 * communication handlers.  If packet classification is enabled, initializes
 * packet filters.
 * 
 * @Param:  - ix_cc_handle arg_hCC - handle to Stack Driver core component;
 *          this shall be used later to get other services from the core
 *          component infrastructure.
 * @Param:  - INOUT void **arg_ppContext - location where the pointer to the
 *          control block (ix_cc_stkdrv_ctrl) allocated by Stack Driver core
 *          component will be stored.  The control block is internal to the
 *          Stack Driver core component and it contains information about
 *          Stack Driver internal data structures, allocated memory and other
 *          relevant information. This pointer will be used later, to be passed
 *          into the ix_cc_stkdrv_fini function for freeing memory when the
 *          Stack Driver component is being destroyed.  On input, this pointer
 *          contains the location of the input context passed in by the caller.
 *
 * @Return: IX_SUCCESS
 *          IX_CC_ERROR_OOM_SYSTEM
 *          IX_CC_STKDRV_ERROR_HANDLER_INIT
 *          IX_CC_STKDRV_ERROR_CCI_ADD_HANDLER
 *          IX_CC_STKDRV_ERROR_RM_ADD_HANDLER
 */
ix_error ix_cc_stkdrv_init(
                           ix_cc_handle arg_hCC,
                           void **arg_ppContext
                           );

/**
 * NAME: ix_cc_stkdrv_fini
 *
 * DESCRIPTION: Termination function. Frees stack driver core component memory
 * and data structures.
 * 
 * @Param:  - IN ix_cc_handle arg_hCC - handle to the core component.
 * @Param:  - IN void* arg_pContext - pointer to the control block memory allocated
 *          earlier in ix_cc_stkdrv_init function.
 * @Return: IX_SUCCESS
 *          IX_CC_STKDRV_ERROR_CCI_REMOVE_HANDLER
 *          IX_CC_STKDRV_ERROR_RM_REMOVE_HANDLERI
 *          IX_CC_STKDRV_ERROR_HANDLER_FINI
 */
ix_error ix_cc_stkdrv_fini(
                           ix_cc_handle arg_hCC,
                           void *arg_pContext
                           );
/**
 * NAME: ix_cc_stkdrv_high_priority_pkt_handler
 *
 * DESCRIPTION: Packet processing function for high priority signaling packets.
 * Calls the internal function _ix_cc_stkdrv_process_pkt().
 * 
 * @Param:  - IN ix_buffer_handle arg_hDataToken - handle to a buffer which
 *          contains exception packets.
 * @Param:  - IN ix_uint32 arg_ExceptionCode - Exception code for the packet.
 *          Ignored in the Stack Driver.
 * @Param:  - IN void* arg_pComponentContext - pointer to Stack Driver core
 *          component context that will be passed to the core component when
 *          a packet arrives. This context was defined by the core component
 *          and passed to core components infrastructure through the
 *          ix_cc_stkdrv_init function.
 * @Return: IX_SUCCESS, or an appropriate error code on failure.
 */
ix_error ix_cc_stkdrv_high_priority_pkt_handler(
                                                ix_buffer_handle arg_hDataToken,
                                                ix_uint32 arg_ExceptionCode,
                                                void* arg_pComponentContext
                                                );


/**
 * NAME: ix_cc_stkdrv_low_priority_pkt_handler
 *
 * DESCRIPTION: Packet processing function for low priority data packets.
 * Calls the internal function _ix_cc_stkdrv_process_pkt().
 * 
 * @Param:  - IN ix_buffer_handle arg_hDataToken - handle to a buffer which
 *          contains exception packets.
 * @Param:  - IN ix_uint32 arg_ExceptionCode - Exception code for the packet.
 *          Ignored in the Stack Driver.
 * @Param:  - IN void* arg_pComponentContext - pointer to Stack Driver core
 *          component context that will be passed to the core component when
 *          a packet arrives. This context was defined by the core component
 *          and passed to core components infrastructure through the
 *          ix_cc_stkdrv_init function.
 * @Return: IX_SUCCESS, or an appropriate error code on failure.
 */
ix_error ix_cc_stkdrv_low_priority_pkt_handler(
                                               ix_buffer_handle arg_hDataToken,
                                               ix_uint32 arg_ExceptionCode,
                                               void* arg_pComponentContext
                                               );

/**
 * Define packet handler that sends packets directly to remote stacks only
 * if packet classification is not enabled.
 */
#if (!defined(IX_CC_STKDRV_PKT_CLASS) && defined(IX_CC_STKDRV_REMOTE_SUPPORT))
/**
 * NAME: ix_cc_stkdrv_pkt_to_remote_handler
 *
 * DESCRIPTION: This function sends all incoming packets to the Transport
 * Module without any classification.
 * 
 * @Param:  - IN ix_buffer_handle arg_hDataToken - handle to a buffer which
 *          contains exception packets from IPv4 Forwarder CC.
 * @Param:  - IN ix_uint32 arg_ExceptionCode - Exception code for the packet.
 *          Ignored in the Stack Driver.
 * @Param:  - IN void* arg_pComponentContext - pointer to Stack Driver core
 *          component context that will be passed to the core component when
 *          a packet arrives. This context was defined by the core component
 *          and passed to core components infrastructure through the
 *          ix_cc_stkdrv_init function.
 * @Return: IX_SUCCESS
 *          IX_CC_STKDRV_ERROR_HANDLER_RECV
 */
ix_error ix_cc_stkdrv_pkt_to_remote_handler (
                                             ix_buffer_handle arg_hDataToken,
                                             ix_uint32 arg_ExceptionCode,
                                             void* arg_pComponentContext
                                             );
#endif /* (!defined(IX_CC_STKDRV_PKT_CLASS) && defined(IX_CC_STKDRV_REMOTE_SUPPORT)) */


/**
 * NAME: ix_cc_stkdrv_msg_handler
 *
 * DESCRIPTION: Message processing function for the stack driver.  Handles
 *              port property updates, and requests to get the number of ports
 *              or port properties.
 * 
 * @Param:  - IN ix_buffer_handle arg_hDataToken - buffer handle embedding
 *          information for the message.
 * @Param:  - IN ix_uint32 arg_UserData - message type, possible values
 *          defined in ix_cc_stkdrv_msg_id.
 * @Param:  - IN void* arg_pComponentContext - pointer to Stack Driver core
 *          component context that will be passed to the core component when
 *          a message arrives. This context was defined by the core component
 *          and passed to core components infrastructure through the
 *          ix_cc_stkdrv_init function.
 * @Return: IX_SUCCESS
 *          IX_CC_ERROR_NULL
 *          IX_CC_ERROR_ENTRY_NOT_FOUND
 *          IX_CC_ERROR_OOM_SYSTEM
 *          IX_CC_STKDRV_ERROR_INVALID_BLADE_ID
 */
ix_error ix_cc_stkdrv_msg_handler(
                                  ix_buffer_handle arg_hDataToken,
                                  ix_uint32 arg_UserData,
                                  void* arg_pComponentContext
                                  );


/**
 * NAME: ix_cc_stkdrv_async_get_num_ports
 *
 * DESCRIPTION: This function is called to get the number of
 * ports configured on the Stack Driver.
 * 
 * @Param:  - IN ix_cc_stkdrv_cb_get_num_ports arg_pCallback - pointer to the
 *          client's callback function to be invoked once the message returns.
 * @Param:  - IN void* arg_pContext - pointer to client context.
 * @Return: IX_SUCCESS
 *          IX_CC_ERROR_OOM_SYSTEM
 */
ix_error ix_cc_stkdrv_async_get_num_ports(
                                         ix_cc_stkdrv_cb_get_num_ports arg_pCallback,
                                         void* arg_pContext
                                         );

/**
 * NAME: ix_cc_stkdrv_async_get_property
 *
 * DESCRIPTION: This function is called to get the interface
 *              properties of a specific port.
 * 
 * @Param:  - IN ix_cc_stkdrv_cb_get_property arg_pCallback - pointer to the
 *          client's callback function to be invoked once the message returns.
 * @Param:  - IN void* arg_pContext - pointer to client context.
 * @Param:  - IN ix_uint32 arg_propId - property IDs for the properties
 *          being requested.
 * @Param:  - IN ix_uint32 arg_portId - ID of port being queried. Use 
 *          IX_CC_GET_ALL_PORTS to get all port properties.
 * @Return: IX_SUCCESS
 *          IX_CC_ERROR_OOM_SYSTEM
 */
ix_error ix_cc_stkdrv_async_get_property(
                                        ix_cc_stkdrv_cb_get_property arg_pCallback,
                                        void* arg_pContext,
                                        ix_uint32 arg_propId,
                                        ix_uint32 arg_portId
                                        );

/**
 * NAME: ix_cc_stkdrv_async_send_handler_msg
 *
 * DESCRIPTION: Function used to send a message to a communication handler
 *              asynchronously.  This caller must be in the same address
 *              space as the communication handler to which it is trying
 *              to send a message.
 *
 * @Param:  - IN ix_cc_msghlp_callback arg_pCallback -
 *          pointer to the client's callback function to be invoked once
 *          the message returns.
 * @Param:  - IN void* arg_pContext - pointer to client context.
 * @Param:  - IN ix_cc_stkdrv_handler_id arg_handlerID - ID of the communication
 *          handler to which the message is to be delivered.
 * @Param:  - IN ix_uint32 arg_msgID - handler-specific message ID.
 * @Param:  - IN void* arg_pMsg - pointer to the message data.
 * @Param:  - IN ix_uint32 arg_msgSize - size of the message in bytes.
 *
 * @Return: IX_SUCCESS
 *          IX_CC_ERROR_NULL
 *          IX_CC_ERROR_OOM_SYSTEM
 */
ix_error ix_cc_stkdrv_async_send_handler_msg(
                                             ix_cc_msghlp_callback arg_pCallback,
                                             void* arg_pContext,
                                             ix_cc_stkdrv_handler_id arg_handlerID,
                                             ix_uint32 arg_msgID,
                                             void* arg_pMsg,
                                             ix_uint32 arg_msgSize
                                             );
                                             
/**
 * NAME: ix_cc_stkdrv_async_register_comm_handler
 *
 * DESCRIPTION: Function used to register a message to a communication handler
 *              asynchronously.  The comm handler must be in the same
 *              address space as the stack driver core component.
 *
 * @Param:  - IN ix_cc_stkdrv_cb_register_comm_handler arg_pCallback -
 *          pointer to the client's callback function to be invoked once
 *          the message returns.
 * @Param:  - IN void* arg_pContext - pointer to client context.
 * @Param:  - IN ix_cc_stkdrv_handler_id arg_handlerID - ID of the comm handler
 *          being registered.
 * @Param:  - IN void* arg_pInitContext - pointer to any user-defined context
 *          to be passed into the initialization routine.
 * @Param:  - IN ix_cc_stkdrv_handler_module_init_cb arg_initCB - callback function
 *          to initialize the comm handler.
 *
 * @Return: IX_SUCCESS
 *          IX_CC_ERROR_NULL
 *          IX_CC_ERROR_OOM_SYSTEM
 */
ix_error ix_cc_stkdrv_async_register_comm_handler(
                                                  ix_cc_stkdrv_cb_register_comm_handler arg_pCallback,
                                                  void* arg_pContext,
                                                  ix_cc_stkdrv_handler_id arg_handlerID,
                                                  void* arg_pInitContext,
                                                  ix_cc_stkdrv_handler_module_init_cb arg_initCB
                                                  );

/**
 * NAME: ix_cc_stkdrv_async_unregister_comm_handler
 *
 * DESCRIPTION: Function used to unregister a message to a communication handler
 *              asynchronously.  The comm handler must be in the same
 *              address space as the stack driver core component.
 *
 * @Param:  - IN ix_cc_stkdrv_cb_register_comm_handler arg_pCallback -
 *          pointer to the client's callback function to be invoked once
 *          the message returns.
 * @Param:  - IN void* arg_pContext - pointer to client context.
 * @Param:  - IN ix_cc_stkdrv_handler_id arg_handlerID - ID of the comm handler
 *          being unregistered.
 *
 * @Return: IX_SUCCESS
 *          IX_CC_ERROR_NULL
 *          IX_CC_ERROR_OOM_SYSTEM
 */
ix_error ix_cc_stkdrv_async_unregister_comm_handler(
                                                  ix_cc_stkdrv_cb_register_comm_handler arg_pCallback,
                                                  void* arg_pContext,
                                                  ix_cc_stkdrv_handler_id arg_handlerID
                                                  );
                                                  
/**
 * Exported variables.
 */

#if defined(__cplusplus)
}
#endif /* end defined(__cplusplus) */

#endif /* end !defined(__IX_CC_STKDRV_H__) */

