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

📄 ipphy.c

📁 TP-LINK公司TL-WR941N无线路由器的Bootloader U_BOOT源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. * * Copyright © 2003 Atheros Communications, Inc.,  All Rights Reserved. *//* * Manage the ICPLUS ethernet PHY. * * All definitions in this file are operating system independent! */#include <config.h>#include <linux/types.h>#include <common.h>#include <miiphy.h>#include "phy.h"#include "ipPhy.h"#define mdelay(_x)  udelay((_x) * 1000)/* PHY selections and access functions */typedef enum {    PHY_SRCPORT_INFO,     PHY_PORTINFO_SIZE,} PHY_CAP_TYPE;typedef enum {    PHY_SRCPORT_NONE,    PHY_SRCPORT_VLANTAG,     PHY_SRCPORT_TRAILER,} PHY_SRCPORT_TYPE;#ifdef DEBUG#define DRV_DEBUG 1#endif#define DRV_DEBUG 1#if DRV_DEBUG#define DRV_DEBUG_PHYERROR  0x00000001#define DRV_DEBUG_PHYCHANGE 0x00000002#define DRV_DEBUG_PHYSETUP  0x00000004int ipPhyDebug = DRV_DEBUG_PHYERROR;#define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)    \{                                                   \    if (ipPhyDebug & (FLG)) {                       \        logMsg(X0, X1, X2, X3, X4, X5, X6);         \    }                                               \}#define DRV_MSG(x,a,b,c,d,e,f)                      \    logMsg(x,a,b,c,d,e,f)#define DRV_PRINT(FLG, X)                           \{                                                   \    if (ipPhyDebug & (FLG)) {                       \        printf X;                                   \    }                                               \}#else /* !DRV_DEBUG */#define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)#define DRV_MSG(x,a,b,c,d,e,f)#define DRV_PRINT(DBG_SW,X)#endif#define IP_LAN_PORT_VLAN          1#define IP_WAN_PORT_VLAN          2#define ENET_UNIT_DEFAULT 0#define BOOL    uint32_t#define TRUE    1#define FALSE   0/* * Track per-PHY port information. */typedef struct {    BOOL   isEnetPort;       /* normal enet port */    BOOL   isPhyAlive;       /* last known state of link */    int    ethUnit;          /* MAC associated with this phy port */    uint32_t phyBase;    uint32_t phyAddr;          /* PHY registers associated with this phy port */    uint32_t VLANTableSetting; /* Value to be written to VLAN table */} ipPhyInfo_t;/* * Per-PHY information, indexed by PHY unit number. */ipPhyInfo_t ipPhyInfo[] = {    /*     * On AP30/AR5312, all PHYs are associated with MAC0.     * AP30/AR5312's MAC1 isn't used for anything.     * CONFIG_VENETDEV==1 (router) configuration:     *    Ports 0,1,2, and 3 are "LAN ports"     *    Port 4 is a WAN port     *    Port 5 connects to MAC0 in the AR5312     * CONFIG_VENETDEV==0 (bridge) configuration:     *    Ports 0,1,2,3,4 are "LAN ports"     *    Port 5 connects to the MAC0 in the AR5312     */    {TRUE,   /* phy port 0 -- LAN port 0 */     FALSE,     ENET_UNIT_DEFAULT,     0,     IP_PHY0_ADDR,     IP_LAN_PORT_VLAN    },    {TRUE,   /* phy port 1 -- LAN port 1 */     FALSE,     ENET_UNIT_DEFAULT,     0,     IP_PHY1_ADDR,     IP_LAN_PORT_VLAN    },    {TRUE,   /* phy port 2 -- LAN port 2 */     FALSE,     ENET_UNIT_DEFAULT,     0,     IP_PHY2_ADDR,      IP_LAN_PORT_VLAN    },    {TRUE,   /* phy port 3 -- LAN port 3 */     FALSE,     ENET_UNIT_DEFAULT,     0,     IP_PHY3_ADDR,      IP_LAN_PORT_VLAN    },    {TRUE,   /* phy port 4 -- WAN port or LAN port 4 */     FALSE,     ENET_UNIT_DEFAULT,     0,     IP_PHY4_ADDR,      IP_LAN_PORT_VLAN   /* Send to all ports */    },    {FALSE,  /* phy port 5 -- CPU port (no RJ45 connector) */     TRUE,     ENET_UNIT_DEFAULT,     0,     0x00,      IP_LAN_PORT_VLAN    /* Send to all ports */    },};#define IP_GLOBALREGBASE    0#define IP_PHY_MAX (sizeof(ipPhyInfo) / sizeof(ipPhyInfo[0]))/* Range of valid PHY IDs is [MIN..MAX] */#define IP_ID_MIN 0#define IP_ID_MAX (IP_PHY_MAX-1)/* Convenience macros to access myPhyInfo */#define IP_IS_ENET_PORT(phyUnit) (ipPhyInfo[phyUnit].isEnetPort)#define IP_IS_PHY_ALIVE(phyUnit) (ipPhyInfo[phyUnit].isPhyAlive)#define IP_ETHUNIT(phyUnit) (ipPhyInfo[phyUnit].ethUnit)#define IP_PHYBASE(phyUnit) (ipPhyInfo[phyUnit].phyBase)#define IP_PHYADDR(phyUnit) (ipPhyInfo[phyUnit].phyAddr)#define IP_VLAN_TABLE_SETTING(phyUnit) (ipPhyInfo[phyUnit].VLANTableSetting)#define IP_IS_ETHUNIT(phyUnit, ethUnit) \            (IP_IS_ENET_PORT(phyUnit) &&        \            IP_ETHUNIT(phyUnit) == (ethUnit))/* Forward references */BOOL       ip_phyIsLinkAlive(int phyUnit);static void ip_VLANInit(int ethUnit);static void ip_verifyReady(int ethUnit);#ifdef DEBUGvoid       ip_phyShow(int phyUnit);void       ip_phySet(int phyUnit, uint32_t regnum, uint32_t value);void       ip_globalSet(uint32_t phyAddr, uint32_t regnum, uint32_t value);#endifuint16_tphyRegRead(uint32_t phybase, uint16_t phyaddr, uint16_t reg){    uint16_t val;    phy_reg_read(phybase, phyaddr, reg, &val);    return val;}voidphyRegWrite(uint32_t phybase, uint16_t phyaddr, uint16_t reg, uint32_t val){    phy_reg_write(phybase, phyaddr, reg, val);}/******************************************************************************** ip_phyIsLinkAlive - test to see if the specified link is alive** RETURNS:*    TRUE  --> link is alive*    FALSE --> link is down*/BOOLip_phyIsLinkAlive(int phyUnit){    uint16_t phyHwStatus;    uint32_t phyBase;    uint32_t phyAddr;    phyBase = IP_PHYBASE(phyUnit);    phyAddr = IP_PHYADDR(phyUnit);    phyHwStatus = phyRegRead(phyBase, phyAddr, IP_PHY_STATUS);    if (phyHwStatus & IP_STATUS_LINK_PASS) {        return TRUE;    } else {        return FALSE;    }}/******************************************************************************** ip_VLANInit - initialize "port-based VLANs" for the specified enet unit.*/static voidip_VLANInit(int ethUnit){    int     phyUnit;    uint32_t  phyBase;    uint32_t  phyReg;    phyBase = IP_GLOBALREGBASE;        for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {        if (IP_ETHUNIT(phyUnit) != ethUnit) {            continue;        }        phyRegWrite(phyBase, IP_GLOBAL_PHY29_ADDR,                     IP_GLOBAL_PHY29_24_REG + ((phyUnit == 5) ? (phyUnit + 1) : phyUnit),                                    IP_VLAN_TABLE_SETTING(phyUnit));                /* Send all packets to all ports */        phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG);        phyReg = phyReg | ((1 << phyUnit) << IP_VLAN1_OUTPUT_PORT_MASK_S);        phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_1_REG, phyReg);    }    phyReg = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_9_REG);    phyReg = phyReg | TAG_VLAN_ENABLE;    phyReg = phyReg & ~VID_INDX_SEL_M;    phyRegWrite(phyBase, IP_GLOBAL_PHY30_ADDR, IP_GLOBAL_PHY30_9_REG, phyReg);}static voidip_verifyReady(int ethUnit){    int     phyUnit;    uint32_t  phyBase = 0;    uint32_t  phyAddr;    uint16_t  phyID1;    uint16_t  phyID2;    /*     * The first read to the Phy port registers always fails and     * returns 0.   So get things started with a bogus read.     */    for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {        if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {            continue;        }        phyBase = IP_PHYBASE(phyUnit);        phyAddr = IP_PHYADDR(phyUnit);            phyID1 = phyRegRead(phyBase, phyAddr, IP_PHY_ID1); /* returns 0 */        break;    }    for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {        if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {            continue;        }        /*******************/        /* Verify phy port */        /*******************/        phyBase = IP_PHYBASE(phyUnit);        phyAddr = IP_PHYADDR(phyUnit);            phyID1 = phyRegRead(phyBase, phyAddr, IP_PHY_ID1);        if (phyID1 != IP_PHY_ID1_EXPECTATION) {            DRV_PRINT(DRV_DEBUG_PHYERROR,                      ("Invalid PHY ID1 for enet%d port%d.  Expected 0x%04x, read 0x%04x\n",                       ethUnit,                       phyUnit,                       IP_PHY_ID1_EXPECTATION,                       phyID1));            return;        }            phyID2 = phyRegRead(phyBase, phyAddr, IP_PHY_ID2);        if ((phyID2 & IP_OUI_LSB_MASK) != IP_OUI_LSB_EXPECTATION) {            DRV_PRINT(DRV_DEBUG_PHYERROR,                      ("Invalid PHY ID2 for enet%d port %d.  Expected 0x%04x, read 0x%04x\n",                       ethUnit,                       phyUnit,                       IP_OUI_LSB_EXPECTATION,                       phyID2));            return;        }            DRV_PRINT(DRV_DEBUG_PHYSETUP,                  ("Found PHY enet%d port%d: model 0x%x revision 0x%x\n",                   ethUnit,                   phyUnit,                   (phyID2 & IP_MODEL_NUM_MASK) >> IP_MODEL_NUM_SHIFT,                   (phyID2 & IP_REV_NUM_MASK) >> IP_REV_NUM_SHIFT));        }}/******************************************************************************** ip_phySetup - reset and setup the PHY associated with* the specified MAC unit number.** Resets the associated PHY port.** RETURNS:*    TRUE  --> associated PHY is alive*    FALSE --> no LINKs on this ethernet unit*/BOOLip_phySetup(int ethUnit){    int     phyUnit;    uint16_t  phyHwStatus;    uint16_t  timeout;    int     liveLinks = 0;    uint32_t  phyBase = 0;    BOOL    foundPhy = FALSE;    uint32_t  phyAddr;        /* Reset PHYs*/    for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {        if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {            continue;        }        phyBase = IP_PHYBASE(phyUnit);        phyAddr = IP_PHYADDR(phyUnit);        phyRegWrite(phyBase, phyAddr, IP_PHY_CONTROL,                    IP_CTRL_SOFTWARE_RESET);    }    /*     * After the phy is reset, it takes a little while before     * it can respond properly.     */    mdelay(300);    /* Verify that the switch is what we think it is, and that it's ready */    ip_verifyReady(ethUnit);    /* See if there's any configuration data for this enet */    for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {        if (IP_ETHUNIT(phyUnit) != ethUnit) {            continue;        }        phyBase = IP_PHYBASE(phyUnit);        foundPhy = TRUE;        break;    }    if (!foundPhy) {        return FALSE; /* No PHY's configured for this ethUnit */    }#ifdef COBRA_TODO    /* Initialize global switch settings */    /* Initialize the aging time */    /* Set the learning properties */#endif    /* start auto negogiation on each phy */    for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) {        if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {            continue;        }        phyBase = IP_PHYBASE(phyUnit);        phyAddr = IP_PHYADDR(phyUnit);                phyRegWrite(phyBase, phyAddr, IP_AUTONEG_ADVERT,                                        IP_ADVERTISE_ALL);        phyRegWrite(phyBase, phyAddr, IP_PHY_CONTROL,                    IP_CTRL_AUTONEGOTIATION_ENABLE | IP_CTRL_START_AUTONEGOTIATION);    }    /*     * Wait up to .75 seconds for ALL associated PHYs to finish     * autonegotiation.  The only way we get out of here sooner is     * if ALL PHYs are connected AND finish autonegotiation.     */    timeout=5;    for (phyUnit=0; (phyUnit < IP_PHY_MAX) /*&& (timeout > 0) */; phyUnit++) {        if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) {            continue;

⌨️ 快捷键说明

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