📄 swrate.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 + -