📄 pivlngrp.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: pivlngrp.c
*
* Purpose: VLAN group setting UI callback functions
*
* Author: Tevin Chen
*
* Date: Jan 08, 2002
*
* Functions:
*
* Revision History:
*
*/
#include "swreg.h"
#include "switch.h"
#include "str.h"
#include "piportmp.h"
#include "picfgmp.h"
#include "pivlngrp.h"
#include "pivlnmod.h"
#include "pivlneep.h"
#include "swmsg.h"
#include "swsys.h"
/*--------------------- EEPROM Content Statement ------------------*/
/*
* NOTE: EEPROM content of all VLAN APIs are of physical 3-byte mask format.
* Thus initializing hardware config from EEPROM needs to transfer from
* 3-byte phy mask to 4-byte phy mask; on the other hand, saving current
* config into EEPROM needs to transfer from 3-byte config mask to 3-byte
* phy mask format.
*/
/*--------------------- Static Definitions -------------------------*/
// Definition for portbase vlan operation
#define DEL_GRP_DUE_TO_DEL_OP TRUE
#define DEL_GRP_DUE_TO_EDIT_OP FALSE
#define PORTBASE_VLAN_GRP_VID_BASE 1
// Definitions to reduce statement length
#define pSCurGrp (&pSPageBuf->SCurGrp)
/*--------------------- Static Classes ----------------------------*/
/*--------------------- Static Variables --------------------------*/
/*--------------------- Static Functions --------------------------*/
// Clear PVID setting related to deleting entry
static void s_vClear8021QPvidOfDelMbr (UINT8 byTblPtr) DIRECT_FUNTYPE_REENT;
// Check if a port being untagged member of more than one group
static UINT16 s_wCheck8021QUntagMbrOverlap (SVlanPageCfg *pSPageBuf) DIRECT_FUNTYPE_REENT;
// Find 802.1Q isolated port (in format of log ptr)
static UINT8 s_byFind8021QIsoPort (SVlanPageCfg *pSPageBuf, PUINT16 pwFailVid) DIRECT_FUNTYPE_REENT;
// Delete a portbase group
static void s_vDelPortBaseGrp (SVlanPageCfg *pSPageBuf, UINT8 byTblPtr, BOOL bIfDelOp) DIRECT_FUNTYPE_REENT;
/*--------------------- Static Macros -----------------------------*/
#define s_wPortBaseGrpVid(byPortId) (UINT16)(byPortId+PORTBASE_VLAN_GRP_VID_BASE)
/*--------------------- Export Variables --------------------------*/
/*--------------------- Export Functions --------------------------*/
// Get a vlan group
BYTE PIVLAN_byGetGrp (SVlanPageCfg *pSPageBuf) DIRECT_FUNTYPE_REENT
{
UINT8 byTblPtr;
// If group id not exist, return error code
byTblPtr = PIVLNEEP_bySearchEntry(pSCurGrp->wVid);
if (byTblPtr == ENTRY_END_FLAG)
return VLAN_OP_GRP_NOT_EXIST;
// Get entry from EEPROM and transfer into config buffer format
PIVLNEEP_vGetEntry(byTblPtr, pSCurGrp);
VLANvTransBufFromEepToCfg();
return OP_OK;
}
// Insert a vlan group
BYTE PIVLAN_byInsGrp (SVlanPageCfg *pSPageBuf, PUINT16 pwFailVid) DIRECT_FUNTYPE_REENT
{
// Init failed vid value
*pwFailVid = UINT16_MAX;
// If no empty group, return error code
if ( pSPageBuf->byValidEntryNum == SWITCH_VLAN_GRP_NUM )
return VLAN_OP_NO_EMPTY_GRP;
// If VID invalid, return error code
if ( (pSCurGrp->wVid < VLAN_MIN_VALID_VID) ||
(pSCurGrp->wVid > ((CHIP_VT3221 == SWSYS_byGetChipType()) ? VLAN_MAX_VALID_VID_3221 : VLAN_MAX_VALID_VID_3077)) )
return VLAN_OP_VID_INVALID;
// If group already exist, return error code
if ( PIVLNEEP_bySearchEntry(pSCurGrp->wVid) != ENTRY_END_FLAG )
return VLAN_OP_GRP_EXIST;
// Insert the current group into hardware
if (pSPageBuf->byVlanMode == VLAN_MODE_8021Q) { // 802.1Q mode
// Check if untagged member overlapped and set content into HW table
*pwFailVid = s_wCheck8021QUntagMbrOverlap(pSPageBuf);
if (*pwFailVid != UINT16_MAX)
return VLAN_OP_UNTAG_BELONG_OTHER_GRP;
VLANvIns8021QEntry(pSPageBuf);
}
else { // PortBase mode
// Insert new group and set PVID & unused group
VLANvInsPortBaseGrp(pSCurGrp);
SWVLAN_vSetPortBaseCfgForAllGrp();
}
// Insert current group into EEPROM and return
VLANvTransBufFromCfgToEep();
PIVLNEEP_byInsEntry(pSCurGrp);
PIVLNEEP_vStatisTblInfo(pSPageBuf);
VLANvTransBufFromEepToCfg();
// Find isolated port
if (pSPageBuf->byVlanMode == VLAN_MODE_8021Q)
return s_byFind8021QIsoPort(pSPageBuf, pwFailVid);
return OP_OK;
}
// Edit a vlan group
BYTE PIVLAN_byEditGrp (SVlanPageCfg *pSPageBuf, PUINT16 pwFailVid) DIRECT_FUNTYPE_REENT
{
UINT8 byTblPtr;
// Init failed vid value
*pwFailVid = UINT16_MAX;
// If group id not exist, return error code
byTblPtr = PIVLNEEP_bySearchEntry(pSCurGrp->wVid);
if (byTblPtr == ENTRY_END_FLAG)
return VLAN_OP_GRP_NOT_EXIST;
// Update the current group in hardware
if (pSPageBuf->byVlanMode == VLAN_MODE_8021Q) { // 802.1Q mode
// Check if untagged member overlapped
*pwFailVid = s_wCheck8021QUntagMbrOverlap(pSPageBuf);
if (*pwFailVid != UINT16_MAX)
return VLAN_OP_UNTAG_BELONG_OTHER_GRP;
// Clear PVID setting of deleting ports
s_vClear8021QPvidOfDelMbr(byTblPtr);
// Set new content into HW table
VLANvIns8021QEntry(pSPageBuf);
}
else { // PortBase mode
// Edit group and set PVID & unused group
s_vDelPortBaseGrp(pSPageBuf, byTblPtr, DEL_GRP_DUE_TO_EDIT_OP);
VLANvInsPortBaseGrp(pSCurGrp);
SWVLAN_vSetPortBaseCfgForAllGrp();
}
// Update group content in EEPROM and return
VLANvTransBufFromCfgToEep();
PIVLNEEP_vEditEntry(byTblPtr, pSCurGrp);
PIVLNEEP_vStatisTblInfo(pSPageBuf);
VLANvTransBufFromEepToCfg();
// Find isolated port
if (pSPageBuf->byVlanMode == VLAN_MODE_8021Q)
return s_byFind8021QIsoPort(pSPageBuf, pwFailVid);
return OP_OK;
}
// Delete a vlan group
BYTE PIVLAN_byDelGrp (SVlanPageCfg *pSPageBuf, PUINT16 pwFailVid) DIRECT_FUNTYPE_REENT
{
UINT8 byTblPtr;
// Init failed vid value
*pwFailVid = UINT16_MAX;
// Default group is not able to be deleted
if ( (pSPageBuf->byVlanMode == VLAN_MODE_8021Q) &&
(pSCurGrp->wVid == VLAN_DEFAULT_GROUP_VID) )
return VLAN_OP_DEFAULT_GRP_CANNOT_DEL;
// If group id not exist, return error code
byTblPtr = PIVLNEEP_bySearchEntry(pSCurGrp->wVid);
if (byTblPtr == ENTRY_END_FLAG)
return VLAN_OP_GRP_NOT_EXIST;
// Delete group from hardware
if (pSPageBuf->byVlanMode == VLAN_MODE_8021Q) { // 802.1Q mode
// Deleting operation
s_vClear8021QPvidOfDelMbr(byTblPtr);
SWVLAN_vClearEntry(pSCurGrp->wVid);
}
else { // PortBase mode
// Delete group and set PVID & unused group
s_vDelPortBaseGrp(pSPageBuf, byTblPtr, DEL_GRP_DUE_TO_DEL_OP);
SWVLAN_vSetPortBaseCfgForAllGrp();
}
// Delete group from EEPROM and return
PIVLNEEP_vDelEntry(byTblPtr);
PIVLNEEP_vStatisTblInfo(pSPageBuf);
// Find isolated port
if (pSPageBuf->byVlanMode == VLAN_MODE_8021Q)
return s_byFind8021QIsoPort(pSPageBuf, pwFailVid);
return OP_OK;
}
// Insert 802.1Q entry into HW table and set related PVID config
void VLANvIns8021QEntry (SVlanPageCfg *pSPageBuf) DIRECT_FUNTYPE_REENT
{
SVlanEntry SEntryBuf;
UINT32 dwUntagMsk, dwTagMsk, dwShftMsk = 0x01;
UINT8 si;
// Transform config bit mask into physical port mask
PICFGMP_v2bLogPtrMskTo4BPhyMsk(pSCurGrp->abyMbrMsk, &dwUntagMsk, &dwTagMsk);
// If a port is set to be untagged member of a group, set PVID to it's VID value.
for (si = 0; si < SWITCH_PORT_NUM; si++) {
if ( dwShftMsk & dwUntagMsk )
SWVLAN_vSetPvid(si, (pSCurGrp->wVid) );
dwShftMsk <<= 1;
}
// Set entry into vlan table
SEntryBuf.wVid = pSCurGrp->wVid;
SEntryBuf.bSvl = FALSE;
SEntryBuf.wFid = pSCurGrp->wVid;
SEntryBuf.dwMbrPortMsk = (dwUntagMsk | dwTagMsk);
SEntryBuf.dwTagPortMsk = dwTagMsk;
// Insert entry into HW table
SWVLAN_vSetEntry(&SEntryBuf);
}
// Clear PVID setting related to deleting entry
static void s_vClear8021QPvidOfDelMbr (UINT8 byTblPtr) DIRECT_FUNTYPE_REENT
{
// NOTE: VLAN group buffer here must be local buffer
// since this function may be executed by PIVLAN_byEditGrp
// and the new content must not be overwritten
SVlanGrp SGrpBuf;
UINT32 dwUntagMsk = 0, dwTagMsk = 0;
UINT8 si;
// Get target group
PIVLNEEP_vGetEntry(byTblPtr, &SGrpBuf);
STRvMemcpy( (PBYTE)(&dwTagMsk)+BYTE_OFFSET_IN_DWORD_OF_CFGMASK,
SGrpBuf.abyMbrMsk, BYTE_NUM_OF_CFGBUF_BIT_MASK );
STRvMemcpy( (PBYTE)(&dwUntagMsk)+BYTE_OFFSET_IN_DWORD_OF_CFGMASK,
SGrpBuf.abyMbrMsk+BYTE_NUM_OF_CFGBUF_BIT_MASK, BYTE_NUM_OF_CFGBUF_BIT_MASK );
// If a port is set to be untagged member of a group, clear its PVID.
for (si = 0; si < SWITCH_PORT_NUM; si++) {
if ( dwUntagMsk & 0x01 )
SWVLAN_vSetPvid(si, 0);
dwUntagMsk >>= 1;
}
}
// Check if a port being untagged member of more than one group
static UINT16 s_wCheck8021QUntagMbrOverlap (SVlanPageCfg *pSPageBuf) DIRECT_FUNTYPE_REENT
{
UINT32 dwUntagMsk, dwTagMsk;
UINT16 wPvidBuf = 0;
UINT8 si, sj;
// Transform config bit mask into physical port mask
PICFGMP_v2bLogPtrMskTo4BPhyMsk(pSCurGrp->abyMbrMsk, &dwUntagMsk, &dwTagMsk);
// If current PVID is already belonging to group with vid N, return GROUP INDEX of group N
for (si = 0; si < SWITCH_PORT_NUM; si++) {
if ( dwUntagMsk & 0x01 ) {
SWVLAN_vGetPvid(si, &wPvidBuf);
if ( (wPvidBuf != 0) && (wPvidBuf != pSCurGrp->wVid) ) {
for (sj = 0; sj < pSPageBuf->byValidEntryNum; sj++) {
if ( pSPageBuf->awValidGrpIdList[sj] == wPvidBuf )
return pSPageBuf->awValidGrpIdList[sj];
}
}
}
dwUntagMsk >>= 1;
}
// If check ok, return UINT16_MAX
return UINT16_MAX;
}
// Find 802.1Q isolated port (in format of log ptr)
static UINT8 s_byFind8021QIsoPort (SVlanPageCfg *pSPageBuf, PUINT16 pwFailVid) DIRECT_FUNTYPE_REENT
{
SVlanGrp SGrpBuf;
UINT32 dwMbrMsk = 0, dwTmp = 0;
UINT8 si;
// Statistic members of all groups
for (si = 0; si < pSPageBuf->byValidEntryNum; si++) {
PIVLNEEP_vGetEntry( PIVLNEEP_bySearchEntry(pSPageBuf->awValidGrpIdList[si]), &SGrpBuf );
// Statistic untagged setting of all groups
STRvMemcpy( (PBYTE)(&dwTmp)+BYTE_OFFSET_IN_DWORD_OF_CFGMASK,
SGrpBuf.abyMbrMsk+BYTE_NUM_OF_CFGBUF_BIT_MASK, BYTE_NUM_OF_CFGBUF_BIT_MASK );
dwMbrMsk |= dwTmp;
// Statistic tagged setting of non-default groups
STRvMemcpy( (PBYTE)(&dwTmp)+BYTE_OFFSET_IN_DWORD_OF_CFGMASK,
SGrpBuf.abyMbrMsk, BYTE_NUM_OF_CFGBUF_BIT_MASK );
dwMbrMsk |= dwTmp;
}
for (si = 0; si < SWITCH_PORT_NUM; si++) {
if ( !(dwMbrMsk & 0x01) ) {
*pwFailVid = PIPORTMP_byPhyIdToLogId(si);
#ifndef __ASIC_VT6524
if (*pwFailVid != ENTRY_END_FLAG) // may be module port is not exist
#endif
return VLAN_OP_FOUND_ISO_PORT;
}
dwMbrMsk >>= 1;
}
return OP_OK;
}
void VLANvInsPortBaseGrp (SVlanGrp *pSGrp) DIRECT_FUNTYPE_REENT
{
UINT32 dwMbrMsk, dwDummy;
PICFGMP_v2bLogPtrMskTo4BPhyMsk( pSGrp->abyMbrMsk, &dwDummy, &dwMbrMsk );
SWVLAN_vAddPortBaseGrp(dwMbrMsk);
}
static void s_vDelPortBaseGrp (SVlanPageCfg *pSPageBuf, UINT8 byTblPtr, BOOL bIfDelOp) DIRECT_FUNTYPE_REENT
{
union // For reducing stack usage
{
SVlanGrp SGrp;
SVlanEntry SEntry;
} UVlanBuf;
UINT32 dwDelMbrMsk = 0, dwMbrMsk = 0;
UINT8 byTmp, si;
// Get target group and transfer config bit mask into physical port mask
PIVLNEEP_vGetEntry(byTblPtr, &UVlanBuf.SGrp);
STRvMemcpy( (PBYTE)(&dwDelMbrMsk)+BYTE_OFFSET_IN_DWORD_OF_CFGMASK,
UVlanBuf.SGrp.abyMbrMsk, BYTE_NUM_OF_CFGBUF_BIT_MASK );
// Remove deleting mbrs from vlan table entries containing one of deleting ports as mbr
for (si = 0; si < SWITCH_PORT_NUM; si++) {
if ( SWVLAN_bGetEntry( s_wPortBaseGrpVid(si), &UVlanBuf.SEntry ) &&
(UVlanBuf.SEntry.dwMbrPortMsk & dwDelMbrMsk & ~PTN_BIT_MASK_CPU_PORT) ) {
UVlanBuf.SEntry.dwMbrPortMsk &= ~dwDelMbrMsk;
// If called by deleting or no more members left, delete whole entry
if ( bIfDelOp || (UVlanBuf.SEntry.dwMbrPortMsk == PTN_BIT_MASK_CPU_PORT) )
SWVLAN_vClearEntry( s_wPortBaseGrpVid(si) );
// If called by editing, keep innocent members untouched
else
SWVLAN_vSetEntry(&UVlanBuf.SEntry);
}
}
// Add all groups back from EEPROM that containing one of deleting ports as member
// (except the deleting one)
for (si = 0; si < pSPageBuf->byValidEntryNum; si++) {
byTmp = PIVLNEEP_bySearchEntry(pSPageBuf->awValidGrpIdList[si]);
if (byTmp == byTblPtr)
continue;
PIVLNEEP_vGetEntry(byTmp, &UVlanBuf.SGrp);
STRvMemcpy( (PBYTE)(&dwMbrMsk)+BYTE_OFFSET_IN_DWORD_OF_CFGMASK,
UVlanBuf.SGrp.abyMbrMsk, BYTE_NUM_OF_CFGBUF_BIT_MASK );
if (dwMbrMsk & dwDelMbrMsk & ~PTN_BIT_MASK_CPU_PORT)
SWVLAN_vAddPortBaseGrp(dwMbrMsk);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -