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

📄 swmii.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:    swmii.c
 *
 * Purpose: Phy register hardware accessing functions
 *
 * Author:  Tevin Chen
 *
 * Date:    Jan 08, 2002
 *
 * Functions:
 *
 * Revision History:
 *
 */


#if !defined(__SWITCH_H__)
#include "switch.h"
#endif
#if !defined(__SWREG_H__)
#include "swreg.h"
#endif
#if !defined(__SWMII_H__)
#include "swmii.h"
#endif




/*---------------------  Static Definitions  ------------------------*/
// Phy module related register patterns
#define PTN_STATUS_COMPLETE     0x02
#define PTN_STATUS_BUSY         0x01

#define PTN_CMD_READ            0x02
#define PTN_CMD_WRITE           0x01

#define PTN_STATUS_AUTOPOLL     0x04
#define PTN_CMD_EN_AUTO         0x08
#define PTN_CMD_DIS_AUTO        0x04

/*---------------------  Static Types  ------------------------------*/

/*---------------------  Static Macros  -----------------------------*/

/*---------------------  Static Classes  ----------------------------*/

/*---------------------  Static Variables  --------------------------*/

/*---------------------  Static Functions  --------------------------*/
#ifdef __ASIC_VT6526
static UINT16 s_wPhyFeatureHandler (BYTE byPortId, BYTE byAddr, UINT16 wData) DIRECT_FUNTYPE_REENT;
static BOOL s_bMiiWriteOp (BYTE byPortId, BYTE byAddr, UINT16 wData) DIRECT_FUNTYPE_REENT;
static BOOL s_bRegBitsOn (BYTE byPortId, BYTE byAddr, UINT16 wBitPtn) DIRECT_FUNTYPE_REENT;
static BOOL s_bRegBitsOff(BYTE byPortId, BYTE byAddr, UINT16 wBitPtn) DIRECT_FUNTYPE_REENT;
#endif

/*---------------------  Export Variables  --------------------------*/




void SWMII_vSetAutoPollOn(void) DIRECT_FUNTYPE_REENT
{
    SWREG_vWriteB(PHY_CMD, PTN_CMD_EN_AUTO);
    SWREG_bWaitStatus(PHY_STATUS, PTN_STATUS_AUTOPOLL, TRUE);
}


void SWMII_vSetAutoPollOff(void) DIRECT_FUNTYPE_REENT
{
    SWREG_vWriteB(PHY_CMD, PTN_CMD_DIS_AUTO);
    SWREG_bWaitStatus(PHY_STATUS, PTN_STATUS_AUTOPOLL, FALSE);
}


BOOL SWMII_bReadW (BYTE byPortId, BYTE byAddr, PUINT16 pwData) DIRECT_FUNTYPE_REENT
{
    BOOL bWasAutoPollOn, bRes;

    // Wait for Phy idle to issue read command
    if (!SWREG_bWaitStatus(PHY_STATUS, PTN_STATUS_BUSY, FALSE))
        return FALSE;

    // Record original auto-polling status and disable it
    bWasAutoPollOn = SWREG_bIfBitsOn(PHY_STATUS, PTN_STATUS_AUTOPOLL);
    if (bWasAutoPollOn)
        SWMII_vSetAutoPollOff();

    // Set port ID
    SWREG_vWriteB(PHY_CMD_PORTID, byPortId);

    // Set phy register address
    SWREG_vWriteB(PHY_REG_ADDR, byAddr);

    // Trigger write operation and wait for complete
    SWREG_vWriteB(PHY_CMD, PTN_CMD_READ);
    bRes = SWREG_bWaitStatus(PHY_STATUS, PTN_STATUS_COMPLETE, TRUE);

    // Read register data
    SWREG_vReadW(PHY_DATA, pwData);

    // Write original auto-polling status back
    if (bWasAutoPollOn)
        SWMII_vSetAutoPollOn();

    return bRes;
}


BOOL SWMII_bIsRegBitsOn (BYTE byPortId, BYTE byAddr, UINT16 wBitPtn) DIRECT_FUNTYPE_REENT
{
    UINT16 wOrgData;

    SWMII_bReadW(byPortId, byAddr, &wOrgData);
    return ((wOrgData & wBitPtn) == wBitPtn);
}

BOOL SWMII_bIsRegBitsOff (BYTE byPortId, BYTE byAddr, UINT16 wBitPtn) DIRECT_FUNTYPE_REENT
{
    UINT16 wOrgData;

    SWMII_bReadW(byPortId, byAddr, &wOrgData);
    return ((wOrgData & wBitPtn) == 0);
}


#ifdef __ASIC_VT6526

BOOL SWMII_bWriteW (BYTE byPortId, BYTE byAddr, UINT16 wData) DIRECT_FUNTYPE_REENT
{
    wData = s_wPhyFeatureHandler (byPortId, byAddr, wData);
    return s_bMiiWriteOp (byPortId, byAddr, wData);
}


static UINT16 s_wPhyFeatureHandler (BYTE byPortId, BYTE byAddr, UINT16 wData) DIRECT_FUNTYPE_REENT
{
    UINT16  wTmp;
    BYTE    byPhyType;

    // Handle different feature of different phy module
    byPhyType = SWMII_byGetPhyType(byPortId);
    switch (byPhyType) {
        case PHY_CICADA_GIGA:
             s_bRegBitsOn (byPortId, MII_REG_CICADA_ACSR, PTN_CICADA_ACSR_MODE_SEL);
             break;

        case PHY_MARVELL_GIGA:
        case PHY_MARVELL_MEGA:
        {
            // If not toggle BMCR, do nothing
            if (byAddr != MII_REG_BMCR)
                break;

            // If toggle [AUTO], toggle MDI bits and OR [RESET]/[REAUTO]
            SWMII_bReadW(byPortId, MII_REG_BMCR, &wTmp);
            if ( ((wTmp^wData) & BMCR_AUTO) != 0 ) {
                // Toggle GIGA MDI/MDIX & OR [RESET]
                if (byPhyType == PHY_MARVELL_GIGA) {
                wData = wData | BMCR_RESET;
                    if ( (wData & BMCR_AUTO) != 0 )     // Auto => auto crossover MDI/MDIX
                        s_bRegBitsOn ( byPortId, MII_REG_MARVELL_PSCR,
                                       PTN_MARVELL_PSCR_MDI0_GIGA | PTN_MARVELL_PSCR_MDI1_GIGA );
                    else                                // Force => manual MDI
                        s_bRegBitsOff( byPortId, MII_REG_MARVELL_PSCR,
                                       PTN_MARVELL_PSCR_MDI0_GIGA | PTN_MARVELL_PSCR_MDI1_GIGA );
                }
                // Toggle MEGA MDI/MDIX & OR [REAUTO]
                else {
                    wData = wData | BMCR_REAUTO;
                    if ( (wData & BMCR_AUTO) != 0 ) {   // Auto => auto crossover MDI/MDIX
                        s_bRegBitsOff(byPortId, MII_REG_MARVELL_PSCR, PTN_MARVELL_PSCR_MDI0_MEGA);
                        s_bRegBitsOn (byPortId, MII_REG_MARVELL_PSCR, PTN_MARVELL_PSCR_MDI1_MEGA);
                    }
                    else {                              // Force => manual MDI
                        s_bRegBitsOn (byPortId, MII_REG_MARVELL_PSCR, PTN_MARVELL_PSCR_MDI0_MEGA);
                        s_bRegBitsOff(byPortId, MII_REG_MARVELL_PSCR, PTN_MARVELL_PSCR_MDI1_MEGA);
                    }
                }
            }

            // If toggle spd/dpx bits, OR [REAUTO]
            else if (((wTmp^wData) & (BMCR_SPEED|BMCR_FDX|BMCR_SPEED_GIGA)) !=0 )
                wData = wData | BMCR_REAUTO;
        } break;
    }

    return wData;
}


static BOOL s_bMiiWriteOp (BYTE byPortId, BYTE byAddr, UINT16 wData) DIRECT_FUNTYPE_REENT
{
    BOOL    bWasAutoPollOn, bRes;

    // Wait for Phy idle to issue write command
    if (!SWREG_bWaitStatus(PHY_STATUS, PTN_STATUS_BUSY, FALSE))
        return FALSE;

    // Record original auto-polling status and disable it
    bWasAutoPollOn = SWREG_bIfBitsOn(PHY_STATUS, PTN_STATUS_AUTOPOLL);
    if (bWasAutoPollOn)
        SWMII_vSetAutoPollOff();

    // Set port ID and switch SPI mode
    SWREG_vWriteB(PHY_CMD_PORTID, byPortId);

    // Set phy register address
    SWREG_vWriteB(PHY_REG_ADDR, byAddr);

    // Set write content
    SWREG_vWriteW(PHY_DATA, wData);

    // Trigger write operation and wait for complete
    SWREG_vWriteB(PHY_CMD, PTN_CMD_WRITE);
    bRes = SWREG_bWaitStatus(PHY_STATUS, PTN_STATUS_COMPLETE, TRUE);

    // Write original auto-polling status back
    if (bWasAutoPollOn)
        SWMII_vSetAutoPollOn();

    return bRes;
}


BYTE SWMII_byGetPhyType(BYTE byPortId) DIRECT_FUNTYPE_REENT
{
    UINT16 wPhyId1, wPhyId2;

    SWMII_bReadW(byPortId, MII_REG_PHYID1, &wPhyId1);
    SWMII_bReadW(byPortId, MII_REG_PHYID2, &wPhyId2);

    switch(wPhyId1) {

        case CID_MARVELL:
            if ( (wPhyId2 & 0xFFF0) == MID_MARVELL_88E1000)
                return PHY_MARVELL_GIGA;
            else
                return PHY_MARVELL_MEGA;

        case CID_CICADA:
            if ( (wPhyId2 & 0xFFF0) == MID_CICADA_CIS8201)
                return PHY_CICADA_GIGA;

        case CID_VIA:
            if ( (wPhyId2 & 0xFFF0) == MID_VIA_VT6108)
                return PHY_VIA_MEGA;

        default:
            return PHY_STANDARD;
    }
}


static BOOL s_bRegBitsOn (BYTE byPortId, BYTE byAddr, UINT16 wBitPtn) DIRECT_FUNTYPE_REENT
{
    UINT16 wOrgData;

    SWMII_bReadW(byPortId, byAddr, &wOrgData);
    return s_bMiiWriteOp(byPortId, byAddr, (UINT16)(wOrgData | wBitPtn));
}


static BOOL s_bRegBitsOff (BYTE byPortId, BYTE byAddr, UINT16 wBitPtn) DIRECT_FUNTYPE_REENT
{
    UINT16 wOrgData;

    SWMII_bReadW(byPortId, byAddr, &wOrgData);
    return s_bMiiWriteOp(byPortId, byAddr, (UINT16)(wOrgData & (~wBitPtn)));
}


BOOL SWMII_bRegBitsOn (BYTE byPortId, BYTE byAddr, UINT16 wBitPtn) DIRECT_FUNTYPE_REENT
{
    UINT16 wOrgData, wNewData;

    if (!SWMII_bReadW(byPortId, byAddr, &wOrgData))
        return FALSE;

    wNewData = s_wPhyFeatureHandler(byPortId, byAddr, (UINT16)(wOrgData | wBitPtn));
    return s_bMiiWriteOp(byPortId, byAddr, wNewData);
}


BOOL SWMII_bRegBitsOff (BYTE byPortId, BYTE byAddr, UINT16 wBitPtn) DIRECT_FUNTYPE_REENT
{
    UINT16 wOrgData, wNewData;

    if (!SWMII_bReadW(byPortId, byAddr, &wOrgData))
        return FALSE;

    wNewData = s_wPhyFeatureHandler(byPortId, byAddr, (UINT16)(wOrgData & (~wBitPtn)));
    return s_bMiiWriteOp(byPortId, byAddr, wNewData);
}

#else

BOOL SWMII_bWriteW (BYTE byPortId, BYTE byAddr, UINT16 wData) DIRECT_FUNTYPE_REENT
{
    BOOL bWasAutoPollOn, bRes;

    // Wait for Phy idle to issue write command
    if (!SWREG_bWaitStatus(PHY_STATUS, PTN_STATUS_BUSY, FALSE))
        return FALSE;

    // Record original auto-polling status and disable it
    bWasAutoPollOn = SWREG_bIfBitsOn(PHY_STATUS, PTN_STATUS_AUTOPOLL);
    if (bWasAutoPollOn)
        SWMII_vSetAutoPollOff();

    // Set port ID and switch SPI mode
    SWREG_vWriteB(PHY_CMD_PORTID, byPortId);

    // Set phy register address
    SWREG_vWriteB(PHY_REG_ADDR, byAddr);

    // Set write content
    SWREG_vWriteW(PHY_DATA, wData);

    // Trigger write operation and wait for complete
    SWREG_vWriteB(PHY_CMD, PTN_CMD_WRITE);
    bRes = SWREG_bWaitStatus(PHY_STATUS, PTN_STATUS_COMPLETE, TRUE);

    // Write original auto-polling status back
    if (bWasAutoPollOn)
        SWMII_vSetAutoPollOn();

    return bRes;
}


BOOL SWMII_bRegBitsOn (BYTE byPortId, BYTE byAddr, UINT16 wBitPtn) DIRECT_FUNTYPE_REENT
{
    UINT16 wOrgData;

    SWMII_bReadW(byPortId, byAddr, &wOrgData);
    return SWMII_bWriteW(byPortId, byAddr, (UINT16)(wOrgData | wBitPtn));
}


BOOL SWMII_bRegBitsOff (BYTE byPortId, BYTE byAddr, UINT16 wBitPtn) DIRECT_FUNTYPE_REENT
{
    UINT16 wOrgData;

    SWMII_bReadW(byPortId, byAddr, &wOrgData);
    return SWMII_bWriteW(byPortId, byAddr, (UINT16)(wOrgData & (~wBitPtn)));
}

#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -