/**
 * ============================================================================
 * = 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_hdlr.c
 *
 * = DESCRIPTION
 *      This file defines message handler and property handler routines.
 *
 *      11/25/2002 - Created.
 *
 * ============================================================================
 * $Id: ix_cc_eth_tx_msg_hdlr.c,v 1.7 2003/02/05 02:25:28 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"

#include "cc/ix_cc_msup.h"


/**
 * NAME: ix_cc_eth_tx_msg_handler
 * 
 * DESCRIPTION: This function is the message handler routine for
 *              Ethernet Tx CC.
 * @Param: arg_Msg - IN: buffer handle that contains message-specific 
 *                       information embedded.
 * @Param: arg_UserData - IN: message type. 
 * @Param: arg_pContext - IN: pointer to the component context allocated
 *                            in the component's init function. 
 * 
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */  
ix_error ix_cc_eth_tx_msg_handler(
    ix_buffer_handle arg_hMsg,  
    ix_uint32 arg_UserData,
    void* arg_pContext)
{
    ix_error err1 = IX_SUCCESS;
    ix_error err2 = IX_SUCCESS;
    void *pContext = NULL;
    void *pMsgData = NULL;

     /* Validate arg_pMsg */
    if(arg_hMsg == IX_NULL_HANDLE)
    {
        return IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                   ("arg_hMsg is NULL"));
    }/* end if invalid arg_hMsg */

     /* Validate arg_pContext */
    if(arg_pContext == NULL)
    {
        ix_rm_buffer_free_chain(arg_hMsg);
        return IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                   ("arg_pContext is NULL"));
    }/* end if invalid arg_pContext */

    /* Extract message data from buffer */
    err1 = IX_MSUP_EXTRACT_MSG(arg_hMsg,&pMsgData,&pContext);
    if(err1 != IX_SUCCESS)
    {
        ix_rm_buffer_free_chain(arg_hMsg);
        return err1;
    }/* end if  */

    if((arg_UserData != IX_CC_ETH_TX_MSG_PURGE_ARP_CACHE) &&
       (arg_UserData != IX_CC_ETH_TX_MSG_DUMP_ARP_CACHE))
    {
        if(pMsgData == NULL)
        {
            IX_ERROR_CRT(ix_rm_buffer_free_chain(arg_hMsg),
                         IX_CC_ETH_TX_ERROR_RM_FREE_BUF,
                         IX_ERROR_LEVEL_WARNING);
            return IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                      ("Invalid Buffer"));
        }/* end if no message data from buffer */
    }/* end if */

   /* Check for eth TX messages */
    switch(arg_UserData)
    {
        case IX_CC_ETH_TX_MSG_GET_STATISTICS_INFO:
        /**
         * the following message is not mentioned in HLD,
         * only used for internal needs
         */ 
        case IX_CC_ETH_RX_MSG_GET_STATISTICS_INFO:
        {
            ix_uint32 dataBufferSize = 1;
            ix_cc_eth_tx_statistics_info_context *pMgInfoContext;
            ix_cc_eth_tx_statistics_info_data buffer;
            pMgInfoContext = (ix_cc_eth_tx_statistics_info_context*)pMsgData;
            /* calculate the buffer size */
            switch(pMgInfoContext->entity)
            {
                case IX_CC_ETH_TX_ALL_DRIVER_COUNTERS:
                    dataBufferSize = IX_CC_ETH_TX_NUM_DRIVER_COUNTERS_PER_PORT;
                    break;
                case IX_CC_ETH_RX_ALL_DRIVER_COUNTERS:
                    dataBufferSize = IX_CC_ETH_RX_NUM_DRIVER_COUNTERS_PER_PORT;
                    break;
#ifdef MICROBLOCK_COUNTERS
                case IX_CC_ETH_TX_ALL_UBLK_COUNTERS:
                    dataBufferSize = IX_CC_ETH_TX_NUM_UBLK_COUNTERS_PER_PORT;
                    break;
#endif
                default:
                    dataBufferSize = 1; /* 1 entry of type ix_uint64 = 8 bytes */
                    break;
            }/* end if buffer size calculation */
            {
            ix_uint64 dataBuffer[dataBufferSize];
            buffer.dataLength = sizeof(dataBuffer);
            buffer.pDataBuffer = (void *)dataBuffer;            
            /* Invoke the corresponding library API */
            err1 = ix_cc_eth_tx_get_statistics_info(pMgInfoContext->entity,
                                                   pMgInfoContext->index,
                                                   &buffer,
                                                   arg_pContext);

            /* Send back the result */
            IX_ERROR_CT(ix_cc_msup_send_reply_msg(pContext,
                                                  (void *)dataBuffer, 
                                                  sizeof(dataBuffer),
                                                  err1),
                        err2, 
                        IX_CC_ETH_TX_ERROR_MSUP_SEND_REPLY, 
                        IX_ERROR_LEVEL_WARNING);
            }       
        }/* end case get tx statistics */
        break;
        case IX_CC_ETH_TX_MSG_GET_INTERFACE_STATE:
        {
            ix_uint32 portId;
            ix_cc_eth_tx_if_state ifState;

            /* Retrieve embedded information */
            portId = ((ix_cc_eth_tx_if_state_context *)pMsgData)->portId;
            /* Invoke the corresponding library API */
            err1 = ix_cc_eth_tx_get_interface_state(portId,
                                                    &ifState,
                                                    arg_pContext);
            /* Send back the result */
            IX_ERROR_CT(ix_cc_msup_send_reply_msg(pContext,
                                                  (void *)&ifState, 
                                                  sizeof(ix_cc_eth_tx_if_state),
                                                  err1),
	                err2,
                        IX_CC_ETH_TX_ERROR_MSUP_SEND_REPLY, 
                        IX_ERROR_LEVEL_WARNING);

            break;
        }/* end case get interface state */
        case IX_CC_ETH_TX_MSG_CREATE_ARP_ENTRY:
        {
            ix_cc_eth_tx_next_hop_info *pArpInfo;
            pArpInfo = (ix_cc_eth_tx_next_hop_info *)pMsgData;
            /* Invoke the corresponding library API */
            err1 = ix_cc_eth_tx_create_arp_entry(pArpInfo,
                                                 arg_pContext);
            /* Send back the result */
            IX_ERROR_CT(ix_cc_msup_send_reply_msg(pContext,
                                                  NULL, 
                                                  0,
                                                  err1),
	                err2,
                        IX_CC_ETH_TX_ERROR_MSUP_SEND_REPLY, 
                        IX_ERROR_LEVEL_WARNING);
            break;
        }
        case IX_CC_ETH_TX_MSG_ADD_ARP_ENTRY:
        {
            ix_cc_eth_tx_next_hop_info *pArpInfo;
            pArpInfo = (ix_cc_eth_tx_next_hop_info *)pMsgData;
            /* Invoke the corresponding library API */
            err1 = ix_cc_eth_tx_add_arp_entry(pArpInfo,
                                              arg_pContext);
            /* Send back the result */
            IX_ERROR_CT(ix_cc_msup_send_reply_msg(pContext,
                                                  NULL, 
                                                  0,
                                                  err1),
	                err2,
                        IX_CC_ETH_TX_ERROR_MSUP_SEND_REPLY, 
                        IX_ERROR_LEVEL_WARNING);
            break;
        }
        case IX_CC_ETH_TX_MSG_DEL_ARP_ENTRY:
        {
            ix_uint32 *pData;
            pData = (ix_uint32 *)pMsgData;
            /* Invoke the corresponding library API */
            err1 = ix_cc_eth_tx_del_arp_entry(*pData,
                                              arg_pContext);
            /* Send back the result */
            IX_ERROR_CT(ix_cc_msup_send_reply_msg(pContext,
                                                  NULL, 
                                                  0,
                                                  err1),
	                err2,
                        IX_CC_ETH_TX_ERROR_MSUP_SEND_REPLY, 
                        IX_ERROR_LEVEL_WARNING);
            break;
        }
        case IX_CC_ETH_TX_MSG_PURGE_ARP_CACHE:
            /* Invoke the corresponding library API */
            err1 = ix_cc_eth_tx_purge_arp_entry(arg_pContext);
            break;   
        case IX_CC_ETH_TX_MSG_DUMP_ARP_CACHE:
           /* Invoke the corresponding library API */
            err1 = ix_cc_eth_tx_dump_arp_entry(arg_pContext);
            break;
        default:
            err1 = IX_ERROR_WARNING(IX_CC_ERROR_UNDEFINED_MSG, 
                                    ("Undefined message type"));
            break; 
    }/* end switch message type*/


    ix_rm_buffer_free_chain(arg_hMsg);

    /* Always return the first error encountered */
    if (err1 != IX_SUCCESS)
    {
        /* Ignore the return code from ix_cc_msup_send_reply_msg. 
         * Just return the first error
         */
        return err1;
    }

    return err2;
} /* ix_cc_eth_tx_msg_handler */



/**
 * NAME: ix_cc_eth_tx_property_msg_handler
 * 
 * DESCRIPTION: This function is the property message handler routine for
 *              ETH Tx CC.
 * 
 * @Param: arg_hMsg - IN: buffer handle that contains message-specific 
 *                       information embedded.
 * @Param: arg_UserData - IN: message type. 
 * @Param: arg_pContext - IN: pointer to the component context allocated
 *                            in the component's init function. 
 * 
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
ix_error ix_cc_eth_tx_property_msg_handler(
    ix_buffer_handle arg_hMsg, 
    ix_uint32 arg_UserData,
    void *arg_pContext)
{
 
    ix_cc_properties_msg *pPropMsg;
    ix_error err1 = IX_SUCCESS;
    void *pContext;

    /* Check whether arg_pContext is invalid */
    if (NULL == arg_pContext)
    {
        /* Free the ix_buffer. Ignore the return code from rm */
        ix_rm_buffer_free_chain(arg_hMsg);
   
        return(IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("NULL argument: arg_pContext")));
    }
    /* Extract message data from buffer */
    err1 = IX_MSUP_EXTRACT_MSG(arg_hMsg,(void **)&pPropMsg,&pContext);
    if(err1 != IX_SUCCESS)
    {
        ix_rm_buffer_free_chain(arg_hMsg);
        return err1;
    }/* end if  */


    if (pPropMsg == NULL)
    {
        /* Free the ix_buffer. Ignore the return code from rm */
        ix_rm_buffer_free_chain(arg_hMsg);
   
        return(IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("null property message")));
    }

    /* Make sure the blade id is our local blade id */
    if (pPropMsg->propData.blade_id != ((ix_cc_eth_tx_ctl_blk *)arg_pContext)->localBladeId)
    {
        /* Free the ix_buffer. Ignore the return code from rm */
        ix_rm_buffer_free_chain(arg_hMsg);

        return(IX_ERROR_WARNING(IX_CC_ETH_TX_ERROR_INVALID_BLADE_ID,
                                ("Blade id received does not match with local blade id.")));
    }

    /* Process the message */
    switch(arg_UserData)
    {
        case IX_CC_COMMON_MSG_ID_PROP_UPDATE:
        {
            /* Invoke the corresponding library API */
            IX_ERROR_C(ix_cc_eth_tx_set_property(pPropMsg->propID, 
                                                     &(pPropMsg->propData),
                                                     arg_pContext),
	               err1);
            break;
        }
        default :
            err1 = IX_ERROR_WARNING(IX_CC_ERROR_UNDEFINED_MSG, 
                                    ("Undefined message type"));
            break;
    }

    /* Free the ix_buffer */
    ix_rm_buffer_free_chain(arg_hMsg);

    return err1;
} /* ix_cc_eth_tx_property_msg_handler */
