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

📄 pitrunk.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:    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 + -