/**
 * ============================================================================
 * = 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 IXP2X00 Network Processor, Release 6
 *
 * = FILENAME
 *      ix_cc_eth_tx_msg_helpers.c
 *
 * = DESCRIPTION
 *      This file contains Async APIs and related 
 *      internal functions of Ethernet Tx core component.
 *
 *      11/25/2002 - Created.
 *
 * ============================================================================
 * $Id: ix_cc_eth_tx_msg_helpers.c,v 1.7 2003/02/13 17:36:34 ktseng Exp $
 */

/**
 * System defined include files required.
 */


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

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

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

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

#include "cc/ix_cc_eth_tx.h"
#include "cc/internal/ix_cc_eth_tx_int.h"

/* Message support library file */
#include "cc/ix_cc_msup.h"

/* device driver common includes */



/**
 * Static function prototypes
 */



/**
 * function definitions.
 */



/**
 * NAME: ix_cc_eth_tx_async_get_statistics_info
 * 
 * DESCRIPTION: This function retrieves a statistics counter value of 
 *              Ethernet Tx CC.
 * 
 * @Param: arg_pMgInfoContext - IN: pointer to interface statistics information structure 
 *                                  which contains type of statistics,
 *                                  port number, and user context
 * @Param: arg_Callback - IN: User callback function pointer
 * 
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
ix_error ix_cc_eth_tx_async_get_statistics_info(
    ix_cc_eth_tx_statistics_info_context *arg_pMgInfoContext,
    ix_cc_eth_tx_cb_get_statistics_info arg_Callback)
{
    ix_cc_eth_tx_cb_entry *pCbEntry;
    ix_error err = IX_SUCCESS;

    /* Check NULL pointer argument */
    if (arg_pMgInfoContext == NULL)
    {
        return(IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("NULL management context argument")));
    }
    /* Check NULL pointer argument */
    if (arg_Callback == NULL)
    {
        return(IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("NULL callback argument")));
    }
    /* Check the range of the counter type  */
    if (arg_pMgInfoContext->entity >= IX_CC_ETH_TX_COUNTER_LAST)
    {
        return(IX_ERROR_WARNING(IX_CC_ERROR_RANGE, 
                                ("Invalid statistics counter type.")));
    }
    pCbEntry = (ix_cc_eth_tx_cb_entry *)ix_ossl_malloc(sizeof(ix_cc_eth_tx_cb_entry));
    if(pCbEntry == NULL)
    {
        return(IX_ERROR_WARNING(IX_CC_ERROR_OOM_SYSTEM,
                                ("No memory for callback context")));
    }/* end if no space for callback entry */
    /* Store the user callback and context into the pCbEntry */
    pCbEntry->pUserCtx = arg_pMgInfoContext->pUserContext;
    pCbEntry->pUserCb = (void *)arg_Callback;;
    /* Call msup to send the message */
    IX_ERROR_CT(ix_cc_msup_send_async_msg(IX_CC_ETH_TX_MSG_INPUT,
                                          _ix_cc_eth_tx_cb_get_statistics_info,
                                          (void *)pCbEntry,
                                          IX_CC_ETH_TX_MSG_GET_STATISTICS_INFO,
                                          (void *)arg_pMgInfoContext,
                                          sizeof(ix_cc_eth_tx_statistics_info_context)),
                err,
                IX_CC_ETH_TX_ERROR_MSUP_SEND_MSG, 
                IX_ERROR_LEVEL_WARNING);
    if (err != IX_SUCCESS)
    {
        ix_ossl_free(pCbEntry);
    }
    return err;
} /* ix_cc_eth_tx_async_get_statistics_info */


/**
 * NAME: ix_cc_eth_tx_async_get_interface_state
 * 
 * DESCRIPTION: This function retrieves interface state of Ethernet driver.
 * 
 * @Param: arg_pStateContext - IN: pointer to interface state information structure 
 *                                  which contains port number and user context
 * @Param: arg_Callback - IN: User callback function pointer
 * 
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
ix_error ix_cc_eth_tx_async_get_interface_state(
    ix_cc_eth_tx_if_state_context *arg_pStateContext,
    ix_cc_eth_tx_cb_get_interface_state arg_Callback)
{
    ix_cc_eth_tx_cb_entry *pCbEntry;
    ix_error err = IX_SUCCESS;

    /* Check NULL pointer argument */
    if (arg_pStateContext == NULL)
    {
        return(IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("NULL state context argument")));
    }
    /* Check NULL pointer argument */
    if (arg_Callback == NULL)
    {
        return(IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("NULL callback argument")));
    }
    pCbEntry = (ix_cc_eth_tx_cb_entry *)ix_ossl_malloc(sizeof(ix_cc_eth_tx_cb_entry));
    if(pCbEntry == NULL)
    {
        return(IX_ERROR_WARNING(IX_CC_ERROR_OOM,
                                ("No memory for callback context")));
    }/* end if no space for callback entry */
    /* Store the user callback and context into the pCbEntry */
    pCbEntry->pUserCtx = arg_pStateContext->pUserContext;
    pCbEntry->pUserCb = (void *)arg_Callback;;
    /* Call msup to send the message */
    IX_ERROR_CT(ix_cc_msup_send_async_msg(IX_CC_ETH_TX_MSG_INPUT,
                                          _ix_cc_eth_tx_cb_get_interface_state,
                                          (void *)pCbEntry,
                                          IX_CC_ETH_TX_MSG_GET_INTERFACE_STATE,
                                          (void *)arg_pStateContext,
                                          sizeof(ix_cc_eth_tx_if_state_context)),
                err,
                IX_CC_ETH_TX_ERROR_MSUP_SEND_MSG, 
                IX_ERROR_LEVEL_WARNING);
    if (err != IX_SUCCESS)
    {
        ix_ossl_free(pCbEntry);
    }
    return err;
} /* ix_cc_eth_tx_async_get_interface_state */


/**
 * NAME: ix_cc_eth_tx_async_create_arp_entry
 * 
 * DESCRIPTION: This function creates an entry in arp library.
 * 
 * @Param: arg_pArpInfo - IN: pointer to arp information structure 
 *                                  which contains l2Index,
 *                                  next hop ip address, output port and
 *                                  l2 address
 * @Param: arg_Callback - IN: User callback function pointer
 *
 * @Param: arg_pContext - IN: User Context
 * 
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
ix_error ix_cc_eth_tx_async_create_arp_entry(
    ix_cc_eth_tx_next_hop_info *arg_pArpInfo,
    ix_cc_eth_tx_cb_create_arp_entry arg_Callback,
    void *arg_pContext)
{
    ix_cc_eth_tx_cb_entry *pCbEntry;
    ix_error err = IX_SUCCESS;

    /* Check NULL pointer argument */
    if (arg_pArpInfo == NULL)
    {
        return(IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("NULL arp info argument")));
    }
    /* Check NULL pointer argument */
    if (arg_Callback == NULL)
    {
        return(IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("NULL callback argument")));
    }
    pCbEntry = (ix_cc_eth_tx_cb_entry *)ix_ossl_malloc(sizeof(ix_cc_eth_tx_cb_entry));
    if(pCbEntry == NULL)
    {
        return(IX_ERROR_WARNING(IX_CC_ERROR_OOM,
                                ("No memory for callback context")));
    }/* end if no space for callback entry */
    /* Store the user callback and context into the pCbEntry */
    pCbEntry->pUserCtx = arg_pContext;
    pCbEntry->pUserCb = (void *)arg_Callback;;
    /* Call msup to send the message */
    IX_ERROR_CT(ix_cc_msup_send_async_msg(IX_CC_ETH_TX_MSG_INPUT,
                                          _ix_cc_eth_tx_cb_arp,
                                          (void *)pCbEntry,
                                          IX_CC_ETH_TX_MSG_CREATE_ARP_ENTRY,
                                          (void *)arg_pArpInfo,
                                          sizeof(ix_cc_eth_tx_next_hop_info)),
                err,
                IX_CC_ETH_TX_ERROR_MSUP_SEND_MSG, 
                IX_ERROR_LEVEL_WARNING);
    if (err != IX_SUCCESS)
    {
        ix_ossl_free(pCbEntry);
    }
    return err;
} /* ix_cc_eth_tx_async_create_arp_entry */



/**
 * NAME: ix_cc_eth_tx_async_add_arp_entry
 * 
 * DESCRIPTION: This function add an entry in arp library.(static)
 * 
 * @Param: arg_pArpInfo - IN: pointer to arp information structure 
 *                                  which contains l2Index,
 *                                  next hop ip address, output port and
 *                                  l2 address
 * @Param: arg_Callback - IN: User callback function pointer
 *
 * @Param: arg_pContext - IN: User Context
 * 
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
ix_error ix_cc_eth_tx_async_add_arp_entry(
    ix_cc_eth_tx_next_hop_info *arg_pArpInfo,
    ix_cc_eth_tx_cb_add_arp_entry arg_Callback,
    void *arg_pContext)
{
    ix_cc_eth_tx_cb_entry *pCbEntry;
    ix_error err = IX_SUCCESS;

    /* Check NULL pointer argument */
    if (arg_pArpInfo == NULL)
    {
        return(IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("NULL arp info argument")));
    }
    /* Check NULL pointer argument */
    if (arg_Callback == NULL)
    {
        return(IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("NULL callback argument")));
    }
    pCbEntry = (ix_cc_eth_tx_cb_entry *)ix_ossl_malloc(sizeof(ix_cc_eth_tx_cb_entry));
    if(pCbEntry == NULL)
    {
        return(IX_ERROR_WARNING(IX_CC_ERROR_OOM,
                                ("No memory for callback context")));
    }/* end if no space for callback entry */
    /* Store the user callback and context into the pCbEntry */
    pCbEntry->pUserCtx = arg_pContext;
    pCbEntry->pUserCb = (void *)arg_Callback;;
    /* Call msup to send the message */
    IX_ERROR_CT(ix_cc_msup_send_async_msg(IX_CC_ETH_TX_MSG_INPUT,
                                          _ix_cc_eth_tx_cb_arp,
                                          (void *)pCbEntry,
                                          IX_CC_ETH_TX_MSG_ADD_ARP_ENTRY,
                                          (void *)arg_pArpInfo,
                                          sizeof(ix_cc_eth_tx_next_hop_info)),
                err,
                IX_CC_ETH_TX_ERROR_MSUP_SEND_MSG, 
                IX_ERROR_LEVEL_WARNING);
    if (err != IX_SUCCESS)
    {
        ix_ossl_free(pCbEntry);
    }
    return err;
} /* ix_cc_eth_tx_async_add_arp_entry */

/**
 * NAME: ix_cc_eth_tx_async_del_arp_entry
 * 
 * DESCRIPTION: This function deletes an entry in arp library.
 * 
 * @Param: arg_L2Index - IN: L2 index used to search for the entry to be removed
 * @Param: arg_Callback - IN: User callback function pointer
 * @Param: arg_pContext - IN: User Context 
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
ix_error ix_cc_eth_tx_async_del_arp_entry(
    ix_uint32 arg_L2Index,
    ix_cc_eth_tx_cb_del_arp_entry arg_Callback,
    void *arg_pContext)
{
    ix_cc_eth_tx_cb_entry *pCbEntry;
    ix_error err = IX_SUCCESS;
    /* Check NULL pointer argument */
    if (arg_Callback == NULL)
    {
        return(IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("NULL callback argument")));
    }
    pCbEntry = (ix_cc_eth_tx_cb_entry *)ix_ossl_malloc(sizeof(ix_cc_eth_tx_cb_entry));
    if(pCbEntry == NULL)
    {
        return(IX_ERROR_WARNING(IX_CC_ERROR_OOM,
                                ("No memory for callback context")));
    }/* end if no space for callback entry */
    /* Store the user callback and context into the pCbEntry */
    pCbEntry->pUserCtx = arg_pContext;
    pCbEntry->pUserCb = (void *)arg_Callback;;
    /* Call msup to send the message */
    IX_ERROR_CT(ix_cc_msup_send_async_msg(IX_CC_ETH_TX_MSG_INPUT,
                                          _ix_cc_eth_tx_cb_arp,
                                          (void *)pCbEntry,
                                          IX_CC_ETH_TX_MSG_DEL_ARP_ENTRY,
                                          (void *)&arg_L2Index,
                                          sizeof(ix_uint32)),
                err,
                IX_CC_ETH_TX_ERROR_MSUP_SEND_MSG, 
                IX_ERROR_LEVEL_WARNING);
    if (err != IX_SUCCESS)
    {
        ix_ossl_free(pCbEntry);
    }
    return err;
} /* ix_cc_eth_tx_async_del_arp_entry */


/**
 * NAME: ix_cc_eth_tx_async_purge_arp_cache
 * 
 * DESCRIPTION: This function purges entries of arp cache
 * 
 * @Param: none
 *
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
ix_error ix_cc_eth_tx_async_purge_arp_cache()
{
    /* Call msup to send the fire and forget message */
    IX_ERROR_CRT(ix_cc_msup_send_msg(IX_CC_ETH_TX_MSG_INPUT,
                                    IX_CC_ETH_TX_MSG_PURGE_ARP_CACHE,
                                    NULL,
                                    0),
                IX_CC_ETH_TX_ERROR_MSUP_SEND_MSG, 
                IX_ERROR_LEVEL_WARNING);
    return IX_SUCCESS;
} /* ix_cc_eth_tx_async_purge_arp_cache */



/**
 * NAME: ix_cc_eth_tx_async_dump_arp_cache
 * 
 * DESCRIPTION: This function dumps entries of arp cache
 * 
 * 
 * @Param: none
 *
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
ix_error ix_cc_eth_tx_async_dump_arp_cache()
{
    /* Call msup to send the fire and forget message */
    IX_ERROR_CRT(ix_cc_msup_send_msg(IX_CC_ETH_TX_MSG_INPUT,
                                    IX_CC_ETH_TX_MSG_DUMP_ARP_CACHE,
                                    NULL,
                                    0),
                IX_CC_ETH_TX_ERROR_MSUP_SEND_MSG, 
                IX_ERROR_LEVEL_WARNING);
    return IX_SUCCESS;
} /* ix_cc_eth_tx_async_dump_arp_cache */


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

/**
 * NAME: _ix_cc_eth_tx_cb_get_statistics_info
 * 
 * DESCRIPTION: This function is an internal callback for the async 
 *              messaging API, ix_cc_eth_tx_async_get_statistics_info().
 * 
 * @Param: arg_Result - IN : result of get_statistics_info library call
 * @Param: arg_pContext - IN : User provided context, ie, ix_cc_eth_tx_cb_entry
 * @Param: arg_Msg - IN : pointer to the return message
 * @Param: arg_MsgLen - IN : length of the return message
 * 
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
ix_error _ix_cc_eth_tx_cb_get_statistics_info(
    ix_error arg_Result,
    void *arg_pContext,
    void *arg_Msg,
    ix_uint32 arg_MsgLen)
{

    ix_cc_eth_tx_cb_get_statistics_info pUserCb;
    void *pUserCtx;

    /* Retrieve the user callback and context from the context pointer */
    pUserCb = ((ix_cc_eth_tx_cb_entry *)arg_pContext)->pUserCb;
    pUserCtx = ((ix_cc_eth_tx_cb_entry *)arg_pContext)->pUserCtx;    

    /* Free the callback context entry */
    ix_ossl_free(arg_pContext);

    /* Invoke the user callback to pass back the result and data */
    if(pUserCb != NULL)
    {
        IX_ERROR_CR((pUserCb)(arg_Result,pUserCtx,(ix_uint64 *)arg_Msg,arg_MsgLen));
  
    }/* end if user callback */          

    return IX_SUCCESS;
} /* _ix_cc_eth_tx_cb_get_statistics_info */


/**
 * NAME: _ix_cc_eth_tx_cb_get_interface_state
 * 
 * DESCRIPTION: This function is an internal callback for the async 
 *              messaging API, ix_cc_eth_tx_async_get_interface_state().
 * 
 * @Param: arg_Result - IN : result of interface_state library call
 * @Param: arg_pContext - IN : User provided context, ie, ix_cc_eth_tx_cb_entry
 * @Param: arg_Msg - IN : pointer to the return message
 * @Param: arg_MsgLen - IN : length of the return message
 * 
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
ix_error _ix_cc_eth_tx_cb_get_interface_state(
    ix_error arg_Result,
    void *arg_pContext,
    void *arg_Msg,
    ix_uint32 arg_MsgLen)
{

    ix_cc_eth_tx_cb_get_interface_state pUserCb;
    void *pUserCtx;

    /* Retrieve the user callback and context from the context pointer */
    pUserCb = ((ix_cc_eth_tx_cb_entry *)arg_pContext)->pUserCb;
    pUserCtx = ((ix_cc_eth_tx_cb_entry *)arg_pContext)->pUserCtx;    
    /* Free the callback context entry */
    ix_ossl_free(arg_pContext);

    /* Invoke the user callback to pass back the result and data */
    if(pUserCb != NULL)
    {
        IX_ERROR_CR((pUserCb)(arg_Result,pUserCtx,(ix_cc_eth_tx_if_state *)arg_Msg));
    }/* end if user callback */          

    return IX_SUCCESS;
} /* _ix_cc_eth_tx_cb_get_interface_state */



/**
 * NAME: _ix_cc_eth_tx_cb_arp
 * 
 * DESCRIPTION: This function is an internal callback for the async 
 *              messaging API for, ix_cc_eth_tx_create/add/del_arp_entry
 * 
 * @Param: arg_Result - IN : result of ix_cc_eth_tx_create/del/arp_arp_entry library call
 * @Param: arg_pContext - IN : User provided context, ie, ix_cc_eth_tx_cb_entry
 * @Param: arg_Msg - IN : pointer to the return message
 * @Param: arg_MsgLen - IN : length of the return message
 * 
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
ix_error _ix_cc_eth_tx_cb_arp(
    ix_error arg_Result,
    void *arg_pContext,
    void *arg_Msg,
    ix_uint32 arg_MsgLen)
{

    ix_cc_eth_tx_cb_create_arp_entry pUserCb;
    void *pUserCtx;

    /* Retrieve the user callback and context from the context pointer */
    pUserCb = ((ix_cc_eth_tx_cb_entry *)arg_pContext)->pUserCb;
    pUserCtx = ((ix_cc_eth_tx_cb_entry *)arg_pContext)->pUserCtx;    
    /* Free the callback context entry */
    ix_ossl_free(arg_pContext);

    /* Invoke the user callback to pass back the result and data */
    if(pUserCb != NULL)
    {
        IX_ERROR_CR((pUserCb)(arg_Result,pUserCtx));
    }/* end if user callback */          

    return IX_SUCCESS;
} /* _ix_cc_eth_tx_cb_arp */
