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

📄 pivlngrp.c

📁 VIA VT6524 8口网管交换机源码
💻 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 + -