#include <Copyright.h>

/********************************************************************************
* gtPortRateCtrl.c
*
* DESCRIPTION:
*       API definitions to handle port rate control registers (0xA).
*
* DEPENDENCIES:
*
* FILE REVISION NUMBER:
*       $Revision: 5 $
*******************************************************************************/

#include <msApi.h>
#include <gtHwCntl.h>
#include <gtDrvSwRegs.h>

/*
 Convert given hw Rate Limit to sw defined Rate Limit.
 This routine is only for Gigabit Managed Switch Device.
 If the given device is not an accepted device, it'll simply copy the hw limit 
 to sw limit.
*/
static GT_STATUS cRateLimit(GT_QD_DEV *dev, GT_U32 hwLimit, GT_U32* swLimit)
{
    GT_U32 sLimit, hLimit, startLimit, endLimit, i;

    if (!((IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH)) ||
        (IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH)) ||
        (IS_IN_DEV_GROUP(dev,DEV_FE_AVB_FAMILY))))
    {
        *swLimit = hwLimit;
        return GT_OK;
    }

    if(hwLimit == 0)
    {
        *swLimit = GT_NO_LIMIT;
        return GT_OK;
    }
        
    sLimit = 1000;

    if ((IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH)) ||
        (IS_IN_DEV_GROUP(dev,DEV_FE_AVB_FAMILY)))
        hLimit = GT_GET_RATE_LIMIT3(sLimit);
    else if (!IS_IN_DEV_GROUP(dev,DEV_88E6183_FAMILY))
        hLimit = GT_GET_RATE_LIMIT2(sLimit);
    else
        hLimit = GT_GET_RATE_LIMIT(sLimit);
    if(hLimit == hwLimit)
    {
        *swLimit = GT_1M;
        return GT_OK;
    }
    
    if(hLimit > hwLimit)
    {
        startLimit = 2000;
        endLimit = 256000;
        *swLimit = GT_2M;
    }
    else
    {
        startLimit = 128;
        endLimit = 512;
        *swLimit = GT_128K;
    }
    
    i = 0;
    for(sLimit=startLimit;sLimit<=endLimit;sLimit *= 2, i++)
    {
        if ((IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH)) ||
            (IS_IN_DEV_GROUP(dev,DEV_FE_AVB_FAMILY)))
            hLimit = GT_GET_RATE_LIMIT3(sLimit);
        else if (!IS_IN_DEV_GROUP(dev,DEV_88E6183_FAMILY))
            hLimit = GT_GET_RATE_LIMIT2(sLimit);
        else
            hLimit = GT_GET_RATE_LIMIT(sLimit);

        if(hLimit == 0)
            hLimit = 1;

        if(hLimit == hwLimit)
        {
            *swLimit += i;
            return GT_OK;
        }

        if(hLimit < hwLimit)
            break;
    }

    *swLimit = hwLimit;
    return GT_OK;
}


/*
 Convert given sw defined Burst Rate to meaningful number.
*/
static GT_STATUS cBurstEnum2Number(GT_QD_DEV *dev, GT_BURST_RATE rate, GT_U32 *rLimit)
{
    GT_U32 rateLimit;

    GT_UNUSED_PARAM(dev);

    switch(rate)
    {
        case GT_BURST_NO_LIMIT :
                rateLimit = 0; /* MAX_RATE_LIMIT; */
                break;
        case GT_BURST_64K :
                rateLimit = 64;
                break;
        case GT_BURST_128K :
                rateLimit = 128;
                break;
        case GT_BURST_256K :
                rateLimit = 256;
                break;
        case GT_BURST_384K :
                rateLimit = 384;
                break;
        case GT_BURST_512K :
                rateLimit = 512;
                break;
        case GT_BURST_640K :
                rateLimit = 640;
                break;
        case GT_BURST_768K :
                rateLimit = 768;
                break;
        case GT_BURST_896K :
                rateLimit = 896;
                break;
        case GT_BURST_1M :
                rateLimit = 1000;
                break;
        case GT_BURST_1500K :
                rateLimit = 1500;
                break;
        case GT_BURST_2M :
                rateLimit = 2000;
                break;
        case GT_BURST_4M :
                rateLimit = 4000;
                break;
        case GT_BURST_8M :
                rateLimit = 8000;
                break;
        case GT_BURST_16M :
                rateLimit = 16000;
                break;
        case GT_BURST_32M :
                rateLimit = 32000;
                break;
        case GT_BURST_64M :
                rateLimit = 64000;
                break;
        case GT_BURST_128M :
                rateLimit = 128000;
                break;
        case GT_BURST_256M :
                rateLimit = 256000;
                break;
        default :
                return GT_BAD_PARAM;
    }

    *rLimit = rateLimit;
    return GT_OK;
}


/*
 Convert given hw Burst Rate Limit to sw defined Burst Rate Limit.
*/
static GT_STATUS cBurstRateLimit(GT_QD_DEV *dev, GT_U32 burstSize, GT_U32 hwLimit, GT_BURST_RATE* swLimit)
{
    GT_BURST_RATE sLimit, startLimit, endLimit;
    GT_U32 rLimit, tmpLimit;
    GT_STATUS       retVal;         /* Functions return value.      */

    if(hwLimit == 0)
    {
        *swLimit = GT_BURST_NO_LIMIT;
        return GT_OK;
    }
        
    startLimit = GT_BURST_64K;
    endLimit = GT_BURST_256M;
    
    for(sLimit=startLimit;sLimit<=endLimit;sLimit++)
    {
        if((retVal = cBurstEnum2Number(dev, sLimit, &rLimit)) != GT_OK)
        {
            DBG_INFO(("Failed.\n"));
               return retVal;
        }

        tmpLimit = GT_GET_BURST_RATE_LIMIT(burstSize,rLimit);

        if(hwLimit == tmpLimit)
        {
            *swLimit = sLimit;
            return GT_OK;
        }
    }

    return GT_FAIL;
}


/*
 Convert given sw defined Burst Rate to meaningful number.
*/
static GT_STATUS cTCPBurstRate(GT_QD_DEV *dev, GT_BURST_RATE rate, GT_U32 *data)
{
    GT_UNUSED_PARAM(dev);

    switch(rate)
    {
        case GT_BURST_NO_LIMIT :
                *data = 0; /* MAX_RATE_LIMIT; */
                break;
        case GT_BURST_64K :
                *data = 0x1D00;
                break;
        case GT_BURST_128K :
                *data = 0x3FFF;
                break;
        case GT_BURST_256K :
                *data = 0x7FFF;
                break;
        case GT_BURST_384K :
                *data = 0x7DE0;
                break;
        case GT_BURST_512K :
                *data = 0x76F0;
                break;
        case GT_BURST_640K :
                *data = 0x7660;
                break;
        case GT_BURST_768K :
                *data = 0x7600;
                break;
        case GT_BURST_896K :
                *data = 0x74EF;
                break;
        case GT_BURST_1M :
                *data = 0x7340;
                break;
        case GT_BURST_1500K :
                *data = 0x7300;
                break;
        default :
                return GT_BAD_PARAM;
    }

    return GT_OK;
}

static GT_STATUS setEnhancedERate(GT_QD_DEV *dev, GT_LPORT port, GT_ERATE_TYPE *rateType)
{
    GT_STATUS    retVal;         /* Functions return value.      */
    GT_U16        data;
    GT_U32        rate, eDec;
    GT_PIRL_ELIMIT_MODE        mode;
    GT_U8        phyPort;        /* Physical port.               */

    phyPort = GT_LPORT_2_PORT(port);

    if((retVal = grcGetELimitMode(dev,port,&mode)) != GT_OK)
    {
        return retVal;
    }

    if (mode == GT_PIRL_ELIMIT_FRAME)    
    {
        /* Count Per Frame */
        rate = rateType->fRate;

        if (rate == 0) /* disable egress rate limit */
        {
            eDec = 0;
            data = 0;
        }
        else if((rate < 7600)  || (rate > 1488000))
        {
            return GT_BAD_PARAM;
        }
        else
        {
            eDec = 1;
            data = (GT_U16)GT_GET_RATE_LIMIT_PER_FRAME(rate,eDec);
        }
    }
    else
    {
        /* Count Per Byte */
        rate = rateType->kbRate;

        if(rate == 0)
        {
            eDec = 0;
        }
        else if(rate < 1000)    /* less than 1Mbps */
        {
            /* it should be divided by 64 */
            if(rate % 64)
                return GT_BAD_PARAM;
            eDec = rate/64;
        }
        else if(rate <= 100000)    /* less than or equal to 100Mbps */
        {
            /* it should be divided by 1000 */
            if(rate % 1000)
                return GT_BAD_PARAM;
            eDec = rate/1000;
        }
        else if(rate <= 1000000)    /* less than or equal to 1000Mbps */
        {
            /* it should be divided by 10000 */
            if(rate % 10000)
                return GT_BAD_PARAM;
            eDec = rate/10000;
        }
        else
            return GT_BAD_PARAM;

        if(rate == 0)
        {
            data = 0;
        }
        else
        {
            data = (GT_U16)GT_GET_RATE_LIMIT_PER_BYTE(rate,eDec);
        }
    }

    retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL0,0,7,(GT_U16)eDec);
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }

    retVal = hwSetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,0,12,(GT_U16)data );
    if(retVal != GT_OK)
       {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }

    DBG_INFO(("OK.\n"));
    return GT_OK;
}


static GT_STATUS getEnhancedERate(GT_QD_DEV *dev, GT_LPORT port, GT_ERATE_TYPE *rateType)
{
    GT_STATUS    retVal;         /* Functions return value.      */
    GT_U16        rate, eDec;
    GT_PIRL_ELIMIT_MODE        mode;
    GT_U8        phyPort;        /* Physical port.               */

    phyPort = GT_LPORT_2_PORT(port);

    if((retVal = grcGetELimitMode(dev,port,&mode)) != GT_OK)
    {
        return retVal;
    }

    retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL0,0,7,&eDec);
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }

    retVal = hwGetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,0,12,&rate );
    if(retVal != GT_OK)
       {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }

    if (mode == GT_PIRL_ELIMIT_FRAME)    
    {
        rateType->fRate = GT_GET_RATE_LIMIT_PER_FRAME(rate,eDec);
    }
    else
    {
        /* Count Per Byte */
        rateType->kbRate = GT_GET_RATE_LIMIT_PER_BYTE(rate,eDec);
    }

    DBG_INFO(("OK.\n"));
    return GT_OK;
}


/*******************************************************************************
* grcSetLimitMode
*
* DESCRIPTION:
*       This routine sets the port's rate control ingress limit mode.
*
* INPUTS:
*       port    - logical port number.
*       mode     - rate control ingress limit mode. 
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_BAD_PARAM        - on bad parameters
*
* COMMENTS: 
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcSetLimitMode
(
    IN GT_QD_DEV             *dev,
    IN GT_LPORT          port,
    IN GT_RATE_LIMIT_MODE    mode
)
{

    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           phyPort;        /* Physical port.               */

    DBG_INFO(("grcSetLimitMode Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
      return retVal;

    if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
    {
        retVal = hwSetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,14,2,(GT_U16)mode );
    }
    else
    {
        retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,14,2,(GT_U16)mode );
    }
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }
    DBG_INFO(("OK.\n"));
    return GT_OK;
}



/*******************************************************************************
* grcGetLimitMode
*
* DESCRIPTION:
*       This routine gets the port's rate control ingress limit mode.
*
* INPUTS:
*       port    - logical port number.
*
* OUTPUTS:
*       mode     - rate control ingress limit mode. 
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_BAD_PARAM        - on bad parameters
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcGetLimitMode
(
    IN GT_QD_DEV *dev,
    IN  GT_LPORT port,
    OUT GT_RATE_LIMIT_MODE    *mode
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16          data;           /* The register's read data.    */
    GT_U8           phyPort;        /* Physical port.               */

    DBG_INFO(("grcGetLimitMode Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
      return retVal;
    
    if(mode == NULL)
    {
        DBG_INFO(("Failed.\n"));
        return GT_BAD_PARAM;
    }

    if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
    {
        retVal = hwGetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,14,2,&data );
    }
    else
    {
        retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,14,2,&data );
    }
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }

    *mode = data;
    DBG_INFO(("OK.\n"));
    return GT_OK;
}

/*******************************************************************************
* grcSetPri3Rate
*
* DESCRIPTION:
*       This routine sets the ingress data rate limit for priority 3 frames.
*       Priority 3 frames will be discarded after the ingress rate selection
*       is reached or exceeded.
*
* INPUTS:
*       port - the logical port number.
*       mode - the priority 3 frame rate limit mode
*              GT_FALSE: use the same rate as Pri2Rate
*              GT_TRUE:  use twice the rate as Pri2Rate
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK   - on success
*       GT_FAIL - on error
*
* COMMENTS:
*
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcSetPri3Rate
(
    IN GT_QD_DEV *dev,
    IN GT_LPORT port,
    IN GT_BOOL  mode
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16          data;           /* Data to be set into the      */
                                    /* register.                    */
    GT_U8           phyPort;        /* Physical port.               */

    DBG_INFO(("grcSetPri3Rate Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
      return retVal;
    
    BOOL_2_BIT(mode,data);

    if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
    {
        retVal = hwSetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,14,1,data );
    }
    else
    {
        retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,13,1,data);
    }
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }

    DBG_INFO(("OK.\n"));
    return GT_OK;
}



/*******************************************************************************
* grcGetPri3Rate
*
* DESCRIPTION:
*       This routine gets the ingress data rate limit for priority 3 frames.
*       Priority 3 frames will be discarded after the ingress rate selection
*       is reached or exceeded.
*
* INPUTS:
*       port - the logical port number.
*       
* OUTPUTS:
*       mode - the priority 3 frame rate limit mode
*              GT_FALSE: use the same rate as Pri2Rate
*              GT_TRUE:  use twice the rate as Pri2Rate
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_BAD_PARAM        - on bad parameters
*
* COMMENTS:
*
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcGetPri3Rate
(
    IN GT_QD_DEV *dev,
    IN  GT_LPORT port,
    OUT GT_BOOL  *mode
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16          data;           /* The register's read data.    */
    GT_U8           phyPort;        /* Physical port.               */

    DBG_INFO(("grcGetPri3Rate Called.\n"));
    if(mode == NULL)
    {
        DBG_INFO(("Failed.\n"));
        return GT_BAD_PARAM;
    }

    phyPort = GT_LPORT_2_PORT(port);

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
      return retVal;
    
    if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
    {
        retVal = hwGetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,14,1,&data );
    }
    else
    {
        retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,13,1,&data);
    }
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }

    BIT_2_BOOL(data,*mode);
    DBG_INFO(("OK.\n"));
    return GT_OK;
}


/*******************************************************************************
* grcSetPri2Rate
*
* DESCRIPTION:
*       This routine sets the ingress data rate limit for priority 2 frames.
*       Priority 2 frames will be discarded after the ingress rate selection
*       is reached or exceeded.
*
* INPUTS:
*       port - the logical port number.
*       mode - the priority 2 frame rate limit mode
*              GT_FALSE: use the same rate as Pri1Rate
*              GT_TRUE:  use twice the rate as Pri1Rate
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK   - on success
*       GT_FAIL - on error
*
* COMMENTS:
*
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcSetPri2Rate
(
    IN GT_QD_DEV *dev,
    IN GT_LPORT port,
    IN GT_BOOL  mode
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16          data;           /* Data to be set into the      */
                                    /* register.                    */
    GT_U8           phyPort;        /* Physical port.               */

    DBG_INFO(("grcSetPri2Rate Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
      return retVal;
    
    BOOL_2_BIT(mode,data);

    if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
    {
        retVal = hwSetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,13,1,data );
    }
    else
    {
        retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,12,1,data);
    }
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }

    DBG_INFO(("OK.\n"));
    return GT_OK;
}



/*******************************************************************************
* grcGetPri2Rate
*
* DESCRIPTION:
*       This routine gets the ingress data rate limit for priority 2 frames.
*       Priority 2 frames will be discarded after the ingress rate selection
*       is reached or exceeded.
*
* INPUTS:
*       port - the logical port number.
*       
* OUTPUTS:
*       mode - the priority 2 frame rate limit mode
*              GT_FALSE: use the same rate as Pri1Rate
*              GT_TRUE:  use twice the rate as Pri1Rate
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_BAD_PARAM        - on bad parameters
*
* COMMENTS:
*
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcGetPri2Rate
(
    IN GT_QD_DEV *dev,
    IN  GT_LPORT port,
    OUT GT_BOOL  *mode
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16          data;           /* The register's read data.    */
    GT_U8           phyPort;        /* Physical port.               */

    DBG_INFO(("grcGetPri2Rate Called.\n"));
    if(mode == NULL)
    {
        DBG_INFO(("Failed.\n"));
        return GT_BAD_PARAM;
    }

    phyPort = GT_LPORT_2_PORT(port);

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
      return retVal;
    
    if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
    {
        retVal = hwGetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,13,1,&data );
    }
    else
    {
        retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,12,1,&data);
    }
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }

    BIT_2_BOOL(data,*mode);
    DBG_INFO(("OK.\n"));
    return GT_OK;
}


/*******************************************************************************
* grcSetPri1Rate
*
* DESCRIPTION:
*       This routine sets the ingress data rate limit for priority 1 frames.
*       Priority 1 frames will be discarded after the ingress rate selection
*       is reached or exceeded.
*
* INPUTS:
*       port - the logical port number.
*       mode - the priority 1 frame rate limit mode
*              GT_FALSE: use the same rate as Pri0Rate
*              GT_TRUE:  use twice the rate as Pri0Rate
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK   - on success
*       GT_FAIL - on error
*
* COMMENTS:
*
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcSetPri1Rate
(
    IN GT_QD_DEV *dev,
    IN GT_LPORT  port,
    IN GT_BOOL   mode
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16          data;           /* Data to be set into the      */
                                    /* register.                    */
    GT_U8           phyPort;        /* Physical port.               */

    DBG_INFO(("grcSetPri1Rate Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);
    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
      return retVal;
    
    BOOL_2_BIT(mode,data);

    if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
    {
        retVal = hwSetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,12,1,data );
    }
    else
    {
        retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,11,1,data);
    }
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }

    DBG_INFO(("OK.\n"));
    return GT_OK;
}



/*******************************************************************************
* grcGetPri1Rate
*
* DESCRIPTION:
*       This routine gets the ingress data rate limit for priority 1 frames.
*       Priority 1 frames will be discarded after the ingress rate selection
*       is reached or exceeded.
*
* INPUTS:
*       port - the logical port number.
*       
* OUTPUTS:
*       mode - the priority 1 frame rate limit mode
*              GT_FALSE: use the same rate as Pri0Rate
*              GT_TRUE:  use twice the rate as Pri0Rate
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_BAD_PARAM        - on bad parameters
*
* COMMENTS:
*
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcGetPri1Rate
(
    IN GT_QD_DEV *dev,
    IN  GT_LPORT port,
    OUT GT_BOOL  *mode
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16          data;           /* The register's read data.    */
    GT_U8           phyPort;        /* Physical port.               */

    DBG_INFO(("grcGetPri1Rate Called.\n"));
    if(mode == NULL)
    {
        DBG_INFO(("Failed.\n"));
        return GT_BAD_PARAM;
    }

    phyPort = GT_LPORT_2_PORT(port);
    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS)) != GT_OK ) 
      return retVal;
    
    if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
    {
        retVal = hwGetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,12,1,&data );
    }
    else
    {
        retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,11,1,&data);
    }
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }

    BIT_2_BOOL(data,*mode);
    DBG_INFO(("OK.\n"));
    return GT_OK;
}


/*******************************************************************************
* grcSetPri0Rate
*
* DESCRIPTION:
*       This routine sets the port's ingress data limit for priority 0 frames.
*
* INPUTS:
*       port    - logical port number.
*       rate    - ingress data rate limit for priority 0 frames. These frames
*             will be discarded after the ingress rate selected is reached 
*             or exceeded. 
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_BAD_PARAM        - on bad parameters
*
* COMMENTS: 
*            GT_16M, GT_32M, GT_64M, GT_128M, and GT_256M in GT_PRI0_RATE enum
*            are supported only by Gigabit Ethernet Switch.
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcSetPri0Rate
(
    IN GT_QD_DEV       *dev,
    IN GT_LPORT        port,
    IN GT_PRI0_RATE    rate
)
{

    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           phyPort;        /* Physical port.               */
    GT_U32            rateLimit, tmpLimit;

    DBG_INFO(("grcSetPri0Rate Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS|DEV_UNMANAGED_SWITCH)) != GT_OK ) 
      return retVal;

    if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_MANAGED_SWITCH))
    {
        dev->devStorage &= ~(GT_RATE_ENUM_NOT_USED);
        switch(rate)
        {
            case GT_NO_LIMIT :
                    rateLimit = 0; /* MAX_RATE_LIMIT; */
                    break;
            case GT_128K :
                    rateLimit = 128;
                    break;
            case GT_256K :
                    rateLimit = 256;
                    break;
            case GT_512K :
                    rateLimit = 512;
                    break;
            case GT_1M :
                    rateLimit = 1000;
                    break;
            case GT_2M :
                    rateLimit = 2000;
                    break;
            case GT_4M :
                    rateLimit = 4000;
                    break;
            case GT_8M :
                    rateLimit = 8000;
                    break;
            case GT_16M :
                    rateLimit = 16000;
                    break;
            case GT_32M :
                    rateLimit = 32000;
                    break;
            case GT_64M :
                    rateLimit = 64000;
                    break;
            case GT_128M :
                    rateLimit = 128000;
                    break;
            case GT_256M :
                    rateLimit = 256000;
                    break;
            default :
                    rateLimit = (GT_U32)rate;
                    dev->devStorage |= GT_RATE_ENUM_NOT_USED;
                    break;                    
        }

        if (!IS_IN_DEV_GROUP(dev,DEV_88E6183_FAMILY))
            tmpLimit = GT_GET_RATE_LIMIT2(rateLimit);
        else
            tmpLimit = GT_GET_RATE_LIMIT(rateLimit);

        if((tmpLimit == 0) && (rateLimit != 0))
            rateLimit = 1;
        else
            rateLimit = tmpLimit;

        retVal = hwSetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,0,12,(GT_U16)rateLimit );
        if(retVal != GT_OK)
        {
            DBG_INFO(("Failed.\n"));
            return retVal;
        }
    }
    else
    {
        switch(rate)
        {
            case GT_NO_LIMIT :
            case GT_128K :
            case GT_256K :
            case GT_512K :
            case GT_1M :
            case GT_2M :
            case GT_4M :
            case GT_8M :
                    break;
            default :
                    return GT_BAD_PARAM;
        }
        retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,8,3,(GT_U16)rate );
        if(retVal != GT_OK)
        {
            DBG_INFO(("Failed.\n"));
            return retVal;
        }
    }
    DBG_INFO(("OK.\n"));
    return GT_OK;
}



/*******************************************************************************
* grcGetPri0Rate
*
* DESCRIPTION:
*       This routine gets the port's ingress data limit for priority 0 frames.
*
* INPUTS:
*       port    - logical port number to set.
*
* OUTPUTS:
*       rate    - ingress data rate limit for priority 0 frames. These frames
*             will be discarded after the ingress rate selected is reached 
*             or exceeded. 
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_BAD_PARAM        - on bad parameters
*
* COMMENTS: 
*            GT_16M, GT_32M, GT_64M, GT_128M, and GT_256M in GT_PRI0_RATE enum
*            are supported only by Gigabit Ethernet Switch.
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcGetPri0Rate
(
    IN  GT_QD_DEV *dev,
    IN  GT_LPORT port,
    OUT GT_PRI0_RATE    *rate
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16          data;           /* The register's read data.    */
    GT_U8           phyPort;        /* Physical port.               */
    GT_U32            tmpLimit;

    DBG_INFO(("grcGetPri0Rate Called.\n"));

    if(rate == NULL)
    {
        DBG_INFO(("Failed.\n"));
        return GT_BAD_PARAM;
    }

    phyPort = GT_LPORT_2_PORT(port);

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS|DEV_UNMANAGED_SWITCH)) != GT_OK ) 
      return retVal;

    if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
    {
        retVal = hwGetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,0,12,&data);
        tmpLimit = (GT_U32)data;

        if(retVal != GT_OK)
        {
            DBG_INFO(("Failed.\n"));
            return retVal;
        }

        if(dev->devStorage & GT_RATE_ENUM_NOT_USED)
        {
            if (!IS_IN_DEV_GROUP(dev,DEV_88E6183_FAMILY))
                *rate = GT_GET_RATE_LIMIT2(tmpLimit);
            else
                *rate = GT_GET_RATE_LIMIT(tmpLimit);
        }
        else
        {
            cRateLimit(dev, tmpLimit, (GT_U32*)rate);
        }
    }
    else
    {
        retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,8,3,&data );
        if(retVal != GT_OK)
        {
            DBG_INFO(("Failed.\n"));
            return retVal;
        }
        *rate = data;
    }

    DBG_INFO(("OK.\n"));
    return GT_OK;
}

/*******************************************************************************
* grcSetBytesCount
*
* DESCRIPTION:
*       This routine sets the byets to count for limiting needs to be determined
*
* INPUTS:
*       port      - logical port number to set.
*        limitMGMT - GT_TRUE: To limit and count MGMT frame bytes
*                GT_FALSE: otherwise
*        countIFG  - GT_TRUE: To count IFG bytes
*                GT_FALSE: otherwise
*        countPre  - GT_TRUE: To count Preamble bytes
*                GT_FALSE: otherwise
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_BAD_PARAM        - on bad parameters
*
* COMMENTS: 
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcSetBytesCount
(
    IN GT_QD_DEV *dev,
    IN GT_LPORT  port,
    IN GT_BOOL      limitMGMT,
    IN GT_BOOL      countIFG,
    IN GT_BOOL      countPre
)
{

    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           phyPort;        /* Physical port.               */
    GT_U16          data;           /* data for bytes count         */

    DBG_INFO(("grcSetBytesCount Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS|DEV_UNMANAGED_SWITCH)) != GT_OK ) 
      return retVal;

    if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
    {
        BOOL_2_BIT(limitMGMT,data);
        retVal = hwSetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,15,1,data );
        if (retVal != GT_OK)
            return retVal;

        data = 0;
        if( countIFG == GT_TRUE ) data |= 2;
        if( countPre == GT_TRUE ) data |= 1;

        retVal = hwSetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,12,2,data );
    }
    else
    {
        data = 0;
        if(    limitMGMT == GT_TRUE ) data |=4;
        if(     countIFG == GT_TRUE ) data |=2;
        if(     countPre == GT_TRUE ) data |=1;

        retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,4,3,data );
    }

       if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }
    DBG_INFO(("OK.\n"));
    return GT_OK;
}



/*******************************************************************************
* grcGetBytesCount
*
* DESCRIPTION:
*       This routine gets the byets to count for limiting needs to be determined
*
* INPUTS:
*       port    - logical port number 
*
* OUTPUTS:
*        limitMGMT - GT_TRUE: To limit and count MGMT frame bytes
*                GT_FALSE: otherwise
*        countIFG  - GT_TRUE: To count IFG bytes
*                GT_FALSE: otherwise
*        countPre  - GT_TRUE: To count Preamble bytes
*                GT_FALSE: otherwise
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_BAD_PARAM        - on bad parameters
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcGetBytesCount
(    
    IN GT_QD_DEV *dev,
    IN GT_LPORT  port,
    IN GT_BOOL      *limitMGMT,
    IN GT_BOOL      *countIFG,
    IN GT_BOOL      *countPre
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16          data;           /* The register's read data.    */
    GT_U8           phyPort;        /* Physical port.               */

    DBG_INFO(("grcGetBytesCount Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_INGRESS_RATE_KBPS|DEV_UNMANAGED_SWITCH)) != GT_OK ) 
      return retVal;

    if (limitMGMT == NULL || countIFG == NULL || countPre == NULL)
    {
        DBG_INFO(("Failed.\n"));
        return GT_BAD_PARAM;
    }
       *limitMGMT = *countIFG = *countPre = GT_FALSE;

    if (IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH))
    {
        retVal = hwGetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,15,1,&data );
        if (retVal != GT_OK)
        {
            DBG_INFO(("Failed.\n"));
            return retVal;
        }

        BIT_2_BOOL(data,*limitMGMT);
        retVal = hwGetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,12,2,&data );
        if (retVal != GT_OK)
        {
            DBG_INFO(("Failed.\n"));
            return retVal;
        }

        if( data & 0x2 ) *countIFG = GT_TRUE;
        if( data & 0x1 ) *countPre = GT_TRUE;

    }
    else
    {

        retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,4,3,&data );
        if(retVal != GT_OK)
        {
            DBG_INFO(("Failed.\n"));
            return retVal;
        }

        if ( data & 4 ) *limitMGMT = GT_TRUE;
        if ( data & 2 ) *countIFG  = GT_TRUE;
        if ( data & 1 ) *countPre  = GT_TRUE;
    
    }
        
    DBG_INFO(("OK.\n"));
    return GT_OK;
}

/*******************************************************************************
* grcSetEgressRate
*
* DESCRIPTION:
*       This routine sets the port's egress data limit.
*        
*
* INPUTS:
*       port      - logical port number.
*       rateType  - egress data rate limit (GT_ERATE_TYPE union type). 
*                    union type is used to support multiple devices with the
*                    different formats of egress rate.
*                    GT_ERATE_TYPE has the following fields:
*                        definedRate - GT_EGRESS_RATE enum type should used for the 
*                            following devices:
*                            88E6218, 88E6318, 88E6063, 88E6083, 88E6181, 88E6183,
*                            88E6093, 88E6095, 88E6185, 88E6108, 88E6065, 88E6061, 
*                            and their variations
*                        kbRate - rate in kbps that should used for the following 
*                            devices:
*                            88E6097, 88E6096 with the GT_PIRL_ELIMIT_MODE of 
*                                GT_PIRL_ELIMIT_LAYER1,
*                                GT_PIRL_ELIMIT_LAYER2, or 
*                                GT_PIRL_ELIMIT_LAYER3 (see grcSetELimitMode)
*                            64kbps ~ 1Mbps    : increments of 64kbps,
*                            1Mbps ~ 100Mbps   : increments of 1Mbps, and
*                            100Mbps ~ 1000Mbps: increments of 10Mbps
*                            Therefore, the valid values are:
*                                64, 128, 192, 256, 320, 384,..., 960,
*                                1000, 2000, 3000, 4000, ..., 100000,
*                                110000, 120000, 130000, ..., 1000000.
*                        fRate - frame per second that should used for the following
*                            devices:
*                            88E6097, 88E6096 with GT_PIRL_ELIMIT_MODE of 
*                                GT_PIRL_ELIMIT_FRAME
*                            Valid values are between 7600 and 1488000
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_BAD_PARAM        - on bad parameters
*
* COMMENTS: 
*            GT_16M, GT_32M, GT_64M, GT_128M, and GT_256M in GT_EGRESS_RATE enum
*            are supported only by Gigabit Ethernet Switch.
*
*******************************************************************************/
GT_STATUS grcSetEgressRate
(
    IN GT_QD_DEV       *dev,
    IN GT_LPORT        port,
    IN GT_ERATE_TYPE   *rateType
)
{

    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           phyPort;        /* Physical port.               */
    GT_U32            rateLimit, tmpLimit;
    GT_EGRESS_RATE  rate;

    DBG_INFO(("grcSetEgressRate Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_EGRESS_RATE_KBPS|DEV_UNMANAGED_SWITCH)) != GT_OK ) 
      return retVal;
    
    if (IS_IN_DEV_GROUP(dev,DEV_ELIMIT_FRAME_BASED))
    {
        return setEnhancedERate(dev,port,rateType);
    }

    rate = rateType->definedRate;

    if ((IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH)) ||
        (IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH)) ||
        (IS_IN_DEV_GROUP(dev,DEV_FE_AVB_FAMILY)))
    {
        dev->devStorage &= ~(GT_RATE_ENUM_NOT_USED);
        switch(rate)
        {
            case GT_NO_LIMIT :
                    rateLimit = 0; /* MAX_RATE_LIMIT; */
                    break;
            case GT_128K :
                    rateLimit = 128;
                    break;
            case GT_256K :
                    rateLimit = 256;
                    break;
            case GT_512K :
                    rateLimit = 512;
                    break;
            case GT_1M :
                    rateLimit = 1000;
                    break;
            case GT_2M :
                    rateLimit = 2000;
                    break;
            case GT_4M :
                    rateLimit = 4000;
                    break;
            case GT_8M :
                    rateLimit = 8000;
                    break;
            case GT_16M :
                    rateLimit = 16000;
                    break;
            case GT_32M :
                    rateLimit = 32000;
                    break;
            case GT_64M :
                    rateLimit = 64000;
                    break;
            case GT_128M :
                    rateLimit = 128000;
                    break;
            case GT_256M :
                    rateLimit = 256000;
                    break;
            default :
                    rateLimit = (GT_U32)rate;
                    dev->devStorage |= GT_RATE_ENUM_NOT_USED;
                    break;                    
        }

        if ((IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH)) ||
            (IS_IN_DEV_GROUP(dev,DEV_FE_AVB_FAMILY)))
            tmpLimit = GT_GET_RATE_LIMIT3(rateLimit);
        else if (!IS_IN_DEV_GROUP(dev,DEV_88E6183_FAMILY))
            tmpLimit = GT_GET_RATE_LIMIT2(rateLimit);
        else
            tmpLimit = GT_GET_RATE_LIMIT(rateLimit);

        if((tmpLimit == 0) && (rateLimit != 0))
            rateLimit = 1;
        else
            rateLimit = tmpLimit;

        retVal = hwSetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,0,12,(GT_U16)rateLimit );
        if(retVal != GT_OK)
        {
            DBG_INFO(("Failed.\n"));
            return retVal;
        }
    }
    else
    {
        switch(rate)
        {
            case GT_NO_LIMIT :
            case GT_128K :
            case GT_256K :
            case GT_512K :
            case GT_1M :
            case GT_2M :
            case GT_4M :
            case GT_8M :
                    break;
            default :
                    return GT_BAD_PARAM;
        }
        retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,0,3,(GT_U16)rate );
        if(retVal != GT_OK)
        {
            DBG_INFO(("Failed.\n"));
            return retVal;
        }
    }

    DBG_INFO(("OK.\n"));
    return GT_OK;
}



/*******************************************************************************
* grcGetEgressRate
*
* DESCRIPTION:
*       This routine gets the port's egress data limit.
*
* INPUTS:
*       port    - logical port number.
*
* OUTPUTS:
*       rateType  - egress data rate limit (GT_ERATE_TYPE union type). 
*                    union type is used to support multiple devices with the
*                    different formats of egress rate.
*                    GT_ERATE_TYPE has the following fields:
*                        definedRate - GT_EGRESS_RATE enum type should used for the 
*                            following devices:
*                            88E6218, 88E6318, 88E6063, 88E6083, 88E6181, 88E6183,
*                            88E6093, 88E6095, 88E6185, 88E6108, 88E6065, 88E6061, 
*                            and their variations
*                        kbRate - rate in kbps that should used for the following 
*                            devices:
*                            88E6097, 88E6096 with the GT_PIRL_ELIMIT_MODE of 
*                                GT_PIRL_ELIMIT_LAYER1,
*                                GT_PIRL_ELIMIT_LAYER2, or 
*                                GT_PIRL_ELIMIT_LAYER3 (see grcSetELimitMode)
*                            64kbps ~ 1Mbps    : increments of 64kbps,
*                            1Mbps ~ 100Mbps   : increments of 1Mbps, and
*                            100Mbps ~ 1000Mbps: increments of 10Mbps
*                            Therefore, the valid values are:
*                                64, 128, 192, 256, 320, 384,..., 960,
*                                1000, 2000, 3000, 4000, ..., 100000,
*                                110000, 120000, 130000, ..., 1000000.
*                        fRate - frame per second that should used for the following
*                            devices:
*                            88E6097, 88E6096 with GT_PIRL_ELIMIT_MODE of 
*                                GT_PIRL_ELIMIT_FRAME
*                            Valid values are between 7600 and 1488000
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_BAD_PARAM        - on bad parameters
*
* COMMENTS:
*            GT_16M, GT_32M, GT_64M, GT_128M, and GT_256M in GT_EGRESS_RATE enum
*            are supported only by Gigabit Ethernet Switch.
*
*******************************************************************************/
GT_STATUS grcGetEgressRate
(
    IN GT_QD_DEV *dev,
    IN  GT_LPORT port,
    OUT GT_ERATE_TYPE  *rateType
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16          data;           /* The register's read data.    */
    GT_U8           phyPort;        /* Physical port.               */
    GT_U32            tmpLimit,tmpRate;

    DBG_INFO(("grcGetEgressRate Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);

    /* check if device supports this feature */
    if((retVal = IS_VALID_API_CALL(dev,phyPort, DEV_EGRESS_RATE_KBPS|DEV_UNMANAGED_SWITCH)) != GT_OK ) 
      return retVal;
    
    if(rateType == NULL)
    {
        DBG_INFO(("Failed.\n"));
        return GT_BAD_PARAM;
    }

    if (IS_IN_DEV_GROUP(dev,DEV_ELIMIT_FRAME_BASED))
    {
        return getEnhancedERate(dev,port,rateType);
    }

    if ((IS_IN_DEV_GROUP(dev,DEV_GIGABIT_SWITCH)) ||
        (IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH)) ||
        (IS_IN_DEV_GROUP(dev,DEV_FE_AVB_FAMILY)))
    {
        retVal = hwGetPortRegField(dev,phyPort,QD_REG_EGRESS_RATE_CTRL,0,12,&data );
        tmpLimit = (GT_U32)data;
        if(retVal != GT_OK)
        {
            DBG_INFO(("Failed.\n"));
            return retVal;
        }

        if(dev->devStorage & GT_RATE_ENUM_NOT_USED)
        {
            if ((IS_IN_DEV_GROUP(dev,DEV_ENHANCED_FE_SWITCH)) ||
                (IS_IN_DEV_GROUP(dev,DEV_FE_AVB_FAMILY)))
                tmpRate = GT_GET_RATE_LIMIT3(tmpLimit);
            else if (!IS_IN_DEV_GROUP(dev,DEV_88E6183_FAMILY))
                tmpRate = GT_GET_RATE_LIMIT2(tmpLimit);
            else
                tmpRate = GT_GET_RATE_LIMIT(tmpLimit);
            rateType->kbRate = tmpRate;
        }
        else
        {
            cRateLimit(dev, tmpLimit, &tmpRate);
            rateType->definedRate = (GT_EGRESS_RATE)tmpRate;
        }
    }
    else
    {
        retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL,0,3,&data );
        if(retVal != GT_OK)
        {
            DBG_INFO(("Failed.\n"));
            return retVal;
        }
        
        rateType->definedRate = (GT_EGRESS_RATE)data;
    }


    DBG_INFO(("OK.\n"));
    return GT_OK;
}


/*******************************************************************************
* grcSetBurstRate
*
* DESCRIPTION:
*       This routine sets the port's ingress data limit based on burst size.
*
* INPUTS:
*       port    - logical port number.
*       bsize    - burst size.
*       rate    - ingress data rate limit. These frames will be discarded after 
*                the ingress rate selected is reached or exceeded. 
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_BAD_PARAM        - on bad parameters 
*                                Minimum rate for Burst Size 24K byte is 128Kbps
*                                Minimum rate for Burst Size 48K byte is 256Kbps
*                                Minimum rate for Burst Size 96K byte is 512Kbps
*        GT_NOT_SUPPORTED    - if current device does not support this feature.
*
* COMMENTS: 
*        If the device supports both priority based Rate Limiting and burst size
*        based Rate limiting, user has to manually change the mode to burst size
*        based Rate limiting by calling gsysSetRateLimitMode.
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcSetBurstRate
(
    IN GT_QD_DEV       *dev,
    IN GT_LPORT        port,
    IN GT_BURST_SIZE   bsize,
    IN GT_BURST_RATE   rate
)
{

    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           phyPort;        /* Physical port.               */
    GT_U32            rateLimit;
    GT_U32            burstSize =0;

    DBG_INFO(("grcSetBurstRate Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);

    /* check if the given Switch supports this feature. */
    if (!IS_IN_DEV_GROUP(dev,DEV_BURST_RATE))
    {
        if (!IS_IN_DEV_GROUP(dev,DEV_NEW_FEATURE_IN_REV) || 
            ((GT_DEVICE_REV)dev->revision < GT_REV_1))
        {
            DBG_INFO(("GT_NOT_SUPPORTED\n"));
            return GT_NOT_SUPPORTED;
        }
    }

    switch (bsize)
    {
        case GT_BURST_SIZE_12K:
            burstSize = 0;
            break;
        case GT_BURST_SIZE_24K:
            if ((rate < GT_BURST_128K) && (rate != GT_BURST_NO_LIMIT))
                return GT_BAD_PARAM;
            burstSize = 1;
            break;
        case GT_BURST_SIZE_48K:
            if ((rate < GT_BURST_256K) && (rate != GT_BURST_NO_LIMIT))
                return GT_BAD_PARAM;
            burstSize = 3;
            break;
        case GT_BURST_SIZE_96K:
            if ((rate < GT_BURST_512K) && (rate != GT_BURST_NO_LIMIT))
                return GT_BAD_PARAM;
            burstSize = 7;
            break;
        default:
            return GT_BAD_PARAM;
    }

    if((retVal = cBurstEnum2Number(dev, rate, &rateLimit)) != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }

    rateLimit = GT_GET_BURST_RATE_LIMIT(burstSize,rateLimit);

    rateLimit |= (GT_U32)(burstSize << 12);

    retVal = hwSetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,0,15,(GT_U16)rateLimit );
    if(retVal != GT_OK)
       {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }
    DBG_INFO(("OK.\n"));
    return GT_OK;
}


/*******************************************************************************
* grcGetBurstRate
*
* DESCRIPTION:
*       This routine retrieves the port's ingress data limit based on burst size.
*
* INPUTS:
*       port    - logical port number.
*
* OUTPUTS:
*       bsize    - burst size.
*       rate    - ingress data rate limit. These frames will be discarded after 
*                the ingress rate selected is reached or exceeded. 
*
* RETURNS:
*       GT_OK            - on success
*       GT_FAIL          - on error
*        GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS: 
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcGetBurstRate
(
    IN  GT_QD_DEV       *dev,
    IN  GT_LPORT        port,
    OUT GT_BURST_SIZE   *bsize,
    OUT GT_BURST_RATE   *rate
)
{

    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           phyPort;        /* Physical port.               */
    GT_U32            rateLimit, burstSize;
    GT_U16            data;

    DBG_INFO(("grcGetBurstRate Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);

    /* check if the given Switch supports this feature. */
    if (!IS_IN_DEV_GROUP(dev,DEV_BURST_RATE))
    {
        if (!IS_IN_DEV_GROUP(dev,DEV_NEW_FEATURE_IN_REV) || 
            ((GT_DEVICE_REV)dev->revision < GT_REV_1))
        {
            DBG_INFO(("GT_NOT_SUPPORTED\n"));
            return GT_NOT_SUPPORTED;
        }
    }
        
    retVal = hwGetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,0,15,&data);
    rateLimit = (GT_U32)data;
    if(retVal != GT_OK)
       {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }

    burstSize = rateLimit >> 12;
    rateLimit &= 0x0FFF;

    retVal = cBurstRateLimit(dev, burstSize, rateLimit, rate);
    if(retVal != GT_OK)
       {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }

    switch (burstSize)
    {
        case 0:
            *bsize = GT_BURST_SIZE_12K;
            break;
        case 1:
            *bsize = GT_BURST_SIZE_24K;
            break;
        case 3:
            *bsize = GT_BURST_SIZE_48K;
            break;
        case 7:
            *bsize = GT_BURST_SIZE_96K;
            break;
        default:
            return GT_BAD_VALUE;
    }

    DBG_INFO(("OK.\n"));
    return GT_OK;
}


/*******************************************************************************
* grcSetTCPBurstRate
*
* DESCRIPTION:
*       This routine sets the port's TCP/IP ingress data limit based on burst size.
*
* INPUTS:
*       port    - logical port number.
*       rate    - ingress data rate limit for TCP/IP packets. These frames will 
*                be discarded after the ingress rate selected is reached or exceeded. 
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_BAD_PARAM        - on bad parameters 
*                                Valid rate is GT_BURST_NO_LIMIT, or between
*                                64Kbps and 1500Kbps.
*        GT_NOT_SUPPORTED    - if current device does not support this feature.
*
* COMMENTS: 
*        If the device supports both priority based Rate Limiting and burst size
*        based Rate limiting, user has to manually change the mode to burst size
*        based Rate limiting by calling gsysSetRateLimitMode.
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcSetTCPBurstRate
(
    IN GT_QD_DEV       *dev,
    IN GT_LPORT        port,
    IN GT_BURST_RATE   rate
)
{

    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           phyPort;        /* Physical port.               */
    GT_U32            rateLimit;

    DBG_INFO(("grcSetTCPBurstRate Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);

    /* check if the given Switch supports this feature. */
    if (!IS_IN_DEV_GROUP(dev,DEV_BURST_RATE))
    {
        if (!IS_IN_DEV_GROUP(dev,DEV_NEW_FEATURE_IN_REV) || 
            ((GT_DEVICE_REV)dev->revision < GT_REV_1))
        {
            DBG_INFO(("GT_NOT_SUPPORTED\n"));
            return GT_NOT_SUPPORTED;
        }
    }

    if((retVal = cTCPBurstRate(dev, rate, &rateLimit)) != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }

    retVal = hwSetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,0,15,(GT_U16)rateLimit );
    if(retVal != GT_OK)
       {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }
    DBG_INFO(("OK.\n"));
    return GT_OK;
}



/*******************************************************************************
* grcGetTCPBurstRate
*
* DESCRIPTION:
*       This routine sets the port's TCP/IP ingress data limit based on burst size.
*
* INPUTS:
*       port    - logical port number.
*
* OUTPUTS:
*       rate    - ingress data rate limit for TCP/IP packets. These frames will 
*                be discarded after the ingress rate selected is reached or exceeded. 
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_BAD_VALUE        - register value is not known
*        GT_NOT_SUPPORTED    - if current device does not support this feature.
*
* COMMENTS: 
*        If the device supports both priority based Rate Limiting and burst size
*        based Rate limiting, user has to manually change the mode to burst size
*        based Rate limiting by calling gsysSetRateLimitMode.
*
* GalTis:
*
*******************************************************************************/
GT_STATUS grcGetTCPBurstRate
(
    IN  GT_QD_DEV       *dev,
    IN  GT_LPORT        port,
    OUT GT_BURST_RATE   *rate
)
{

    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           phyPort;        /* Physical port.               */
    GT_U32            rateLimit;
    GT_U32            data;
    GT_U16            u16Data;
    GT_BURST_RATE sLimit, startLimit, endLimit;

    DBG_INFO(("grcGetTCPBurstRate Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);

    /* check if the given Switch supports this feature. */
    if (!IS_IN_DEV_GROUP(dev,DEV_BURST_RATE))
    {
        if (!IS_IN_DEV_GROUP(dev,DEV_NEW_FEATURE_IN_REV) || 
            ((GT_DEVICE_REV)dev->revision < GT_REV_1))
        {
            DBG_INFO(("GT_NOT_SUPPORTED\n"));
            return GT_NOT_SUPPORTED;
        }
    }

    retVal = hwGetPortRegField(dev,phyPort,QD_REG_INGRESS_RATE_CTRL,0,15,&u16Data);
    data = (GT_U32)u16Data;
    if(retVal != GT_OK)
       {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }

    if ((data & 0xFFF) == 0)
    {
        *rate = GT_BURST_NO_LIMIT;
        return GT_OK;
    }

    startLimit = GT_BURST_64K;
    endLimit = GT_BURST_1500K;

    for(sLimit=startLimit;sLimit<=endLimit;sLimit++)
    {
        if((retVal = cTCPBurstRate(dev, sLimit, &rateLimit)) != GT_OK)
        {
            break;
        }

        if(rateLimit == data)
        {
            *rate = sLimit;
            return GT_OK;
        }
    }

    DBG_INFO(("Fail to find TCP Rate.\n"));
    return GT_BAD_VALUE;
}


/*******************************************************************************
* grcSetVidNrlEn
*
* DESCRIPTION:
*       This routine enables/disables VID None Rate Limit (NRL).
*        When VID NRL is enabled and the determined VID of a frame results in a VID
*        whose VIDNonRateLimit in the VTU Table is set to GT_TURE, then the frame
*        will not be ingress nor egress rate limited.
*
* INPUTS:
*       port - logical port number.
*        mode - GT_TRUE to enable VID None Rate Limit
*               GT_FALSE otherwise
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*        GT_NOT_SUPPORTED    - if current device does not support this feature.
*
* COMMENTS: 
*
*******************************************************************************/
GT_STATUS grcSetVidNrlEn
(
    IN  GT_QD_DEV    *dev,
    IN  GT_LPORT    port,
    IN  GT_BOOL        mode
)
{
    GT_U16          data;           
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           hwPort;        /* Physical port.               */

    DBG_INFO(("grcSetVidNrlEn Called.\n"));

    hwPort = GT_LPORT_2_PORT(port);

    /* check if the given Switch supports this feature. */
    if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
    {
           DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    /* translate BOOL to binary */
    BOOL_2_BIT(mode, data);

    /* Set the VidNrlEn mode.            */
    retVal = hwSetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,15,1,data);
    if(retVal != GT_OK)
       {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }

    DBG_INFO(("OK.\n"));

    return GT_OK;
}

/*******************************************************************************
* grcGetVidNrlEn
*
* DESCRIPTION:
*       This routine gets VID None Rate Limit (NRL) mode.
*        When VID NRL is enabled and the determined VID of a frame results in a VID
*        whose VIDNonRateLimit in the VTU Table is set to GT_TURE, then the frame
*        will not be ingress nor egress rate limited.
*
* INPUTS:
*       port - logical port number.
*
* OUTPUTS:
*        mode - GT_TRUE to enable VID None Rate Limit
*               GT_FALSE otherwise
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*        GT_NOT_SUPPORTED    - if current device does not support this feature.
*
* COMMENTS: 
*
*******************************************************************************/
GT_STATUS grcGetVidNrlEn
(
    IN  GT_QD_DEV    *dev,
    IN  GT_LPORT    port,
    OUT GT_BOOL        *mode
)
{
    GT_U16          data;           
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           hwPort;        /* Physical port.               */

    DBG_INFO(("grcGetVidNrlEn Called.\n"));

    hwPort = GT_LPORT_2_PORT(port);

    /* check if the given Switch supports this feature. */
    if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
    {
           DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    /* Get the VidNrlEn mode.            */
    retVal = hwGetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,15,1,&data);
    if(retVal != GT_OK)
       {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }

    BIT_2_BOOL(data, *mode);

    DBG_INFO(("OK.\n"));

    return GT_OK;
}


/*******************************************************************************
* grcSetSaNrlEn
*
* DESCRIPTION:
*       This routine enables/disables SA None Rate Limit (NRL).
*        When SA NRL is enabled and the source address of a frame results in a ATU
*        hit where the SA's MAC address returns an EntryState that indicates Non
*        Rate Limited, then the frame will not be ingress nor egress rate limited.
*
* INPUTS:
*       port - logical port number.
*        mode - GT_TRUE to enable SA None Rate Limit
*               GT_FALSE otherwise
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*        GT_NOT_SUPPORTED    - if current device does not support this feature.
*
* COMMENTS: 
*
*******************************************************************************/
GT_STATUS grcSetSaNrlEn
(
    IN  GT_QD_DEV    *dev,
    IN  GT_LPORT    port,
    IN  GT_BOOL        mode
)
{
    GT_U16          data;           
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           hwPort;        /* Physical port.               */

    DBG_INFO(("grcSetSaNrlEn Called.\n"));

    hwPort = GT_LPORT_2_PORT(port);

    /* check if the given Switch supports this feature. */
    if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
    {
           DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    /* translate BOOL to binary */
    BOOL_2_BIT(mode, data);

    /* Set the SaNrlEn mode.            */
    retVal = hwSetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,14,1,data);
    if(retVal != GT_OK)
       {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }

    DBG_INFO(("OK.\n"));

    return GT_OK;
}

/*******************************************************************************
* grcGetSaNrlEn
*
* DESCRIPTION:
*       This routine gets SA None Rate Limit (NRL) mode.
*        When SA NRL is enabled and the source address of a frame results in a ATU
*        hit where the SA's MAC address returns an EntryState that indicates Non
*        Rate Limited, then the frame will not be ingress nor egress rate limited.
*
* INPUTS:
*       port - logical port number.
*
* OUTPUTS:
*        mode - GT_TRUE to enable SA None Rate Limit
*               GT_FALSE otherwise
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*        GT_NOT_SUPPORTED    - if current device does not support this feature.
*
* COMMENTS: 
*
*******************************************************************************/
GT_STATUS grcGetSaNrlEn
(
    IN  GT_QD_DEV    *dev,
    IN  GT_LPORT    port,
    OUT GT_BOOL        *mode
)
{
    GT_U16          data;           
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           hwPort;        /* Physical port.               */

    DBG_INFO(("grcGetSaNrlEn Called.\n"));

    hwPort = GT_LPORT_2_PORT(port);

    /* check if the given Switch supports this feature. */
    if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
    {
           DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    /* Get the SaNrlEn mode.            */
    retVal = hwGetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,14,1,&data);
    if(retVal != GT_OK)
       {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }

    BIT_2_BOOL(data, *mode);

    DBG_INFO(("OK.\n"));

    return GT_OK;
}

/*******************************************************************************
* grcSetDaNrlEn
*
* DESCRIPTION:
*       This routine enables/disables DA None Rate Limit (NRL).
*        When DA NRL is enabled and the destination address of a frame results in 
*        a ATU hit where the DA's MAC address returns an EntryState that indicates 
*        Non Rate Limited, then the frame will not be ingress nor egress rate 
*        limited.
*
* INPUTS:
*       port - logical port number.
*        mode - GT_TRUE to enable DA None Rate Limit
*               GT_FALSE otherwise
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*        GT_NOT_SUPPORTED    - if current device does not support this feature.
*
* COMMENTS: 
*
*******************************************************************************/
GT_STATUS grcSetDaNrlEn
(
    IN  GT_QD_DEV    *dev,
    IN  GT_LPORT    port,
    IN  GT_BOOL        mode
)
{
    GT_U16          data;           
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           hwPort;        /* Physical port.               */

    DBG_INFO(("grcSetDaNrlEn Called.\n"));

    hwPort = GT_LPORT_2_PORT(port);

    /* check if the given Switch supports this feature. */
    if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
    {
           DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    /* translate BOOL to binary */
    BOOL_2_BIT(mode, data);

    /* Set the DaNrlEn mode.            */
    retVal = hwSetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,13,1,data);
    if(retVal != GT_OK)
       {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }

    DBG_INFO(("OK.\n"));

    return GT_OK;
}

/*******************************************************************************
* grcGetDaNrlEn
*
* DESCRIPTION:
*       This routine gets SA None Rate Limit (NRL) mode.
*        When DA NRL is enabled and the destination address of a frame results in 
*        a ATU hit where the DA's MAC address returns an EntryState that indicates 
*        Non Rate Limited, then the frame will not be ingress nor egress rate 
*        limited.
*
* INPUTS:
*       port - logical port number.
*
* OUTPUTS:
*        mode - GT_TRUE to enable DA None Rate Limit
*               GT_FALSE otherwise
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*        GT_NOT_SUPPORTED    - if current device does not support this feature.
*
* COMMENTS: 
*
*******************************************************************************/
GT_STATUS grcGetDaNrlEn
(
    IN  GT_QD_DEV    *dev,
    IN  GT_LPORT    port,
    OUT GT_BOOL        *mode
)
{
    GT_U16          data;           
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           hwPort;        /* Physical port.               */

    DBG_INFO(("grcGetDaNrlEn Called.\n"));

    hwPort = GT_LPORT_2_PORT(port);

    /* check if the given Switch supports this feature. */
    if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
    {
           DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    /* Get the DaNrlEn mode.            */
    retVal = hwGetPortRegField(dev,hwPort, QD_REG_INGRESS_RATE_CTRL,13,1,&data);
    if(retVal != GT_OK)
       {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }

    BIT_2_BOOL(data, *mode);

    DBG_INFO(("OK.\n"));

    return GT_OK;
}


/*******************************************************************************
* grcSetELimitMode
*
* DESCRIPTION:
*       This routine sets Egress Rate Limit counting mode.
*        The supported modes are as follows:
*            GT_PIRL_ELIMIT_FRAME -
*                Count the number of frames
*            GT_PIRL_ELIMIT_LAYER1 -
*                Count all Layer 1 bytes: 
*                Preamble (8bytes) + Frame's DA to CRC + IFG (12bytes)
*            GT_PIRL_ELIMIT_LAYER2 -
*                Count all Layer 2 bytes: Frame's DA to CRC
*            GT_PIRL_ELIMIT_LAYER1 -
*                Count all Layer 1 bytes: 
*                Frame's DA to CRC - 18 - 4 (if frame is tagged)
*
* INPUTS:
*       port - logical port number
*        mode - GT_PIRL_ELIMIT_MODE enum type
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*        GT_NOT_SUPPORTED    - if current device does not support this feature.
*
* COMMENTS: 
*
*******************************************************************************/
GT_STATUS grcSetELimitMode
(
    IN  GT_QD_DEV    *dev,
    IN  GT_LPORT    port,
    IN  GT_PIRL_ELIMIT_MODE        mode
)
{
    GT_U16            data;
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           hwPort;        /* Physical port.               */

    DBG_INFO(("grcSetELimitMode Called.\n"));

    hwPort = GT_LPORT_2_PORT(port);

    /* check if the given Switch supports this feature. */
    if (!((IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE)) ||
        (IS_IN_DEV_GROUP(dev,DEV_ELIMIT_FRAME_BASED))))
    {
           DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    if (!IS_IN_DEV_GROUP(dev,DEV_ELIMIT_FRAME_BASED))
    {
        if(mode == GT_PIRL_ELIMIT_FRAME)
            return GT_NOT_SUPPORTED;
    }

    data = (GT_U16)mode & 0x3;

    /* Set the Elimit mode.            */
    retVal = hwSetPortRegField(dev,hwPort, QD_REG_EGRESS_RATE_CTRL,14,2,data);
    if(retVal != GT_OK)
       {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }

    DBG_INFO(("OK.\n"));

    return GT_OK;
}


/*******************************************************************************
* grcGetELimitMode
*
* DESCRIPTION:
*       This routine gets Egress Rate Limit counting mode.
*        The supported modes are as follows:
*            GT_PIRL_ELIMIT_FRAME -
*                Count the number of frames
*            GT_PIRL_ELIMIT_LAYER1 -
*                Count all Layer 1 bytes: 
*                Preamble (8bytes) + Frame's DA to CRC + IFG (12bytes)
*            GT_PIRL_ELIMIT_LAYER2 -
*                Count all Layer 2 bytes: Frame's DA to CRC
*            GT_PIRL_ELIMIT_LAYER1 -
*                Count all Layer 1 bytes: 
*                Frame's DA to CRC - 18 - 4 (if frame is tagged)
*
* INPUTS:
*       port - logical port number
*
* OUTPUTS:
*        mode - GT_PIRL_ELIMIT_MODE enum type
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*        GT_NOT_SUPPORTED    - if current device does not support this feature.
*
* COMMENTS: 
*
*******************************************************************************/
GT_STATUS grcGetELimitMode
(
    IN  GT_QD_DEV    *dev,
    IN  GT_LPORT    port,
    OUT GT_PIRL_ELIMIT_MODE        *mode
)
{
    GT_U16            data;
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           hwPort;        /* Physical port.               */

    DBG_INFO(("grcGetELimitMode Called.\n"));

    hwPort = GT_LPORT_2_PORT(port);

    /* check if the given Switch supports this feature. */
    if (!((IS_IN_DEV_GROUP(dev,DEV_PIRL_RESOURCE)) ||
        (IS_IN_DEV_GROUP(dev,DEV_ELIMIT_FRAME_BASED))))
    {
           DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    /* Get the Elimit mode.            */
    retVal = hwGetPortRegField(dev,hwPort, QD_REG_EGRESS_RATE_CTRL,14,2,&data);
    if(retVal != GT_OK)
       {
        DBG_INFO(("Failed.\n"));
           return retVal;
    }

    *mode = data;

    DBG_INFO(("OK.\n"));

    return GT_OK;
}

/*******************************************************************************
* grcSetRsvdNrlEn
*
* DESCRIPTION:
*       This routine sets Reserved Non Rate Limit.
*        When this feature is enabled, frames that match the requirements of the 
*        Rsvd2Cpu bit below will also be considered to be ingress and egress non 
*        rate limited.
*
* INPUTS:
*       en - GT_TRUE to enable Reserved Non Rate Limit,
*             GT_FALSE to disable
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK   - on success
*       GT_FAIL - on error
*        GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*       None.
*
*******************************************************************************/
GT_STATUS grcSetRsvdNrlEn
(
    IN  GT_QD_DEV *dev,
    IN  GT_BOOL   en
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16            data;

    DBG_INFO(("grcSetRsvdNrlEn Called.\n"));

    if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
    {
        DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    BOOL_2_BIT(en,data);

    /* Set the RsvdNrl bit.            */
    retVal = hwSetGlobalRegField(dev,QD_REG_MANGEMENT_CONTROL,4,1,data);
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }

    DBG_INFO(("OK.\n"));
    return GT_OK;
}

/*******************************************************************************
* grcGetRsvdNrlEn
*
* DESCRIPTION:
*       This routine gets Reserved Non Rate Limit.
*        When this feature is enabled, frames that match the requirements of the 
*        Rsvd2Cpu bit below will also be considered to be ingress and egress non 
*        rate limited.
*
* INPUTS:
*       en - GT_TRUE to enable Reserved Non Rate Limit,
*             GT_FALSE to disable
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK   - on success
*       GT_FAIL - on error
*        GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS:
*       None.
*
*******************************************************************************/
GT_STATUS grcGetRsvdNrlEn
(
    IN  GT_QD_DEV *dev,
    OUT GT_BOOL   *en
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16            data;

    DBG_INFO(("grcGetRsvdNrlEn Called.\n"));

    if (!IS_IN_DEV_GROUP(dev,DEV_NONE_RATE_LIMIT))
    {
        DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    /* Get the RsvdNrl bit.            */
    retVal = hwGetGlobalRegField(dev,QD_REG_MANGEMENT_CONTROL,4,1,&data);
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }

    BIT_2_BOOL(data, *en);

    DBG_INFO(("OK.\n"));
    return GT_OK;
}


/*******************************************************************************
* grcSetFrameOverhead
*
* DESCRIPTION:
*       Egress rate frame overhead adjustment.
*        This field is used to adjust the number of bytes that need to be added to a
*        frame's IFG on a per frame basis.
*
*        The egress rate limiter multiplies the value programmed in this field by four
*        for computing the frame byte offset adjustment value (i.e., the amount the
*        IPG is increased for every frame). This adjustment, if enabled, is made to
*        every egressing frame's IPG and it is made in addition to any other IPG
*        adjustments due to other Egress Rate Control settings.
*
*        The egress overhead adjustment can add the following number of byte times
*        to each frame's IPG: 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52,
*        56 and 60.
*
*        Example:
*        If FrameOverhead = 11, the egress rate limiter would increase the IPG
*        between every frame by an additional 44 bytes.
*
*        Note: When the Count Mode (port offset 0x0A) is in Frame based egress rate
*        shaping mode, these Frame Overhead bits must be 0x0.
*
* INPUTS:
*       port     - logical port number.
*       overhead - Frame overhead (0 ~ 15)
*
* OUTPUTS:
*       None.
*
* RETURNS:
*       GT_OK               - on success
*       GT_FAIL             - on error
*       GT_BAD_PARAM        - on bad parameters
*        GT_NOT_SUPPORTED - if current device does not support this feature.
*
* COMMENTS: 
*
*******************************************************************************/
GT_STATUS grcSetFrameOverhead
(
    IN GT_QD_DEV        *dev,
    IN GT_LPORT            port,
    IN GT_32            overhead
)
{

    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U8           phyPort;        /* Physical port.               */

    DBG_INFO(("grcSetFrameOverhead Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);

    /* check if device supports this feature */
    if (!IS_IN_DEV_GROUP(dev,DEV_ELIMIT_FRAME_BASED))
    {
        DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }

    if (overhead > 15)
    {
        DBG_INFO(("GT_BAD_PARAM \n"));
        return GT_BAD_PARAM;
    }

    retVal = hwSetPortRegField(dev,phyPort,QD_REG_RATE_CTRL0,8,4,(GT_U16)overhead );
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }
    DBG_INFO(("OK.\n"));
    return GT_OK;
}



/*******************************************************************************
* grcGetFrameOverhead
*
* DESCRIPTION:
*       Egress rate frame overhead adjustment.
*        This field is used to adjust the number of bytes that need to be added to a
*        frame's IFG on a per frame basis.
*
*        The egress rate limiter multiplies the value programmed in this field by four
*        for computing the frame byte offset adjustment value (i.e., the amount the
*        IPG is increased for every frame). This adjustment, if enabled, is made to
*        every egressing frame's IPG and it is made in addition to any other IPG
*        adjustments due to other Egress Rate Control settings.
*
*        The egress overhead adjustment can add the following number of byte times
*        to each frame's IPG: 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52,
*        56 and 60.
*
*        Example:
*        If FrameOverhead = 11, the egress rate limiter would increase the IPG
*        between every frame by an additional 44 bytes.
*
*        Note: When the Count Mode (port offset 0x0A) is in Frame based egress rate
*        shaping mode, these Frame Overhead bits must be 0x0.
*
* INPUTS:
*       port    - logical port number.
*
* OUTPUTS:
*       overhead - Frame overhead (0 ~ 15)
*
* RETURNS:
*       GT_OK            - on success
*       GT_FAIL          - on error
*        GT_NOT_SUPPORTED - if current device does not support this feature.
*
*******************************************************************************/
GT_STATUS grcGetFrameOverhead
(
    IN GT_QD_DEV *dev,
    IN  GT_LPORT port,
    OUT GT_32    *overhead
)
{
    GT_STATUS       retVal;         /* Functions return value.      */
    GT_U16          data;           /* The register's read data.    */
    GT_U8           phyPort;        /* Physical port.               */

    DBG_INFO(("grcGetFrameOverhead Called.\n"));

    phyPort = GT_LPORT_2_PORT(port);

    /* check if device supports this feature */
    if (!IS_IN_DEV_GROUP(dev,DEV_ELIMIT_FRAME_BASED))
    {
        DBG_INFO(("GT_NOT_SUPPORTED\n"));
        return GT_NOT_SUPPORTED;
    }
    
    retVal = hwGetPortRegField(dev,phyPort,QD_REG_RATE_CTRL0,8,4,&data);
    if(retVal != GT_OK)
    {
        DBG_INFO(("Failed.\n"));
        return retVal;
    }

    *overhead = (GT_U32)data;
    DBG_INFO(("OK.\n"));
    return GT_OK;
}

