/**
 * ============================================================================
 * = 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.X for the IXP2X00 Network Processor
 *
 * = FILENAME
 *      ix_cc_eth_tx_init.c
 *
 * = DESCRIPTION
 *      This file defines Ethernet Tx init routines.
 *
 * = CHANGE HISTORY
 *      11/25/2002 - Created.
 *
 * ============================================================================
 * $Id: ix_cc_eth_tx_init.c,v 1.50 2003/12/12 20:28:19 ttschlue Exp $
 */

/**
 * System defined include files required.
 */
#include <ix_ossl.h>
#include <ix_rm.h>

#ifndef IX_EXCLUDE_CCI
#include <ix_cci.h>
#endif
#include <cc/ix_cc_msup.h>

#include <ix_cc_error.h>
#include <ix_error.h>
#include <ix_cc.h>
#include <bindings.h>
#include <ix_cc_properties.h>

/**
 * User defined include files required.
 */
#include "cc/ix_cc_eth_tx.h"
#include "cc/internal/ix_cc_eth_tx_int.h"


#include "cc/ix_cc_arp.h"
#include "cc/ix_cc_l2tm.h"

/* ethernet driver files */
#if (defined IX_PLATFORM_2401) || (defined IX_PLATFORM_2801)
#if (defined USE_HW_CONFIG) || (defined USE_BB_DRV_CONFIG)
/* extern definition for HW_CONFIG information provided in xml config file */
ix_uint32 hwConfigEthPortMask;/* ETH Port Mask */
ix_uint32 hwConfigEthMode[IX_CC_ETH_TX_MAX_NUM_PORTS]; /* ETH Port configuration mode value */
#endif /* USE_HW_CONFIG || USE_BB_DRV_CONFIG */
#endif /* IX_PLATFORM_2x01 */


#if (_IX_BOARD_TYPE_ == _IX_IXDP2401_) || (_IX_BOARD_TYPE_ == _IX_IXDP2801_)

#include "ixf1104ce_driver_api.h"
#include "ixf1104ce_ioctl.h"

#else /* _IX_BOARD_TYPE_ */

#if defined(IX_PLATFORM_2400)

#if (_IX_OS_TYPE_ == _IX_OS_LINUX_KERNEL_)
#include "ixf1104ce_ioctl.h"
#include "ixf1104ce_internal.h"
#include "cc/internal/ix_cc_eth_tx_drv_wrapper.h"
#else
#include "ixf1104ce_driver_api.h"
#include "ixf1104ce_ioctl.h"
#include "ixf1104ce_internal.h"
#endif

#elif defined(IX_PLATFORM_2800)

#if (_IX_OS_TYPE_ == _IX_OS_LINUX_KERNEL_)
#include "common_types.h"
#include "common_def.h"
#include "bld1110.h"
#include "ixf_api_ether_d.h"
#include "ixf_api_d.h" /* BroadBand Utility Definitions and Function headers */
#include "ixf_api.h"
#include "hal.h"
#include "ixf1110_alarms_d.h"
#include "ixd2810Mmap.h" /* for alarm callback GS_RX_STARTING_BIT definition */
#else
/* Include VxWorks media driver header files here */
#endif

#endif /* defined(IX_PLATFORM_2800) */

#endif /* _IX_BOARD_TYPE_ */

/* Static functions */
PRIVATE ix_error _ix_cc_eth_tx_get_static_data(ix_cc_eth_tx_ctl_blk *arg_pCtlBlk);
PRIVATE ix_error _ix_cc_eth_tx_alloc_local_interface_table(ix_cc_eth_tx_ctl_blk *arg_pCtlBlk);
PRIVATE ix_error _ix_cc_eth_tx_alloc_symbols(ix_cc_eth_tx_ctl_blk *arg_pCtlBlk);
PRIVATE ix_error _ix_cc_eth_tx_patch_symbols(ix_cc_eth_tx_ctl_blk *arg_pCtlBlk);
PRIVATE ix_error _ix_cc_eth_tx_register_msg_pkt_handlers(ix_cc_eth_tx_ctl_blk *arg_pCtlBlk);
PRIVATE ix_error _ix_cc_eth_tx_update_local_interface_table(void **arg_ppContext,
                                  ix_cc_eth_tx_ctl_blk *arg_pCtlBlk);


#if defined(IX_PLATFORM_2800)
ix_error _ix_cc_eth_tx_configure_media(ix_cc_eth_tx_ctl_blk *);
PRIVATE void _ix_cc_eth_tx_media_alarm_callback(bb_ChipData_t *, bb_AlarmType_e, void *);
extern int ixd2810IsrInit(bb_ChipData_t *); /* required for alarm callback */
#endif

#if defined(IX_PLATFORM_2800)

/**
 * The following table provides initialization data that can be
 * used in calling the IXF API function IxfApiInitChip().
 */
InitRegTable_t BoardInitIXF1110Table[] =
{
	{ (bb_RegPointer_type) 0x509, 0x2}, /* LED control*/
	{ (bb_RegPointer_type) 0x502, 0x3ff}, /* LED Enalble of first four ports */
	{ (bb_RegPointer_type) 0x500, 0x3FF}, /* Port Enalble*/

        /* Start auto-negotiation and enable padding for undersize packets */
	{ (bb_RegPointer_type) ((0*0x80)+0x0018), 0x11ED},
	{ (bb_RegPointer_type) ((1*0x80)+0x0018), 0x11ED},
	{ (bb_RegPointer_type) ((2*0x80)+0x0018), 0x11ED},
	{ (bb_RegPointer_type) ((3*0x80)+0x0018), 0x11ED},
	{ (bb_RegPointer_type) ((4*0x80)+0x0018), 0x11ED},
	{ (bb_RegPointer_type) ((5*0x80)+0x0018), 0x11ED},
	{ (bb_RegPointer_type) ((6*0x80)+0x0018), 0x11ED},
	{ (bb_RegPointer_type) ((7*0x80)+0x0018), 0x11ED},
	{ (bb_RegPointer_type) ((8*0x80)+0x0018), 0x11ED},
	{ (bb_RegPointer_type) ((9*0x80)+0x0018), 0x11ED},

        /* Set MAX frame size to 9k for each port */
	{ (bb_RegPointer_type) ((0*0x80)+0x000f), 0x240A},
	{ (bb_RegPointer_type) ((1*0x80)+0x000f), 0x240A},
	{ (bb_RegPointer_type) ((2*0x80)+0x000f), 0x240A},
	{ (bb_RegPointer_type) ((3*0x80)+0x000f), 0x240A},
	{ (bb_RegPointer_type) ((4*0x80)+0x000f), 0x240A},
	{ (bb_RegPointer_type) ((5*0x80)+0x000f), 0x240A},
	{ (bb_RegPointer_type) ((6*0x80)+0x000f), 0x240A},
	{ (bb_RegPointer_type) ((7*0x80)+0x000f), 0x240A},
	{ (bb_RegPointer_type) ((8*0x80)+0x000f), 0x240A},
	{ (bb_RegPointer_type) ((9*0x80)+0x000f), 0x240A},

        /* Set Rx High watermark. When this watermark is exceeded, the MAC will start sending PAUSE frames */
	{ (bb_RegPointer_type) 0x580, 0x2710},
	{ (bb_RegPointer_type) 0x581, 0x2710},
	{ (bb_RegPointer_type) 0x582, 0x2710},
	{ (bb_RegPointer_type) 0x583, 0x2710},
	{ (bb_RegPointer_type) 0x584, 0x2710},
	{ (bb_RegPointer_type) 0x585, 0x2710},
	{ (bb_RegPointer_type) 0x586, 0x2710},
	{ (bb_RegPointer_type) 0x587, 0x2710},
	{ (bb_RegPointer_type) 0x588, 0x2710},
	{ (bb_RegPointer_type) 0x589, 0x2710},

	/* Rx Low watermark.  When this watermark is crossed the MAC will start sending PAUSE/Resume frames */
	{ (bb_RegPointer_type) 0x58A, 0x1F40},
	{ (bb_RegPointer_type) 0x58B, 0x1F40},
	{ (bb_RegPointer_type) 0x58C, 0x1F40},
	{ (bb_RegPointer_type) 0x58D, 0x1F40},
	{ (bb_RegPointer_type) 0x58E, 0x1F40},
	{ (bb_RegPointer_type) 0x58F, 0x1F40},
	{ (bb_RegPointer_type) 0x590, 0x1F40},
	{ (bb_RegPointer_type) 0x591, 0x1F40},
	{ (bb_RegPointer_type) 0x592, 0x1F40},
	{ (bb_RegPointer_type) 0x593, 0x1F40},

        /**
         * Set MaxBurst1 to 8 in order to allow RX receiving 128 bytes
         * Set MaxBurst2 to 4 to avoid length error for 10gx1 pipeline.
         */
	{ (bb_RegPointer_type) 0x700, 0x00080004}, /* RX Burst Size Register */

	{ (bb_RegPointer_type) 0xffff, 0xa5a5}	/* end marker */
};

#endif /* defined(IX_PLATFORM_2800) */


/**
 * NAME: _ix_cc_eth_tx_get_static_data
 *
 *
 * DESCRIPTION: This function retrieves all Ethernet Tx static data from
 *              either system repository or ix_cc_eth_tx.h and store them
 *              into the corresponding field in the control block
 *
 * @Param: arg_pCtlBlk - 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.
 *
 * Error Codes:
 * IX_CC_ERROR_ENTRY_NOT_FOUND - entry not in registry
 */
PRIVATE ix_error _ix_cc_eth_tx_get_static_data(ix_cc_eth_tx_ctl_blk *arg_pCtlBlk)
{

    /**
     * Retrieve static configuration data
     */
#ifdef IX_INCLUDE_REGISTRY
    ix_configuration_property_handle hProperty = (ix_configuration_property_handle)NULL;

    /* open the property */
    IX_ERROR_CRT(ix_rm_cp_property_open(IX_CP_CORE_PROPERTY_ROOT,
                                        IX_CC_ETH_TX_PROP_MEV2_NUM_MASK,
                                        &hProperty),
                 IX_CC_ERROR_ENTRY_NOT_FOUND,
                 IX_ERROR_LEVEL_LOCAL);

    /* read the property */
    IX_ERROR_CRT(ix_rm_cp_property_get_value_uint32(hProperty,
                                                    &(arg_pCtlBlk->mev2NumMask)),
                 IX_CC_ERROR_ENTRY_NOT_FOUND,
                 IX_ERROR_LEVEL_LOCAL);

#else /* IX_INCLUDE_REGISTRY */

    arg_pCtlBlk->mev2NumMask = IX_CC_ETH_TX_MEV2_NUM_MASK;

#endif /* IX_INCLUDE_REGISTRY */

    return(IX_SUCCESS);

} /* _ix_cc_eth_tx_get_static_data */


/**
 * NAME: _ix_cc_eth_tx_alloc_local_interface_table
 *
 * DESCRIPTION: This primitive will be used to allocate memory for local
 *              interface table.
 *
 * @Param: arg_pCtlBlk - IN: pointer to the component context allocated
 *                           in the component's init function.
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *
 * IX_CC_ERROR_OOM_SYSTEM  - not able to allocate memory
 *
 */

PRIVATE ix_error _ix_cc_eth_tx_alloc_local_interface_table(
    ix_cc_eth_tx_ctl_blk *arg_pCtlBlk)
{
    ix_uint32 memSize;
    memSize =  sizeof(ix_cc_eth_tx_local_interface_table) * IX_CC_ETH_TX_MAX_NUM_PORTS;
    /* Allocation of memory for  local interface table */
    arg_pCtlBlk->pInterfaceTable = (ix_cc_eth_tx_local_interface_table *)ix_ossl_malloc(memSize);
    if(arg_pCtlBlk->pInterfaceTable == NULL)
    {
        return IX_ERROR_LOCAL(IX_CC_ERROR_OOM_SYSTEM,
                                ("Failed to allocate memory for Ethernet Tx local interface table"));
     }/* end if ethernet tx control block memory allocation */

    ix_ossl_memset(arg_pCtlBlk->pInterfaceTable,
                   0,
                   memSize);

    return IX_SUCCESS;

}/* end _ix_cc_eth_tx_alloc_local_interface_table */


/**
 * NAME: _ix_cc_eth_tx_alloc_symbols
 *
 * DESCRIPTION: This primitive will be used to allocate memory for symbols to be patched.
 *
 * @Param: arg_pCtlBlk - IN: pointer to the component context allocated
 *                           in the component's init function.
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *
 * IX_CC_ERROR_OOM_SRAM  - not able to allocate memory
 *
 */

PRIVATE ix_error _ix_cc_eth_tx_alloc_symbols(ix_cc_eth_tx_ctl_blk *arg_pCtlBlk)
{
#ifdef MICROBLOCK_COUNTERS
    ix_error err = IX_SUCCESS;
    /* Allocation of memory for  microblock counters */
    err = ix_rm_mem_alloc(IX_MEMORY_TYPE_SRAM,
                          IX_CC_ETH_TX_DEFAULT_SRAM_CH_NUM,
                          IX_CC_ETH_TX_SIZE_32BIT_COUNTER_BUF,
                          (void**)&(arg_pCtlBlk->pCounterBase32Bit));
    if(err != IX_SUCCESS)
    {
        return IX_ERROR_LOCAL(IX_CC_ERROR_OOM_SRAM,
                                ("Memory allocation failed for symbols to be patched"));
    }/* end if (err != IX_SUCCESS) */

    ix_ossl_memset(arg_pCtlBlk->pCounterBase32Bit,0,IX_CC_ETH_TX_SIZE_32BIT_COUNTER_BUF);
#endif

    return IX_SUCCESS;
}/* end _ix_cc_eth_tx_alloc_symbols */


/**
 * NAME: _ix_cc_eth_tx_patch_symbols
 *
 * DESCRIPTION: This primitive will be used to patch symbols to ethernet tx microblocks.
 *
 * @Param: arg_pCtlBlk - IN: pointer to the component context allocated
 *                           in the component's init function.
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 * IX_CC_ETH_TX_ERROR_RM_PATCH_SYMBOL - failed patching by calling resource manager function
 * IX_CC_ETH_TX_ERROR_GET_L2_SYMBOL - failed to get l2 sysmbol
 *
 */

PRIVATE ix_error _ix_cc_eth_tx_patch_symbols(ix_cc_eth_tx_ctl_blk *arg_pCtlBlk)
{
    ix_imported_symbol ethTxSymbols[IX_CC_ETH_TX_NUM_SYMBOLS_PATCHED];
    ix_uint32 ethTxIndex = 0;

#ifdef MICROBLOCK_COUNTERS
    ix_memory_type memType;
    ix_uint32 memChannel;
    ix_uint32 memOffset;
    void* pPhysAddr;
    /* Patch base address for statistics */
    /* Get the pghysical offset */
    IX_ERROR_CRT(ix_rm_get_phys_offset(arg_pCtlBlk->pCounterBase32Bit,
                                       &memType,
                                       &memChannel,
                                       &memOffset,
                                       &pPhysAddr),
                 IX_CC_ETH_TX_ERROR_RM_GET_PHYS_OFFSET,
                 IX_ERROR_LEVEL_LOCAL);
    if(memType == IX_MEMORY_TYPE_SRAM)
    {
        IX_CC_SET_SRAM_CHANNEL_INTO_OFFSET(memChannel,memOffset);
    }/* end if memorry type */
    ethTxSymbols[ethTxIndex].m_Value = memOffset;
    ethTxSymbols[ethTxIndex++].m_Name = IX_CC_ETH_TX_SYMBOL_COUNTERS_BASE;
#endif

    /* Get L2TM symbol */
    IX_ERROR_CRT(ix_cc_l2tm_get_symbols(arg_pCtlBlk->hL2TM,
                                        &(arg_pCtlBlk->l2TMSymbol)),
                 IX_CC_ETH_TX_ERROR_L2TM_GET_SYMBOL,
                 IX_ERROR_LEVEL_LOCAL);

    ethTxSymbols[ethTxIndex].m_Value = arg_pCtlBlk->l2TMSymbol.l2TableBase;
    ethTxSymbols[ethTxIndex].m_Name = IX_CC_ETH_TX_SYMBOL_L2_TABLE_BASE;

    for (ethTxIndex = 0; ethTxIndex < IX_CC_ETH_TX_MAX_ME_NUM; ethTxIndex++)
    {
         /* if the bit is set, then patch the symbols */
        if(((arg_pCtlBlk->mev2NumMask) & (1 << ethTxIndex)) != 0)
        {
            IX_ERROR_CRT(ix_rm_ueng_patch_symbols(g_aMicroengineNumberMapping[ethTxIndex],
                         IX_CC_ETH_TX_NUM_SYMBOLS_PATCHED,ethTxSymbols),
                         IX_CC_ETH_TX_ERROR_RM_PATCH_SYMBOL,
                         IX_ERROR_LEVEL_LOCAL);
        }/* end if */
    }/* end for  */

    return IX_SUCCESS;
}/* end _ix_cc_eth_tx_patch_symbols */


/**
 * NAME: _ix_cc_eth_tx_register_msg_pkt_handlers
 *
 * DESCRIPTION: This primitive will be used to register message and packet handlers.
 *
 * @Param: arg_pCtlBlk - IN: pointer to the component context allocated
 *                           in the component's init function.
 *
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *
 * IX_CC_ETH_TX_ERROR_REG_HDLR - Error from CCI/RM
 *
 */

PRIVATE ix_error _ix_cc_eth_tx_register_msg_pkt_handlers(ix_cc_eth_tx_ctl_blk *arg_pCtlBlk)
{
    /* Call CCI message/packet handler if CCI is enabled */
#if defined(IX_EXCLUDE_CCI)
    /* Register message handler */
    IX_ERROR_CRT(ix_rm_message_handler_register(IX_CC_ETH_TX_MSG_INPUT,
                                                ix_cc_eth_tx_msg_handler,
                                                arg_pCtlBlk),
                 IX_CC_ETH_TX_ERROR_REG_HDLR,
                 IX_ERROR_LEVEL_LOCAL);
    /* Register the property message handler */
    IX_ERROR_CT(ix_rm_message_handler_register(IX_CC_ETH_TX_PROPERTY_MSG_INPUT,
                                               ix_cc_eth_tx_property_msg_handler,
                                               arg_pCtlBlk),
                IX_CC_ETH_TX_ERROR_REG_HDLR,
                IX_ERROR_LEVEL_LOCAL);
    /* Register high priority packet input via message handler */
    IX_ERROR_CRT(ix_rm_message_handler_register(IX_CC_ETH_TX_ARP_PKT_INPUT,
                                                ix_cc_eth_tx_pkt_handler,
                                                arg_pCtlBlk),
                 IX_CC_ETH_TX_ERROR_REG_HDLR,
                 IX_ERROR_LEVEL_LOCAL);
#if (_IX_BOARD_TYPE_ == _IX_IXDP2401_) || (_IX_BOARD_TYPE_ == _IX_IXDP2801_)
    /*
     * Since on IXDP2401 we don't use RX CC, register also for high priority
     * packets from ucode coming as messages.
     */
    IX_ERROR_CRT(ix_rm_message_handler_register(IX_CC_ETH_TX_UBLK_PKT_INPUT,
                                                ix_cc_eth_tx_pkt_handler,
                                                arg_pCtlBlk),
                 IX_CC_ETH_TX_ERROR_REG_HDLR,
                 IX_ERROR_LEVEL_LOCAL);
#endif
    /* Register low priority packet handler input via packet handler */
    IX_ERROR_CRT(ix_rm_packet_handler_register(IX_CC_ETH_TX_UBLK_PKT_INPUT,
                                               ix_cc_eth_tx_pkt_handler,
                                               arg_pCtlBlk),
                 IX_CC_ETH_TX_ERROR_REG_HDLR,
                 IX_ERROR_LEVEL_LOCAL);

#else
    /* Register message handler */
    IX_ERROR_CRT(ix_cci_cc_add_message_handler(arg_pCtlBlk->hEthTxHandle,
                                               IX_CC_ETH_TX_MSG_INPUT,
                                               ix_cc_eth_tx_msg_handler,
                                               IX_INPUT_TYPE_MULTI_SRC),
                 IX_CC_ETH_TX_ERROR_REG_HDLR,
                 IX_ERROR_LEVEL_LOCAL);
    /* Register the property message handler */
    IX_ERROR_CRT(ix_cci_cc_add_message_handler(arg_pCtlBlk->hEthTxHandle,
                                               IX_CC_ETH_TX_PROPERTY_MSG_INPUT,
                                               ix_cc_eth_tx_property_msg_handler,
                                               IX_INPUT_TYPE_SINGLE_SRC),
                 IX_CC_ETH_TX_ERROR_REG_HDLR,
                 IX_ERROR_LEVEL_LOCAL);
    /* Register high priority packet input via message handler */
    IX_ERROR_CRT(ix_cci_cc_add_message_handler(arg_pCtlBlk->hEthTxHandle,
                                               IX_CC_ETH_TX_ARP_PKT_INPUT,
                                               ix_cc_eth_tx_pkt_handler,
                                               IX_INPUT_TYPE_SINGLE_SRC),
                 IX_CC_ETH_TX_ERROR_REG_HDLR,
                 IX_ERROR_LEVEL_LOCAL);
#if (_IX_BOARD_TYPE_ == _IX_IXDP2401_) || (_IX_BOARD_TYPE_ == _IX_IXDP2801_)
    /*
     * Since on IXDP2401 we don't use RX CC, register also for high priority
     * packets from ucode coming as messages.
     */
    IX_ERROR_CRT(ix_cci_cc_add_message_handler(arg_pCtlBlk->hEthTxHandle,
                                               IX_CC_ETH_TX_UBLK_PKT_INPUT,
                                               ix_cc_eth_tx_pkt_handler,
                                               IX_INPUT_TYPE_MULTI_SRC),
                 IX_CC_ETH_TX_ERROR_REG_HDLR,
                 IX_ERROR_LEVEL_LOCAL);
#endif
    /* Register low priority packet handler input via packet handler */
    IX_ERROR_CRT(ix_cci_cc_add_packet_handler(arg_pCtlBlk->hEthTxHandle,
                                              IX_CC_ETH_TX_UBLK_PKT_INPUT,
                                              ix_cc_eth_tx_pkt_handler,
                                              IX_INPUT_TYPE_MULTI_SRC),
                 IX_CC_ETH_TX_ERROR_REG_HDLR,
                 IX_ERROR_LEVEL_LOCAL);
#endif
    return IX_SUCCESS;
}/* end _ix_cc_eth_tx_register_msg_pkt_handlers */


/**
 * NAME: _ix_cc_eth_tx_update_local_interface_table
 *
 * DESCRIPTION: This primitive will be used to update local interface table
 * with  port id, mac address, IP address. The physical status notification
 * will be propagated to driver by calling driver primitive to update
 * the status(default is UP).
 *
 * This function calls ix_cc_eth_tx_set_property_update to update the table.
 *
 * @Param: arg_ppContext - IN: pointer to init context structured received
 *                           in init function.
 *
 * @Param: arg_pCtlBlk - IN: pointer to the component context allocated
 *                           in the component's init function.
 *
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *
 * IX_CC_ERROR_ENTRY_NOT_FOUND - passed invalid number of port nodes
 *
 */

PRIVATE ix_error _ix_cc_eth_tx_update_local_interface_table(void **arg_ppContext,
                                  ix_cc_eth_tx_ctl_blk *arg_pCtlBlk)
{
    ix_uint32 i;
    ix_uint32 propId;
    /* Variables used to retrieve static data from arg_ppContext */
    ix_cc_init_context *pInitCtx;
    ix_cc_properties_node *pPropNode;

    pInitCtx = (ix_cc_init_context *)*arg_ppContext;

    /**
     * Retrieve the port id information of each channel from the
     * init context (This will work for both level-1 and level-0 modes).
     */
    pPropNode = pInitCtx->pPropertyList;
    if (pPropNode == NULL)
    {
        return IX_ERROR_WARNING(IX_CC_ERROR_ENTRY_NOT_FOUND,
                                ("null port property"));
    } /* endif pPropNode is null */

    /* Get the number of channels from property node */
    i = 0;
    while(pPropNode != NULL)
    {
#if ((defined IX_PLATFORM_2401) || (defined IX_PLATFORM_2801))
	/* Support for baseboard driver added*/
#if ((_IX_BOARD_TYPE_ == _IX_IXDP2401_) || (_IX_BOARD_TYPE_ == _IX_IXDP2801_))
#if (defined USE_HW_CONFIG)
        if ((pPropNode->pPropertyInfo->media_type == IX_MEDIA_TYPE_1GB_ETHERNET) &&
            (arg_pCtlBlk->portMask & (1 << pPropNode->pPropertyInfo->port_id)))
#elif (defined USE_BB_DRV_CONFIG)
#if (_IX_BOARD_TYPE_ == _IX_IXDP2401_)
        if (pPropNode->pPropertyInfo->media_type == IX_MEDIA_TYPE_1GB_ETHERNET)
#elif (_IX_BOARD_TYPE_ == _IX_IXDP2801_)
        if ((pPropNode->pPropertyInfo->media_type == IX_MEDIA_TYPE_1GB_ETHERNET) &&
            (arg_pCtlBlk->portMask & (1 << pPropNode->pPropertyInfo->port_id)))
#endif /* _IX_BOARD_TYPE_ == _IX_IXDP2x01_ */
#else /* USE_HW_CONFIG || USE_BB_DRV_CONFIG*/
        if (pPropNode->pPropertyInfo->media_type == IX_MEDIA_TYPE_1GB_ETHERNET)
#endif /* USE_HW_CONFIG || USE_BB_DRV_CONFIG*/
#else /* _IX_BOARD_TYPE_ == _IX_IXDP2401_ || _IX_BOARD_TYPE_ == _IX_IXDP2801_ */
        if (pPropNode->pPropertyInfo->media_type == IX_MEDIA_TYPE_1GB_ETHERNET)
#endif /* _IX_BOARD_TYPE_ == _IX_IXDP2401_ || _IX_BOARD_TYPE_ == _IX_IXDP2801_ */
#else /* IX_PLATFORM_2x01 */
		/* Original code */
        if (pPropNode->pPropertyInfo->media_type == IX_MEDIA_TYPE_1GB_ETHERNET)
#endif /* IX_PLATFORM_2x01 */
        {
            arg_pCtlBlk->portId[i] = pPropNode->pPropertyInfo->port_id;
            /* Assign the port id to the local interface table */
            (arg_pCtlBlk->pInterfaceTable + i)->portId = arg_pCtlBlk->portId[i];
            /**
             * Store the local blade id. Assuming all nodes have same
             * blade id so it's ok to keep overwriting.
             */
            arg_pCtlBlk->localBladeId = pPropNode->pPropertyInfo->blade_id;
            /* Call set property update local interface table */
            propId = IX_CC_SET_PROPERTY_ADD_INTERFACE_IPV4 |
                     IX_CC_SET_PROPERTY_MAC_ADDR |
                     IX_CC_SET_PROPERTY_PHYSICAL_IF_STATUS;
            i ++;
            arg_pCtlBlk->numberOfChannels = i;
            IX_ERROR_CR(ix_cc_eth_tx_set_property(propId,pPropNode->pPropertyInfo,arg_pCtlBlk));

        }
#if (defined IX_PLATFORM_2401) || (defined IX_PLATFORM_2801)
#if (_IX_BOARD_TYPE_ == _IX_IXDP2401_) || (_IX_BOARD_TYPE_ == _IX_IXDP2801_)
        /* Platform specific
         * See the comment below.
         */

        else
        {
            /*
             * In a mixed POS/Gigabit Ethernet application on IXDP2x01
             * there are some ports that work in POS mode.
             * Left then markes as unused.
             */
            arg_pCtlBlk->portId[i] = -1;         /* put invalid port id here */
            arg_pCtlBlk->numberOfChannels = ++i;
        }
#endif /* _IX_BOARD_TYPE_ == _IX_IXDP2x01_ */
#endif /* IX_PLATFORM_2401 || IX_PLATFORM_2801 */
        pPropNode = pPropNode->pNextPropNode;
    }/* end while */



    if(arg_pCtlBlk->numberOfChannels > IX_CC_ETH_TX_MAX_NUM_PORTS)
    {
        return IX_ERROR_LOCAL(IX_CC_ERROR_OVERFLOW,
                                ("Found more ports from property update"));
    }/* end if channel count validity check */

    return IX_SUCCESS;
}/* end _ix_cc_eth_tx_update_local_interface_table */


/**
 * NAME: _ix_cc_eth_tx_driver_callback
 *
 * DESCRIPTION: This primitive will be called by ethernet driver
 *
 * @Param: arg_pContext - IN: pointer to the component context allocated
 *                           in the component's init function.
 * @Param: arg_PortId - IN: Port Id
 *
 * @Param: arg_PortStatus - IN: Status(UP/DOWN) of the port
 *
 */

void _ix_cc_eth_tx_driver_callback(void *arg_pCtlBlk,
                                   ix_uint32 arg_PortId,
                                   ix_uint32 arg_PortStatus)
{
    ix_cc_properties propData;
    ix_uint32 portStatus = 0;

    portStatus = arg_PortStatus & (1 << arg_PortId);
    propData.port_id = ((ix_cc_eth_tx_ctl_blk*)arg_pCtlBlk)->portId[arg_PortId];
    propData.blade_id = ((ix_cc_eth_tx_ctl_blk*)arg_pCtlBlk)->localBladeId;
    propData.media_type = IX_MEDIA_TYPE_1GB_ETHERNET;

    if(portStatus == 0)
    {
#ifdef IX_DEBUG
        ix_ossl_message_log("Eth Tx CC: port %ld is DOWN.\n", arg_PortId);
#endif
        propData.link_state = IX_CC_LINK_STATUS_DOWN;
    }
    else
    {
#ifdef IX_DEBUG
        ix_ossl_message_log("Eth Tx CC: port %ld is UP.\n", arg_PortId);
#endif
        propData.link_state = IX_CC_LINK_STATUS_UP;
    }

    ix_cc_async_set_property(IX_CC_SET_PROPERTY_LINK_STATUS,&propData);
}/* end _ix_cc_eth_tx_driver_callback */

/**
 * NAME: ix_cc_eth_tx_init
 *
 * DESCRIPTION: This function initializes Ethernet Tx CC.It shall be called
 * and returned successfully before requesting any service from Ethernet Tx
 * core component.
 *
 * @Param: arg_hCcHandle - IN : Handle of Ethernet Tx core component
 * @Param: arg_ppContext - IN OUT: This parameter is a pointer to init
 * context of type ix_cc_init_context as an input. As an output, this is a
 * location of Ethernet Tx control block data structure.
 *
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
ix_error ix_cc_eth_tx_init(
                           ix_cc_handle arg_hCcHandle,
                           void** arg_ppContext)
{
    ix_error err = IX_SUCCESS;
    ix_cc_eth_tx_ctl_blk *pCtlBlk = NULL;
    ix_arp_init_context arpContext;
    /* Variables used to retrieve static data from arg_ppContext */
    ix_cc_init_context *pInitCtx;
#if (_IX_BOARD_TYPE_ == _IX_IXDP2401_) || (_IX_BOARD_TYPE_ == _IX_IXDP2801_)
    unsigned mask = 0;
#endif

#if defined(IX_PLATFORM_2800)
    bb_ChipSegment_t section;
#else
    ix_uint32 i;
    gbe_mac_ioctl_ptr macIoctlInfo;
#endif
#if defined(IX_PLATFORM_2401) || defined(IX_PLATFORM_2801)
#if (_IX_BOARD_TYPE_ == _IX_IXDP2401_) || (_IX_BOARD_TYPE_ == _IX_IXDP2801_)
#if !defined(USE_HW_CONFIG)
    ix_cc_properties_node *pProp;
#endif /* USE_HW_CONFIG */
#endif
#endif

    /* Check for argument validity */
    if(arg_ppContext == NULL)
    {
        return IX_ERROR_LOCAL(IX_CC_ERROR_NULL,
                                ("Input parameter(arg_ppContext) is null"));
    }/* end if null context */
    /* Get the generic init context */
    pInitCtx = (ix_cc_init_context *)*arg_ppContext;
    if(pInitCtx == NULL)
    {
        return IX_ERROR_LOCAL(IX_CC_ERROR_NULL,
                                ("init context is null"));
    }/* end if null init context */
    /* Allocate memory for ethernet tx control block */
    pCtlBlk = (ix_cc_eth_tx_ctl_blk*)ix_ossl_malloc(sizeof(ix_cc_eth_tx_ctl_blk));
    if(pCtlBlk == NULL)
    {
        return IX_ERROR_LOCAL(IX_CC_ERROR_OOM_SYSTEM,
                                ("Failed to allocate memory for ethernrt tx control block"));
     }/* end if ethernet tx control block memory allocation */
    /* initialize the structure */
    ix_ossl_memset(pCtlBlk,0,sizeof(ix_cc_eth_tx_ctl_blk));


    /* Retrieve free list handle  */
    pCtlBlk->hBufferFreeList = pInitCtx->hFreeList;
    /* store eth tx  component handle in control block */
    pCtlBlk->hEthTxHandle = arg_hCcHandle;
    /* Retrieve static configuration data */
    IX_ERROR_CG(_ix_cc_eth_tx_get_static_data(pCtlBlk),err,cleanupCtlBlk);
    /*
     * Create mutex for critical section.
     */
    IX_ERROR_C(ix_ossl_mutex_init(OS_MUTEX_UNLOCK,&(pCtlBlk->mid)),err);
    if(err != IX_SUCCESS)
    {
        ix_ossl_free(pCtlBlk);
        return IX_ERROR_LOCAL(IX_CC_ETH_TX_ERROR_OSSL_MUTEX_INIT,
                               ("Failed to create mutex"));

    }/* end if mutex_init error */
    /* Allocate memory for local interface table */
    IX_ERROR_CG(_ix_cc_eth_tx_alloc_local_interface_table(pCtlBlk),err,cleanupMutex);
    /* Allocate memory for symbols to be patched */
    IX_ERROR_CG(_ix_cc_eth_tx_alloc_symbols(pCtlBlk),err,cleanupInterfaceTable);
    /* Create L2TM library */
    IX_ERROR_CGT(ix_cc_l2tm_create(IX_CC_ETH_TX_L2TM_NAME,
                                &(pCtlBlk->hL2TM)),err,
                                IX_CC_ETH_TX_ERROR_L2TM_INIT,
                                IX_ERROR_LEVEL_LOCAL,cleanupSymbols);
    /* Initialize arp library */
    arpContext.pContext = pCtlBlk;
    arpContext.pIpLkupCb = _ix_cc_eth_tx_get_port_mac_address;
    arpContext.pPortLkupCb = _ix_cc_eth_tx_get_port_data;
    arpContext.pArpSendPkt = _ix_cc_eth_tx_arp_send_packet;
    arpContext.pCcInitContext = pInitCtx;
    IX_ERROR_CGT(ix_cc_arp_init(&arpContext),
                 err,IX_CC_ETH_TX_ERROR_ARP_INIT,
                 IX_ERROR_LEVEL_LOCAL,cleanupL2tm);

#if (_IX_BOARD_TYPE_ == _IX_IXDP2401_) || (_IX_BOARD_TYPE_ == _IX_IXDP2801_)
    {
        /* Platform specific
         * The below IXDP2x01 platforms specific driver initialization has
         * changed. Now it calculates the mask of ports what shall be
         * controlled by this core component according to properies in XML
         * registry, so that applications running interfacaes in various modes,
         * like OC12 POS can work smoothly.
         */

        pCtlBlk->portMask = 0;
#if (defined IX_PLATFORM_2401) || (defined IX_PLATFORM_2801)

#if !defined (USE_HW_CONFIG)
        for (pProp = pInitCtx->pPropertyList;
             pProp != NULL; pProp = pProp->pNextPropNode)
        {
            if (pProp->pPropertyInfo->media_type == IX_MEDIA_TYPE_1GB_ETHERNET)
            {
                pCtlBlk->portMask |= 1 << pProp->pPropertyInfo->port_id;
            }
        }
#endif /* USE_HW_CONFIG */

        /*
         * Use HW_CONFIG or baseboard driver data to configure ETH interface
         * Store Port mask in Control Block in pCtlBlk->portMask
         */
#if (defined USE_HW_CONFIG)
        pCtlBlk->portMask = hwConfigEthPortMask;
#elif (defined USE_BB_DRV_CONFIG)

#if (_IX_BOARD_TYPE_ == _IX_IXDP2401_)
        pCtlBlk->portMask = hwConfigEthPortMask;
#elif (_IX_BOARD_TYPE_ == _IX_IXDP2801_)
        pCtlBlk->portMask &= hwConfigEthPortMask;
#endif /* IX_BOARD_TYPE */

#endif /* USE_HW_CONFIG || USE_BB_DRV_CONFIG */

#if (defined USE_HW_CONFIG) || (defined USE_BB_DRV_CONFIG)
        pCtlBlk->hEthDriver = 0;

        /* Allow each port to be started in different mode. */
        for (i = 0; i < IX_CC_ETH_TX_MAX_NUM_PORTS; i++)
        {
          if (pCtlBlk->portMask & (1 << i))
          {
              err = GbEMAC_DeviceStart((1 << i), &pCtlBlk->hEthDriver,
                                       hwConfigEthMode[i]);
              if (err != SUCCESS)
              {
                  err = IX_ERROR_REMOTE(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                                        ("Media driver start failed!"));
                  goto cleanupArp;
              }
          }
        }
#else /* USE_HW_CONFIG || USE_BB_DRV_CONFIG */

#if (_IX_HARDWARE_TYPE_ == _IX_HW_2400_)

#ifdef SPI23_TO_FRONT

    /*
     * Initialize also front ports.
     */
#ifdef GIGE_FRONT_COPPER

    err = GbEMAC_DeviceStart(IX_CC_ETH_TX_DRIVER_PORT_MASK_01, &pCtlBlk->hEthDriver,
                             IX_CC_ETH_TX_DRIVER_MODE_GIGA_FULL_DUPLEX |
                             IX_CC_ETH_TX_DRIVER_MODE_PARITY_EVEN |
                             IX_CC_ETH_TX_DRIVER_MODE_BLOCK_4_8);

#else /* GIGE_FRONT_COPPER - so fiber ports */

    err = GbEMAC_DeviceStart(IX_CC_ETH_TX_DRIVER_PORT_MASK_01, &pCtlBlk->hEthDriver,
                             IX_CC_ETH_TX_DRIVER_MODE_FIBER |
                             IX_CC_ETH_TX_DRIVER_MODE_PARITY_EVEN |
                             IX_CC_ETH_TX_DRIVER_MODE_BLOCK_4_8);

#endif /* GIGE_FRONT_COPPER */

    if (err != SUCCESS)
    {
        err = IX_ERROR_REMOTE(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                              ("Media driver start failed!"));
        goto cleanupArp;
    }

    mask = pCtlBlk->portMask & (~IX_CC_ETH_TX_DRIVER_PORT_MASK_01);
    /*
     * rest of the ports must be initialized in copper mode
     */
    err = GbEMAC_DeviceStart(mask, &pCtlBlk->hEthDriver,
                             IX_CC_ETH_TX_DRIVER_MODE_GIGA_FULL_DUPLEX |
                             IX_CC_ETH_TX_DRIVER_MODE_PARITY_EVEN |
                             IX_CC_ETH_TX_DRIVER_MODE_BLOCK_4_8);

#else /* SPI23_TO_FRONT */

#ifdef GIGE_FRONT_COPPER
    err = GbEMAC_DeviceStart(pCtlBlk->portMask, &pCtlBlk->hEthDriver,
                             IX_CC_ETH_TX_DRIVER_MODE_GIGA_FULL_DUPLEX |
                             IX_CC_ETH_TX_DRIVER_MODE_PARITY_EVEN |
                             IX_CC_ETH_TX_DRIVER_MODE_BLOCK_4_8);

#else /* GIGE_FRONT_COPPER - so fiber front ports */
    {
        /*
         * Check if ports 0,1 are in port mask
         */
        mask = pCtlBlk->portMask & IX_CC_ETH_TX_DRIVER_PORT_MASK_01;

        if (mask != 0)
        {

            err = GbEMAC_DeviceStart(mask, &pCtlBlk->hEthDriver,
                                     IX_CC_ETH_TX_DRIVER_MODE_FIBER |
                                     IX_CC_ETH_TX_DRIVER_MODE_PARITY_EVEN |
                                     IX_CC_ETH_TX_DRIVER_MODE_BLOCK_4_8);

            if (err != SUCCESS)
            {
                err = IX_ERROR_REMOTE(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                                      ("Media driver start failed!"));
                goto cleanupArp;
            }
        }

        /*
         * Ports 2,3 must be always copper
         */
        mask = pCtlBlk->portMask & (~IX_CC_ETH_TX_DRIVER_PORT_MASK_01);

        if (mask != 0)
        {
            err = GbEMAC_DeviceStart(mask, &pCtlBlk->hEthDriver,
                                     IX_CC_ETH_TX_DRIVER_MODE_GIGA_FULL_DUPLEX |
                                     IX_CC_ETH_TX_DRIVER_MODE_PARITY_EVEN |
                                     IX_CC_ETH_TX_DRIVER_MODE_BLOCK_4_8);
        }

    }
#endif /* GIGE_FRONT_COPPER */
#endif /* SPI23_TO_FRONT */

#elif (_IX_HARDWARE_TYPE_ == _IX_HW_2800_)

    err = GbEMAC_DeviceStart(pCtlBlk->portMask, &pCtlBlk->hEthDriver,
                             IX_CC_ETH_TX_DRIVER_MODE_GIGA_FULL_DUPLEX |
                             IX_CC_ETH_TX_DRIVER_MODE_PARITY_ODD |
                             IX_CC_ETH_TX_DRIVER_MODE_BLOCK_MPHY);

#else
#error Wrong usage of compilation flags...
#endif

    if (err != SUCCESS)
    {
        err = IX_ERROR_REMOTE(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                              ("Media driver start failed!"));
        goto cleanupArp;
    }

#endif /* USE_HW_CONFIG || USE_BB_DRV_CONFIG */
        mask = pCtlBlk->portMask;

#else /* IX_PLATFORM_2x01 */
        /* Original code */

        for (pProp = pInitCtx->pPropertyList;
             pProp != NULL; pProp = pProp->pNextPropNode)
        {
            if (pProp->pPropertyInfo->media_type == IX_MEDIA_TYPE_1GB_ETHERNET)
            {
                mask |= 1 << pProp->pPropertyInfo->port_id;
            }
        }

        err = GbEMAC_DeviceStart(mask, &pCtlBlk->hEthDriver,
                                 IX_CC_ETH_TX_DRIVER_MODE_DEFAULT);
        if (err != SUCCESS)
        {
            err = IX_ERROR_REMOTE(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                                  ("Media driver start failed!"));
            goto cleanupArp;
        }

#endif /* IX_PLATFORM_2x01 */

        /* Set the JUMBO MTU size for all ports */
        for (i = 0; i < IX_CC_ETH_TX_MAX_NUM_PORTS; i++)
        {
          if (mask & (1 << i))
          {
#ifdef ETHERNET_TX_PROMISCOUS_MODE
            /* Set promiscous mode in driver */
            macIoctlInfo.portIndex = i;
            macIoctlInfo.value = 0x20;
            err = GbEMAC_Ioctl(&(pCtlBlk->hEthDriver), SET_PKT_FILTER_CTL, (void *)(&macIoctlInfo));
            if(err != SUCCESS)
            {
                err = IX_ERROR_NEW(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                                   IX_ERROR_LEVEL_LOCAL);
                goto cleanupEthDriver;
            }/* end if */
#endif
            macIoctlInfo.portIndex = i;
            macIoctlInfo.value = IX_CC_ETH_TX_FRAME_SIZE;
            err = GbEMAC_Ioctl(&pCtlBlk->hEthDriver,
                               SET_MAX_FRAME_SIZE, (void*)&macIoctlInfo);
            if (err != SUCCESS)
            {
                err = IX_ERROR_REMOTE(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                                      ("frame size set failed"));
                goto cleanupEthDriver;
            }
            /*
             *  ENABLE THE FLOW CONTROL CAPABILITY IN VALLEJO
             * The approximate value of high water mark is calculated according
             * to the following algorithm:
             * (MAC_FIFO_SIZE - 2 * IX_CC_ETH_TX_FRAME_SIZE) / 8
             */
            macIoctlInfo.value = 0x700; /* high water mark 0x700 of 8 bytes */
            err = GbEMAC_Ioctl(&pCtlBlk->hEthDriver,
                               SET_RFIFO_HIGH_WATERMARK, (void*)&macIoctlInfo);
            if (err != SUCCESS)
            {
                err = IX_ERROR_REMOTE(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                                      ("high water mark set failed"));
                goto cleanupEthDriver;
            }
            macIoctlInfo.value = 0x300; /* low water mark 0x300 of 8 bytes */
            err = GbEMAC_Ioctl(&pCtlBlk->hEthDriver,
                               SET_RFIFO_LOW_WATERMARK, (void *)&macIoctlInfo);
            if( err != SUCCESS)
            {
                err = IX_ERROR_REMOTE(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                                      ("low water mark set failed"));
                goto cleanupEthDriver;
            }
            macIoctlInfo.value = 0x7; /* enable flow control capabilities */
            err = GbEMAC_Ioctl(&pCtlBlk->hEthDriver,
                               SET_FC_MODE, (void*)&macIoctlInfo);
            if (err != SUCCESS)
            {
                err = IX_ERROR_REMOTE(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                                      ("flow control set failed"));
                goto cleanupEthDriver;
            }

#if defined(IX_PLATFORM_2401) || defined(IX_PLATFORM_2801)
#ifdef ETH_TX_FLOW_CTRL
            /* TFIFO high watermark = 0x3E0 (default) */
            macIoctlInfo.portIndex = i;
            macIoctlInfo.value = ((1024 * 7.75)/8);
            err = GbEMAC_Ioctl(&(pCtlBlk->hEthDriver),
                               SET_TX_FIFO_HIGH_WATERMARK,
                               (void *)(&macIoctlInfo));
            if (err != SUCCESS)
            {
                err = IX_ERROR_NEW(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                                   IX_ERROR_LEVEL_LOCAL);
                goto cleanupEthDriver;
            }

            /**
             * TFIFO low watermark = 0x2D0 (changed from 0xD0(default)
             * to 0x2D0 to get rid of Line errors, CRC errors, byte-alignment
             * errors).
             */
            macIoctlInfo.portIndex = i;
            macIoctlInfo.value = ((1024 * 5.625)/8);
            err = GbEMAC_Ioctl(&(pCtlBlk->hEthDriver),
                               SET_TX_FIFO_LOW_WATERMARK,
                               (void *)(&macIoctlInfo));
            if (err != SUCCESS)
            {
                err = IX_ERROR_NEW(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                                   IX_ERROR_LEVEL_LOCAL);
                goto cleanupEthDriver;
            }

            /* MAC Threshold = 0x1BE (default) */
            macIoctlInfo.portIndex = i;
            macIoctlInfo.value = ((1024 * 3.485)/8);
            err = GbEMAC_Ioctl(&(pCtlBlk->hEthDriver),
                               SET_MAC_THRESHOLD,
                               (void *)(&macIoctlInfo));
            if (err != SUCCESS)
            {
                err = IX_ERROR_NEW(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                                   IX_ERROR_LEVEL_LOCAL);
                goto cleanupEthDriver;
            }
#endif /* ETH_TX_FLOW_CTRL */
#endif /* IX_PLATFORM_2x01 */

            macIoctlInfo.value = IX_CC_ETH_TX_FRAME_SIZE >> 3;
            err = GbEMAC_Ioctl(&pCtlBlk->hEthDriver,
                               SET_JUMBO_PKT_SIZE, (void *)&macIoctlInfo);
            if (err != SUCCESS)
            {
                err = IX_ERROR_REMOTE(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                                      ("jumbo frame size set failed"));
                goto cleanupEthDriver;
            }
          }
        } /* end for */
        /*
         * Register callback function with ethernet driver
         */
        err = GbEMAC_Callback(&pCtlBlk->hEthDriver,
                              (void *)_ix_cc_eth_tx_driver_callback, pCtlBlk);
        if (err != SUCCESS)
        {
            err = IX_ERROR_REMOTE(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                                  ("callback register failed"));
            goto cleanupEthDriver;
        }
    }
#else /* not _IX_BOARD_TYPE_ == _IX_IXDP2x01_ */

#if defined(IX_PLATFORM_2400)

    /* Initialize ethernet driver */
    err = GbEMAC_DeviceStart(IX_CC_ETH_TX_DRIVER_PORT_MASK,
                             &(pCtlBlk->hEthDriver),
                             IX_CC_ETH_TX_DRIVER_MODE_DEFAULT);
    if(err != SUCCESS)
    {
        err = IX_ERROR_NEW(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                           IX_ERROR_LEVEL_LOCAL);
        goto cleanupArp;
    }/* end if */

    for (i = 0; i < IX_CC_ETH_TX_MAX_NUM_PORTS;i++)
    {
        /* Set the JUMBO MTU size for all ports */
        macIoctlInfo.portIndex = i;
        macIoctlInfo.value = IX_CC_ETH_TX_FRAME_SIZE;
        err = GbEMAC_Ioctl(&(pCtlBlk->hEthDriver),
                           SET_MAX_FRAME_SIZE,
                           (void *)(&macIoctlInfo));
        if(err != SUCCESS)
        {
            err = IX_ERROR_NEW(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                               IX_ERROR_LEVEL_LOCAL);
            goto cleanupEthDriver;
        }/* end if */

        /* TFIFO high watermark = 0x3E0 (default) */
        macIoctlInfo.portIndex = i;
        macIoctlInfo.value = ((1024 * 7.75)/8);
        if (GbEMAC_Ioctl(&(pCtlBlk->hEthDriver), SET_TX_FIFO_HIGH_WATERMARK, (void *)(&macIoctlInfo)) != SUCCESS)
        {
            err = IX_ERROR_NEW(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                           IX_ERROR_LEVEL_LOCAL);
            goto cleanupEthDriver;
        }

        /**
         * TFIFO low watermark = 0x2D0 (changed from 0xD0(default) to 0x2D0 to
         * get rid of Line errors. CRC errors, byte-alignment errors).
         */
        macIoctlInfo.portIndex = i;
        macIoctlInfo.value = ((1024 * 5.625)/8);
        if (GbEMAC_Ioctl(&(pCtlBlk->hEthDriver), SET_TX_FIFO_LOW_WATERMARK, (void *)(&macIoctlInfo)) != SUCCESS)
        {
            err = IX_ERROR_NEW(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                           IX_ERROR_LEVEL_LOCAL);
            goto cleanupEthDriver;
        }

        /* MAC Threshold = 0x1BE (default) */
        macIoctlInfo.portIndex = i;
        macIoctlInfo.value = ((1024 * 3.485)/8);
        if (GbEMAC_Ioctl(&(pCtlBlk->hEthDriver), SET_MAC_THRESHOLD, (void *)(&macIoctlInfo)) != SUCCESS)
        {
            err = IX_ERROR_NEW(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                           IX_ERROR_LEVEL_LOCAL);
            goto cleanupEthDriver;
        }

        /* Set Tx padding enable bit for undersize packets */
        macIoctlInfo.portIndex = i;
        if (GbEMAC_Ioctl(&(pCtlBlk->hEthDriver), GET_DIV_CONFIG_WORD, (void *)(&macIoctlInfo)) != SUCCESS)
        {
            err = IX_ERROR_NEW(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                           IX_ERROR_LEVEL_LOCAL);
            goto cleanupEthDriver;
        }

        macIoctlInfo.portIndex = i;
        macIoctlInfo.value = macIoctlInfo.value | 0x80; /* bit 7 of the div config reg */
        if (GbEMAC_Ioctl(&(pCtlBlk->hEthDriver), SET_DIV_CONFIG_WORD, (void *)(&macIoctlInfo)) != SUCCESS)
        {
            err = IX_ERROR_NEW(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                           IX_ERROR_LEVEL_LOCAL);
            goto cleanupEthDriver;
        }
    }/* end for */

    /* Register callback function with ethernet driver */
    err = GbEMAC_Callback(&(pCtlBlk->hEthDriver),
                          (void *)_ix_cc_eth_tx_driver_callback,
                          pCtlBlk);
    if(err != SUCCESS)
    {
        err = IX_ERROR_NEW(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                           IX_ERROR_LEVEL_LOCAL);
        goto cleanupEthDriver;
    }/* end if */

#elif defined(IX_PLATFORM_2800)
    IX_ERROR_CG(_ix_cc_eth_tx_configure_media(pCtlBlk),
                err,
                cleanupEthDriver);
#endif /* defined(IX_PLATFORM_2800) */

#endif /* _IX_BOARD_TYPE_ */


    /* Update local interface table - property update */
#if (defined IX_PLATFORM_2401) || (defined IX_PLATFORM_2801)
#if (defined USE_HW_CONFIG)
    pCtlBlk->numberOfChannels = 0;
    for (i = 0; i < IX_CC_ETH_TX_MAX_NUM_PORTS; i++)
    {
        if (hwConfigEthPortMask & (1 << i))
        {
            pCtlBlk->portId[i] = i;

            /* Assign the port id to the local interface table */
            (pCtlBlk->pInterfaceTable + i)->portId = pCtlBlk->portId[i];
            /**
             * Store the local blade id. Assuming all nodes have same
             * blade id so it's ok to keep overwriting.
             */
            pCtlBlk->localBladeId = 1;
            pCtlBlk->numberOfChannels++;
        }
    }
#else
    IX_ERROR_CG(_ix_cc_eth_tx_update_local_interface_table(arg_ppContext,pCtlBlk),
                err,
                cleanupEthDriver);
#endif /* USE_HW_CONFIG */

#else /* IX_PLATFORM_2x01 */
    /* Orginal code */

    IX_ERROR_CG(_ix_cc_eth_tx_update_local_interface_table(arg_ppContext,pCtlBlk),
                err,
                cleanupEthDriver);
#endif /* IX_PLATFORM_2x01 */

    /* Register Message and packet Handlers */
    IX_ERROR_CG(_ix_cc_eth_tx_register_msg_pkt_handlers(pCtlBlk),err,cleanupEthDriver);
    /* Patch symbols */
    IX_ERROR_CG(_ix_cc_eth_tx_patch_symbols(pCtlBlk),err,cleanupMsgPktHandlers);

#ifdef MICROBLOCK_COUNTERS
    /* Create 64 bit counter */
    IX_ERROR_CGT(ix_rm_counter_64bit_new(IX_CC_ETH_TX_TOTAL_NUM_COUNTERS,
                                  pCtlBlk->pCounterBase32Bit,
                                  IX_CC_ETH_TX_32BIT_COUNTER_OVERFLOW_TIME,
                                  pCtlBlk->ahCounterHandlers64Bit),
                 err,IX_CC_ERROR_OOM_64BIT_COUNTER,
                 IX_ERROR_LEVEL_LOCAL,cleanupMsgPktHandlers);
#endif

    /* Set the initialization flag */
    pCtlBlk->initialized = TRUE;

    /* Assign ctrolblock structure to arg_ppContext */
    *arg_ppContext = (void *)pCtlBlk;
    return IX_SUCCESS;

cleanupMsgPktHandlers:
    _ix_cc_eth_tx_unregister_msg_pkt_handlers();

cleanupEthDriver:


#if defined(IX_PLATFORM_2401) || defined(IX_PLATFORM_2801)
    /* Platform specific. Use portMask variable instead of a fixed constant
     */
#if (_IX_BOARD_TYPE_ == _IX_IXDP2401_) || (_IX_BOARD_TYPE_ == _IX_IXDP2801_)

    GbEMAC_DeviceStop(pCtlBlk->portMask, &(pCtlBlk->hEthDriver));

#elif (_IX_BOARD_TYPE_ == _IX_IXDP2800_)
    IxfApiReset(pCtlBlk->pChipData, &section, bb_RESET_CHIP);
#elif (_IX_BOARD_TYPE_ == _IX_IXDP2400_)
    GbEMAC_DeviceStop(IX_CC_ETH_TX_DRIVER_PORT_MASK, &(pCtlBlk->hEthDriver));
#else /* _IX_BOARD_TYPE_ == ... */
#error Board type undefined.
#endif /* _IX_BOARD_TYPE_ == ... */

#else /* defined(IX_PLATFORM_2401) || defined(IX_PLATFORM_2801) */
    /* Original code before changes */

#if defined(IX_PLATFORM_2800)
    IxfApiReset(pCtlBlk->pChipData, &section, bb_RESET_CHIP);
#else
    GbEMAC_DeviceStop(IX_CC_ETH_TX_DRIVER_PORT_MASK, &(pCtlBlk->hEthDriver));
#endif /* defined(IX_PLATFORM_2800) */

#endif //#if defined(IX_PLATFORM_2401) || defined(IX_PLATFORM_2801)


#if !defined(IX_PLATFORM_2800)
cleanupArp:
    ix_cc_arp_fini();
#endif /* !defined(IX_PLATFORM_2800) */

cleanupL2tm:
    ix_cc_l2tm_destroy(pCtlBlk->hL2TM);
cleanupSymbols:
    _ix_cc_eth_tx_free_symbols(pCtlBlk);
cleanupInterfaceTable:
    _ix_cc_eth_tx_free_local_interface_table(pCtlBlk);
cleanupMutex:
    ix_ossl_mutex_fini(pCtlBlk->mid);
    pCtlBlk->mid = 0;
cleanupCtlBlk:
    ix_ossl_free(pCtlBlk);
    pCtlBlk = NULL;
    return err;
} /* ix_cc_eth_tx_init */


#if defined(IX_PLATFORM_2800)

/**
 * NAME: _ix_cc_eth_tx_configure_media
 *
 * DESCRIPTION: This function configures the 10x1Gb media interface.
 *
 * @Param: arg_pContext - IN: pointer to the component context number
 *
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
ix_error _ix_cc_eth_tx_configure_media(
    ix_cc_eth_tx_ctl_blk *arg_pCtlBlk)
{

    ix_uint8 *media_chip_virtual_addr = NULL;

    /* Get the media chip virtual address */
    if ((media_chip_virtual_addr = (ix_uint8 *)ioremap_nocache(IXF1110_BASE_ADDRESS, IXF1110_SIZE)) == 0)
    {
        return(IX_ERROR_LOCAL(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                              ("Failed to map media interface virtual address.")));
    }

    /* Allocate the bb_ChipData_t structure */
    if ((arg_pCtlBlk->pChipData = (bb_ChipData_t *)ix_ossl_malloc(sizeof(bb_ChipData_t))) == NULL)
    {
        return(IX_ERROR_REMOTE(IX_CC_ERROR_OOM_SYSTEM,
                               ("Out of memory for media driver bb_ChipData_t structure.")));
    }

    /* Initialize the framer device driver */
    if (IxfApiInit((bb_RegPointer_type)media_chip_virtual_addr,
                   bb_1110_CHIP,
                   arg_pCtlBlk->pChipData) != bb_NO_ERROR)
    {
        ix_ossl_free(arg_pCtlBlk->pChipData);
        return(IX_ERROR_LOCAL(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                              ("Initialization of ETHERNET media device failed.")));
    }

    /**
     * Allocate memory within the pChipData for members that
     * need dynamic allocation.  This is required for enabling alarm capability.
     */
    if (IxfApiAllocDataStructureMem(arg_pCtlBlk->pChipData) != bb_NO_ERROR)
    {
        /* Free framer data structures */
        ix_ossl_free(arg_pCtlBlk->pChipData);

        return(IX_ERROR_LOCAL(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                              ("Dynamic memory allocation required by media device driver failed.")));
    }

    /* Configure the media card using the pre-generated table. */
    if (IxfApiInitChip(arg_pCtlBlk->pChipData,
                       BoardInitIXF1110Table) != bb_NO_ERROR)
    {
        IxfApiDeAllocMemory(arg_pCtlBlk->pChipData);
        ix_ossl_free(arg_pCtlBlk->pChipData);
        return(IX_ERROR_LOCAL(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                              ("Configuration of media device failed.")));
    }

    /* Initialization driver ISR */
    if (ixd2810IsrInit(arg_pCtlBlk->pChipData) != bb_NO_ERROR)
    {
        IxfApiDeAllocMemory(arg_pCtlBlk->pChipData);
        ix_ossl_free(arg_pCtlBlk->pChipData);
        return(IX_ERROR_LOCAL(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                              ("Initialization of media driver ISR failed.")));
    }

    /* Register an alarm callback function into the device driver. */
    if (IxfApiInitAlarmCallback(arg_pCtlBlk->pChipData,
                                (AlarmCallBack)_ix_cc_eth_tx_media_alarm_callback) != bb_NO_ERROR)
    {
        IxfApiDeAllocMemory(arg_pCtlBlk->pChipData);
        ix_ossl_free(arg_pCtlBlk->pChipData);
        return(IX_ERROR_LOCAL(IX_CC_ETH_TX_ERROR_MEDIA_INIT,
                              ("Registering of media alarm callback failed.")));
    }

    return(IX_SUCCESS);

} /* _ix_cc_eth_tx_configure_media */



/**
 * NAME: _ix_cc_eth_tx_media_alarm_callback
 *
 * DESCRIPTION: This function is the framer alarm callback function.
 *              The function is registered in the init function and
 *              will be called by the IXF API function, IxfApiChipIsr.
 *
 * @Param: arg_pChipdata - IN: framer chip data structure
 * @Param: arg_AlarmType - IN: alarm type
 * @Param: arg_AlarmStatus - IN: alarm status structure
 *
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 */
void _ix_cc_eth_tx_media_alarm_callback(
    bb_ChipData_t* arg_pChipData,
    bb_AlarmType_e arg_AlarmType,
    void* arg_pAlarmStatus)
{
    ix_uint32 port;
    ix_uint32 rxBitIndex = GS_RX_STARTING_BIT; /* GBIC_STATUS bits 29:20 */
    ix_uint32 changedBit;
    ix_uint32 gbicStatus;
    ix_cc_properties propData;
/*
    propData.blade_id = ((ix_cc_eth_tx_ctl_blk*)arg_pCtlBlk)->localBladeId;
*/

    propData.media_type = IX_MEDIA_TYPE_1GB_ETHERNET;

    if (arg_AlarmType != bb_1110_XGMAC_ALARM)
    {
        /* Other alarm will not be processed in this release */
#ifdef IX_DEBUG
        ix_ossl_message_log("Media alarm type %d is not processed in current release.\n", arg_AlarmType);
#endif
        return;
    }

    /* Retrieve the current GBIC status and changed bit */
    changedBit = ((ixf1110_AlarmCfgSet_t *)arg_pAlarmStatus)->Gbic_Change.ulReg;
    gbicStatus = ((ixf1110_AlarmCfgSet_t *)arg_pAlarmStatus)->Gbic_Status.ulReg;

    /* Traverse ecah changed port */
    for (port = 0; port < IX_CC_ETH_TX_MAX_NUM_PORTS; port++, rxBitIndex <<= 1)
    {
        if (changedBit & rxBitIndex) /* bit changed for this port */
        {
            if (gbicStatus & rxBitIndex)
            {
#ifdef IX_DEBUG
                ix_ossl_message_log("\nEth Tx CC: port %ld is DOWN.\n", port);
#endif
                propData.link_state = IX_CC_LINK_STATUS_DOWN;
            }
            else
            {
#ifdef IX_DEBUG
                ix_ossl_message_log("\nEth Tx CC: port %ld is UP.\n", port);
#endif
                propData.link_state = IX_CC_LINK_STATUS_UP;
            }

            /* Send broadcast message to all clients */
/*            propData.port_id = ((ix_cc_eth_tx_ctl_blk*)arg_pCtlBlk)->portId[port]; */
            ix_cc_async_set_property(IX_CC_SET_PROPERTY_LINK_STATUS,&propData);
        }
    }

    return;

} /* _ix_cc_eth_tx_media_alarm_callback */

#endif /* defined(IX_PLATFORM_2800) */











