📄 ipphy.c
字号:
} for (;;) { phyBase = IP_PHYBASE(phyUnit); phyAddr = IP_PHYADDR(phyUnit); phyHwStatus = phyRegRead(phyBase, phyAddr, IP_PHY_STATUS); if (IP_AUTONEG_DONE(phyHwStatus)) { DRV_PRINT(DRV_DEBUG_PHYSETUP, ("Port %d, Neg Success\n", phyUnit)); break; } if (timeout == 0) { DRV_PRINT(DRV_DEBUG_PHYSETUP, ("Port %d, Negogiation timeout\n", phyUnit)); break; } if (--timeout == 0) { DRV_PRINT(DRV_DEBUG_PHYSETUP, ("Port %d, Negogiation timeout\n", phyUnit)); break; } mdelay(150); } } /* * All PHYs have had adequate time to autonegotiate. * Now initialize software status. * * It's possible that some ports may take a bit longer * to autonegotiate; but we can't wait forever. They'll * get noticed by mv_phyCheckStatusChange during regular * polling activities. */ for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) { if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } if (ip_phyIsLinkAlive(phyUnit)) { liveLinks++; IP_IS_PHY_ALIVE(phyUnit) = TRUE; } else { IP_IS_PHY_ALIVE(phyUnit) = FALSE; } DRV_PRINT(DRV_DEBUG_PHYSETUP, ("eth%d: Phy Status=%4.4x\n", ethUnit, phyRegRead(IP_PHYBASE(phyUnit), IP_PHYADDR(phyUnit), IP_PHY_STATUS))); } ip_VLANInit(ethUnit); return (liveLinks > 0);}/******************************************************************************** ip_phyIsDuplexFull - Determines whether the phy ports associated with the* specified device are FULL or HALF duplex.** RETURNS:* 1 --> FULL* 0 --> HALF*/intip_phyIsFullDuplex(int ethUnit){ int phyUnit; uint32_t phyBase; uint32_t phyAddr; uint16_t phyHwStatus; for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) { if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } if (ip_phyIsLinkAlive(phyUnit)) { phyBase = IP_PHYBASE(phyUnit); phyAddr = IP_PHYADDR(phyUnit); phyHwStatus = phyRegRead(phyBase, phyAddr, IP_LINK_PARTNER_ABILITY); printf("ipPhy.c: phyHwStatus 0x%x\n",phyHwStatus); if ((phyHwStatus & IP_LINK_100BASETX_FULL_DUPLEX) || (phyHwStatus & IP_LINK_10BASETX_FULL_DUPLEX)) { return TRUE; } } return -1; } return FALSE;}/******************************************************************************** ip_phyIsSpeed100 - Determines the speed of phy ports associated with the* specified device.** RETURNS:* TRUE --> 100Mbit* FALSE --> 10Mbit*/BOOLip_phySpeed(int ethUnit){ int phyUnit; uint16_t phyHwStatus; uint32_t phyBase; uint32_t phyAddr; for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) { if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } if (ip_phyIsLinkAlive(phyUnit)) { phyBase = IP_PHYBASE(phyUnit); phyAddr = IP_PHYADDR(phyUnit); phyHwStatus = phyRegRead(phyBase, phyAddr, IP_LINK_PARTNER_ABILITY); if (phyHwStatus & IP_LINK_100BASETX) { return _100BASET; } } } return _10BASET;}/******************************************************************************* ip_phyCheckStatusChange -- checks for significant changes in PHY state.** A "significant change" is:* dropped link (e.g. ethernet cable unplugged) OR* autonegotiation completed + link (e.g. ethernet cable plugged in)** When a PHY is plugged in, phyLinkGained is called.* When a PHY is unplugged, phyLinkLost is called.*/voidip_phyIsUp(int ethUnit){ int phyUnit; uint16_t phyHwStatus; ipPhyInfo_t *lastStatus; int linkCount = 0; int lostLinks = 0; int gainedLinks = 0; uint32_t phyBase; uint32_t phyAddr; for (phyUnit=0; phyUnit < IP_PHY_MAX; phyUnit++) { if (!IP_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = IP_PHYBASE(phyUnit); phyAddr = IP_PHYADDR(phyUnit); lastStatus = &ipPhyInfo[phyUnit]; phyHwStatus = phyRegRead(phyBase, phyAddr, IP_PHY_STATUS); if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */ /* See if we've lost link */ if (phyHwStatus & IP_STATUS_LINK_PASS) { linkCount++; } else { lostLinks++;#ifdef COBRA_TODO mv_flushATUDB(phyUnit);#endif DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d down\n", ethUnit, phyUnit)); lastStatus->isPhyAlive = FALSE; } } else { /* last known link status was DEAD */ /* Check for AutoNegotiation complete */ if (IP_AUTONEG_DONE(phyHwStatus)) { gainedLinks++; linkCount++; DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d up\n", ethUnit, phyUnit)); lastStatus->isPhyAlive = TRUE; } } } return (linkCount);#if 0 if (linkCount == 0) { if (lostLinks) { /* We just lost the last link for this MAC */ phyLinkLost(ethUnit); } } else { if (gainedLinks == linkCount) { /* We just gained our first link(s) for this MAC */ phyLinkGained(ethUnit); } }#endif}#ifdef DEBUG/* Define the registers of interest for a phyShow command */typedef struct ipRegisterTableEntry_s { uint32_t regNum; char *regIdString;} ipRegisterTableEntry_t;ipRegisterTableEntry_t ipPhyRegisterTable[] = { {IP_PHY_CONTROL, "PHY Control "}, {IP_PHY_STATUS, "PHY Status "}, {IP_PHY_ID1, "PHY Identifier 1 "}, {IP_PHY_ID2, "PHY Identifier 2 "}, {IP_AUTONEG_ADVERT, "Auto-Negotiation Advertisement "}, {IP_LINK_PARTNER_ABILITY, "Link Partner Ability "}, {IP_AUTONEG_EXPANSION, "Auto-Negotiation Expansion "},};int ipPhyNumRegs = sizeof(ipPhyRegisterTable) / sizeof(ipPhyRegisterTable[0]);ipRegisterTableEntry_t ipPhy29GlobalRegisterTable[] = { {IP_GLOBAL_PHY29_18_REG, "29_18_REG "}, {IP_GLOBAL_PHY29_19_REG, "29_19_REG "}, {IP_GLOBAL_PHY29_20_REG, "29_20_REG "}, {IP_GLOBAL_PHY29_21_REG, "29_21_REG "}, {IP_GLOBAL_PHY29_22_REG, "29_22_REG "}, {IP_GLOBAL_PHY29_23_REG, "29_23_REG "}, {IP_GLOBAL_PHY29_24_REG, "29_24_REG "}, {IP_GLOBAL_PHY29_25_REG, "29_25_REG "}, {IP_GLOBAL_PHY29_26_REG, "29_26_REG "}, {IP_GLOBAL_PHY29_27_REG, "29_27_REG "}, {IP_GLOBAL_PHY29_28_REG, "29_28_REG "}, {IP_GLOBAL_PHY29_29_REG, "29_29_REG "}, {IP_GLOBAL_PHY29_30_REG, "29_30_REG "}, {IP_GLOBAL_PHY29_31_REG, "29_31_REG "},};int ipPhy29GlobalNumRegs = sizeof(ipPhy29GlobalRegisterTable) / sizeof(ipPhy29GlobalRegisterTable[0]);ipRegisterTableEntry_t ipPhy30GlobalRegisterTable[] = { {IP_GLOBAL_PHY30_0_REG, "30_0_REG "}, {IP_GLOBAL_PHY30_1_REG, "30_1_REG "}, {IP_GLOBAL_PHY30_2_REG, "30_2_REG "}, {IP_GLOBAL_PHY30_3_REG, "30_3_REG "}, {IP_GLOBAL_PHY30_4_REG, "30_4_REG "}, {IP_GLOBAL_PHY30_5_REG, "30_5_REG "}, {IP_GLOBAL_PHY30_6_REG, "30_6_REG "}, {IP_GLOBAL_PHY30_7_REG, "30_7_REG "}, {IP_GLOBAL_PHY30_8_REG, "30_8_REG "}, {IP_GLOBAL_PHY30_9_REG, "30_9_REG "}, {IP_GLOBAL_PHY30_10_REG, "30_10_REG "}, {IP_GLOBAL_PHY30_11_REG, "30_11_REG "}, {IP_GLOBAL_PHY30_12_REG, "30_12_REG "}, {IP_GLOBAL_PHY30_13_REG, "30_13_REG "}, {IP_GLOBAL_PHY30_16_REG, "30_16_REG "}, {IP_GLOBAL_PHY30_17_REG, "30_17_REG "}, {IP_GLOBAL_PHY30_18_REG, "30_18_REG "}, {IP_GLOBAL_PHY30_20_REG, "30_20_REG "}, {IP_GLOBAL_PHY30_21_REG, "30_21_REG "}, {IP_GLOBAL_PHY30_22_REG, "30_22_REG "}, {IP_GLOBAL_PHY30_23_REG, "30_23_REG "}, {IP_GLOBAL_PHY30_24_REG, "30_24_REG "}, {IP_GLOBAL_PHY30_25_REG, "30_25_REG "}, {IP_GLOBAL_PHY30_26_REG, "30_26_REG "}, {IP_GLOBAL_PHY30_27_REG, "30_27_REG "}, {IP_GLOBAL_PHY30_28_REG, "30_28_REG "}, {IP_GLOBAL_PHY30_29_REG, "30_29_REG "}, {IP_GLOBAL_PHY30_30_REG, "30_30_REG "}, {IP_GLOBAL_PHY30_31_REG, "30_31_REG "},};int ipPhy30GlobalNumRegs = sizeof(ipPhy30GlobalRegisterTable) / sizeof(ipPhy30GlobalRegisterTable[0]);ipRegisterTableEntry_t ipPhy31GlobalRegisterTable[] = { {IP_GLOBAL_PHY31_0_REG, "31_0_REG "}, {IP_GLOBAL_PHY31_1_REG, "31_1_REG "}, {IP_GLOBAL_PHY31_2_REG, "31_2_REG "}, {IP_GLOBAL_PHY31_3_REG, "31_3_REG "}, {IP_GLOBAL_PHY31_4_REG, "31_4_REG "}, {IP_GLOBAL_PHY31_5_REG, "31_5_REG "}, {IP_GLOBAL_PHY31_6_REG, "31_6_REG "},};int ipPhy31GlobalNumRegs = sizeof(ipPhy31GlobalRegisterTable) / sizeof(ipPhy31GlobalRegisterTable[0]);/******************************************************************************* ip_phyShow - Dump the state of a PHY.* There are two sets of registers for each phy port:* "phy registers" and* "switch port registers"* We dump 'em all, plus the switch global registers.*/voidip_phyShow(int phyUnit){ int i; uint16_t value; uint32_t phyBase; uint32_t phyAddr; phyBase = IP_PHYBASE(phyUnit); phyAddr = IP_PHYADDR(phyUnit); printf("PHY state for PHY%d (enet%d, phyBase 0x%8x, phyAddr 0x%x)\n", phyUnit, IP_ETHUNIT(phyUnit), IP_PHYBASE(phyUnit), IP_PHYADDR(phyUnit)); printf("PHY Registers:\n"); for (i=0; i < ipPhyNumRegs; i++) { value = phyRegRead(phyBase, phyAddr, ipPhyRegisterTable[i].regNum); printf("Reg %02d (0x%02x) %s = 0x%08x\n", ipPhyRegisterTable[i].regNum, ipPhyRegisterTable[i].regNum, ipPhyRegisterTable[i].regIdString, value); } phyBase = IP_GLOBALREGBASE; printf("Switch Global Registers:\n"); printf("Phy29 Registers:\n"); for (i=0; i < ipPhy29GlobalNumRegs; i++) { value = phyRegRead(phyBase, IP_GLOBAL_PHY29_ADDR, ipPhy29GlobalRegisterTable[i].regNum); printf("Reg %02d (0x%02x) %s = 0x%08x\n", ipPhy29GlobalRegisterTable[i].regNum, ipPhy29GlobalRegisterTable[i].regNum, ipPhy29GlobalRegisterTable[i].regIdString, value); } printf("Phy30 Registers:\n"); for (i=0; i < ipPhy30GlobalNumRegs; i++) { value = phyRegRead(phyBase, IP_GLOBAL_PHY30_ADDR, ipPhy30GlobalRegisterTable[i].regNum); printf("Reg %02d (0x%02x) %s = 0x%08x\n", ipPhy30GlobalRegisterTable[i].regNum, ipPhy30GlobalRegisterTable[i].regNum, ipPhy30GlobalRegisterTable[i].regIdString, value); } printf("Phy31 Registers:\n"); for (i=0; i < ipPhy31GlobalNumRegs; i++) { value = phyRegRead(phyBase, IP_GLOBAL_PHY31_ADDR, ipPhy31GlobalRegisterTable[i].regNum); printf("Reg %02d (0x%02x) %s = 0x%08x\n", ipPhy31GlobalRegisterTable[i].regNum, ipPhy31GlobalRegisterTable[i].regNum, ipPhy31GlobalRegisterTable[i].regIdString, value); }}/******************************************************************************* ip_phySet - Modify the value of a PHY register (debug only).*/voidip_phySet(int phyUnit, uint32_t regnum, uint32_t value){ uint32_t phyBase; uint32_t phyAddr; phyBase = IP_PHYBASE(phyUnit); phyAddr = IP_PHYADDR(phyUnit); phyRegWrite(phyBase, phyAddr, regnum, value);}/******************************************************************************* ip_globalSet - Modify the value of a global register* (debug only).*/voidip_globalSet(uint32_t phyAddr, uint32_t regnum, uint32_t value){ uint32_t phyBase; phyBase = IP_GLOBALREGBASE; phyRegWrite(phyBase, phyAddr, regnum, value);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -