/** * @file IxEthMii.c * * @author Intel Corporation * @date * * @brief MII control functions * * Design Notes: * * * @par * IXP400 SW Release version 2.0 * * -- Copyright Notice -- * * @par * Copyright 2001-2005, Intel Corporation. * All rights reserved. * * @par * SPDX-License-Identifier: BSD-3-Clause * @par * -- End of Copyright Notice -- */ #include "IxOsal.h" #include "IxEthAcc.h" #include "IxEthMii_p.h" #ifdef __wince #include "IxOsPrintf.h" #endif /* Array to store the phy IDs of the discovered phys */ PRIVATE UINT32 ixEthMiiPhyId[IXP425_ETH_ACC_MII_MAX_ADDR]; /********************************************************* * * Scan for PHYs on the MII bus. This function returns * an array of booleans, one for each PHY address. * If a PHY is found at a particular address, the * corresponding entry in the array is set to true. * */ PUBLIC IX_STATUS ixEthMiiPhyScan(BOOL phyPresent[], UINT32 maxPhyCount) { UINT32 i; UINT16 regval, regvalId1, regvalId2; /*Search for PHYs on the MII*/ /*Search for existant phys on the MDIO bus*/ if ((phyPresent == NULL) || (maxPhyCount > IXP425_ETH_ACC_MII_MAX_ADDR)) { return IX_FAIL; } /* fill the array */ for(i=0; i 0 && i= IX_ETH_MII_RESET_DELAY_MS) { ixEthAccMiiWriteRtn(phyAddr, IX_ETH_MII_CTRL_REG, IX_ETH_MII_CR_NORM_EN); return IX_FAIL; } return IX_SUCCESS; } /* end of if(ixEthMiiPhyId) */ else if (ixEthMiiPhyId[phyAddr] == IX_ETH_MII_KS8995_PHY_ID) { /* reset bit is reserved, just reset the control register */ ixEthAccMiiWriteRtn(phyAddr, IX_ETH_MII_CTRL_REG, IX_ETH_MII_CR_NORM_EN); return IX_SUCCESS; } else { /* unknown PHY, set the control register reset bit, * wait 2 s. and clear the control register. */ ixEthAccMiiWriteRtn(phyAddr, IX_ETH_MII_CTRL_REG, IX_ETH_MII_CR_RESET); ixOsalSleep (IX_ETH_MII_RESET_DELAY_MS); ixEthAccMiiWriteRtn(phyAddr, IX_ETH_MII_CTRL_REG, IX_ETH_MII_CR_NORM_EN); return IX_SUCCESS; } /* end of if-else(ixEthMiiPhyId) */ } /* end of if(phyAddr) */ return IX_FAIL; } /***************************************************************** * * Link state query functions */ PUBLIC IX_STATUS ixEthMiiLinkStatus(UINT32 phyAddr, BOOL *linkUp, BOOL *speed100, BOOL *fullDuplex, BOOL *autoneg) { UINT16 ctrlRegval, statRegval, regval, regval4, regval5; /* check the parameters */ if ((linkUp == NULL) || (speed100 == NULL) || (fullDuplex == NULL) || (autoneg == NULL)) { return IX_FAIL; } *linkUp = false; *speed100 = false; *fullDuplex = false; *autoneg = false; if ((phyAddr < IXP425_ETH_ACC_MII_MAX_ADDR) && (ixEthMiiPhyId[phyAddr] != IX_ETH_MII_INVALID_PHY_ID)) { if ((ixEthMiiPhyId[phyAddr] == IX_ETH_MII_LXT971_PHY_ID) || (ixEthMiiPhyId[phyAddr] == IX_ETH_MII_LXT972_PHY_ID) || (ixEthMiiPhyId[phyAddr] == IX_ETH_MII_LXT9785_PHY_ID) ) { /* --------------------------------------------------*/ /* Retrieve information from PHY specific register */ /* --------------------------------------------------*/ if (ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_STAT2_REG, ®val) != IX_ETH_ACC_SUCCESS) { return IX_FAIL; } *linkUp = ((regval & IX_ETH_MII_SR2_LINK) != 0); *speed100 = ((regval & IX_ETH_MII_SR2_100) != 0); *fullDuplex = ((regval & IX_ETH_MII_SR2_FD) != 0); *autoneg = ((regval & IX_ETH_MII_SR2_AUTO) != 0); return IX_SUCCESS; } /* end of if(ixEthMiiPhyId) */ else { /* ----------------------------------------------------*/ /* Retrieve information from status and ctrl registers */ /* ----------------------------------------------------*/ if (ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_CTRL_REG, &ctrlRegval) != IX_ETH_ACC_SUCCESS) { return IX_FAIL; } ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_STAT_REG, &statRegval); *linkUp = ((statRegval & IX_ETH_MII_SR_LINK_STATUS) != 0); if (*linkUp) { *autoneg = ((ctrlRegval & IX_ETH_MII_CR_AUTO_EN) != 0) && ((statRegval & IX_ETH_MII_SR_AUTO_SEL) != 0) && ((statRegval & IX_ETH_MII_SR_AUTO_NEG) != 0); if (*autoneg) { /* mask the current stat values with the capabilities */ ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_AN_ADS_REG, ®val4); ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_AN_PRTN_REG, ®val5); /* merge the flags from the 3 registers */ regval = (statRegval & ((regval4 & regval5) << 6)); /* initialise from status register values */ if ((regval & IX_ETH_MII_SR_TX_FULL_DPX) != 0) { /* 100 Base X full dplx */ *speed100 = true; *fullDuplex = true; return IX_SUCCESS; } if ((regval & IX_ETH_MII_SR_TX_HALF_DPX) != 0) { /* 100 Base X half dplx */ *speed100 = true; return IX_SUCCESS; } if ((regval & IX_ETH_MII_SR_10T_FULL_DPX) != 0) { /* 10 mb full dplx */ *fullDuplex = true; return IX_SUCCESS; } if ((regval & IX_ETH_MII_SR_10T_HALF_DPX) != 0) { /* 10 mb half dplx */ return IX_SUCCESS; } } /* end of if(autoneg) */ else { /* autonegotiate not complete, return setup parameters */ *speed100 = ((ctrlRegval & IX_ETH_MII_CR_100) != 0); *fullDuplex = ((ctrlRegval & IX_ETH_MII_CR_FDX) != 0); } } /* end of if(linkUp) */ } /* end of if-else(ixEthMiiPhyId) */ } /* end of if(phyAddr) */ else { return IX_FAIL; } /* end of if-else(phyAddr) */ return IX_SUCCESS; } /***************************************************************** * * Link state display functions */ PUBLIC IX_STATUS ixEthMiiPhyShow (UINT32 phyAddr) { BOOL linkUp, speed100, fullDuplex, autoneg; UINT16 cregval; UINT16 sregval; ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_STAT_REG, &sregval); ixEthAccMiiReadRtn(phyAddr, IX_ETH_MII_CTRL_REG, &cregval); /* get link information */ if (ixEthMiiLinkStatus(phyAddr, &linkUp, &speed100, &fullDuplex, &autoneg) != IX_ETH_ACC_SUCCESS) { printf("PHY Status unknown\n"); return IX_FAIL; } printf("PHY ID [phyAddr]: %8.8x\n",ixEthMiiPhyId[phyAddr]); printf( " Status reg: %4.4x\n",sregval); printf( " control reg: %4.4x\n",cregval); /* display link information */ printf("PHY Status:\n"); printf(" Link is %s\n", (linkUp ? "Up" : "Down")); if((sregval & IX_ETH_MII_SR_REMOTE_FAULT) != 0) { printf(" Remote fault detected\n"); } printf(" Auto Negotiation %s\n", (autoneg ? "Completed" : "Not Completed")); printf("PHY Configuration:\n"); printf(" Speed %sMb/s\n", (speed100 ? "100" : "10")); printf(" %s Duplex\n", (fullDuplex ? "Full" : "Half")); printf(" Auto Negotiation %s\n", (autoneg ? "Enabled" : "Disabled")); return IX_SUCCESS; }