📄 pitrunk.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: pitrunk.c
*
* Purpose: Trunk module UI callback functions
*
* Author: Tevin Chen
*
* Date: Jan 08, 2002
*
* Functions:
*
* Revision History:
*
*/
#include "str.h"
#if !defined(__BITOP_H__)
#include "bitop.h"
#endif
#include "switch.h"
#include "swfwd.h"
#include "swsnf.h"
#include "swtrk.h"
#include "swvlan.h"
#include "swmsg.h"
#include "pieeprom.h"
#include "piportmp.h"
#include "pitrunk.h"
#include "pivlan.h"
#include "pivlnmod.h"
/*--------------------- EEPROM Content Statement ------------------*/
/*
* NOTE: EEPROM content of all trunk APIs are of config mask format.
* i.e. The format of UI config buffer. Thus initializing hardware config
* from EEPROM needs to transfer from config mask into physcial port mask;
* on the other hand, saving current config into EEPROM doesn't need any
* format transferring.
*/
/*--------------------- Static Definitions -------------------------*/
/*--------------------- Static Classes ----------------------------*/
/*--------------------- Static Variables --------------------------*/
/*--------------------- Static Functions --------------------------*/
static void s_vTransPortCfgToGrpCfg (STrkPageCfg *pSPageBuf, PUINT32 adwTrkGrpMbr) DIRECT_FUNTYPE_REENT;
static BYTE s_byCheckIfCfgValid (PUINT32 adwTrkGrpMbr, PUINT16 pwFailGrpId) DIRECT_FUNTYPE_REENT;
/*--------------------- Static Macros -----------------------------*/
/*--------------------- Export Variables --------------------------*/
/*--------------------- Export Functions --------------------------*/
// Get config from EEPROM and set into page buf
void PITRK_vInitPage (STrkPageCfg *pSPageBuf) DIRECT_FUNTYPE_REENT
{
// We use function here because using macro would cause several *.h files including each other
PIEEP_vGetCfgFromEep( EEP_ADDR_TRUNK_CFG, EEP_SIZE_TRUNK_CFG, (PBYTE)pSPageBuf );
}
// Get config from EEPROM and set into hardeare
void PITRK_vSetHwFromEep (STrkPageCfg *pSPageBuf) DIRECT_FUNTYPE_REENT
{
//UINT32 adwTrkGrpMbr[SWITCH_TRUNK_GRP_NUM];
PUINT32 adwTrkGrpMbr = pSPageBuf->adwTrkGrpMbr;
UINT8 si;
// Get trunk port config
PITRK_vInitPage(pSPageBuf);
// Transfer port-oriented config to group-oriented and set into HW
s_vTransPortCfgToGrpCfg(pSPageBuf, adwTrkGrpMbr);
for (si = 0; si < SWITCH_TRUNK_GRP_NUM; si++) {
if ( adwTrkGrpMbr[si] )
SWTRK_byInsGrp( (UINT8)(MIN_TRK_GRP_ID+si), adwTrkGrpMbr[si] );
}
// Update logical port id list
PIPORTMP_vUpdateLogIdList();
}
// Set trunk block EEPROM into default value
void PITRK_vSetEepDefault (STrkPageCfg *pSPageBuf) DIRECT_FUNTYPE_REENT
{
// Clear all group set in EEPROM
STRvMemset( pSPageBuf, 0, EEP_SIZE_TRUNK_CFG );
PIEEP_vSetCfgIntoEep( (PBYTE)pSPageBuf, EEP_ADDR_TRUNK_CFG, EEP_SIZE_TRUNK_CFG );
PIEEP_vUpdateChecksum();
// Clear all group in register
// NOTE this should put in "PITRK_vSetHwFromEep",
// but that function may also be called by "PITRK_vFailOverForLnkChg".
// To increase performance we put it here.
SWTRK_vDelGrp(PTN_BIT_MASK_ALL_PORT);
}
// Save all trunk groups
BYTE PITRK_bySavePage (STrkPageCfg *pSPageBuf, PUINT16 pwFailGrpId) DIRECT_FUNTYPE_REENT
{
//UINT32 adwTrkGrpMbr[SWITCH_TRUNK_GRP_NUM];
PUINT32 adwTrkGrpMbr = pSPageBuf->adwTrkGrpMbr;
UINT8 byRes, si;
// Transfer port-oriented config to group-oriented
s_vTransPortCfgToGrpCfg(pSPageBuf, adwTrkGrpMbr);
// If trunk config invalid, return error code
byRes = s_byCheckIfCfgValid(adwTrkGrpMbr, pwFailGrpId);
if (byRes != OP_OK)
return byRes;
// Clear orginal trunk config of hardware
SWTRK_vDelGrp(PTN_BIT_MASK_ALL_PORT);
// Insert groups into hardware. If failed, recover to original and return
for (si = 0; si < SWITCH_TRUNK_GRP_NUM; si++) {
if ( adwTrkGrpMbr[si] ) {
byRes = SWTRK_byInsGrp( (UINT8)(MIN_TRK_GRP_ID+si), adwTrkGrpMbr[si] );
if (byRes != OP_OK) {
SWTRK_vDelGrp(PTN_BIT_MASK_ALL_PORT);
// In order to keep original user config, PITRK_vSetHwFromEep needs a new
// memory buffer. Unfortunately, the RAM is not enough. However, the union
// of config buffer, g_UCfgBuf, is much larger than STrkPageCfg. Therefore,
// the unused memory of g_UCfgBuf is passed to as a new config buffer.
PITRK_vSetHwFromEep((STrkPageCfg*)(((PBYTE)pSPageBuf)+EEP_SIZE_TRUNK_CFG));
(*pwFailGrpId) = PORTMAP_BASE_TRKGRP_LOG_ID + si;
//return byRes;
return TRK_OP_MBR_NUM_INVALID;
}
}
}
// Set trunk page config in EEPROM
PIEEP_vSetCfgIntoEep( (PBYTE)pSPageBuf, EEP_ADDR_TRUNK_CFG, EEP_SIZE_TRUNK_CFG );
PIEEP_vUpdateChecksum();
// Update logical port id list if config changed
PIPORTMP_vUpdateLogIdList();
// Clear MAC table to prevent table lookup problems and return
SWFWD_vClearMacTable();
return OP_OK;
}
// Adjust admin criteria for link change fail over
void PITRK_vFailOverForLnkChg (void) DIRECT_FUNTYPE_REENT
{
// NOTE: Trunk config buffer here must be local buffer
// since this function may be executed anytime by
// software fail-over polling.
STrkPageCfg SPageBuf;
UINT32 dwLnkChgMsk = 0;
// Polling for link change => if so, execute trunk failover function
SWREG_vReadDW(PHY_LINK_STATUS_CHANGE, &dwLnkChgMsk);
/*#ifndef __ASIC_VT6524
if (dwLnkChgMsk & 0x00FFFFFF) // skip module ports
PITRK_vSetHwFromEep(&SPageBuf);
#else */
//if (dwLnkChgMsk)
if (dwLnkChgMsk & 0x00FFFF00) // skip module ports and 0~7 ports heaychen
PITRK_vSetHwFromEep(&SPageBuf);
//#endif
}
static void s_vTransPortCfgToGrpCfg (STrkPageCfg *pSPageBuf, PUINT32 adwTrkGrpMbr) DIRECT_FUNTYPE_REENT
{
UINT8 byValidGrpMsk = *((PBYTE)pSPageBuf), byCfg, si;
// Clear trunk group buffer
for (si = 0; si < SWITCH_TRUNK_GRP_NUM; si++)
adwTrkGrpMbr[si] = 0;
// Transfer per-port config into group config (valid group only)
for (si = 0; si < SWITCH_TRUNKABLE_PORT_NUM; si++) {
BITvExtractBits( pSPageBuf->abyCfgBuf, (UINT8)(si*TRUNK_GRP_ID_BIT_NUM),
(UINT8)((si+1)*TRUNK_GRP_ID_BIT_NUM-1), &byCfg );
if ( (byCfg != 0) && ( (byValidGrpMsk >> (byCfg-MIN_TRK_GRP_ID)) & 0x01 ) )
adwTrkGrpMbr[byCfg-MIN_TRK_GRP_ID] |= PIPORTMP_dwLogIdToPhyMsk(si);
}
}
// Used only in this function
#define SHIFT_BUF_32_BIT 0x00000001UL
typedef struct tagSPortCfgBuf
{
// BEWARE: it should be modify when per port config size is not 1 Byte.
BYTE byOldPortCfg;
BYTE byNewPortCfg;
BYTE byMbrCnt;
#ifdef __ASIC_VT6526
// for rate control
UINT16 wOldRateCfg;
UINT16 wNewRateCfg;
#endif
} SPortCfgBuf;
static BYTE s_byCheckIfCfgValid (PUINT32 adwTrkGrpMbr, PUINT16 pwFailGrpId) DIRECT_FUNTYPE_REENT
{
union // For reducing stack usage
{
SVlanGrp SVlanBuf;
SSniffCfg SSnifBuf;
SPortCfgBuf SPortBuf;
SVlanIngrFilterPageCfg SVifBuf;
} UCfgBuf;
UINT8 byTrkId, byTmp, si;
// check port config consistency
for (byTrkId = 0; byTrkId < SWITCH_TRUNK_GRP_NUM; byTrkId++)
{
UCfgBuf.SPortBuf.byMbrCnt = 0;
for (si = 0; si < SWITCH_TRUNKABLE_PORT_NUM; si++)
{
if ((adwTrkGrpMbr[byTrkId]>>si) & 0x01)
{
#ifndef __ASIC_VT6524
PIEEP_vGetCfgFromEep( (EEP_ADDR_MEGA_PORT_CFG + EEP_SIZE_MEGA_PORT_OFFSET*si),
EEP_SIZE_MEGA_PORT_OFFSET,
&UCfgBuf.SPortBuf.byNewPortCfg );
#ifdef __ASIC_VT6526
// for rate control
PIEEP_vGetCfgFromEep( (EEP_ADDR_RATE_CFG + EEP_SIZE_RATE_PORT_OFFSET*si),
EEP_SIZE_RATE_PORT_OFFSET,
(PBYTE)(&UCfgBuf.SPortBuf.wNewRateCfg) );
#endif
if (UCfgBuf.SPortBuf.byMbrCnt == 0)
{
UCfgBuf.SPortBuf.byOldPortCfg = UCfgBuf.SPortBuf.byNewPortCfg;
#ifdef __ASIC_VT6526
UCfgBuf.SPortBuf.wOldRateCfg = UCfgBuf.SPortBuf.wNewRateCfg;
#endif
}
else
{
if (UCfgBuf.SPortBuf.byOldPortCfg != UCfgBuf.SPortBuf.byNewPortCfg)
{
byTmp = TRK_OP_MBR_DIFF_PORT_CFG;
goto CfgCheckFail;
}
#ifdef __ASIC_VT6526
if (UCfgBuf.SPortBuf.wOldRateCfg != UCfgBuf.SPortBuf.wNewRateCfg)
{
byTmp = TRK_OP_MBR_DIFF_RATE_CFG;
goto CfgCheckFail;
}
#endif
}
#else // for VT6524
PIEEP_vGetCfgFromEep( (EEP_ADDR_PORT_CFG + EEP_SIZE_PORT_OFFSET*si),
EEP_SIZE_PORT_OFFSET,
&UCfgBuf.SPortBuf.byNewPortCfg );
if (UCfgBuf.SPortBuf.byMbrCnt == 0)
UCfgBuf.SPortBuf.byOldPortCfg = UCfgBuf.SPortBuf.byNewPortCfg;
else if (UCfgBuf.SPortBuf.byOldPortCfg != UCfgBuf.SPortBuf.byNewPortCfg)
{
byTmp = TRK_OP_MBR_DIFF_PORT_CFG;
goto CfgCheckFail;
}
#endif
UCfgBuf.SPortBuf.byMbrCnt++;
}
}
}
// Check 802.1Q vlan ingress filter consistency
PIVLAN_vGetVlanMode(&byTmp);
if (byTmp == VLAN_MODE_8021Q)
{
UINT32 dwMbrMsk1=0, dwMbrMsk2=0;
PIEEP_vGetCfgFromEep(EEP_ADDR_VLAN_INGRESS_FILTER, EEP_SIZE_VLAN_INGRESS_FILTER, UCfgBuf.SVifBuf.abyCfg);
// extract 3B to 2 dword mask
for (byTrkId = 0; byTrkId < SWITCH_PORT_NUM; byTrkId++)
{
if ( UCfgBuf.SVifBuf.abyCfg[byTrkId*2/8] & (0x01<<(byTrkId*2)%8) )
dwMbrMsk1 |= (SHIFT_BUF_32_BIT<<byTrkId);
if ( UCfgBuf.SVifBuf.abyCfg[(byTrkId*2+1)/8] & (0x01<<(byTrkId*2+1)%8) )
dwMbrMsk2 |= (SHIFT_BUF_32_BIT<<byTrkId);
}
for (byTrkId = 0; byTrkId < SWITCH_TRUNK_GRP_NUM; byTrkId++)
{
if ( (((adwTrkGrpMbr[byTrkId] & dwMbrMsk1) != 0) &&
((adwTrkGrpMbr[byTrkId] & dwMbrMsk1) != adwTrkGrpMbr[byTrkId])) ||
(((adwTrkGrpMbr[byTrkId] & dwMbrMsk2) != 0) &&
((adwTrkGrpMbr[byTrkId] & dwMbrMsk2) != adwTrkGrpMbr[byTrkId])) ) {
byTmp = TRK_OP_MBR_DIFF_8021Q_INGS;
goto CfgCheckFail;
}
}
}
// Check vlan constraint (trunk member cannot belong to different VLANs)
// (We use the format of vlan EEPROM content => 2B VID + 3B Untagged Phy Msk + 3B Tagged Phy Msk
if (byTmp != VLAN_MODE_DISABLE)
{
for (si = 0; si < SWITCH_VLAN_GRP_NUM; si++)
{
PIEEP_vGetCfgFromEep( (EEP_ADDR_VLAN_GROUP + si*EEP_SIZE_VLAN_TBL_ENTRY),
EEP_SIZE_VLAN_TBL_ENTRY, (PBYTE)&UCfgBuf.SVlanBuf);
if (UCfgBuf.SVlanBuf.wVid != 0) {
UINT32 dwMbrBuf = 0;
for (byTrkId = 0; byTrkId < SWITCH_TRUNK_GRP_NUM; byTrkId++) {
// Check if tagged member consistent
STRvMemcpy( (PBYTE)(&dwMbrBuf)+BYTE_OFFSET_IN_DWORD_OF_CFGMASK,
UCfgBuf.SVlanBuf.abyMbrMsk, BYTE_NUM_OF_CFGBUF_BIT_MASK );
if ( ((adwTrkGrpMbr[byTrkId] & dwMbrBuf) != 0) &&
((adwTrkGrpMbr[byTrkId] & dwMbrBuf) != adwTrkGrpMbr[byTrkId]) ) {
byTmp = TRK_OP_MBR_DIFF_VLAN_CFG;
goto CfgCheckFail;
}
// Check if untagged member consistent
STRvMemcpy( (PBYTE)(&dwMbrBuf)+BYTE_OFFSET_IN_DWORD_OF_CFGMASK,
UCfgBuf.SVlanBuf.abyMbrMsk+BYTE_NUM_OF_CFGBUF_BIT_MASK, BYTE_NUM_OF_CFGBUF_BIT_MASK );
if ( ((adwTrkGrpMbr[byTrkId] & dwMbrBuf) != 0) &&
((adwTrkGrpMbr[byTrkId] & dwMbrBuf) != adwTrkGrpMbr[byTrkId]) ) {
byTmp = TRK_OP_MBR_DIFF_VLAN_CFG;
goto CfgCheckFail;
}
}
}
}
}
// Check sniffer constraint
SWSNF_vGetSniffCfg(&UCfgBuf.SSnifBuf);
if ( UCfgBuf.SSnifBuf.byMode != SNIFF_MODE_DISABLE)
{
for (byTrkId = 0; byTrkId < SWITCH_TRUNK_GRP_NUM; byTrkId++) {
// Check if trunk cross sniffer source port and non sniffer source port
if ( ((adwTrkGrpMbr[byTrkId] & UCfgBuf.SSnifBuf.dwSrcPortMsk) != 0) &&
((adwTrkGrpMbr[byTrkId] & UCfgBuf.SSnifBuf.dwSrcPortMsk) != adwTrkGrpMbr[byTrkId]) ) {
byTmp = TRK_OP_MBR_DIFF_MONITORED;
goto CfgCheckFail;
}
// Check if trunk member include sniffer destination port
if ( (adwTrkGrpMbr[byTrkId] & (SHIFT_BUF_32_BIT << UCfgBuf.SSnifBuf.byDestPort)) != 0 ) {
byTmp = TRK_OP_MBR_IS_MONITORING;
goto CfgCheckFail;
}
}
}
*pwFailGrpId = UINT16_MAX;
return OP_OK;
CfgCheckFail:
*pwFailGrpId = PORTMAP_BASE_TRKGRP_LOG_ID + byTrkId;
return byTmp;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -