/**
 * ============================================================================
 * = COPYRIGHT
 *              INTEL CORPORATION PROPRIETARY INFORMATION
 *   This software is supplied under the terms of a license agreement or
 *   nondisclosure agreement with Intel Corporation and may not be copied 
 *   or disclosed except in accordance with the terms in that agreement.
 *      Copyright (C) 2000-2001 Intel Corporation. All rights reserved.
 *
 * = PRODUCT
 *      Intel(r) IXA SDK 3.0 for the IXP2000 Network Processor
 *
 * = LIBRARY
 *      
 *
 * = MODULE
 *      ATM TM4.1 Core Component
 *
 * = FILENAME
 *      ix_cc_atmtm41_plugin.c
 *
 * = DESCRIPTION
 *      The file defines functions that are registered in ATM SAR as
 *      plugin functions.
 *
 * = AUTHOR
 *       Jaroslaw Kogut
 *       jaroslaw.kogut@intel.com
 *
 * = AKNOWLEDGEMENTS
 *      
 *
 * = CREATION TIME
 *      11/07/2002
 *
 * = CHANGE HISTORY
 *
 * ============================================================================
 */
#define IX_ERROR_FILE_IDENT "$Id: ix_cc_atmtm41_plugin.c,v 1.9 2003/12/12 19:18:29 adziecia Exp $";

/**
 * System defined include files
 */
#include "ix_cc_error.h"
#include "ix_rm.h"
#include "ix_ossl.h"
#include "ix_cc.h"
#include "ix_cc_macros.h"
#include "ix_config.h"
#include "bindings.h"
#include "cc/ix_cc_atmsar_plugin.h"

/**
 * User defined include files
 */
#include "cc/ix_cc_atmtm41_cci.h"
#include "cc/internal/ix_cc_atmtm41_private.h"

/**
 * Preprocessor symbols and Macros used in this file
 */

/**
 * Type definitions whose scope is limited to this file
 */


/**
 * Variable declarations global to this file only. Externs are followed by 
 * static variables.
 */

/** 
 * Extern function prototypes.
 */


/** 
 * Static function prototypes.
 */

static ix_error _ix_cc_atmtm41_port_add_vc(
_ix_cc_atmtm41_context_t *arg_pContext,
ix_uint16 arg_portNo,
ix_cc_atmsar_vc_handle_t arg_hVc,
ix_uint32 arg_cps);

static ix_error _ix_cc_atmtm41_port_del_vc(
_ix_cc_atmtm41_context_t *arg_pContext,
ix_cc_atmsar_vc_handle_t arg_hVc);

/** 
 * Function definitions.
 */

ix_uint32 _ix_cc_atmtm41_plugin_get_hbr_slots(ix_uint32 arg_rate);

#define LINE_RATE_X_ONE_TRANS_SLOT    (_IX_CC_ATMTM41_LINE_RATE * ONE_TRANS_SLOT)


/******************************************************************************
 *                        SUPPORT FOR GCRA TABLE
 *****************************************************************************/

/*
 * GCRA STRUCTURE:
 *
 *        3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 
 *        1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 <- bits
 *       +---------------+---------------+---------------+---------------+
 *    LW0| TAT1_low                                                      |
 *       +---------------+---------------+---------------+---------------+
 *    LW1| TAT1_high                                                     |
 *       +---------------+---------------+---------------+---------------+
 *    LW2| DEBIT                                                         |
 *       +---------------+---------------+---------------+---------------+
 *    LW3| DEBIT_LIMIT                                                   |
 *       +---------------+---------------+---------------+---------------+
 *    LW4|V|R| PRI |       Port#         | X - GFR credit                |
 *       +---------------+---------------+---------------+---------------+
 *    LW5|     tau1      |           T1                                  |
 *       +---------------+---------------+---------------+---------------+
 *    LW6|     delta                                     |   code        |
 *       +---------------+---------------+---------------+---------------+
 *    LW7| resv. | LR    |           T2                                  |
 *       +---------------+---------------+---------------+---------------+
 *    LW8|             QUANTIZATION ERROR          |        THmask       |
 *       +-----------------------------------------+---------------------+
 *    R - reserved
 *    V - valid entry
 *    T - TAT1 timestap 0-SCR timestamp, 1-PCR timestamp
 *
 * NOTE 1 : unused parameters (like pri for CBR traffic) should be set 0
 */

/*                               funcPfx,            varName, lw, offset, mask */
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_gcra, debit,   2,  0,      0x0FFFFFFFF);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_gcra, debit_limit, 3,  0,      0x0FFFFFFFF);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_gcra, pri,     4,  27,     0x07);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_gcra, port,    4,  16,     0x07FF);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_gcra, valid,   4,  31,     0x01);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_gcra, t_type,  4,  30,     0x01);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_gcra, t1,      5,   0,     0x0FFFFFF);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_gcra, tau1,    5,  24,     0x0FF);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_gcra, code,    6,   0,     0x0FF);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_gcra, delta,   6,   8,     0x0FFFFFF);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_gcra, t2,      7,   0,     0x0FFFFFF);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_gcra, lr,      7,  24,     0x0F);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_gcra, th_mask, 8,   0,     0x7FF);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_gcra, qerror,  8,  11,     0x1FFFFF);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_gcra, tau2,    6,   8,     0x0FFFFFF);

/**
 * NAME: _ix_cc_atmtm41_gcra_get_entry
 *
 * DESCRIPTION:
 *    Find pointer to secondary bucket.
 *
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - IN arg_entryId - Id of requested bucket
 *
 * @Return: NULL if error occurs, otherwise pointer to secondary bucket.
 */
ix_uint32*
_ix_cc_atmtm41_gcra_get_entry(
_ix_cc_atmtm41_context_t* arg_pContext,
ix_uint16 arg_entryId)
{
    if(arg_entryId>=IX_CC_ATMSAR_VCID_INVALID)
    {
        return NULL;
    }
    return arg_pContext->pSymbolTable[_IX_CC_ATMTM41_GCRA_PARAM_TABLE_SYMBOL_ID]+(arg_entryId*(GCRA_ENTRY_SIZE>>2));
} /* end _ix_cc_atmtm41_gcra_get_entry */


/**
 * NAME: _ix_cc_atmtm41_show_gcra_param
 *
 * DESCRIPTION:
 *    This function calculates and sets up the TM4.1 parameters in the
 *    GCRA table.
 *
 * @Param:  IN  arg_hVC :  handle to VC.
 * @Param:  IN  arg_pVcDescr : parameters describing requested VC.
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_SUCCESS - ATM port successfully created
 *    IX_CC_ATMSAR_ERROR_INVALID_PARAM - invalid input parameters
 *    IX_CC_ATMSAR_ERROR_NO_RESOURCES - no resources to add the entry
 */
static void
_ix_cc_atmtm41_show_gcra_param(
ix_uint32* arg_pEntry)
{
    _IX_CC_ATMTM41_DBG_VC(("GCRA PARAMS:\n"));
    _IX_CC_ATMTM41_DBG_VC(("   PORT: %-8lx, PRI:  %-8lx, thMask: %-8lx, LR:   %-8lx\n",
                           _ix_cc_atmtm41_gcra_get_port(arg_pEntry), _ix_cc_atmtm41_gcra_get_pri(arg_pEntry),
                           _ix_cc_atmtm41_gcra_get_th_mask(arg_pEntry), _ix_cc_atmtm41_gcra_get_lr(arg_pEntry)));
    _IX_CC_ATMTM41_DBG_VC(("   T1:   %-8lx, tau1: %-8lx, T2:     %-8lx\n",
                           _ix_cc_atmtm41_gcra_get_t1(arg_pEntry), _ix_cc_atmtm41_gcra_get_tau1(arg_pEntry),
                           _ix_cc_atmtm41_gcra_get_t2(arg_pEntry)));
    _IX_CC_ATMTM41_DBG_VC(("   debit: %-8lx, debit_limit: %-8lx, delta: %-8lx\n", _ix_cc_atmtm41_gcra_get_debit(arg_pEntry),
                           _ix_cc_atmtm41_gcra_get_debit_limit(arg_pEntry), _ix_cc_atmtm41_gcra_get_delta(arg_pEntry)));
    _IX_CC_ATMTM41_DBG_VC(("   QERROR: %-8lx\n",
                           _ix_cc_atmtm41_gcra_get_qerror(arg_pEntry)));
} /* end _ix_cc_atmtm41_show_gcra_param */

/**
 * NAME: _ix_cc_atmtm41_set_lbr_vc_param
 *
 * DESCRIPTION:
 *    This function calculates and sets up the TM4.1 parameters in the
 *    GCRA table.
 *
 * @Param:  IN  arg_pContext - pointer to context of current core component.
 * @Param:  IN  arg_vcq :  VC queue number
 * @Param:  IN  arg_pEntry :  entry to fill with GCRA Parameters
 * @Param:  IN  arg_pVcDescr : parameters describing requested VC.
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_SUCCESS - ATM port successfully created
 *    IX_CC_ATMSAR_ERROR_INVALID_PARAM - invalid input parameters
 *    IX_CC_ATMSAR_ERROR_NO_RESOURCES - no resources to add the entry 
 */
static ix_error
_ix_cc_atmtm41_set_lbr_vc_param(
_ix_cc_atmtm41_context_t* arg_pContext,
const ix_uint16 arg_vcq,
ix_uint32* arg_pEntry,
const ix_cc_atmsar_vc_descr_t *arg_pVcDescr)
{
#define ROUND(x) (((x-((ix_uint32)x))>=0.5)?((ix_uint32)x+1):((ix_uint32)x))
    
#define GCRA_T_PARAM(__value) (ROUND((LINK_RATE_PCR/(__value * ONE_TIMESTAMP)))*ONE_TRANS_SLOT)

#define GCRA_TAU_PARAM(__value) (((__value)*ONE_TRANS_SLOT)>>arg_pContext->log2Aggregation)
    /*#define GCRA_TAU_PARAM(__value) (__value)*/
    
    const ix_cc_atmsar_tp_direction_t* pDesc;
    ix_uint32 n;

    _IX_CC_ATMTM41_DBG_VC(("Starting _ix_cc_atmtm41_set_lbr_vc_param() \n"));

    /* Extract trafic contract related parameters */
    pDesc = &arg_pVcDescr->trafficParams.fwd;

    /*  Fill in the parameters for different Service Classes defined in TM4.1
     *  All time related parameters should be calculated in MEV2 timestamps units
     *  Therefore the are multiplied by ONE_TRANS_SLOT/ONE_TIMESTAMP.
     *  ONE_TIMESTAMP = 16 - use >>4 instead of division. */

	/* Initialize the new entry */
    ix_ossl_memset((void *)arg_pEntry, 0, GCRA_ENTRY_SIZE);

    switch (arg_pVcDescr->trafficParams.serviceClass)
    {
    case IX_CC_ATMSAR_ATM_SERVICE_CBR:
		/*  CBR  is defined by the following constraints:
		 * 1. The flow with a given PCR and CDVT should conform to
		 *    GCRA(T1 = LR/PCR, tt1 = CDVT), where LR is the Link Rate.
		 * 2. The cells of the flow may have a maximum per node delay of Max CTD (?) */
        if(pDesc->pcr == 0)
        {
            return IX_ERROR_WARNING(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                                    ("ATM TM4.1> PCR parameter for CBR VC is zero\n"));
        }

        _ix_cc_atmtm41_gcra_set_t1(arg_pEntry, GCRA_T_PARAM(pDesc->pcr));
		_ix_cc_atmtm41_gcra_set_tau1(arg_pEntry, GCRA_TAU_PARAM(pDesc->cdvt));
        _ix_cc_atmtm41_gcra_set_code(arg_pEntry, 0x01);
		break;

    case IX_CC_ATMSAR_ATM_SERVICE_RT_VBR:
		/*  rtVBR/nrtVBR is defined by the following constraints:
		 *  1. The flow with a given PCR and CDVT should conform to
		 *     GCRA(T1 = LR/PCR, tt1 = CDVT)
		 *  2. The flow with a given SCR and BT should conform to
		 *     GCRA(T2 = LR/SCR, tt2 = CDVT+BT)
		 *  3. for rtVBR - the cells of the flow may have a maximum per
		 *     node delay of Max CTD (?) */
        if(pDesc->pcr == 0)
        {
            return IX_ERROR_WARNING(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                                    ("ATM TM4.1> PCR parameter for rt-VBR VC is zero\n"));
        }
        if(pDesc->scr == 0)
        {
            return IX_ERROR_WARNING(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                                    ("ATM TM4.1> SCR parameter for rt-VBR VC is zero\n"));
        }
        if(pDesc->mbs == 0)
        {
            return IX_ERROR_WARNING(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                                    ("ATM TM4.1> MBS parameter for rt-VBR VC is zero\n"));
        }
		_ix_cc_atmtm41_gcra_set_t1(arg_pEntry, GCRA_T_PARAM(pDesc->pcr));
		_ix_cc_atmtm41_gcra_set_tau1(arg_pEntry, GCRA_TAU_PARAM(pDesc->cdvt));
		_ix_cc_atmtm41_gcra_set_t2(arg_pEntry, GCRA_T_PARAM(pDesc->scr));
		n =_ix_cc_atmtm41_gcra_get_t2(arg_pEntry)-_ix_cc_atmtm41_gcra_get_t1(arg_pEntry);
		_ix_cc_atmtm41_gcra_set_delta(arg_pEntry, n);
		n *= (pDesc->mbs-1);
		_ix_cc_atmtm41_gcra_set_debit_limit(arg_pEntry, n);
                _ix_cc_atmtm41_gcra_set_code(arg_pEntry, 0x02);
		break;

    case IX_CC_ATMSAR_ATM_SERVICE_NRT_VBR:
		/*  rtVBR/nrtVBR is defined by the following constraints:
		 *  1. The flow with a given PCR and CDVT should conform to
		 *     GCRA(T1 = LR/PCR, tt1 = CDVT)
		 *  2. The flow with a given SCR and BT should conform to
		 *     GCRA(T2 = LR/SCR, tt2 = CDVT+BT)
		 *  3. for rtVBR - the cells of the flow may have a maximum per
		 *     node delay of Max CTD (?) */
        if(pDesc->pcr == 0)
        {
            return IX_ERROR_WARNING(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                                    ("ATM TM4.1> PCR parameter for nrt-VBR VC is zero\n"));
        }
        if(pDesc->scr == 0)
        {
            return IX_ERROR_WARNING(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                                    ("ATM TM4.1> SCR parameter for nrt-VBR VC is zero\n"));
        }
        if(pDesc->mbs == 0)
        {
            return IX_ERROR_WARNING(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                                    ("ATM TM4.1> MBS parameter for rt-VBR VC is zero\n"));
        }
		_ix_cc_atmtm41_gcra_set_t1(arg_pEntry, GCRA_T_PARAM(pDesc->pcr));
		_ix_cc_atmtm41_gcra_set_tau1(arg_pEntry, GCRA_TAU_PARAM(pDesc->cdvt));
		_ix_cc_atmtm41_gcra_set_t2(arg_pEntry, GCRA_T_PARAM(pDesc->scr));
		n =_ix_cc_atmtm41_gcra_get_t2(arg_pEntry)-_ix_cc_atmtm41_gcra_get_t1(arg_pEntry);
		_ix_cc_atmtm41_gcra_set_delta(arg_pEntry, n);
		n *= (pDesc->mbs-1);
		_ix_cc_atmtm41_gcra_set_debit_limit(arg_pEntry, n);
        _ix_cc_atmtm41_gcra_set_code(arg_pEntry, 0x03);
		break;

    case IX_CC_ATMSAR_ATM_SERVICE_UBR:
		/* UBR (Plain UBR) is equivalent to the best effort traffic in an IP network
		 * and hence is given the lowest priority in the TM space for ATM networks.
		 * Hence it does not undergo any GCRA based shaping for the most part. */
        switch(pDesc->ubrBcs)
        {
        case IX_CC_ATMSAR_UBR_BCS_NO_PCR:
            /* without PCR, it is with priority */
            _ix_cc_atmtm41_gcra_set_pri(arg_pEntry, pDesc->ubrPriority);
            _ix_cc_atmtm41_gcra_set_code(arg_pEntry, 0x00);
            break;
        case IX_CC_ATMSAR_UBR_BCS_PCR:
            /* with PCR */
            if(pDesc->pcr == 0)
            {
                return IX_ERROR_WARNING(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                                        ("ATM TM4.1> PCR parameter for UBR VC with PCR is zero\n"));
            }
            _ix_cc_atmtm41_gcra_set_t1(arg_pEntry, GCRA_T_PARAM(pDesc->pcr));
            _ix_cc_atmtm41_gcra_set_tau1(arg_pEntry, GCRA_TAU_PARAM(pDesc->cdvt));
            _ix_cc_atmtm41_gcra_set_code(arg_pEntry, 0x04);
            break;

        case IX_CC_ATMSAR_UBR_BCS_MDCR:
            /* TBD Toma schould explain         */
            _ix_cc_atmtm41_gcra_set_code(arg_pEntry, 0x05);
            break;

        default:
            /* invalid UBR behavior class - return error */
            return IX_ERROR_WARNING(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                                    ("ATM TM4.1> Undefined UBR behavior class %d\n", pDesc->ubrBcs));
        }
		break;
        
    case IX_CC_ATMSAR_ATM_SERVICE_GFR:
        /* GFR is defined by the flowing constraints:
         * 1. The flow with a given PCR and CDVT should conform to 
         *    GCRA(LR/PCR, CDVT), where LR is the Link Rate.
         * 2. The flow with a given MCR and BT should conform to 
         *    FGCRA(LR/MCR, CDVT+BT), where LR is the Link Rate
         * 3. Frame Size < MFS for all the frames of a given flow
         * 4. All the cells in the frame should have CLP = 0.*/

        if(pDesc->pcr == 0)
        {
            return IX_ERROR_WARNING(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                                    ("ATM TM4.1> PCR parameter for GFR VC is zero\n"));
        }
        if(pDesc->mcr == 0)
        {
            return IX_ERROR_WARNING(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                                    ("ATM TM4.1> MCR parameter for GFR VC is zero\n"));
        }
        _ix_cc_atmtm41_gcra_set_t1(arg_pEntry, GCRA_T_PARAM(pDesc->pcr));
		_ix_cc_atmtm41_gcra_set_tau1(arg_pEntry, GCRA_TAU_PARAM(pDesc->cdvt));
		_ix_cc_atmtm41_gcra_set_t2(arg_pEntry, GCRA_T_PARAM(pDesc->mcr));
		_ix_cc_atmtm41_gcra_set_tau2(arg_pEntry, GCRA_TAU_PARAM(pDesc->cdvt + pDesc->mbs));
        _ix_cc_atmtm41_gcra_set_code(arg_pEntry, 0x06);
        break;

    default:
		return IX_ERROR_WARNING(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                                ("ATM TM4.1> invalid service type\n"));
    }
    _ix_cc_atmtm41_gcra_set_port(arg_pEntry, arg_pVcDescr->spec.portNo);
    n=arg_pContext->portsTab[arg_pVcDescr->spec.portNo].n;
    _ix_cc_atmtm41_gcra_set_lr(arg_pEntry, n);
    _ix_cc_atmtm41_gcra_set_th_mask(arg_pEntry, ((1<<(arg_pContext->log2TqTot - n))-1) );
    _ix_cc_atmtm41_gcra_set_qerror(arg_pEntry,(1 << ( POW_OF_PRECISION + arg_pContext->log2Aggregation + n - 1 - THMASK_SIZE_LOG2 )));
    _IX_CC_ATMTM41_DBG_GCRA(("atm_tm_4_1_set_gcra_param() Successfuly completed\n"));
    _ix_cc_atmtm41_show_gcra_param(arg_pEntry);
    return IX_SUCCESS;
#undef GCRA_T_PARAM
#undef GCRA_TAU_PARAM
#undef ROUND
} /* end _ix_cc_atmtm41_set_lbr_vc_param */


/**
 * NAME: _ix_cc_atmtm41_set_hbr_vc_param
 *
 * DESCRIPTION:
 *    This function calculates and sets up the TM4.1 parameters in the
 *    GCRA table. The function fills HBR VC Table.
 *
 * @Param:  IN  arg_pContext - pointer to context of current core component.
 * @Param:  IN  arg_hVc :  VC queue number
 * @Param:  IN  arg_pEntry :  entry to fill with GCRA Parameters
 * @Param:  IN  arg_pVcDescr : parameters describing requested VC.
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_SUCCESS - ATM port successfully created
 *    IX_CC_ATMSAR_ERROR_INVALID_PARAM - invalid input parameters
 *    IX_CC_ATMSAR_ERROR_NO_RESOURCES - no resources to add the entry
 */
static ix_error
_ix_cc_atmtm41_set_hbr_vc_param(
_ix_cc_atmtm41_context_t* arg_pContext,
const ix_uint16 arg_hVc,
ix_uint32 *arg_pEntry,
const ix_cc_atmsar_vc_descr_t *arg_pVcDescr)
{
    ix_uint32 n, i, j, step, idx;
    _ix_cc_atmtm41_hbr_descr_t *pHbrDescr;
    ix_uint8 *pHbrVcInSram;
    ix_int32 *ptr,location;

    /* bandwidth for HBR VC was calculated during VC handle allocation */
    n = _ix_cc_atmtm41_plugin_get_hbr_slots(arg_pContext->vc[arg_hVc].shared.bandwidth);

    _IX_CC_ATMTM41_DBG_VC(("_ix_cc_atmtm41_set_hbr_vc_param(), entries in HBR table: %ld\n", n));

	/* Initialize the GCRA structure */
    ix_ossl_memset((void *)arg_pEntry, 0, GCRA_ENTRY_SIZE);

	/* Update GCRA description - for HBR VC set only portNo */
    _ix_cc_atmtm41_gcra_set_port(arg_pEntry, arg_pVcDescr->spec.portNo);

    /* Update HBR Table entries
     * Read HBR description. Port structure contains HBR descriptor ID.
     * Prepare list of free entries
     */
    i=arg_pContext->portsTab[arg_pVcDescr->spec.portNo].hbrDescr;
    pHbrDescr=&arg_pContext->hbrDescrForPort[i];
    for(i=pHbrDescr->first, j=0;
        i<_IX_CC_ATMTM41_VC_HBR_MAX;
        i+=pHbrDescr->step)
    {
        if(arg_pContext->hbrVc[i]==_IX_CC_ATMTM41_HBR_VC_EMPTY)
        {
            arg_pContext->tmpHbrVc[j]=i;
            j++;
        }
    }

    /* n - requested slots, j - free slots */
    if(j<n)
    {
        return IX_ERROR_WARNING(IX_CC_ATMSAR_ERROR_NO_RESOURCES,
                                ("ATM TM4.1 No slots for HBR VC\n"));
    }
    step=j/n;
    pHbrVcInSram=(ix_uint8*) arg_pContext->pSymbolTable[_IX_CC_ATMTM41_HBR_TQ_SRAM_BASE_SYMBOL_ID];
    for(i=0, j=0;i<n;i++, j+=step)
    {
        idx=arg_pContext->tmpHbrVc[j];
        arg_pContext->hbrVc[idx]=arg_hVc; /* update local copy */

        location = ((ix_uint8)(idx/4))*4 + (3-(idx % 4));

        pHbrVcInSram[location]=arg_hVc; /* update SRAM */
    }

    /* Set up SRAM INDICATOR */
    ptr = arg_pContext->pSymbolTable[_IX_CC_ATMTM41_HBR_TQ_SRAM_INDICATOR_SYMBOL_ID];
    *ptr = 0xffff;

    return IX_SUCCESS;
} /* end _ix_cc_atmtm41_set_hbr_vc_param */


/**
 * NAME: _ix_cc_atmtm41_plugin_vc_create
 *
 * DESCRIPTION:
 *    This is function for plug-in registering. The ATM SAR
 *    calls the function if it services "VC create" operation. The called
 *    function should perform the operation on internal structures.
 * 
 * @Param:  IN  arg_pInstance :  pointer to structure describing serviced
 *                  instance.
 * @Param:  IN  arg_hVc :  handle to created VC.
 * @Param:  IN  arg_pVcDescr : parameters describing requested VC.
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_SUCCESS - ATM port successfully created
 *    IX_CC_ATMSAR_ERROR_INVALID_PARAM - invalid input parameters
 *    IX_CC_ATMSAR_ERROR_NO_RESOURCES - no resources to add the entry 
 */
ix_error
_ix_cc_atmtm41_plugin_vc_create(
void* arg_pInstance,
const ix_cc_atmsar_vc_handle_t arg_hVc,
const ix_cc_atmsar_vc_descr_t* arg_pVcDescr)
{
    ix_uint32 newEntry[(GCRA_ENTRY_SIZE>>2)+1];  /* the structure where we will build the new entry. */
    ix_uint32 *pEntry;
    _ix_cc_atmtm41_context_t* pCtx=arg_pInstance;
    ix_error err;
    
    if( pCtx == NULL )
    {
        return IX_ERROR_GLOBAL(IX_CC_ERROR_NULL, ("ATM TM4.1 Context is NULL\n"));
    }
    
    _IX_CC_ATMTM41_DBG_VC(("_ix_cc_atmtm41_plugin_vc_create\n"));

    if(arg_hVc<_IX_CC_ATMTM41_VC_HBR_MAX)
    {
        err=_ix_cc_atmtm41_set_hbr_vc_param(pCtx, arg_hVc, newEntry, arg_pVcDescr);
    }
    else
    {
        err=_ix_cc_atmtm41_set_lbr_vc_param(pCtx, arg_hVc, newEntry, arg_pVcDescr);
    }

    if(err!=IX_SUCCESS)
    {
        return err;
    }

    /* Deposit the data into the gcra_param_table SRAM */
    _ix_cc_atmtm41_gcra_set_valid(newEntry, 0);
    pEntry=_ix_cc_atmtm41_gcra_get_entry(pCtx, arg_hVc);
    ix_ossl_memcpy((ix_uint8*)(pEntry), newEntry, GCRA_ENTRY_SIZE);

    return IX_SUCCESS;
} /* end _ix_cc_atmtm41_plugin_vc_create */

/**
 * NAME: _ix_cc_atmtm41_plugin_vc_update
 *
 * DESCRIPTION:
 *    This is function for plug-in registering. The ATM SAR
 *    calls the function if it services "VC update" operation. The called
 *    function should perform the operation on internal structures.
 * 
 * @Param:  IN  arg_pInstance :  pointer to structure describing serviced
 *                  instance.
 * @Param:  IN  arg_hVc :  handle to created VC.
 * @Param:  IN  arg_pVcDescr : parameters describing requested VC.
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_SUCCESS - ATM port successfully created
 *    IX_CC_ATMSAR_ERROR_INVALID_PARAM - invalid input parameters
 *    IX_CC_ATMSAR_ERROR_NO_RESOURCES - no resources to add the entry 
 */
ix_error
_ix_cc_atmtm41_plugin_vc_update(
void* arg_pInstance,
const ix_cc_atmsar_vc_handle_t arg_hVc,
const ix_cc_atmsar_update_data_t* arg_pUpdate)
{
    ix_uint32 *pEntry;
    _ix_cc_atmtm41_context_t* pCtx=arg_pInstance;
    
    if( pCtx == NULL )
    {
        return IX_ERROR_GLOBAL(IX_CC_ERROR_NULL, ("ATM TM4.1 Context is NULL\n"));
    }
    
    _IX_CC_ATMTM41_DBG_VC(("_ix_cc_atmtm41_plugin_vc_update: %d\n",arg_hVc));

    /* All data is ready. Now, we can set valid bit for the VC */
    pEntry=_ix_cc_atmtm41_gcra_get_entry(pCtx, arg_hVc);
    _ix_cc_atmtm41_gcra_set_valid(pEntry, 1);
    
    return IX_SUCCESS;
} /* end _ix_cc_atmtm41_plugin_vc_update */

/**
 * NAME: _ix_cc_atmtm41_plugin_vc_remove
 *
 * DESCRIPTION:
 *    This is function for plug-in registering. The ATM SAR
 *    calls the function if it services "VC remove" operation. The called
 *    function should perform the operation on internal structures.
 * 
 * @Param:  IN  arg_pInstance :  pointer to structure describing serviced
 *                  instance.
 * @Param:  IN  arg_hVc : handle to VC to be removed
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_SUCCESS - vc successfully removed
 *    IX_CC_ATMSAR_ERROR_INVALID_PARAM - invalid input parameters
 */
ix_error
_ix_cc_atmtm41_plugin_vc_remove(
void* arg_pInstance,
ix_cc_atmsar_vc_handle_t arg_hVc)
{
    ix_uint32 newEntry[(GCRA_ENTRY_SIZE>>2)+1];  /* the structure where we will build the new entry. */
    ix_uint32 *pEntry;
    ix_uint8 *pHbrVcInSram;
    _ix_cc_atmtm41_hbr_descr_t *pHbrDescr;
    ix_uint32 i,step;
    _ix_cc_atmtm41_context_t* pCtx=arg_pInstance;

    if( pCtx == NULL )
    {
        return IX_ERROR_GLOBAL(IX_CC_ERROR_NULL, ("ATM TM4.1 Context is NULL\n"));
    }
    _IX_CC_ATMTM41_DBG_VC(("_ix_cc_atmtm41_plugin_vc_remove\n"));

    /* Clear GCRA structures */
    ix_ossl_memset((void *)&newEntry, 0, sizeof(newEntry));
    pEntry=_ix_cc_atmtm41_gcra_get_entry(pCtx, arg_hVc);
    ix_ossl_memcpy((ix_uint8*)(pEntry), newEntry, GCRA_ENTRY_SIZE);

    if(arg_hVc<_IX_CC_ATMTM41_VC_HBR_MAX)
    {
        /* It is HBR VC. We need to remove the VC from HBR structures */
        i=pCtx->portsTab[pCtx->vc[arg_hVc].port].hbrDescr;
        pHbrDescr=&pCtx->hbrDescrForPort[i];
        pHbrVcInSram=(ix_uint8*) pCtx->pSymbolTable[_IX_CC_ATMTM41_HBR_TQ_SRAM_BASE_SYMBOL_ID];
        for(i=pHbrDescr->first, step=pHbrDescr->step;
            i<_IX_CC_ATMTM41_VC_HBR_MAX;
            i+=step)
        {
            if(pCtx->hbrVc[i]==arg_hVc)
            {
                pCtx->hbrVc[i]=_IX_CC_ATMTM41_HBR_VC_EMPTY; /* update local copy */
                pHbrVcInSram[i]=_IX_CC_ATMTM41_HBR_VC_EMPTY; /* update SRAM */
            }
        }
    }
    return IX_SUCCESS;
} /* end _ix_cc_atmtm41_plugin_vc_remove */

/**
 * NAME:  _ix_cc_atmtm41_plugin_get_hbr_slots
 *
 * DESCRIPTION:
 *    This is function for calculating number of HBRTQ slots from VC rate.
 *
 * @Return: Number of HBRTQ slots
 */
ix_uint32 _ix_cc_atmtm41_plugin_get_hbr_slots(ix_uint32 arg_rate)
{
    ix_uint32 tmp;
    
#define ROUND(x) (((x-((ix_uint32)x))>=0.5)?((ix_uint32)x+1):((ix_uint32)x))
 
#if (_IX_OS_TYPE_ != _IX_OS_LINUX_KERNEL_) 
    tmp = ROUND(((double)arg_rate*(double)(_IX_CC_ATMTM41_VC_HBR_MAX/_IX_CC_ATMTM41_LINE_RATE)));
#else    
    /*
     * The Linux Kernel mode does not support float operations. This is a workaroud.
     */
    ix_uint64 res,val;
    
#if (defined(OC48) || (defined(DUAL_OC24)))
#define REMINDER_SHIFT 23
#elif defined(OC12)
#define REMINDER_SHIFT 21
#else
#error LINK RATE is not defined (OC48, DUAL_OC24, OC12)!!!
#endif
    
    res =  (((ix_uint64)arg_rate*_IX_CC_ATMTM41_VC_HBR_MAX*(1<<REMINDER_SHIFT))/(_IX_CC_ATMTM41_LINE_RATE))&(1<REMINDER_SHIFT-1);
    val =  (((ix_uint64)arg_rate*_IX_CC_ATMTM41_VC_HBR_MAX*(1<<REMINDER_SHIFT))/(_IX_CC_ATMTM41_LINE_RATE))>>(REMINDER_SHIFT);

    tmp = (ix_uint32)val;
    if (res > (_IX_CC_ATMTM41_LINE_RATE>>1))
    {
        tmp++;
    }
   
#endif /* _IX_OS_TYPE_ != _IX_OS_LINUX_KERNEL_ */
    
#undef ROUND

	return tmp;

}


/**
 * NAME:  _ix_cc_atmtm41_plugin_round_hbr_rate
 *
 * DESCRIPTION:
 *    This is function for calculating HBR VC rate from number of HBRTQ slots.
 *
 * @Return: VC rate
 */
ix_uint32 _ix_cc_atmtm41_plugin_round_hbr_rate(ix_uint32 arg_slots)
{
ix_uint32 tmp;

	tmp = (arg_slots * _IX_CC_ATMTM41_LINE_RATE) / _IX_CC_ATMTM41_VC_HBR_MAX;
	return tmp;
}

#define _IX_CC_ATMTM41_HBR_VC_SLOT_LR ((_IX_CC_ATMTM41_LINE_RATE)/_IX_CC_ATMTM41_VC_HBR_MAX)
/**
 * NAME: _ix_cc_atmtm41_plugin_vc_alloc
 *
 * DESCRIPTION:
 *    This is function for plug-in registering. The ATM SAR
 *    calls the function if it wants to allocate VC for VC creation.
 *    The called function should allocate and return new VC handle.
 *    The 'arg_pVcDescr' agrument is passed to the function because
 *    parameters of VC could influent on assigned handle
 *
 * @Param:  IN  arg_pInstance :  pointer to structure describing serviced
 *                  instance.
 * @Param:  IN  arg_pVcDescr : pointer to data describing parameters
 *                  for requested VC
 * @Param:  OUT arg_pHVc : poiter to data where assigned handle is stored
 *                  VC handle
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_SUCCESS - ATM port successfully created
 *    IX_CC_ATMSAR_ERROR_INVALID_PARAM - invalid input parameters
 *    IX_CC_ATMSAR_ERROR_NO_RESOURCES - no resources to add the entry
 */
ix_error
_ix_cc_atmtm41_plugin_vc_alloc(
void* arg_pInstance,
ix_cc_atmsar_vc_handle_t *arg_pHVc,
const ix_cc_atmsar_vc_descr_t *arg_pVcDescr)
{
    const ix_cc_atmsar_tp_direction_t* pDesc;
    ix_uint16 *pHead, vcHandle;
    ix_uint8  lbrFlag;
    ix_uint32 maxLbrForPort;
    ix_uint32 tmp;
    ix_error err;
    _ix_cc_atmtm41_context_t* pCtx=arg_pInstance;

    *arg_pHVc=IX_CC_ATMSAR_VCID_INVALID;
   
    if( pCtx == NULL )
    {
        return IX_ERROR_GLOBAL(IX_CC_ERROR_NULL, ("ATM TM4.1 Context is NULL\n"));
    }

    /* Extract trafic contraact related parameters */
    pDesc = &(arg_pVcDescr->trafficParams.fwd);

	/* Check if the connection is high bit rate or low bit rate.
	 * The calculation should be done in slot units. */
    switch (arg_pVcDescr->trafficParams.serviceClass)
    {
    case IX_CC_ATMSAR_ATM_SERVICE_UBR:
        switch(pDesc->ubrBcs)
        {
        case IX_CC_ATMSAR_UBR_BCS_PCR:
            /* with PCR */
            tmp=pDesc->pcr;
            break;

        default:
            tmp = 0;
            break;
        }
		break;

    case IX_CC_ATMSAR_ATM_SERVICE_CBR:
    case IX_CC_ATMSAR_ATM_SERVICE_GFR:
		/*  For CBR /GFR  (and UBR) PCR parameter is used */
        tmp = pDesc->pcr;
        break;
    case IX_CC_ATMSAR_ATM_SERVICE_RT_VBR:
    case IX_CC_ATMSAR_ATM_SERVICE_NRT_VBR:
        /*	      case IX_ATM_SERV_TYPE_VBR_NRT:   */
		/*  For rtVBR/nrtVBR SCR parameter is used */
        tmp = pDesc->scr;
        break;
    case IX_CC_ATMSAR_ATM_SERVICE_ABR:
    default:
		/* invalid service type - return error */
        return IX_ERROR_WARNING(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                                ("Invalid parameters %d\n",
                                 arg_pVcDescr->trafficParams.serviceClass));
    }

    /* For UBR traffic hight bit rate queue is used (?) - this may be changed in
     * the future. */

    maxLbrForPort=pCtx->portsTab[arg_pVcDescr->spec.portNo].lrCfg/ONE_TIMESTAMP;

    /* This VCC has high bit rate. Default Value */
    lbrFlag=0;

    if(tmp <= maxLbrForPort)
    {   /* This VCC has low bit rate. */
        lbrFlag=1;
    }
    else if((maxLbrForPort<tmp) &&
            (arg_pVcDescr->trafficParams.serviceClass != IX_CC_ATMSAR_ATM_SERVICE_CBR))
    {   /* This VCC has low bit rate. */
        lbrFlag=1;
    }

    if(lbrFlag==1)
    {   /* This VCC has low bit rate. */
        pHead=&pCtx->freeLbrVcs;
    }
    else
    {   /* This VCC has high bit rate. */
        pHead=&pCtx->freeHbrVcs;

        /* Update allocated bandwidth. It can be only equal
         * _IX_CC_ATMTM41_HBR_VC_SLOT_LR * n, where n is power of 2 and n is in range
         * from 1 to _IX_CC_ATMTM41_VC_HBR_MAX. */
        tmp = _ix_cc_atmtm41_plugin_round_hbr_rate(_ix_cc_atmtm41_plugin_get_hbr_slots(tmp));
    }
    /* Allocate an entry from the low bit rate free list */
    if (*pHead == IX_CC_ATM_LIST_INVALID_HANDLE)
    {
        return IX_ERROR_WARNING(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                                ("No free VC handles\n"));
    }
    
    vcHandle=*pHead;
    /* verify that the VC is not in use */
    if(pCtx->vc[vcHandle].port != IX_CC_ATMSAR_PORTID_INVALID)
    {
        return IX_ERROR_GLOBAL(IX_CC_ERROR_OOM,
                               ("VC with vcHandle=%d in use. I cannot allocate it.", vcHandle));
    }
    /* remove from free VC list */    
    ix_cc_atm_list_remove(vcHandle, 0, pHead, &pCtx->listVc);

    /* Add vc to port. Function verifies requested bandwidth. If accessible
     * bandwidth of port is not sufficiet, the VC is link to port */
    IX_ERROR_CT(_ix_cc_atmtm41_port_add_vc(pCtx, arg_pVcDescr->spec.portNo, vcHandle, tmp),
                err,
                IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                IX_ERROR_LEVEL_GLOBAL);
    if(err != IX_SUCCESS)
    {
        
        if(ix_cc_atm_list_insert(vcHandle, 0, pHead, &pCtx->listVc) != IX_CC_ATM_LIST_OK)
        {
            _IX_CC_ATMTM41_DBG_VC(("_ix_cc_atmtm41_plugin_vc_alloc() insert failed for VC %d\n", vcHandle));
        }

        return err;
    }

    *arg_pHVc=vcHandle;
    _IX_CC_ATMTM41_DBG_VC(("_ix_cc_atmtm41_plugin_vc_alloc() ALLOCATED VC %d\n", *arg_pHVc));
    return IX_SUCCESS;
} /* end _ix_cc_atmtm41_plugin_vc_alloc */


/**
 * NAME: _ix_cc_atmtm41_plugin_vc_free
 *
 * DESCRIPTION:
 *    This is function for plug-in registering. The ATM SAR
 *    calls the function if it wants to free VC for VC destroying.
 * 
 * @Param:  IN  arg_pInstance :  pointer to structure describing serviced
 *                  instance.
 * @Param:  IN arg_hVc : handle of freeing VC.
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_SUCCESS - ATM port successfully created
 *    IX_CC_ATMSAR_ERROR_INVALID_PARAM - invalid input parameters
 */
ix_error
_ix_cc_atmtm41_plugin_vc_free(
void* arg_pInstance,
ix_cc_atmsar_vc_handle_t arg_hVc)
{
    ix_error err;
    ix_uint16 *pHead;
    _ix_cc_atmtm41_context_t* pCtx=arg_pInstance;

    if( pCtx == NULL )
    {
        return IX_ERROR_GLOBAL(IX_CC_ERROR_NULL, ("ATM TM4.1 Context is NULL\n"));
    }
    if(arg_hVc == IX_CC_ATMSAR_VCID_INVALID)
    {
        return IX_SUCCESS;
    }
    if(pCtx->vc[arg_hVc].port == IX_CC_ATMSAR_PORTID_INVALID)
    {
        return IX_ERROR_GLOBAL(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                               ("Fatal Error the situation should happend never for VC %d", arg_hVc));
    }
    
    if(arg_hVc<_IX_CC_ATMTM41_VC_HBR_MAX)
    {
        pHead=&pCtx->freeHbrVcs;
    }
    else
    {
        pHead=&pCtx->freeLbrVcs;
    }

    IX_ERROR_CT(_ix_cc_atmtm41_port_del_vc(pCtx, arg_hVc), err,
                IX_CC_ATMSAR_ERROR_INVALID_PARAM, IX_ERROR_LEVEL_GLOBAL);

    if(ix_cc_atm_list_insert(arg_hVc, 0, pHead, &pCtx->listVc) != IX_CC_ATM_LIST_OK)
    {
        _IX_CC_ATMTM41_DBG_VC(("_ix_cc_atmtm41_plugin_vc_alloc() insert failed for VC %d\n", arg_hVc));
    }

    _IX_CC_ATMTM41_DBG_VC(("_ix_cc_atmtm41_plugin_vc_free\n"));
    return err;
} /* _ix_cc_atmtm41_plugin_vc_free */


/******************************************************************************
 *                        SUPPORT FOR PORTS
 *****************************************************************************/

/* Each PortInfo table entry has following structure:
 *    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 
 *    1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 <- bits
 *   +---------------+---------------+---------------+---------------+
 *LW0| RT_for_LBR_TQ | CurTQ                         | 			 |V	F|
 *   +---------------+---------------+---------------+---------------+	
 *LW1| RTQnum        				 | NRTQnum          			 |
 *   +---------------+---------------+---------------+---------------+
 *LW2| DQRTlen						 | DQNRTlen                      |
 *   +---------------+---------------+---------------+---------------+
 *LW3| RTQlen        | NRTQlen       | Work._RTQlen  | Work._NRTQlen |
 *   +---------------+---------------+---------------+---------------+
 *LW4| Schcount	     | MaxTQ             | UP_currVC | UP_currCredit |
 *   +---------------+---------------+---------------+---------------+
 *LW5| UBRTQnum						 | DQUBRTlen                     |
 *   +---------------+---------------+---------------+---------------+
 *LW6| TQ_offset					 | UBRTQlen		 | Work.UBRTQlen |
 *   +---------------+---------------+---------------+---------------+
 *LW7|rt_lm_p|rt_lm_c|nrt_l_p|nrt_l_c|ubr_l_p|ubr_l_c| UBRwPRIcache  |
 *   +---------------+---------------+---------------+---------------+
 *
 * V - EntryValid
 * F - FlowControl 
 * UP_currVC - UbrPri_currVC
 * UP_currCredit - UbrPri_currCredit
 * rt_lm_p - Rtdq_lm_producer
 * rt_lm_c - Rtdq_lm_consumer
 * nrt_l_p - Nrtdq_lm_producer
 * nrt_l_c - Nrtdq_lm_consumer
 * ubr_l_p - Ubrdq_lm_producer
 * ubr_l_c - Ubrdq_lm_consumer
 */

/*                               funcPfx,           varName,    lw, offset, mask */
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_port_info, valid,      0,  1,      0x01);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_port_info, max_tq,     4,  12,     0x0FFF);
ATMSAR_BITS_SUPPORT_FUNC_DEFINE(_ix_cc_atmtm41_port_info, tq_offset,  6,  16,     0x0FFFF);


/**
 * NAME: _ix_cc_atmtm41_port_info_get_entry
 *
 * DESCRIPTION:
 *    Find pointer to entry with port info data. 
 * 
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - IN arg_entryId - Id of requested port
 *
 * @Return: NULL if error occurs, otherwise pointer to secondary bucket.
 */
static ix_uint32*
_ix_cc_atmtm41_port_info_get_entry(
_ix_cc_atmtm41_context_t* arg_pContext,
ix_uint16 arg_entryId)
{
    if(arg_entryId>=IX_CC_ATMSAR_PORTID_INVALID)
    {
        return NULL;
    }
#ifndef PORTINFO_IN_SDRAM
    return arg_pContext->pSymbolTable[_IX_CC_ATMTM41_PORTINFO_SRAM_BASE_SYMBOL_ID]+(arg_entryId*((1<<PORTDATA_SRAM_ENTRY_SIZE_LOG2)>>2));
#else
    return arg_pContext->pSymbolTable[_IX_CC_ATMTM41_PORTINFO_SRAM_BASE_SYMBOL_ID]+(arg_entryId*((1<<PORTDATA_SDRAM_ENTRY_SIZE_LOG2)>>2));
#endif
/* PORTINFO_ENTRY_SIZE>>2) */
}


/**
 * NAME: ix_cc_atmtm41_show_port
 *
 * DESCRIPTION:
 *    This function show parameters for port.
 * 
 * @Param:  IN  arg_pContext - pointer to context of current core component.
 * @Param:  IN  arg_idx :  index of entry in port info table
 * 
 * @Return: none
 */
void
ix_cc_atmtm41_show_port(
_ix_cc_atmtm41_context_t* arg_pContext,
ix_uint16 arg_idx)
{
    ix_uint32* pEntry;

    _IX_CC_ATMTM41_DBG_PORT(("PORT (%d) GENERAL DATA:\n", arg_idx));
    if(arg_idx>=arg_pContext->pluginCfg.numberOfPorts)
    {
        _IX_CC_ATMTM41_DBG_PORT(("   Wrong port number\n"));
        return;
    }

    
    pEntry=_ix_cc_atmtm41_port_info_get_entry(arg_pContext, arg_idx);
    _IX_CC_ATMTM41_DBG_PORT(("PORT INFO:\n"));
    if(pEntry==NULL)
    {
        _IX_CC_ATMTM41_DBG_PORT(("   ENTRY IS NULL\n"));
        return;
    }
    _IX_CC_ATMTM41_DBG_PORT(("   Valid(%ld), MaxTQ=%-4ld, TqOffset=%ld\n",
                             _ix_cc_atmtm41_port_info_get_valid(pEntry),
                             _ix_cc_atmtm41_port_info_get_max_tq(pEntry),
                             _ix_cc_atmtm41_port_info_get_tq_offset(pEntry)));
} /* end ix_cc_atmtm41_show_port */


/**
 * NAME: _ix_cc_atmtm41_port_info_init
 *
 * DESCRIPTION:
 *    The function fills PORT INFO with read static configuration.
 * 
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 *
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_CC_ATMTM41_ERROR_INVALID_PARAM - port table contains port with wrong
 *       input parameters
 */
ix_error
_ix_cc_atmtm41_port_info_init(
_ix_cc_atmtm41_context_t *arg_pContext)
{
    ix_uint16 i;
    ix_uint32* pEntry;
    ix_uint32 tqOffset;
    ix_uint32 thMask;
    ix_uint32 MaxTqMask;

    tqOffset = 0;
    
    for (i = 0; i<arg_pContext->pluginCfg.numberOfPorts; i++)
    {
        if(arg_pContext->portsTab[i].n != _IX_CC_ATMTM41_INVALID_PORT_RATE_EXP)
        {
            if(tqOffset>=arg_pContext->tq_tot)
            {
                return IX_ERROR_GLOBAL(IX_CC_ATMTM41_ERROR_INVALID_PARAM,
                                       ("WRONG DEFINED LIST OF PORTS: TQ OFFSET %d, TQ_TOT %d\n",
                                        tqOffset, (ix_uint16)arg_pContext->tq_tot));
            }
            pEntry=_ix_cc_atmtm41_port_info_get_entry(arg_pContext, i);
            thMask=arg_pContext->log2TqTot - arg_pContext->portsTab[i].n;            
            MaxTqMask=(1<<thMask) - 1;
            _ix_cc_atmtm41_port_info_set_tq_offset(pEntry, tqOffset);
            _ix_cc_atmtm41_port_info_set_max_tq(pEntry, MaxTqMask);
            tqOffset+=(1<<thMask);
        }
    }

    for (i = 0; i<arg_pContext->pluginCfg.numberOfPorts; i++)
    {
        if(arg_pContext->portsTab[i].n != _IX_CC_ATMTM41_INVALID_PORT_RATE_EXP)
        {
            ix_cc_atmtm41_show_port(arg_pContext, i);
        }
    }

    if(tqOffset>arg_pContext->tq_tot)
    {
        /* overflow of tqOffset */
        return IX_ERROR_GLOBAL(IX_CC_ATMTM41_ERROR_INVALID_PARAM,
                               ("WRONG DEFINED LIST OF PORTS: TQ OFFSET %d OVERFLOW , TQ_TOT %d\n",
                                tqOffset, (ix_uint16)arg_pContext->tq_tot));
    }
    return IX_SUCCESS;
} /* end _ix_cc_atmtm41_port_info_init */


/**
 * NAME: _ix_cc_atmtm41_port_info_show
 *
 * DESCRIPTION:
 *    The function show parameters for entry from  PORT INFO table.
 * 
 * @Param:  - IN arg_pContext - pointer to context of current core component.
 * @Param:  - IN arg_portId - port identificator/index
 *
 * @Return: none
 */
void
_ix_cc_atmtm41_port_info_show(
_ix_cc_atmtm41_context_t *arg_pContext,
ix_uint16 arg_portId)
{
    ix_uint32* pEntry;

    if(arg_pContext == NULL)
    {
        _IX_CC_ATMTM41_DBG_PORT(("_ix_cc_atmtm41_port_info_show() TM4.1 context is NULL.\n"));
        return;
    }
    if(arg_portId>=arg_pContext->pluginCfg.numberOfPorts)
    {
        _IX_CC_ATMTM41_DBG_PORT(("_ix_cc_atmtm41_port_info_show() Wrong port ID. Allowed range is 0..%d.\n",
                            (ix_uint16)arg_pContext->pluginCfg.numberOfPorts));
    }
    pEntry=_ix_cc_atmtm41_port_info_get_entry(arg_pContext, arg_portId);
    _IX_CC_ATMTM41_DBG_PORT(("TQ_OFFSET: %-8ld, MAX_TQ:  %-8ld\n",
                        _ix_cc_atmtm41_port_info_get_tq_offset(pEntry),
                        _ix_cc_atmtm41_port_info_get_max_tq(pEntry)));
} /* end _ix_cc_atmtm41_port_info_show */


/**
 * NAME: _ix_cc_atmtm41_port_add_vc
 *
 * DESCRIPTION:
 *    The function allocates bandwidth for VC.
 * 
 * @Param:  IN  arg_pContext : pointer to context of current core component.
 * @Param:  IN  arg_portNo : port identifier for which add VC
 * @Param:  IN  arg_hVc : vc handle to add
 * @Param:  IN  arg_cps : requested banwitch of VC counted in cells per seconds
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_SUCCESS - ATM port successfully created
 *    IX_CC_ATMSAR_ERROR_INVALID_PARAM - invalid input parameters
 */
static ix_error
_ix_cc_atmtm41_port_add_vc(
_ix_cc_atmtm41_context_t *arg_pContext,
ix_uint16 arg_portNo,
ix_cc_atmsar_vc_handle_t arg_hVc,
ix_uint32 arg_cps)
{
    _ix_cc_atmtm41_port_t *pPort;
    if(arg_portNo >= arg_pContext->pluginCfg.numberOfPorts)
    {
        return IX_ERROR_GLOBAL(IX_CC_ATMTM41_ERROR_INVALID_PARAM,
                               ("Requested port %d is out of scope 0..%d\n",
                                arg_portNo, (ix_uint16)arg_pContext->pluginCfg.numberOfPorts));
    }

    pPort=&arg_pContext->portsTab[arg_portNo];
    if(pPort->n == _IX_CC_ATMTM41_INVALID_PORT_RATE_EXP)
    {
        return IX_ERROR_GLOBAL(IX_CC_ATMTM41_ERROR_INVALID_PARAM,
                               ("Requested port %d is not configured\n",
                                arg_portNo));
    }
    if(pPort->lrCfg<(pPort->lrUsed+arg_cps))
    {
        return IX_ERROR_GLOBAL(IX_CC_ATMTM41_ERROR_INVALID_PARAM,
                               ("Cannot add VC(cps=%d) to port %d with lrCfg=%d and lrUsed=%d\n",
                                arg_cps, arg_portNo, pPort->lrCfg, pPort->lrUsed));
    }
    arg_pContext->vc[arg_hVc].port=arg_portNo;
    arg_pContext->vc[arg_hVc].shared.bandwidth=arg_cps;
    pPort->lrUsed+=arg_cps;
    _IX_CC_ATMTM41_DBG_PORT(("_ix_cc_atmtm41_port_add_vc() Port[%d]: lrCfg=%ld, lrUsed=%ld\n",
                   arg_portNo, pPort->lrCfg, pPort->lrUsed));
    return IX_SUCCESS;
} /* end _ix_cc_atmtm41_port_add_vc */


/**
 * NAME: _ix_cc_atmtm41_port_del_vc
 *
 * DESCRIPTION:
 *    The function unlink VC from port structures. It frees bandwidth allocated
 *    for the VC.
 * 
 * @Param:  IN  arg_pContext : pointer to context of current core component.
 * @Param:  IN  arg_hVc : vc handle to add
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_SUCCESS - ATM port successfully created
 *    IX_CC_ATMSAR_ERROR_INVALID_PARAM - invalid input parameters
 */
static ix_error
_ix_cc_atmtm41_port_del_vc(
_ix_cc_atmtm41_context_t *arg_pContext,
ix_cc_atmsar_vc_handle_t arg_hVc)
{
    _ix_cc_atmtm41_port_t *pPort;
    ix_uint16 portNo;

    portNo=arg_pContext->vc[arg_hVc].port;
    if(portNo==IX_CC_ATMSAR_PORTID_INVALID)
    {
        _IX_CC_ATMTM41_DBG_PORT(("_ix_cc_atmtm41_port_del_vc() VC %d does not has assigned port\n",
                       arg_hVc));
        return IX_SUCCESS;
    }
    
    if(portNo >= arg_pContext->pluginCfg.numberOfPorts)
    {
        return IX_ERROR_GLOBAL(IX_CC_ATMTM41_ERROR_INVALID_PARAM,
                               ("Requested port %d is out of scope 0..%d\n",
                                portNo, (ix_uint16)arg_pContext->pluginCfg.numberOfPorts));
    }

    pPort=&arg_pContext->portsTab[portNo];
    
    if(pPort->n == _IX_CC_ATMTM41_INVALID_PORT_RATE_EXP)
    {
        return IX_ERROR_GLOBAL(IX_CC_ATMTM41_ERROR_INVALID_PARAM,
                               ("Requested port %d is not configured\n",
                                portNo));
    }
    pPort->lrUsed-=arg_pContext->vc[arg_hVc].shared.bandwidth;
    
    arg_pContext->vc[arg_hVc].port=IX_CC_ATMSAR_PORTID_INVALID;

    _IX_CC_ATMTM41_DBG_PORT(("_ix_cc_atmtm41_port_del_vc() Port[%d]: lrCfg=%ld, lrUsed=%ld\n",
                   portNo, pPort->lrCfg, pPort->lrUsed));
    return IX_SUCCESS;
} /* end _ix_cc_atmtm41_port_del_vc */


/**
 * NAME: _ix_cc_atmtm41_plugin_port_create
 *
 * DESCRIPTION:
 *    This is function for plug-in registering. The ATM SAR
 *    calls the function if it services "PORT CREATE" operation. The called
 *    function should perform the operation on internal structures.
 * 
 * @Param:  IN  arg_pInstance :  pointer to structure describing serviced
 *                  instance.
 * @Param:  IN  arg_pPortDescr : pointer to data describing parameters
 *                  for requested port
 * @Param:  OUT arg_hPort : ATM port handle
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_SUCCESS - ATM port successfully created
 *    IX_CC_ATMSAR_ERROR_INVALID_PARAM - invalid input parameters
 *    IX_CC_ATMSAR_ERROR_NO_RESOURCES - no resources to add the entry 
 */
ix_error
_ix_cc_atmtm41_plugin_port_create(
void* arg_pInstance,
ix_cc_atmsar_port_handle_t arg_hPort,
const ix_cc_atmsar_port_descr_t *arg_pPortDescr)
{
    return IX_ERROR_GLOBAL(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                           ("ATM TM4.1 Dynamic port management is not implemented\n"));
} /* end _ix_cc_atmtm41_plugin_port_create */


/**
 * NAME: _ix_cc_atmtm41_plugin_port_remove
 *
 * DESCRIPTION:
 *    This is function for plug-in registering. The ATM SAR
 *    calls the function if it services "PORT REMOVE" operation. The called
 *    function should perform the operation on internal structures.
 * 
 * @Param:  IN  arg_pInstance :  pointer to structure describing serviced
 *                  instance.
 * @Param:  IN  arg_port : ATM port to be removed
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_SUCCESS - port successfully removed
 *    IX_CC_INVALID_PORT - specified port does not exist
 */
ix_error
_ix_cc_atmtm41_plugin_port_remove(
void* arg_pInstance,
ix_cc_atmsar_port_handle_t arg_port)
{
    return IX_ERROR_GLOBAL(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                           ("ATM TM4.1 Dynamic port management is not implemented\n"));
} /* end _ix_cc_atmtm41_plugin_port_remove */


/**
 * NAME: _ix_cc_atmtm41_plugin_port_alloc
 *
 * DESCRIPTION:
 *    This is function for plug-in registering. The ATM SAR
 *    calls the function if it wants to allocate port for port creation.
 *    The called function should allocate and return new port handle.
 *    The 'arg_pPortDescr' agrument is passed to the function because
 *    parameters of port could influent on assigned handle
 * 
 * @Param:  IN  arg_pInstance :  pointer to structure describing serviced
 *                  instance.
 * @Param:  IN  arg_pPortDescr : pointer to data describing parameters
 *                  for requested port
 * @Param:  OUT arg_pHPort : poiter to data where assigned handle is stored
 *                  ATM port handle
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_SUCCESS - ATM port successfully created
 *    IX_CC_ATMSAR_ERROR_INVALID_PARAM - invalid input parameters
 *    IX_CC_ATMSAR_ERROR_NO_RESOURCES - no resources to add the entry 
 */
ix_error
_ix_cc_atmtm41_plugin_port_alloc(
void* arg_pInstance,
ix_cc_atmsar_port_handle_t *arg_pHPort,
const ix_cc_atmsar_port_descr_t *arg_pPortDescr)
{
    return IX_ERROR_GLOBAL(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                           ("ATM TM4.1 Dynamic port management is not implemented\n"));
} /* end _ix_cc_atmtm41_plugin_port_alloc */


/**
 * NAME: _ix_cc_atmtm41_plugin_port_free
 *
 * DESCRIPTION:
 *    This is function for plug-in registering. The ATM SAR
 *    calls the function if it wants to free port for port destroying.
 * 
 * @Param:  IN  arg_pInstance :  pointer to structure describing serviced
 *                  instance.
 * @Param:  IN arg_hPort : handle of freeing ATM port.
 * 
 * @Return: IX_SUCCESS if successful or a valid error token for failure.
 *
 * Error Codes:
 *    IX_SUCCESS - ATM port successfully created
 *    IX_CC_ATMSAR_ERROR_INVALID_PARAM - invalid input parameters
 */
ix_error
_ix_cc_atmtm41_plugin_port_free(
void* arg_pInstance,
ix_cc_atmsar_port_handle_t arg_hPort)
{
    return IX_ERROR_GLOBAL(IX_CC_ATMSAR_ERROR_INVALID_PARAM,
                           ("ATM TM4.1 Dynamic port management is not implemented\n"));
} /* end _ix_cc_atmtm41_plugin_port_free */


