/**
 * ============================================================================
 * = 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_fini.c
 *
 * = DESCRIPTION
 *      This file defines fini routines.
 *
 * = CHANGE HISTORY
 *      11/25/2002 - Created.
 *
 * ============================================================================
 * $Id: ix_cc_eth_tx_fini.c,v 1.17 2003/10/29 02:09:55 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"
#include "cc/ix_cc_arp.h"
#include "cc/ix_cc_l2tm.h"

/* ethernet driver files */
#if (_IX_BOARD_TYPE_ == _IX_IXDP2401_) || (_IX_BOARD_TYPE_ == _IX_IXDP2801_)

#include "ixf1104ce_driver_api.h"

#else /* (_IX_BOARD_TYPE_ == _IX_IXDP2x01_) */

#if defined(IX_PLATFORM_2400)

#if (_IX_OS_TYPE_ == _IX_OS_LINUX_KERNEL_)
#include "ixf1104ce_linux_driver.h"
#include "cc/internal/ix_cc_eth_tx_drv_wrapper.h"
#else
#include "ixf1104ce_driver_api.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"
#else
/* Include VxWorks media driver header files here */
#endif /* (_IX_OS_TYPE_ == _IX_OS_LINUX_KERNEL_) */

#endif /* defined(IX_PLATFORM_2800) */

#endif /* _IX_BOARD_TYPE_ */


#if defined(IX_PLATFORM_2800)
PRIVATE ix_error _ix_cc_eth_tx_fini_media(ix_cc_eth_tx_ctl_blk *);
#endif /* defined(IX_PLATFORM_2800) */

/* static functions */

/**
 * NAME: _ix_cc_eth_tx_delete_64bit_counters
 *
 * DESCRIPTION: This primitive will be used to free 64 bit counters 
 * 
 * @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_DELETE_64BIT_COUNTER  - not able to delete 64 bit counters
 * 
 */

ix_error _ix_cc_eth_tx_delete_64bit_counters(ix_cc_eth_tx_ctl_blk *arg_pCtlBlk)
{

#ifdef MICROBLOCK_COUNTERS
    ix_uint32 ethTxIndex;
    for(ethTxIndex =0; ethTxIndex < IX_CC_ETH_TX_TOTAL_NUM_COUNTERS;ethTxIndex++)
    {
        IX_ERROR_CRT(ix_rm_counter_64bit_delete(arg_pCtlBlk->ahCounterHandlers64Bit[ethTxIndex]),
                     IX_CC_ETH_TX_ERROR_RM_DELETE_64BIT_COUNTER,
                     IX_ERROR_LEVEL_LOCAL);
        arg_pCtlBlk->ahCounterHandlers64Bit[ethTxIndex] = 0;
    }/* end for delete 64 bit counters */
#endif
    return IX_SUCCESS;
}/* end _ix_cc_eth_tx_delete_64bit_counters */


/**
 * NAME: _ix_cc_eth_tx_free_local_interface_table
 *
 * DESCRIPTION: This primitive will be used to free memory of 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  - not able to allocate memory
 * 
 */

ix_error _ix_cc_eth_tx_free_local_interface_table(ix_cc_eth_tx_ctl_blk *arg_pCtlBlk)
{
    ix_uint32 i;
    ix_cc_eth_tx_ip_addr_table *ipAddrEntry = NULL;
    ix_cc_eth_tx_ip_addr_table *ipAddrNextEntry = NULL;
    ix_cc_eth_tx_local_interface_table *pLocalTable = arg_pCtlBlk->pInterfaceTable;

    if(pLocalTable != NULL)
    {
        for(i = 0; i < IX_CC_ETH_TX_MAX_NUM_PORTS; i ++)
        {
            ipAddrEntry = (pLocalTable + i)->pIpAddrTable;
            if(ipAddrEntry != NULL)
            {        
                while(ipAddrEntry->pNextEntry != NULL)
                {
                    ipAddrNextEntry = ipAddrEntry->pNextEntry;
                    /* empty the content of this node */
                    ix_ossl_memset(ipAddrEntry,0,sizeof(ix_cc_eth_tx_ip_addr_table));
                    ix_ossl_free(ipAddrEntry);
                    ipAddrEntry = ipAddrNextEntry;
                }/* end while ipAddr list */
        
            }/* end if traverse the IP Address table */
        }/* end for traverse the local interface table */
        /* empty the content of table */
        ix_ossl_memset(arg_pCtlBlk->pInterfaceTable,0,
        sizeof(ix_cc_eth_tx_local_interface_table) * IX_CC_ETH_TX_MAX_NUM_PORTS);
        ix_ossl_free(arg_pCtlBlk->pInterfaceTable);
    }/* end if interface table is not null */

    return IX_SUCCESS;
}/* end _ix_cc_eth_tx_free_local_interface_table */


/**
 * NAME: _ix_cc_eth_tx_free_symbols
 *
 * DESCRIPTION: This primitive will be used to free 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  - not able to allocate memory
 * 
 */

ix_error _ix_cc_eth_tx_free_symbols(ix_cc_eth_tx_ctl_blk *arg_pCtlBlk)
{

#ifdef MICROBLOCK_COUNTERS
    ix_error err = IX_SUCCESS;
    if(arg_pCtlBlk->pCounterBase32Bit != NULL)
    {
        err = ix_rm_mem_free(arg_pCtlBlk->pCounterBase32Bit);

        if(err != IX_SUCCESS)
        {
            return IX_ERROR_LOCAL(IX_CC_ETH_TX_ERROR_RM_FREE_MEM,
                                ("Memory free failed for symbols"));
        }/* end if (err != IX_SUCCESS) */
        arg_pCtlBlk->pCounterBase32Bit = NULL;
    }/* end if counterbase is not null */
#endif
    return IX_SUCCESS;
}/* end _ix_cc_eth_tx_free_symbols */

/**
 * NAME: _ix_cc_eth_tx_unregister_msg_pkt_handlers
 *
 * DESCRIPTION: This primitive will be used to unregister message and packet handlers. 
 * 
 * @Param: none
 *
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 * 
 * IX_CC_ETH_TX_ERROR_REM_HDLR - Error from CCI/RM
 * 
 */

ix_error _ix_cc_eth_tx_unregister_msg_pkt_handlers()
{
    /* Call CCI message/packet handler if CCI is enabled */
#if defined(IX_EXCLUDE_CCI)
    /* Un register low priority packet handler input via packet handler */
    IX_ERROR_CRT(ix_rm_packet_handler_unregister(IX_CC_ETH_TX_UBLK_PKT_INPUT),
                 IX_CC_ETH_TX_ERROR_REM_HDLR,
                 IX_ERROR_LEVEL_LOCAL);
    /* Un register high priority packet input via message handler */
    IX_ERROR_CRT(ix_rm_message_handler_unregister(IX_CC_ETH_TX_ARP_PKT_INPUT),
                 IX_CC_ETH_TX_ERROR_REM_HDLR,
                 IX_ERROR_LEVEL_LOCAL);
    /* Un register the property message handler */
    IX_ERROR_CT(ix_rm_message_handler_unregister(IX_CC_ETH_TX_PROPERTY_MSG_INPUT),
                IX_CC_ETH_TX_ERROR_REM_HDLR, 
                IX_ERROR_LEVEL_LOCAL);
    /* UN register message handler */
    IX_ERROR_CRT(ix_rm_message_handler_unregister(IX_CC_ETH_TX_MSG_INPUT),
                 IX_CC_ETH_TX_ERROR_REM_HDLR,
                 IX_ERROR_LEVEL_LOCAL);

#else
    /* Un register low priority packet handler input via packet handler */
    IX_ERROR_CRT(ix_cci_cc_remove_packet_handler(IX_CC_ETH_TX_UBLK_PKT_INPUT),
                 IX_CC_ETH_TX_ERROR_REM_HDLR,
                 IX_ERROR_LEVEL_LOCAL);
    /* Un register high priority packet input via message handler */
    IX_ERROR_CRT(ix_cci_cc_remove_message_handler(IX_CC_ETH_TX_ARP_PKT_INPUT),
                 IX_CC_ETH_TX_ERROR_REM_HDLR,
                 IX_ERROR_LEVEL_LOCAL);
    /* Un register the property message handler */
    IX_ERROR_CRT(ix_cci_cc_remove_message_handler(IX_CC_ETH_TX_PROPERTY_MSG_INPUT),
                 IX_CC_ETH_TX_ERROR_REM_HDLR, 
                 IX_ERROR_LEVEL_LOCAL);
    /* Un register message handler */
    IX_ERROR_CRT(ix_cci_cc_remove_message_handler(IX_CC_ETH_TX_MSG_INPUT),
                 IX_CC_ETH_TX_ERROR_REM_HDLR,
                 IX_ERROR_LEVEL_LOCAL);

#endif
    return IX_SUCCESS;
} /* _ix_cc_eth_tx_unregister_msg_pkt_handlers */


/**
 * NAME: ix_cc_eth_tx_fini
 * 
 * DESCRIPTION: This function terminates Ethernet Tx CC.
 * This will free all the allocated resources by init function.
 * 
 * @Param: arg_hCcHandle - IN : Handle of Ethernet Tx core component
 * @Param: arg_pContext - IN : pointer to control block structure of 
 * eth tx core component
 * @Return: IX_SUCCESS if successful or a valid ix_error for failure.
 *
 */    
ix_error ix_cc_eth_tx_fini(
         ix_cc_handle arg_hCcHandle,  
         void* arg_pContext)
{
    /* Validate input argument: arg_pContext */
    if(arg_pContext == NULL)
    {
        return IX_ERROR_WARNING(IX_CC_ERROR_NULL,
                                ("Input parameter(arg_ppContext) is null"));
    }/* end if null context */
    /* Validate input argument: arg_hCcHandle */
    if(arg_hCcHandle != ((ix_cc_eth_tx_ctl_blk *)arg_pContext)->hEthTxHandle)
    {
        return IX_ERROR_WARNING(IX_CC_ETH_TX_ERROR_INVALID_HANDLE,
                                ("Input parameter(arg_hCcHandle) is invalid"));
    }/* end if invalid handle */     
    /* Delete 64 bit counters */
    IX_ERROR_CR(_ix_cc_eth_tx_delete_64bit_counters((ix_cc_eth_tx_ctl_blk *)arg_pContext));
    /* Unregister message and packet handlers */
    IX_ERROR_CR(_ix_cc_eth_tx_unregister_msg_pkt_handlers());

#if defined(IX_PLATFORM_2800)

    /* Reset the media device */
    IX_ERROR_CR(_ix_cc_eth_tx_fini_media(arg_pContext));

#else /* defined(IX_PLATFORM_2800) */

    /* Terminate Ethernet driver */
#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_)

    IX_ERROR_CRT(GbEMAC_DeviceStop(((ix_cc_eth_tx_ctl_blk *)arg_pContext)->portMask,
                                   (unsigned int *)&(((ix_cc_eth_tx_ctl_blk *)arg_pContext)->hEthDriver)),
                 IX_CC_ETH_TX_ERROR_MEDIA_FINI,
                 IX_ERROR_LEVEL_LOCAL);

#else // _IX_BOARD_TYPE_ == ...

    IX_ERROR_CRT(GbEMAC_DeviceStop(IX_CC_ETH_TX_DRIVER_PORT_MASK,
                                   (unsigned int *)&(((ix_cc_eth_tx_ctl_blk *)arg_pContext)->hEthDriver)),
                 IX_CC_ETH_TX_ERROR_MEDIA_FINI,
                 IX_ERROR_LEVEL_LOCAL);
    
#endif // _IX_BOARD_TYPE_ == ...
    
#else //#if defined(IX_PLATFORM_2401) || defined(IX_PLATFORM_2801)
    /* Original code before changes */
      
    IX_ERROR_CRT(GbEMAC_DeviceStop(IX_CC_ETH_TX_DRIVER_PORT_MASK,
                                   (unsigned int *)&(((ix_cc_eth_tx_ctl_blk *)arg_pContext)->hEthDriver)),
                 IX_CC_ETH_TX_ERROR_MEDIA_FINI,
                 IX_ERROR_LEVEL_LOCAL);
    
#endif //#if defined(IX_PLATFORM_2401) || defined(IX_PLATFORM_2801)
    

#endif /* defined(IX_PLATFORM_2800) */

    /* Terminate ARP library */
    IX_ERROR_CRT(ix_cc_arp_fini(),
                IX_CC_ETH_TX_ERROR_ARP_FINI,
                IX_ERROR_LEVEL_LOCAL);
    /* Terminate L2TM library */
    IX_ERROR_CRT(ix_cc_l2tm_destroy(((ix_cc_eth_tx_ctl_blk *)arg_pContext)->hL2TM),
                 IX_CC_ETH_TX_ERROR_L2TM_FINI,
                 IX_ERROR_LEVEL_LOCAL);
    /* Free memory for symbols */
    IX_ERROR_CR(_ix_cc_eth_tx_free_symbols((ix_cc_eth_tx_ctl_blk *)arg_pContext));
    /* Free memory for local_interface_table */
    IX_ERROR_CR(_ix_cc_eth_tx_free_local_interface_table( (ix_cc_eth_tx_ctl_blk *)arg_pContext));
    /* Free the mutex */
    IX_ERROR_CRT(ix_ossl_mutex_fini(((ix_cc_eth_tx_ctl_blk *)arg_pContext)->mid),
                 IX_CC_ETH_TX_ERROR_OSSL_MUTEX_FINI,
                 IX_ERROR_LEVEL_LOCAL);
    /* erase the content of control block structure */
    ix_ossl_memset(arg_pContext,0,sizeof(ix_cc_eth_tx_ctl_blk));
    /* Free the control block structure */
    ix_ossl_free(arg_pContext);
    return IX_SUCCESS;
} /* ix_cc_eth_tx_fini */



#if defined(IX_PLATFORM_2800)

/**
 * NAME: _ix_cc_eth_tx_fini_media
 *
 * DESCRIPTION: This function reset the media device.
 *
 * @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.
 */
PRIVATE ix_error _ix_cc_eth_tx_fini_media(
    ix_cc_eth_tx_ctl_blk *arg_pCtlBlk)
{

    bb_ChipSegment_t section;
    section.group.channel = 0;

    /* Reset the media chip. */
    if (IxfApiReset(arg_pCtlBlk->pChipData, &section, bb_RESET_CHIP) != bb_NO_ERROR)
    {
        return(IX_ERROR_LOCAL(IX_CC_ETH_TX_ERROR_MEDIA_RESET,
                              ("Reset of Ethernet media device failed.")));
    }

    /* Free framer data structures */
    ix_ossl_free(arg_pCtlBlk->pChipData);

    return(IX_SUCCESS);

} /* _ix_cc_eth_tx_fini_media */

#endif /* defined(IX_PLATFORM_2800) */
