BOOL adm_phySpeed(int ethUnit) { int phyUnit; uint16_t phyHwStatus; uint32_t phyBase; uint32_t phyAddr; for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } if (adm_phyIsLinkAlive(phyUnit)) { phyBase = ADM_PHYBASE(phyUnit); phyAddr = ADM_PHYADDR(phyUnit); phyHwStatus = phy_reg_read(phyBase, phyAddr, ADM_LINK_PARTNER_ABILITY); if (phyHwStatus & ADM_LINK_100BASETX) { return AG7100_PHY_SPEED_100TX; } } } return AG7100_PHY_SPEED_10T; }
/****************************************************************************** * * adm_phyIsDuplexFull - Determines whether the phy ports associated with the * specified device are FULL or HALF duplex. * * RETURNS: * 1 --> FULL * 0 --> HALF */ int adm_phyIsFullDuplex(int ethUnit) { int phyUnit; uint32_t phyBase; uint32_t phyAddr; uint16_t phyHwStatus; for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } if (adm_phyIsLinkAlive(phyUnit)) { phyBase = ADM_PHYBASE(phyUnit); phyAddr = ADM_PHYADDR(phyUnit); phyHwStatus = phy_reg_read(phyBase, phyAddr, ADM_LINK_PARTNER_ABILITY); if ((phyHwStatus & ADM_LINK_100BASETX_FULL_DUPLEX) || (phyHwStatus & ADM_LINK_10BASETX_FULL_DUPLEX)) { return TRUE; } } return -1; } return FALSE; }
int adm_phyIsLinkAlive(int phyUnit) { unsigned short phyHwStatus; unsigned int phyBase; unsigned int phyAddr; phyAddr = ADM_PHYADDR(phyUnit); phyHwStatus = getPhy(phyAddr, ADM_PHY_STATUS); if (phyHwStatus & ADM_STATUS_LINK_PASS) { return TRUE; } else { return FALSE; } }
/****************************************************************************** * * adm_phyIsLinkAlive - test to see if the specified link is alive * * RETURNS: * TRUE --> link is alive * FALSE --> link is down */ BOOL adm_phyIsLinkAlive(int phyUnit) { uint16_t phyHwStatus; uint32_t phyBase; uint32_t phyAddr; phyBase = ADM_PHYBASE(phyUnit); phyAddr = ADM_PHYADDR(phyUnit); phyHwStatus = phy_reg_read(phyBase, phyAddr, ADM_PHY_STATUS); if (phyHwStatus & ADM_STATUS_LINK_PASS) { return TRUE; } else { return FALSE; } }
void vlan_init(int numports) { int phyUnit; UINT16 phyHwStatus; UINT16 timeout; int liveLinks = 0; UINT32 phyBase = 0; BOOL foundPhy = FALSE; UINT32 phyAddr; UINT32 reg = 0; /* * Reset PHYs */ for (phyUnit = 0; phyUnit < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, 0)) { continue; } phyAddr = ADM_PHYADDR(phyUnit); setPhy(phyAddr, ADM_PHY_CONTROL, ADM_CTRL_SOFTWARE_RESET); } /* * After the phy is reset, it takes a little while before * it can respond properly. */ sleep(1); /* * Verify that the switch is what we think it is, and that it's ready */ adm_verifyReady(0); /* * LAN SETTING: enable Auto-MDIX */ phyAddr = ADM_SW_PHY_PORT0_REG / ADM_PHY_BASE_REG_NUM; reg = getPhy(phyAddr, ADM_SW_PHY_PORT0_REG); reg |= ADM_SW_AUTO_MDIX_EN; setPhy(phyAddr, ADM_SW_PHY_PORT0_REG, reg); phyAddr = ADM_SW_PHY_PORT1_REG / ADM_PHY_BASE_REG_NUM; reg = getPhy(phyAddr, ADM_SW_PHY_PORT1_REG); reg |= ADM_SW_AUTO_MDIX_EN; setPhy(phyAddr, ADM_SW_PHY_PORT1_REG, reg); phyAddr = ADM_SW_PHY_PORT2_REG / ADM_PHY_BASE_REG_NUM; getPhy(phyAddr, ADM_SW_PHY_PORT2_REG); reg |= ADM_SW_AUTO_MDIX_EN; setPhy(phyAddr, ADM_SW_PHY_PORT2_REG, reg); phyAddr = ADM_SW_PHY_PORT3_REG / ADM_PHY_BASE_REG_NUM; reg = getPhy(phyAddr, ADM_SW_PHY_PORT3_REG); reg |= ADM_SW_AUTO_MDIX_EN; setPhy(phyAddr, ADM_SW_PHY_PORT3_REG, reg); phyAddr = ADM_SW_PHY_PORT4_REG / ADM_PHY_BASE_REG_NUM; reg = getPhy(phyAddr, ADM_SW_PHY_PORT4_REG); reg |= ADM_SW_AUTO_MDIX_EN; setPhy(phyAddr, ADM_SW_PHY_PORT4_REG, reg); phyAddr = ADM_SW_PHY_PORT5_REG / ADM_PHY_BASE_REG_NUM; reg = getPhy(phyAddr, ADM_SW_PHY_PORT5_REG); reg |= ADM_SW_AUTO_MDIX_EN; setPhy(phyAddr, ADM_SW_PHY_PORT5_REG, reg); /* * See if there's any configuration data for this enet */ for (phyUnit = 0; phyUnit < ADM_PHY_MAX; phyUnit++) { if (ADM_ETHUNIT(phyUnit) != 0) { continue; } foundPhy = TRUE; break; } if (!foundPhy) { return FALSE; /* No PHY's configured for this ethUnit */ } /* * start auto negogiation on each phy */ for (phyUnit = 0; phyUnit < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, 0)) { continue; } phyAddr = ADM_PHYADDR(phyUnit); setPhy(phyAddr, ADM_AUTONEG_ADVERT, ADM_ADVERTISE_ALL); setPhy(phyAddr, ADM_PHY_CONTROL, ADM_CTRL_AUTONEGOTIATION_ENABLE | ADM_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 = 15; for (phyUnit = 0; (phyUnit < ADM_PHY_MAX) /* && (timeout > 0) */ ; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, 0)) { continue; } for (;;) { phyAddr = ADM_PHYADDR(phyUnit); phyHwStatus = getPhy(phyAddr, ADM_PHY_STATUS); if (ADM_AUTONEG_DONE(phyHwStatus)) { fprintf(stderr, "Port %d, Negotiation Success\n", phyUnit); break; } if (timeout == 0) { fprintf(stderr, "Port %d, Negotiation timeout\n", phyUnit); break; } if (--timeout == 0) { fprintf(stderr, "Port %d, Negotiation timeout\n", phyUnit); break; } usleep(75); } } /* * 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 < ADM_PHY_MAX; phyUnit++) { if (adm_phyIsLinkAlive(phyUnit)) { liveLinks++; ADM_IS_PHY_ALIVE(phyUnit) = TRUE; } else { ADM_IS_PHY_ALIVE(phyUnit) = FALSE; } fprintf(stderr, "adm_phySetup: eth%d phy%d: Phy Status=%4.4x\n", 0, phyUnit, getPhy(ADM_PHYADDR(phyUnit), ADM_PHY_STATUS)); } config_vlan(); eval("vconfig", "set_name_type", "VLAN_PLUS_VID_NO_PAD"); eval("vconfig", "add", "eth0", "1"); eval("vconfig", "add", "eth0", "2"); struct ifreq ifr; int s; if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW))) { char eabuf[32]; strncpy(ifr.ifr_name, "eth0", IFNAMSIZ); ioctl(s, SIOCGIFHWADDR, &ifr); char macaddr[32]; strcpy(macaddr, ether_etoa((unsigned char *)ifr.ifr_hwaddr.sa_data, eabuf)); nvram_set("et0macaddr", macaddr); MAC_ADD(macaddr); ether_atoe(macaddr, (unsigned char *)ifr.ifr_hwaddr.sa_data); strncpy(ifr.ifr_name, "vlan2", IFNAMSIZ); ioctl(s, SIOCSIFHWADDR, &ifr); close(s); } }
int adm_phyIsUp(int ethUnit) { int phyUnit; uint16_t phyHwStatus; admPhyInfo_t *lastStatus; int linkCount = 0; int lostLinks = 0; int gainedLinks = 0; uint32_t phyBase; uint32_t phyAddr; for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = ADM_PHYBASE(phyUnit); phyAddr = ADM_PHYADDR(phyUnit); lastStatus = &admPhyInfo[phyUnit]; phyHwStatus = phy_reg_read(phyBase, phyAddr, ADM_PHY_STATUS); if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */ /* See if we've lost link */ if (phyHwStatus & ADM_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 (ADM_AUTONEG_DONE(phyHwStatus)) { //printk("autoneg done\n"); 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 }
BOOL adm_phySetup(int ethUnit) { int phyUnit, global; uint16_t phyHwStatus; uint16_t timeout; int liveLinks = 0; uint32_t phyBase = 0; BOOL foundPhy = FALSE; uint32_t phyAddr; static int inited = 0; /* Reset PHYs*/ for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = ADM_PHYBASE(phyUnit); phyAddr = ADM_PHYADDR(phyUnit); phy_reg_write(phyBase, phyAddr, ADM_PHY_CONTROL, ADM_CTRL_SOFTWARE_RESET); } /* * After the phy is reset, it takes a little while before * it can respond properly. */ sysMsDelay(300); /* See if there's any configuration data for this enet */ for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = ADM_PHYBASE(phyUnit); foundPhy = TRUE; break; } if (!foundPhy) { return FALSE; /* No PHY's configured for this ethUnit */ } /* start auto negogiation on each phy */ for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = ADM_PHYBASE(phyUnit); phyAddr = ADM_PHYADDR(phyUnit); phy_reg_write(phyBase, phyAddr, ADM_AUTONEG_ADVERT, ADM_ADVERTISE_ALL); phy_reg_write(phyBase, phyAddr, ADM_PHY_CONTROL, ADM_CTRL_AUTONEGOTIATION_ENABLE | ADM_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 < ADM_PHY_MAX) /*&& (timeout > 0) */; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } for (;;) { phyBase = ADM_PHYBASE(phyUnit); phyAddr = ADM_PHYADDR(phyUnit); phyHwStatus = phy_reg_read(phyBase, phyAddr, ADM_PHY_STATUS); if (ADM_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; } sysMsDelay(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 < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } if (adm_phyIsLinkAlive(phyUnit)) { liveLinks++; ADM_IS_PHY_ALIVE(phyUnit) = TRUE; } else { ADM_IS_PHY_ALIVE(phyUnit) = FALSE; } DRV_PRINT(DRV_DEBUG_PHYSETUP, ("eth%d: Phy Status=%4.4x\n", ethUnit, phy_reg_read(ADM_PHYBASE(phyUnit), ADM_PHYADDR(phyUnit), ADM_PHY_STATUS))); } /* * XXX */ phy_reg_write(0, 0, 0x10, 0x50); return (liveLinks > 0); }
BOOL adm_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 < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = ADM_PHYBASE(phyUnit); phyAddr = ADM_PHYADDR(phyUnit); phy_reg_write(phyBase, phyAddr, ADM_PHY_CONTROL, ADM_CTRL_SOFTWARE_RESET); } /* * After the phy is reset, it takes a little while before * it can respond properly. */ mdelay(300); /* See if there's any configuration data for this enet */ for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = ADM_PHYBASE(phyUnit); foundPhy = TRUE; break; } if (!foundPhy) { return FALSE; /* No PHY's configured for this ethUnit */ } /* start auto negogiation on each phy */ for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = ADM_PHYBASE(phyUnit); phyAddr = ADM_PHYADDR(phyUnit); phy_reg_write(phyBase, phyAddr, ADM_AUTONEG_ADVERT, ADM_ADVERTISE_ALL); phy_reg_write(phyBase, phyAddr, ADM_PHY_CONTROL, ADM_CTRL_AUTONEGOTIATION_ENABLE | ADM_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 < ADM_PHY_MAX) /*&& (timeout > 0) */; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } for (;;) { phyBase = ADM_PHYBASE(phyUnit); phyAddr = ADM_PHYADDR(phyUnit); phyHwStatus = phy_reg_read(phyBase, phyAddr, ADM_PHY_STATUS); if (ADM_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 < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } if (adm_phyIsLinkAlive(phyUnit)) { liveLinks++; ADM_IS_PHY_ALIVE(phyUnit) = TRUE; } else { ADM_IS_PHY_ALIVE(phyUnit) = FALSE; } DRV_PRINT(DRV_DEBUG_PHYSETUP, ("eth%d: Phy Status=%4.4x\n", ethUnit, phy_reg_read(ADM_PHYBASE(phyUnit), ADM_PHYADDR(phyUnit), ADM_PHY_STATUS))); } #ifdef CONFIG_MV6060 /* added by lsz 30Apri07 to configure port vlan registers */ /**************************************************************************** Port VLan: --------------------------------------------------------------- | | Port6 | Port5 | Port4 | Port3 | Port2 | Port1 | Port0 | --------------------------------------------------------------- | Port0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | --------------------------------------------------------------- | Port1 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | --------------------------------------------------------------- | Port2 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | --------------------------------------------------------------- | Port3 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | --------------------------------------------------------------- | Port4 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | --------------------------------------------------------------- | Port5 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | --------------------------------------------------------------- | Port6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | --------------------------------------------------------------- Port 0: Wan Port 1~4: Lan e.g. Port 0 is 010 0000, i.e. 0x20. ****************************************************************************/ #define PORT_VALN_MAP_REG 0x06 uint32_t portAddr[7] = {0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE}; phy_reg_write(0, portAddr[0], PORT_VALN_MAP_REG, 0x103E); phy_reg_write(0, portAddr[1], PORT_VALN_MAP_REG, 0x103D); phy_reg_write(0, portAddr[2], PORT_VALN_MAP_REG, 0x103B); phy_reg_write(0, portAddr[3], PORT_VALN_MAP_REG, 0x1037); phy_reg_write(0, portAddr[4], PORT_VALN_MAP_REG, 0x102F); phy_reg_write(0, portAddr[5], PORT_VALN_MAP_REG, 0x101F); /* phy_reg_write(0, portAddr[0], PORT_VALN_MAP_REG, 0x1020); phy_reg_write(0, portAddr[1], PORT_VALN_MAP_REG, 0x103C); phy_reg_write(0, portAddr[2], PORT_VALN_MAP_REG, 0x103A); phy_reg_write(0, portAddr[3], PORT_VALN_MAP_REG, 0x1036); phy_reg_write(0, portAddr[4], PORT_VALN_MAP_REG, 0x102E); phy_reg_write(0, portAddr[5], PORT_VALN_MAP_REG, 0x101F);*/ //phy_reg_write(0, portAddr[6], PORT_VALN_MAP_REG, 0x0000); /* added by lsz to configure header mode registers */ #define PORT_CONTROL_REG 0x04 uint16_t reg_data = 0x8803; /* Flow Control | Header Mode | Forwarding */ phy_reg_write(0, portAddr[0], PORT_CONTROL_REG, 0x8003); phy_reg_write(0, portAddr[1], PORT_CONTROL_REG, 0x8003); phy_reg_write(0, portAddr[2], PORT_CONTROL_REG, 0x8003); phy_reg_write(0, portAddr[3], PORT_CONTROL_REG, 0x8003); phy_reg_write(0, portAddr[4], PORT_CONTROL_REG, 0x8003); phy_reg_write(0, portAddr[5], PORT_CONTROL_REG, 0x8003); phy_reg_write(0, 0x1E, PORT_CONTROL_REG, reg_data); #else /* * XXX */ phy_reg_write(0, 0, 0x10, 0x50); #endif return (liveLinks > 0); }