⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swrate.c

📁 vt6528芯片交换机API函数和文档运行程序
💻 C
字号:
/*
 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
 * All rights reserved.
 *
 * This software is copyrighted by and is the sole property of
 * VIA Networking Technologies, Inc. This software may only be used
 * in accordance with the corresponding license agreement. Any unauthorized
 * use, duplication, transmission, distribution, or disclosure of this
 * software is expressly forbidden.
 *
 * This software is provided by VIA Networking Technologies, Inc. "as is"
 * and any express or implied warranties, including, but not limited to, the
 * implied warranties of merchantability and fitness for a particular purpose
 * are disclaimed. In no event shall VIA Networking Technologies, Inc.
 * be liable for any direct, indirect, incidental, special, exemplary, or
 * consequential damages.
 *
 *
 * File:    swrate.c
 *
 * Purpose: Ingress/Egress Rate Control and BSF hardware accessing functions
 *
 * Author:  Henry Lin
 *
 * Date:    Apr 14, 2005
 *
 * Functions:
 *
 * Revision History:
 *
 */


#if !defined(__SWITCH_H__)
#include "switch.h"
#endif
#if !defined(__SWREG_H__)
#include "swreg.h"
#endif
#if !defined(__SWRATE_H__)
#include "swrate.h"
#endif
#if !defined(__SWCFG_H__)
#include "swcfg.h"
#endif



/*---------------------  Static Definitions  ------------------------*/
#define BW_CTRL_INGRS_BUDGET_FACTOR      (15625) // 1000000 / 64
#define BW_CTRL_BURST_LIMIT_SET1_DEFAULT (32)    // 32*32 = 1024 budget > 256 (max budget)
#define BW_CTRL_BURST_LIMIT_SET2_DEFAULT (128)   // 128*32 = 4094 budget > 256 (max budget)

#define BW_CTRL_INGRESS_QUOTA_HWDEF      (160)   //Hardware default vaule
#define BW_CTRL_INGRESS_TIME_HWDEF       (3)
/*---------------------  Static Types  ------------------------------*/

/*---------------------  Static Macros  -----------------------------*/

/*---------------------  Static Classes  ----------------------------*/

/*---------------------  Static Variables  --------------------------*/

/*---------------------  Static Functions  --------------------------*/
static UINT16 s_u16CalIngrsRateRegVal(UINT16 u16IngrsRate);
static UINT16 s_u16CalEgrsRateRegVal(UINT32 u32EgrsRate, UINT16 u16LinkSpeed);
static UINT32 s_u32RoundValue(float fQuota);

/*---------------------  Export Variables  --------------------------*/


/*
 *  Calculation of ingress rate:
 */
static UINT16 s_u16CalIngrsRateRegVal(UINT16 u16IngrsRate)
{
    UINT32  u32Budget = u16IngrsRate, u32Round;

    
    //Be careful, this quota vlaue will use by BSF also.
    //So if disable ingress rate control, restore to hardware default value.
    if (u16IngrsRate == 0)
        return (BW_CTRL_INGRESS_QUOTA_HWDEF | (BW_CTRL_INGRESS_TIME_HWDEF << 8));

    //Budget = IngrsRate * 1000000 / 64
    u32Budget *= BW_CTRL_INGRS_BUDGET_FACTOR;

    // Use Round(u32Budget*Time tick)
    if (u16IngrsRate <= 10){
        //Time tick=1000us=0.001sec
        u32Round = s_u32RoundValue(u32Budget*0.001);
        return ( ((UINT8)u32Round) | INGRS_RATE_CTRL_ENABLE | INGRS_RATE_TIME_1000us );
    }
    else if (u16IngrsRate > 50){
        //Time tick=10us=0.00001sec
        u32Round = s_u32RoundValue(u32Budget*0.00001);
        return ( ((UINT8)u32Round) | INGRS_RATE_CTRL_ENABLE | INGRS_RATE_TIME_10us );
    }
    else{
        //Time tick=100us=0.0001sec (IngressRate between 10 and 50)
        u32Round = s_u32RoundValue(u32Budget*0.0001);
        return ( ((UINT8)u32Round) | INGRS_RATE_CTRL_ENABLE | INGRS_RATE_TIME_100us );
    }
}


static UINT32 s_u32RoundValue(float fQuota)
{
    UINT32  u32Cmp;
    
    
    u32Cmp = (((UINT32)fQuota) * 10) + 5;
    
    if ((fQuota*10) >= u32Cmp)
        return ((UINT32)fQuota + 1);
    else
        return ((UINT32)fQuota);
}


/*
 * Calculation of engress rate:
 * Input : u16EgrsRate: unit is Kb(ex:3,000 means 3Mb)
 *         bySpeed:     vaule is 10/100/1000
 */
static UINT16 s_u16CalEgrsRateRegVal(UINT32 u32EgrsRate, UINT16 u16LinkSpeed)
{
    UINT32  u32H = u16LinkSpeed;
    UINT16  u16M, u16R;
    float   fH = u32H * 1000, fL = u32EgrsRate, fRate;

    
    if (u32EgrsRate == 0)
        return 0;
    
    // r =  Ceiling{16*((H/L)-1)} mod 16 or Round{16*((H/L)-1)} mod 16
    // m = (Ceiling{16*((H/L)-1)} - r) / 16 or (Round{16*((H/L)-1)} - r) / 16
    fRate = 16 * ((fH / fL) - 1);
    
    // use Ceiling
    if (fRate > (UINT32)fRate)
        fRate = (UINT32)fRate + 1;
    u16R = ((UINT32)fRate) % 16;
    u16M = (((UINT32)fRate) - u16R) / 16;
    
    return (u16M | (u16R << 11) | EGRS_RATE_CTRL_ENABLE);
}


void SWRATE_vSetRateCtrl(UINT8 byPortId, UINT8 byIngrsMb, UINT8 byEgrsMb)
{
    UINT8 u8Data;
    UINT16 u16LinkSpeed;
    UINT32 u32RateCfg = 0, u32RateSet = 0;


    SWREG_vWriteU16(PORTCFG_INGRS_RATE_CFG_BASE + byPortId * PORTCFG_PORT_OFFSET, s_u16CalIngrsRateRegVal(byIngrsMb));

    // Get port link speed
    SWREG_vReadU8(PHYCTL_OPER_CFG_BASE+byPortId, &u8Data);
    if (u8Data & PORT_ABL_SPD100)
        u16LinkSpeed = 100;
    else if (u8Data & PORT_ABL_SPD1000)
        u16LinkSpeed = 1000;
    else
        u16LinkSpeed = 10;
    

    u32RateSet = s_u16CalEgrsRateRegVal(byEgrsMb * 1000, u16LinkSpeed);
    SWREG_vReadU32(PORTCFG_EGRS_RATE_OVHD_BASE + (byPortId * PORTCFG_PORT_OFFSET), &u32RateCfg);
    u32RateCfg = (u32RateCfg & 0xFF) + (u32RateSet << 8);
    SWREG_vWriteU32(PORTCFG_EGRS_RATE_OVHD_BASE + (byPortId * PORTCFG_PORT_OFFSET), u32RateCfg);
}

void SWRATE_vSetRateCtrlExt(UINT8 byPortId, UINT16 u16IngrsMb, UINT32 u32EgrsKb)
{
    UINT8 u8Data;
    UINT16 u16LinkSpeed;
    UINT32 u32RateCfg = 0, u32RateSet = 0;
    

    SWREG_vWriteU16(PORTCFG_INGRS_RATE_CFG_BASE + byPortId * PORTCFG_PORT_OFFSET, s_u16CalIngrsRateRegVal(u16IngrsMb));

    // Get port link speed
    SWREG_vReadU8(PHYCTL_OPER_CFG_BASE+byPortId, &u8Data);
    if (u8Data & PORT_ABL_SPD100)
        u16LinkSpeed = 100;
    else if (u8Data & PORT_ABL_SPD1000)
        u16LinkSpeed = 1000;
    else
        u16LinkSpeed = 10;

    u32RateSet = s_u16CalEgrsRateRegVal(u32EgrsKb, u16LinkSpeed);
    SWREG_vReadU32(PORTCFG_EGRS_RATE_OVHD_BASE + (byPortId * PORTCFG_PORT_OFFSET), &u32RateCfg);
    u32RateCfg = (u32RateCfg & 0xFF) + (u32RateSet << 8);
    SWREG_vWriteU32(PORTCFG_EGRS_RATE_OVHD_BASE + (byPortId * PORTCFG_PORT_OFFSET), u32RateCfg);
}


void SWRATE_vGetRateCtrl(UINT8 byPortId, PUINT16 pu16IngrsMb, PUINT32 pu32EgrsKb)
{
    UINT16  u16RateCfg, u16LinkSpeed;
    float   fRate;
    UINT8   u8Data;
    UINT32  u32RateCfg = 0;


    SWREG_vReadU16(PORTCFG_INGRS_RATE_CFG_BASE + byPortId * PORTCFG_PORT_OFFSET, &u16RateCfg);

    // Check IRC enable
    if ((u16RateCfg & INGRS_RATE_CTRL_ENABLE) != INGRS_RATE_CTRL_ENABLE)
    {
        if (byPortId >= SWITCH_MEGA_PORT_NUM)
            *pu16IngrsMb = 1000;
        else
            *pu16IngrsMb = 100;
    
        goto    IngressExit;    
    }
    
    //Check unit, and get ingress rate
    if ((u16RateCfg & INGRS_RATE_TIME_100us) == INGRS_RATE_TIME_100us){
        //(IngressRate between 10 and 50)
        fRate = (((UINT8)u16RateCfg)/0.0001)/BW_CTRL_INGRS_BUDGET_FACTOR;
        *pu16IngrsMb = (UINT16)s_u32RoundValue(fRate);
    }
    else if ((u16RateCfg & INGRS_RATE_TIME_10us) == INGRS_RATE_TIME_10us){
        fRate = (((UINT8)u16RateCfg)/0.00001)/BW_CTRL_INGRS_BUDGET_FACTOR;
        *pu16IngrsMb = (UINT16)s_u32RoundValue(fRate);
    }
    else{
        //INGRS_RATE_TIME_1000us
        fRate = (((UINT8)u16RateCfg)/0.001)/BW_CTRL_INGRS_BUDGET_FACTOR;
        *pu16IngrsMb = (UINT16)s_u32RoundValue(fRate);
    }
IngressExit:

    SWREG_vReadU32(PORTCFG_EGRS_RATE_OVHD_BASE + byPortId * PORTCFG_PORT_OFFSET, &u32RateCfg);
    u16RateCfg = ((u32RateCfg & 0x00FFFF00) >> 8);
    // Check ERC enable
    if ((u16RateCfg & EGRS_RATE_CTRL_ENABLE) != EGRS_RATE_CTRL_ENABLE){
        if (byPortId >= SWITCH_MEGA_PORT_NUM)
            *pu32EgrsKb = 1000*1000;    //unit is Kb
        else
            *pu32EgrsKb = 100*1000;
        goto EgressExit;
    }
    
    fRate = (u16RateCfg & EGRS_RATE_CNST_M_MSK) * 16 + ((u16RateCfg & EGRS_RATE_CNST_R_MSK) >> 11);
    // Get port link speed
    SWREG_vReadU8(PHYCTL_OPER_CFG_BASE+byPortId, &u8Data);
    if (u8Data & PORT_ABL_SPD100)
        u16LinkSpeed = 100;
    else if (u8Data & PORT_ABL_SPD1000)
        u16LinkSpeed = 1000;
    else
        u16LinkSpeed = 10;

    *pu32EgrsKb = s_u32RoundValue((u16LinkSpeed*1000) / ((fRate /16) + 1));

EgressExit:;
 }


void SWRATE_vGetCnstMR(UINT8 byPortId, PUINT16 pu16M, PUINT8 pu8R)
{
    UINT16 u16MR;
    UINT32  u32RateCfg = 0;
    
    
    SWREG_vReadU32(PORTCFG_EGRS_RATE_OVHD_BASE + byPortId * PORTCFG_PORT_OFFSET, &u32RateCfg);
    u16MR = ((u32RateCfg & 0x00FFFF00) >> 8);
    *pu16M = u16MR & EGRS_RATE_CNST_M_MSK;
    *pu8R  = (u16MR & EGRS_RATE_CNST_R_MSK) >> 11;
}


/*
 * Input : bySetId:   vaule between 1 and 2
 */
void SWRATE_vSetIRCLimitSet(UINT8 bySetId, SIRCLimitSetCfg sLimitSet)
{
    
    // set IRC Limit value
    SWREG_vWriteU32(RESMGMT_INGRS_RATE_LIMIT1 + (bySetId-1)*4, sLimitSet.byQueue[0] | (sLimitSet.byQueue[1]<<8) | (sLimitSet.byQueue[2]<<16) | (sLimitSet.byQueue[3]<<24)); 
}


/*
 * Input : byGigaPortId: vaule between 0 and 1
 *         bySetId:      vaule between 1 and 2
 */
void SWRATE_vSetGigaPortIRCLimitSetId(UINT8 byGigaPortId, UINT8 bySetId)
{
    // set port24/port25 IRC Limit Set
    if (byGigaPortId){
        // giga1(port25)
        if (bySetId == 2)
            SWREG_vBitsOnU8(RESMGMT_PORT24_25_CFG, IRC_PORT25_USE_SET2);
        else
            SWREG_vBitsOffU8(RESMGMT_PORT24_25_CFG, IRC_PORT25_USE_SET2);
    }
    else{
        // giga0(port24)
        if (bySetId == 2)
            SWREG_vBitsOnU8(RESMGMT_PORT24_25_CFG, IRC_PORT24_USE_SET2);
        else
            SWREG_vBitsOffU8(RESMGMT_PORT24_25_CFG, IRC_PORT24_USE_SET2);
    }
}


void SWRATE_vSetBSFEn(UINT8 byPortId, BOOL bBsfEn)
{
    if (bBsfEn)
        SWREG_vBitsOnU8(PORTCFG_BSF_CFG_BASE + byPortId * PORTCFG_PORT_OFFSET, BSF_ENABLE);
    else
        SWREG_vBitsOffU8(PORTCFG_BSF_CFG_BASE + byPortId * PORTCFG_PORT_OFFSET, BSF_ENABLE);
}


void SWRATE_vGetBsfCfg(SBsfCfg* psBSFCfg)
{
    UINT8 u8Data;


    SWREG_vReadU8(RESMGMT_MANAGER_CFG, &u8Data);

    psBSFCfg->bBcstEn = (u8Data & BSF_BCAST_ENABLE) ? TRUE : FALSE;
    psBSFCfg->bIpMcstEn = (u8Data & BSF_IP_MCAST_ENABLE) ? TRUE : FALSE;
    psBSFCfg->bCtrlPktEn = (u8Data & BSF_CTRL_PKT_ENABLE) ? TRUE : FALSE;
    psBSFCfg->bFldUcstMcstEn = (u8Data & BSF_FLD_ENABLE) ? TRUE : FALSE;

    switch(u8Data & BSF_RATE_MSK)
    {
        case BSF_RATE_1DIV2:
            psBSFCfg->byRateSel = BSF_RATE_50;    break;
        case BSF_RATE_1DIV4:
            psBSFCfg->byRateSel = BSF_RATE_25;    break;
        case BSF_RATE_1DIV8:
            psBSFCfg->byRateSel = BSF_RATE_12;    break;
        case BSF_RATE_1DIV16:
            psBSFCfg->byRateSel = BSF_RATE_6;    break;
    }
}


BOOL SWRATE_bSetBsfCfg(SBsfCfg* psBSFCfg)
{
    UINT8 u8Data = 0;

    u8Data |= (psBSFCfg->bBcstEn) ? BSF_BCAST_ENABLE : 0;
    u8Data |= (psBSFCfg->bIpMcstEn) ? BSF_IP_MCAST_ENABLE : 0;
    u8Data |= (psBSFCfg->bCtrlPktEn) ? BSF_CTRL_PKT_ENABLE : 0;
    u8Data |= (psBSFCfg->bFldUcstMcstEn) ? BSF_FLD_ENABLE : 0;

    switch(psBSFCfg->byRateSel)
    {
        case BSF_RATE_50:
            u8Data |= BSF_RATE_1DIV2;    break;
        case BSF_RATE_25:
            u8Data |= BSF_RATE_1DIV4;    break;
        case BSF_RATE_12:
            u8Data |= BSF_RATE_1DIV8;    break;
        case BSF_RATE_6:
            u8Data |= BSF_RATE_1DIV16;    break;
        default:
            return FALSE;
    }
    SWREG_vWriteU8(RESMGMT_MANAGER_CFG, u8Data);

    return TRUE;
}


void SWRATE_vGetEgrsOverhead(UINT8 byPortId, PUINT8 pbyCL, PINT8 pi8CH)
{
    // global config
    SWREG_vReadU8(INITCTL_EGRS_RATE_GBL_CFG, pbyCL);
    
    //per-port
    SWREG_vReadU8(PORTCFG_EGRS_RATE_OVHD_BASE + byPortId * PORTCFG_PORT_OFFSET,
                 (PUINT8) pi8CH);
}


void SWRATE_vSetEgrsOverhead(UINT8 byPortId, UINT8 byCL, INT8 i8CH)
{
    // global config
    SWREG_vWriteU8(INITCTL_EGRS_RATE_GBL_CFG, byCL);
    
    //per-port
    i8CH &= 0x3F;   //only bit[5:0] valid
    SWREG_vWriteU8(PORTCFG_EGRS_RATE_OVHD_BASE + byPortId * PORTCFG_PORT_OFFSET, i8CH);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -