18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci mii.c: MII interface library 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci Maintained by Jeff Garzik <jgarzik@pobox.com> 68c2ecf20Sopenharmony_ci Copyright 2001,2002 Jeff Garzik 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci Various code came from myson803.c and other files by 98c2ecf20Sopenharmony_ci Donald Becker. Copyright: 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci Written 1998-2002 by Donald Becker. 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci This software may be used and distributed according 148c2ecf20Sopenharmony_ci to the terms of the GNU General Public License (GPL), 158c2ecf20Sopenharmony_ci incorporated herein by reference. Drivers based on 168c2ecf20Sopenharmony_ci or derived from this code fall under the GPL and must 178c2ecf20Sopenharmony_ci retain the authorship, copyright and license notice. 188c2ecf20Sopenharmony_ci This file is not a complete program and may only be 198c2ecf20Sopenharmony_ci used when the entire operating system is licensed 208c2ecf20Sopenharmony_ci under the GPL. 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci The author may be reached as becker@scyld.com, or C/O 238c2ecf20Sopenharmony_ci Scyld Computing Corporation 248c2ecf20Sopenharmony_ci 410 Severn Ave., Suite 210 258c2ecf20Sopenharmony_ci Annapolis MD 21403 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci */ 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include <linux/kernel.h> 318c2ecf20Sopenharmony_ci#include <linux/module.h> 328c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 338c2ecf20Sopenharmony_ci#include <linux/ethtool.h> 348c2ecf20Sopenharmony_ci#include <linux/mii.h> 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic u32 mii_get_an(struct mii_if_info *mii, u16 addr) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci int advert; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci advert = mii->mdio_read(mii->dev, mii->phy_id, addr); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci return mii_lpa_to_ethtool_lpa_t(advert); 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/** 468c2ecf20Sopenharmony_ci * mii_ethtool_gset - get settings that are specified in @ecmd 478c2ecf20Sopenharmony_ci * @mii: MII interface 488c2ecf20Sopenharmony_ci * @ecmd: requested ethtool_cmd 498c2ecf20Sopenharmony_ci * 508c2ecf20Sopenharmony_ci * The @ecmd parameter is expected to have been cleared before calling 518c2ecf20Sopenharmony_ci * mii_ethtool_gset(). 528c2ecf20Sopenharmony_ci * 538c2ecf20Sopenharmony_ci * Returns 0 for success, negative on error. 548c2ecf20Sopenharmony_ci */ 558c2ecf20Sopenharmony_ciint mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci struct net_device *dev = mii->dev; 588c2ecf20Sopenharmony_ci u16 bmcr, bmsr, ctrl1000 = 0, stat1000 = 0; 598c2ecf20Sopenharmony_ci u32 nego; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci ecmd->supported = 628c2ecf20Sopenharmony_ci (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | 638c2ecf20Sopenharmony_ci SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | 648c2ecf20Sopenharmony_ci SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); 658c2ecf20Sopenharmony_ci if (mii->supports_gmii) 668c2ecf20Sopenharmony_ci ecmd->supported |= SUPPORTED_1000baseT_Half | 678c2ecf20Sopenharmony_ci SUPPORTED_1000baseT_Full; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci /* only supports twisted-pair */ 708c2ecf20Sopenharmony_ci ecmd->port = PORT_MII; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci /* only supports internal transceiver */ 738c2ecf20Sopenharmony_ci ecmd->transceiver = XCVR_INTERNAL; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci /* this isn't fully supported at higher layers */ 768c2ecf20Sopenharmony_ci ecmd->phy_address = mii->phy_id; 778c2ecf20Sopenharmony_ci ecmd->mdio_support = ETH_MDIO_SUPPORTS_C22; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); 828c2ecf20Sopenharmony_ci bmsr = mii->mdio_read(dev, mii->phy_id, MII_BMSR); 838c2ecf20Sopenharmony_ci if (mii->supports_gmii) { 848c2ecf20Sopenharmony_ci ctrl1000 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); 858c2ecf20Sopenharmony_ci stat1000 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000); 868c2ecf20Sopenharmony_ci } 878c2ecf20Sopenharmony_ci if (bmcr & BMCR_ANENABLE) { 888c2ecf20Sopenharmony_ci ecmd->advertising |= ADVERTISED_Autoneg; 898c2ecf20Sopenharmony_ci ecmd->autoneg = AUTONEG_ENABLE; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci ecmd->advertising |= mii_get_an(mii, MII_ADVERTISE); 928c2ecf20Sopenharmony_ci if (mii->supports_gmii) 938c2ecf20Sopenharmony_ci ecmd->advertising |= 948c2ecf20Sopenharmony_ci mii_ctrl1000_to_ethtool_adv_t(ctrl1000); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci if (bmsr & BMSR_ANEGCOMPLETE) { 978c2ecf20Sopenharmony_ci ecmd->lp_advertising = mii_get_an(mii, MII_LPA); 988c2ecf20Sopenharmony_ci ecmd->lp_advertising |= 998c2ecf20Sopenharmony_ci mii_stat1000_to_ethtool_lpa_t(stat1000); 1008c2ecf20Sopenharmony_ci } else { 1018c2ecf20Sopenharmony_ci ecmd->lp_advertising = 0; 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci nego = ecmd->advertising & ecmd->lp_advertising; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci if (nego & (ADVERTISED_1000baseT_Full | 1078c2ecf20Sopenharmony_ci ADVERTISED_1000baseT_Half)) { 1088c2ecf20Sopenharmony_ci ethtool_cmd_speed_set(ecmd, SPEED_1000); 1098c2ecf20Sopenharmony_ci ecmd->duplex = !!(nego & ADVERTISED_1000baseT_Full); 1108c2ecf20Sopenharmony_ci } else if (nego & (ADVERTISED_100baseT_Full | 1118c2ecf20Sopenharmony_ci ADVERTISED_100baseT_Half)) { 1128c2ecf20Sopenharmony_ci ethtool_cmd_speed_set(ecmd, SPEED_100); 1138c2ecf20Sopenharmony_ci ecmd->duplex = !!(nego & ADVERTISED_100baseT_Full); 1148c2ecf20Sopenharmony_ci } else { 1158c2ecf20Sopenharmony_ci ethtool_cmd_speed_set(ecmd, SPEED_10); 1168c2ecf20Sopenharmony_ci ecmd->duplex = !!(nego & ADVERTISED_10baseT_Full); 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci } else { 1198c2ecf20Sopenharmony_ci ecmd->autoneg = AUTONEG_DISABLE; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci ethtool_cmd_speed_set(ecmd, 1228c2ecf20Sopenharmony_ci ((bmcr & BMCR_SPEED1000 && 1238c2ecf20Sopenharmony_ci (bmcr & BMCR_SPEED100) == 0) ? 1248c2ecf20Sopenharmony_ci SPEED_1000 : 1258c2ecf20Sopenharmony_ci ((bmcr & BMCR_SPEED100) ? 1268c2ecf20Sopenharmony_ci SPEED_100 : SPEED_10))); 1278c2ecf20Sopenharmony_ci ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci mii->full_duplex = ecmd->duplex; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci /* ignore maxtxpkt, maxrxpkt for now */ 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci return 0; 1358c2ecf20Sopenharmony_ci} 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci/** 1388c2ecf20Sopenharmony_ci * mii_ethtool_get_link_ksettings - get settings that are specified in @cmd 1398c2ecf20Sopenharmony_ci * @mii: MII interface 1408c2ecf20Sopenharmony_ci * @cmd: requested ethtool_link_ksettings 1418c2ecf20Sopenharmony_ci * 1428c2ecf20Sopenharmony_ci * The @cmd parameter is expected to have been cleared before calling 1438c2ecf20Sopenharmony_ci * mii_ethtool_get_link_ksettings(). 1448c2ecf20Sopenharmony_ci */ 1458c2ecf20Sopenharmony_civoid mii_ethtool_get_link_ksettings(struct mii_if_info *mii, 1468c2ecf20Sopenharmony_ci struct ethtool_link_ksettings *cmd) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci struct net_device *dev = mii->dev; 1498c2ecf20Sopenharmony_ci u16 bmcr, bmsr, ctrl1000 = 0, stat1000 = 0; 1508c2ecf20Sopenharmony_ci u32 nego, supported, advertising, lp_advertising; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | 1538c2ecf20Sopenharmony_ci SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | 1548c2ecf20Sopenharmony_ci SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); 1558c2ecf20Sopenharmony_ci if (mii->supports_gmii) 1568c2ecf20Sopenharmony_ci supported |= SUPPORTED_1000baseT_Half | 1578c2ecf20Sopenharmony_ci SUPPORTED_1000baseT_Full; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci /* only supports twisted-pair */ 1608c2ecf20Sopenharmony_ci cmd->base.port = PORT_MII; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci /* this isn't fully supported at higher layers */ 1638c2ecf20Sopenharmony_ci cmd->base.phy_address = mii->phy_id; 1648c2ecf20Sopenharmony_ci cmd->base.mdio_support = ETH_MDIO_SUPPORTS_C22; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci advertising = ADVERTISED_TP | ADVERTISED_MII; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); 1698c2ecf20Sopenharmony_ci bmsr = mii->mdio_read(dev, mii->phy_id, MII_BMSR); 1708c2ecf20Sopenharmony_ci if (mii->supports_gmii) { 1718c2ecf20Sopenharmony_ci ctrl1000 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); 1728c2ecf20Sopenharmony_ci stat1000 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000); 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci if (bmcr & BMCR_ANENABLE) { 1758c2ecf20Sopenharmony_ci advertising |= ADVERTISED_Autoneg; 1768c2ecf20Sopenharmony_ci cmd->base.autoneg = AUTONEG_ENABLE; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci advertising |= mii_get_an(mii, MII_ADVERTISE); 1798c2ecf20Sopenharmony_ci if (mii->supports_gmii) 1808c2ecf20Sopenharmony_ci advertising |= mii_ctrl1000_to_ethtool_adv_t(ctrl1000); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci if (bmsr & BMSR_ANEGCOMPLETE) { 1838c2ecf20Sopenharmony_ci lp_advertising = mii_get_an(mii, MII_LPA); 1848c2ecf20Sopenharmony_ci lp_advertising |= 1858c2ecf20Sopenharmony_ci mii_stat1000_to_ethtool_lpa_t(stat1000); 1868c2ecf20Sopenharmony_ci } else { 1878c2ecf20Sopenharmony_ci lp_advertising = 0; 1888c2ecf20Sopenharmony_ci } 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci nego = advertising & lp_advertising; 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci if (nego & (ADVERTISED_1000baseT_Full | 1938c2ecf20Sopenharmony_ci ADVERTISED_1000baseT_Half)) { 1948c2ecf20Sopenharmony_ci cmd->base.speed = SPEED_1000; 1958c2ecf20Sopenharmony_ci cmd->base.duplex = !!(nego & ADVERTISED_1000baseT_Full); 1968c2ecf20Sopenharmony_ci } else if (nego & (ADVERTISED_100baseT_Full | 1978c2ecf20Sopenharmony_ci ADVERTISED_100baseT_Half)) { 1988c2ecf20Sopenharmony_ci cmd->base.speed = SPEED_100; 1998c2ecf20Sopenharmony_ci cmd->base.duplex = !!(nego & ADVERTISED_100baseT_Full); 2008c2ecf20Sopenharmony_ci } else { 2018c2ecf20Sopenharmony_ci cmd->base.speed = SPEED_10; 2028c2ecf20Sopenharmony_ci cmd->base.duplex = !!(nego & ADVERTISED_10baseT_Full); 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci } else { 2058c2ecf20Sopenharmony_ci cmd->base.autoneg = AUTONEG_DISABLE; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci cmd->base.speed = ((bmcr & BMCR_SPEED1000 && 2088c2ecf20Sopenharmony_ci (bmcr & BMCR_SPEED100) == 0) ? 2098c2ecf20Sopenharmony_ci SPEED_1000 : 2108c2ecf20Sopenharmony_ci ((bmcr & BMCR_SPEED100) ? 2118c2ecf20Sopenharmony_ci SPEED_100 : SPEED_10)); 2128c2ecf20Sopenharmony_ci cmd->base.duplex = (bmcr & BMCR_FULLDPLX) ? 2138c2ecf20Sopenharmony_ci DUPLEX_FULL : DUPLEX_HALF; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci lp_advertising = 0; 2168c2ecf20Sopenharmony_ci } 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci mii->full_duplex = cmd->base.duplex; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, 2218c2ecf20Sopenharmony_ci supported); 2228c2ecf20Sopenharmony_ci ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, 2238c2ecf20Sopenharmony_ci advertising); 2248c2ecf20Sopenharmony_ci ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, 2258c2ecf20Sopenharmony_ci lp_advertising); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci /* ignore maxtxpkt, maxrxpkt for now */ 2288c2ecf20Sopenharmony_ci} 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci/** 2318c2ecf20Sopenharmony_ci * mii_ethtool_sset - set settings that are specified in @ecmd 2328c2ecf20Sopenharmony_ci * @mii: MII interface 2338c2ecf20Sopenharmony_ci * @ecmd: requested ethtool_cmd 2348c2ecf20Sopenharmony_ci * 2358c2ecf20Sopenharmony_ci * Returns 0 for success, negative on error. 2368c2ecf20Sopenharmony_ci */ 2378c2ecf20Sopenharmony_ciint mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci struct net_device *dev = mii->dev; 2408c2ecf20Sopenharmony_ci u32 speed = ethtool_cmd_speed(ecmd); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci if (speed != SPEED_10 && 2438c2ecf20Sopenharmony_ci speed != SPEED_100 && 2448c2ecf20Sopenharmony_ci speed != SPEED_1000) 2458c2ecf20Sopenharmony_ci return -EINVAL; 2468c2ecf20Sopenharmony_ci if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) 2478c2ecf20Sopenharmony_ci return -EINVAL; 2488c2ecf20Sopenharmony_ci if (ecmd->port != PORT_MII) 2498c2ecf20Sopenharmony_ci return -EINVAL; 2508c2ecf20Sopenharmony_ci if (ecmd->transceiver != XCVR_INTERNAL) 2518c2ecf20Sopenharmony_ci return -EINVAL; 2528c2ecf20Sopenharmony_ci if (ecmd->phy_address != mii->phy_id) 2538c2ecf20Sopenharmony_ci return -EINVAL; 2548c2ecf20Sopenharmony_ci if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE) 2558c2ecf20Sopenharmony_ci return -EINVAL; 2568c2ecf20Sopenharmony_ci if ((speed == SPEED_1000) && (!mii->supports_gmii)) 2578c2ecf20Sopenharmony_ci return -EINVAL; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci /* ignore supported, maxtxpkt, maxrxpkt */ 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci if (ecmd->autoneg == AUTONEG_ENABLE) { 2628c2ecf20Sopenharmony_ci u32 bmcr, advert, tmp; 2638c2ecf20Sopenharmony_ci u32 advert2 = 0, tmp2 = 0; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci if ((ecmd->advertising & (ADVERTISED_10baseT_Half | 2668c2ecf20Sopenharmony_ci ADVERTISED_10baseT_Full | 2678c2ecf20Sopenharmony_ci ADVERTISED_100baseT_Half | 2688c2ecf20Sopenharmony_ci ADVERTISED_100baseT_Full | 2698c2ecf20Sopenharmony_ci ADVERTISED_1000baseT_Half | 2708c2ecf20Sopenharmony_ci ADVERTISED_1000baseT_Full)) == 0) 2718c2ecf20Sopenharmony_ci return -EINVAL; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci /* advertise only what has been requested */ 2748c2ecf20Sopenharmony_ci advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); 2758c2ecf20Sopenharmony_ci tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4); 2768c2ecf20Sopenharmony_ci if (mii->supports_gmii) { 2778c2ecf20Sopenharmony_ci advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); 2788c2ecf20Sopenharmony_ci tmp2 = advert2 & ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci tmp |= ethtool_adv_to_mii_adv_t(ecmd->advertising); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci if (mii->supports_gmii) 2838c2ecf20Sopenharmony_ci tmp2 |= 2848c2ecf20Sopenharmony_ci ethtool_adv_to_mii_ctrl1000_t(ecmd->advertising); 2858c2ecf20Sopenharmony_ci if (advert != tmp) { 2868c2ecf20Sopenharmony_ci mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp); 2878c2ecf20Sopenharmony_ci mii->advertising = tmp; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci if ((mii->supports_gmii) && (advert2 != tmp2)) 2908c2ecf20Sopenharmony_ci mii->mdio_write(dev, mii->phy_id, MII_CTRL1000, tmp2); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci /* turn on autonegotiation, and force a renegotiate */ 2938c2ecf20Sopenharmony_ci bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); 2948c2ecf20Sopenharmony_ci bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); 2958c2ecf20Sopenharmony_ci mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci mii->force_media = 0; 2988c2ecf20Sopenharmony_ci } else { 2998c2ecf20Sopenharmony_ci u32 bmcr, tmp; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci /* turn off auto negotiation, set speed and duplexity */ 3028c2ecf20Sopenharmony_ci bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); 3038c2ecf20Sopenharmony_ci tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | 3048c2ecf20Sopenharmony_ci BMCR_SPEED1000 | BMCR_FULLDPLX); 3058c2ecf20Sopenharmony_ci if (speed == SPEED_1000) 3068c2ecf20Sopenharmony_ci tmp |= BMCR_SPEED1000; 3078c2ecf20Sopenharmony_ci else if (speed == SPEED_100) 3088c2ecf20Sopenharmony_ci tmp |= BMCR_SPEED100; 3098c2ecf20Sopenharmony_ci if (ecmd->duplex == DUPLEX_FULL) { 3108c2ecf20Sopenharmony_ci tmp |= BMCR_FULLDPLX; 3118c2ecf20Sopenharmony_ci mii->full_duplex = 1; 3128c2ecf20Sopenharmony_ci } else 3138c2ecf20Sopenharmony_ci mii->full_duplex = 0; 3148c2ecf20Sopenharmony_ci if (bmcr != tmp) 3158c2ecf20Sopenharmony_ci mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci mii->force_media = 1; 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci return 0; 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci/** 3238c2ecf20Sopenharmony_ci * mii_ethtool_set_link_ksettings - set settings that are specified in @cmd 3248c2ecf20Sopenharmony_ci * @mii: MII interfaces 3258c2ecf20Sopenharmony_ci * @cmd: requested ethtool_link_ksettings 3268c2ecf20Sopenharmony_ci * 3278c2ecf20Sopenharmony_ci * Returns 0 for success, negative on error. 3288c2ecf20Sopenharmony_ci */ 3298c2ecf20Sopenharmony_ciint mii_ethtool_set_link_ksettings(struct mii_if_info *mii, 3308c2ecf20Sopenharmony_ci const struct ethtool_link_ksettings *cmd) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci struct net_device *dev = mii->dev; 3338c2ecf20Sopenharmony_ci u32 speed = cmd->base.speed; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci if (speed != SPEED_10 && 3368c2ecf20Sopenharmony_ci speed != SPEED_100 && 3378c2ecf20Sopenharmony_ci speed != SPEED_1000) 3388c2ecf20Sopenharmony_ci return -EINVAL; 3398c2ecf20Sopenharmony_ci if (cmd->base.duplex != DUPLEX_HALF && cmd->base.duplex != DUPLEX_FULL) 3408c2ecf20Sopenharmony_ci return -EINVAL; 3418c2ecf20Sopenharmony_ci if (cmd->base.port != PORT_MII) 3428c2ecf20Sopenharmony_ci return -EINVAL; 3438c2ecf20Sopenharmony_ci if (cmd->base.phy_address != mii->phy_id) 3448c2ecf20Sopenharmony_ci return -EINVAL; 3458c2ecf20Sopenharmony_ci if (cmd->base.autoneg != AUTONEG_DISABLE && 3468c2ecf20Sopenharmony_ci cmd->base.autoneg != AUTONEG_ENABLE) 3478c2ecf20Sopenharmony_ci return -EINVAL; 3488c2ecf20Sopenharmony_ci if ((speed == SPEED_1000) && (!mii->supports_gmii)) 3498c2ecf20Sopenharmony_ci return -EINVAL; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci /* ignore supported, maxtxpkt, maxrxpkt */ 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci if (cmd->base.autoneg == AUTONEG_ENABLE) { 3548c2ecf20Sopenharmony_ci u32 bmcr, advert, tmp; 3558c2ecf20Sopenharmony_ci u32 advert2 = 0, tmp2 = 0; 3568c2ecf20Sopenharmony_ci u32 advertising; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci ethtool_convert_link_mode_to_legacy_u32( 3598c2ecf20Sopenharmony_ci &advertising, cmd->link_modes.advertising); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci if ((advertising & (ADVERTISED_10baseT_Half | 3628c2ecf20Sopenharmony_ci ADVERTISED_10baseT_Full | 3638c2ecf20Sopenharmony_ci ADVERTISED_100baseT_Half | 3648c2ecf20Sopenharmony_ci ADVERTISED_100baseT_Full | 3658c2ecf20Sopenharmony_ci ADVERTISED_1000baseT_Half | 3668c2ecf20Sopenharmony_ci ADVERTISED_1000baseT_Full)) == 0) 3678c2ecf20Sopenharmony_ci return -EINVAL; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci /* advertise only what has been requested */ 3708c2ecf20Sopenharmony_ci advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); 3718c2ecf20Sopenharmony_ci tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4); 3728c2ecf20Sopenharmony_ci if (mii->supports_gmii) { 3738c2ecf20Sopenharmony_ci advert2 = mii->mdio_read(dev, mii->phy_id, 3748c2ecf20Sopenharmony_ci MII_CTRL1000); 3758c2ecf20Sopenharmony_ci tmp2 = advert2 & 3768c2ecf20Sopenharmony_ci ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci tmp |= ethtool_adv_to_mii_adv_t(advertising); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci if (mii->supports_gmii) 3818c2ecf20Sopenharmony_ci tmp2 |= ethtool_adv_to_mii_ctrl1000_t(advertising); 3828c2ecf20Sopenharmony_ci if (advert != tmp) { 3838c2ecf20Sopenharmony_ci mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp); 3848c2ecf20Sopenharmony_ci mii->advertising = tmp; 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci if ((mii->supports_gmii) && (advert2 != tmp2)) 3878c2ecf20Sopenharmony_ci mii->mdio_write(dev, mii->phy_id, MII_CTRL1000, tmp2); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci /* turn on autonegotiation, and force a renegotiate */ 3908c2ecf20Sopenharmony_ci bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); 3918c2ecf20Sopenharmony_ci bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); 3928c2ecf20Sopenharmony_ci mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci mii->force_media = 0; 3958c2ecf20Sopenharmony_ci } else { 3968c2ecf20Sopenharmony_ci u32 bmcr, tmp; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci /* turn off auto negotiation, set speed and duplexity */ 3998c2ecf20Sopenharmony_ci bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); 4008c2ecf20Sopenharmony_ci tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | 4018c2ecf20Sopenharmony_ci BMCR_SPEED1000 | BMCR_FULLDPLX); 4028c2ecf20Sopenharmony_ci if (speed == SPEED_1000) 4038c2ecf20Sopenharmony_ci tmp |= BMCR_SPEED1000; 4048c2ecf20Sopenharmony_ci else if (speed == SPEED_100) 4058c2ecf20Sopenharmony_ci tmp |= BMCR_SPEED100; 4068c2ecf20Sopenharmony_ci if (cmd->base.duplex == DUPLEX_FULL) { 4078c2ecf20Sopenharmony_ci tmp |= BMCR_FULLDPLX; 4088c2ecf20Sopenharmony_ci mii->full_duplex = 1; 4098c2ecf20Sopenharmony_ci } else { 4108c2ecf20Sopenharmony_ci mii->full_duplex = 0; 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci if (bmcr != tmp) 4138c2ecf20Sopenharmony_ci mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci mii->force_media = 1; 4168c2ecf20Sopenharmony_ci } 4178c2ecf20Sopenharmony_ci return 0; 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci/** 4218c2ecf20Sopenharmony_ci * mii_check_gmii_support - check if the MII supports Gb interfaces 4228c2ecf20Sopenharmony_ci * @mii: the MII interface 4238c2ecf20Sopenharmony_ci */ 4248c2ecf20Sopenharmony_ciint mii_check_gmii_support(struct mii_if_info *mii) 4258c2ecf20Sopenharmony_ci{ 4268c2ecf20Sopenharmony_ci int reg; 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci reg = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); 4298c2ecf20Sopenharmony_ci if (reg & BMSR_ESTATEN) { 4308c2ecf20Sopenharmony_ci reg = mii->mdio_read(mii->dev, mii->phy_id, MII_ESTATUS); 4318c2ecf20Sopenharmony_ci if (reg & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF)) 4328c2ecf20Sopenharmony_ci return 1; 4338c2ecf20Sopenharmony_ci } 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci return 0; 4368c2ecf20Sopenharmony_ci} 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci/** 4398c2ecf20Sopenharmony_ci * mii_link_ok - is link status up/ok 4408c2ecf20Sopenharmony_ci * @mii: the MII interface 4418c2ecf20Sopenharmony_ci * 4428c2ecf20Sopenharmony_ci * Returns 1 if the MII reports link status up/ok, 0 otherwise. 4438c2ecf20Sopenharmony_ci */ 4448c2ecf20Sopenharmony_ciint mii_link_ok (struct mii_if_info *mii) 4458c2ecf20Sopenharmony_ci{ 4468c2ecf20Sopenharmony_ci /* first, a dummy read, needed to latch some MII phys */ 4478c2ecf20Sopenharmony_ci mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); 4488c2ecf20Sopenharmony_ci if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS) 4498c2ecf20Sopenharmony_ci return 1; 4508c2ecf20Sopenharmony_ci return 0; 4518c2ecf20Sopenharmony_ci} 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci/** 4548c2ecf20Sopenharmony_ci * mii_nway_restart - restart NWay (autonegotiation) for this interface 4558c2ecf20Sopenharmony_ci * @mii: the MII interface 4568c2ecf20Sopenharmony_ci * 4578c2ecf20Sopenharmony_ci * Returns 0 on success, negative on error. 4588c2ecf20Sopenharmony_ci */ 4598c2ecf20Sopenharmony_ciint mii_nway_restart (struct mii_if_info *mii) 4608c2ecf20Sopenharmony_ci{ 4618c2ecf20Sopenharmony_ci int bmcr; 4628c2ecf20Sopenharmony_ci int r = -EINVAL; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci /* if autoneg is off, it's an error */ 4658c2ecf20Sopenharmony_ci bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR); 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci if (bmcr & BMCR_ANENABLE) { 4688c2ecf20Sopenharmony_ci bmcr |= BMCR_ANRESTART; 4698c2ecf20Sopenharmony_ci mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr); 4708c2ecf20Sopenharmony_ci r = 0; 4718c2ecf20Sopenharmony_ci } 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci return r; 4748c2ecf20Sopenharmony_ci} 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci/** 4778c2ecf20Sopenharmony_ci * mii_check_link - check MII link status 4788c2ecf20Sopenharmony_ci * @mii: MII interface 4798c2ecf20Sopenharmony_ci * 4808c2ecf20Sopenharmony_ci * If the link status changed (previous != current), call 4818c2ecf20Sopenharmony_ci * netif_carrier_on() if current link status is Up or call 4828c2ecf20Sopenharmony_ci * netif_carrier_off() if current link status is Down. 4838c2ecf20Sopenharmony_ci */ 4848c2ecf20Sopenharmony_civoid mii_check_link (struct mii_if_info *mii) 4858c2ecf20Sopenharmony_ci{ 4868c2ecf20Sopenharmony_ci int cur_link = mii_link_ok(mii); 4878c2ecf20Sopenharmony_ci int prev_link = netif_carrier_ok(mii->dev); 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci if (cur_link && !prev_link) 4908c2ecf20Sopenharmony_ci netif_carrier_on(mii->dev); 4918c2ecf20Sopenharmony_ci else if (prev_link && !cur_link) 4928c2ecf20Sopenharmony_ci netif_carrier_off(mii->dev); 4938c2ecf20Sopenharmony_ci} 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci/** 4968c2ecf20Sopenharmony_ci * mii_check_media - check the MII interface for a carrier/speed/duplex change 4978c2ecf20Sopenharmony_ci * @mii: the MII interface 4988c2ecf20Sopenharmony_ci * @ok_to_print: OK to print link up/down messages 4998c2ecf20Sopenharmony_ci * @init_media: OK to save duplex mode in @mii 5008c2ecf20Sopenharmony_ci * 5018c2ecf20Sopenharmony_ci * Returns 1 if the duplex mode changed, 0 if not. 5028c2ecf20Sopenharmony_ci * If the media type is forced, always returns 0. 5038c2ecf20Sopenharmony_ci */ 5048c2ecf20Sopenharmony_ciunsigned int mii_check_media (struct mii_if_info *mii, 5058c2ecf20Sopenharmony_ci unsigned int ok_to_print, 5068c2ecf20Sopenharmony_ci unsigned int init_media) 5078c2ecf20Sopenharmony_ci{ 5088c2ecf20Sopenharmony_ci unsigned int old_carrier, new_carrier; 5098c2ecf20Sopenharmony_ci int advertise, lpa, media, duplex; 5108c2ecf20Sopenharmony_ci int lpa2 = 0; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci /* check current and old link status */ 5138c2ecf20Sopenharmony_ci old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0; 5148c2ecf20Sopenharmony_ci new_carrier = (unsigned int) mii_link_ok(mii); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci /* if carrier state did not change, this is a "bounce", 5178c2ecf20Sopenharmony_ci * just exit as everything is already set correctly 5188c2ecf20Sopenharmony_ci */ 5198c2ecf20Sopenharmony_ci if ((!init_media) && (old_carrier == new_carrier)) 5208c2ecf20Sopenharmony_ci return 0; /* duplex did not change */ 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci /* no carrier, nothing much to do */ 5238c2ecf20Sopenharmony_ci if (!new_carrier) { 5248c2ecf20Sopenharmony_ci netif_carrier_off(mii->dev); 5258c2ecf20Sopenharmony_ci if (ok_to_print) 5268c2ecf20Sopenharmony_ci netdev_info(mii->dev, "link down\n"); 5278c2ecf20Sopenharmony_ci return 0; /* duplex did not change */ 5288c2ecf20Sopenharmony_ci } 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci /* 5318c2ecf20Sopenharmony_ci * we have carrier, see who's on the other end 5328c2ecf20Sopenharmony_ci */ 5338c2ecf20Sopenharmony_ci netif_carrier_on(mii->dev); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci if (mii->force_media) { 5368c2ecf20Sopenharmony_ci if (ok_to_print) 5378c2ecf20Sopenharmony_ci netdev_info(mii->dev, "link up\n"); 5388c2ecf20Sopenharmony_ci return 0; /* duplex did not change */ 5398c2ecf20Sopenharmony_ci } 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci /* get MII advertise and LPA values */ 5428c2ecf20Sopenharmony_ci if ((!init_media) && (mii->advertising)) 5438c2ecf20Sopenharmony_ci advertise = mii->advertising; 5448c2ecf20Sopenharmony_ci else { 5458c2ecf20Sopenharmony_ci advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE); 5468c2ecf20Sopenharmony_ci mii->advertising = advertise; 5478c2ecf20Sopenharmony_ci } 5488c2ecf20Sopenharmony_ci lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA); 5498c2ecf20Sopenharmony_ci if (mii->supports_gmii) 5508c2ecf20Sopenharmony_ci lpa2 = mii->mdio_read(mii->dev, mii->phy_id, MII_STAT1000); 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci /* figure out media and duplex from advertise and LPA values */ 5538c2ecf20Sopenharmony_ci media = mii_nway_result(lpa & advertise); 5548c2ecf20Sopenharmony_ci duplex = (media & ADVERTISE_FULL) ? 1 : 0; 5558c2ecf20Sopenharmony_ci if (lpa2 & LPA_1000FULL) 5568c2ecf20Sopenharmony_ci duplex = 1; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci if (ok_to_print) 5598c2ecf20Sopenharmony_ci netdev_info(mii->dev, "link up, %uMbps, %s-duplex, lpa 0x%04X\n", 5608c2ecf20Sopenharmony_ci lpa2 & (LPA_1000FULL | LPA_1000HALF) ? 1000 : 5618c2ecf20Sopenharmony_ci media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? 5628c2ecf20Sopenharmony_ci 100 : 10, 5638c2ecf20Sopenharmony_ci duplex ? "full" : "half", 5648c2ecf20Sopenharmony_ci lpa); 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci if ((init_media) || (mii->full_duplex != duplex)) { 5678c2ecf20Sopenharmony_ci mii->full_duplex = duplex; 5688c2ecf20Sopenharmony_ci return 1; /* duplex changed */ 5698c2ecf20Sopenharmony_ci } 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci return 0; /* duplex did not change */ 5728c2ecf20Sopenharmony_ci} 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci/** 5758c2ecf20Sopenharmony_ci * generic_mii_ioctl - main MII ioctl interface 5768c2ecf20Sopenharmony_ci * @mii_if: the MII interface 5778c2ecf20Sopenharmony_ci * @mii_data: MII ioctl data structure 5788c2ecf20Sopenharmony_ci * @cmd: MII ioctl command 5798c2ecf20Sopenharmony_ci * @duplex_chg_out: pointer to @duplex_changed status if there was no 5808c2ecf20Sopenharmony_ci * ioctl error 5818c2ecf20Sopenharmony_ci * 5828c2ecf20Sopenharmony_ci * Returns 0 on success, negative on error. 5838c2ecf20Sopenharmony_ci */ 5848c2ecf20Sopenharmony_ciint generic_mii_ioctl(struct mii_if_info *mii_if, 5858c2ecf20Sopenharmony_ci struct mii_ioctl_data *mii_data, int cmd, 5868c2ecf20Sopenharmony_ci unsigned int *duplex_chg_out) 5878c2ecf20Sopenharmony_ci{ 5888c2ecf20Sopenharmony_ci int rc = 0; 5898c2ecf20Sopenharmony_ci unsigned int duplex_changed = 0; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci if (duplex_chg_out) 5928c2ecf20Sopenharmony_ci *duplex_chg_out = 0; 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci mii_data->phy_id &= mii_if->phy_id_mask; 5958c2ecf20Sopenharmony_ci mii_data->reg_num &= mii_if->reg_num_mask; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci switch(cmd) { 5988c2ecf20Sopenharmony_ci case SIOCGMIIPHY: 5998c2ecf20Sopenharmony_ci mii_data->phy_id = mii_if->phy_id; 6008c2ecf20Sopenharmony_ci fallthrough; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci case SIOCGMIIREG: 6038c2ecf20Sopenharmony_ci mii_data->val_out = 6048c2ecf20Sopenharmony_ci mii_if->mdio_read(mii_if->dev, mii_data->phy_id, 6058c2ecf20Sopenharmony_ci mii_data->reg_num); 6068c2ecf20Sopenharmony_ci break; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci case SIOCSMIIREG: { 6098c2ecf20Sopenharmony_ci u16 val = mii_data->val_in; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci if (mii_data->phy_id == mii_if->phy_id) { 6128c2ecf20Sopenharmony_ci switch(mii_data->reg_num) { 6138c2ecf20Sopenharmony_ci case MII_BMCR: { 6148c2ecf20Sopenharmony_ci unsigned int new_duplex = 0; 6158c2ecf20Sopenharmony_ci if (val & (BMCR_RESET|BMCR_ANENABLE)) 6168c2ecf20Sopenharmony_ci mii_if->force_media = 0; 6178c2ecf20Sopenharmony_ci else 6188c2ecf20Sopenharmony_ci mii_if->force_media = 1; 6198c2ecf20Sopenharmony_ci if (mii_if->force_media && 6208c2ecf20Sopenharmony_ci (val & BMCR_FULLDPLX)) 6218c2ecf20Sopenharmony_ci new_duplex = 1; 6228c2ecf20Sopenharmony_ci if (mii_if->full_duplex != new_duplex) { 6238c2ecf20Sopenharmony_ci duplex_changed = 1; 6248c2ecf20Sopenharmony_ci mii_if->full_duplex = new_duplex; 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci break; 6278c2ecf20Sopenharmony_ci } 6288c2ecf20Sopenharmony_ci case MII_ADVERTISE: 6298c2ecf20Sopenharmony_ci mii_if->advertising = val; 6308c2ecf20Sopenharmony_ci break; 6318c2ecf20Sopenharmony_ci default: 6328c2ecf20Sopenharmony_ci /* do nothing */ 6338c2ecf20Sopenharmony_ci break; 6348c2ecf20Sopenharmony_ci } 6358c2ecf20Sopenharmony_ci } 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci mii_if->mdio_write(mii_if->dev, mii_data->phy_id, 6388c2ecf20Sopenharmony_ci mii_data->reg_num, val); 6398c2ecf20Sopenharmony_ci break; 6408c2ecf20Sopenharmony_ci } 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci default: 6438c2ecf20Sopenharmony_ci rc = -EOPNOTSUPP; 6448c2ecf20Sopenharmony_ci break; 6458c2ecf20Sopenharmony_ci } 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci if ((rc == 0) && (duplex_chg_out) && (duplex_changed)) 6488c2ecf20Sopenharmony_ci *duplex_chg_out = 1; 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci return rc; 6518c2ecf20Sopenharmony_ci} 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ciMODULE_AUTHOR ("Jeff Garzik <jgarzik@pobox.com>"); 6548c2ecf20Sopenharmony_ciMODULE_DESCRIPTION ("MII hardware support library"); 6558c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mii_link_ok); 6588c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mii_nway_restart); 6598c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mii_ethtool_gset); 6608c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mii_ethtool_get_link_ksettings); 6618c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mii_ethtool_sset); 6628c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mii_ethtool_set_link_ksettings); 6638c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mii_check_link); 6648c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mii_check_media); 6658c2ecf20Sopenharmony_ciEXPORT_SYMBOL(mii_check_gmii_support); 6668c2ecf20Sopenharmony_ciEXPORT_SYMBOL(generic_mii_ioctl); 6678c2ecf20Sopenharmony_ci 668