mii_physubr.c revision 128870
150120Swpaul/* $NetBSD: mii_physubr.c,v 1.5 1999/08/03 19:41:49 drochner Exp $ */ 250120Swpaul 350120Swpaul/*- 495718Sphk * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. 550120Swpaul * All rights reserved. 650120Swpaul * 750120Swpaul * This code is derived from software contributed to The NetBSD Foundation 850120Swpaul * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 950120Swpaul * NASA Ames Research Center. 1050120Swpaul * 1150120Swpaul * Redistribution and use in source and binary forms, with or without 1250120Swpaul * modification, are permitted provided that the following conditions 1350120Swpaul * are met: 1450120Swpaul * 1. Redistributions of source code must retain the above copyright 1550120Swpaul * notice, this list of conditions and the following disclaimer. 1650120Swpaul * 2. Redistributions in binary form must reproduce the above copyright 1750120Swpaul * notice, this list of conditions and the following disclaimer in the 1850120Swpaul * documentation and/or other materials provided with the distribution. 1950120Swpaul * 3. All advertising materials mentioning features or use of this software 2050120Swpaul * must display the following acknowledgement: 2150120Swpaul * This product includes software developed by the NetBSD 2250120Swpaul * Foundation, Inc. and its contributors. 2350120Swpaul * 4. Neither the name of The NetBSD Foundation nor the names of its 2450120Swpaul * contributors may be used to endorse or promote products derived 2550120Swpaul * from this software without specific prior written permission. 2650120Swpaul * 2750120Swpaul * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2850120Swpaul * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2950120Swpaul * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 3050120Swpaul * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 3150120Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 3250120Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 3350120Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3450120Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3550120Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3650120Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3750120Swpaul * POSSIBILITY OF SUCH DAMAGE. 3850120Swpaul */ 3950120Swpaul 40119418Sobrien#include <sys/cdefs.h> 41119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/mii/mii_physubr.c 128870 2004-05-03 13:01:34Z andre $"); 42119418Sobrien 4350120Swpaul/* 4450120Swpaul * Subroutines common to all PHYs. 4550120Swpaul */ 4650120Swpaul 47113038Sobrien#include <sys/cdefs.h> 48113038Sobrien__FBSDID("$FreeBSD: head/sys/dev/mii/mii_physubr.c 128870 2004-05-03 13:01:34Z andre $"); 49113038Sobrien 5050120Swpaul#include <sys/param.h> 5150120Swpaul#include <sys/systm.h> 5250120Swpaul#include <sys/kernel.h> 5350120Swpaul#include <sys/socket.h> 5450120Swpaul#include <sys/errno.h> 5550120Swpaul#include <sys/module.h> 5650120Swpaul#include <sys/bus.h> 5750120Swpaul 5850120Swpaul 5950120Swpaul#include <net/if.h> 6050120Swpaul#include <net/if_media.h> 6150120Swpaul 6250120Swpaul#include <dev/mii/mii.h> 6350120Swpaul#include <dev/mii/miivar.h> 6450120Swpaul 6550120Swpaul#include "miibus_if.h" 6650120Swpaul 6795707Sphk/* 6895707Sphk * Media to register setting conversion table. Order matters. 6995707Sphk */ 7095707Sphkconst struct mii_media mii_media_table[MII_NMEDIA] = { 7195707Sphk /* None */ 7295707Sphk { BMCR_ISO, ANAR_CSMA, 7395707Sphk 0, }, 7495707Sphk 7595707Sphk /* 10baseT */ 7695707Sphk { BMCR_S10, ANAR_CSMA|ANAR_10, 7795707Sphk 0, }, 7895707Sphk 7995707Sphk /* 10baseT-FDX */ 8095707Sphk { BMCR_S10|BMCR_FDX, ANAR_CSMA|ANAR_10_FD, 8195707Sphk 0, }, 8295707Sphk 8395707Sphk /* 100baseT4 */ 8495707Sphk { BMCR_S100, ANAR_CSMA|ANAR_T4, 8595707Sphk 0, }, 8695707Sphk 8795707Sphk /* 100baseTX */ 8895707Sphk { BMCR_S100, ANAR_CSMA|ANAR_TX, 8995707Sphk 0, }, 9095707Sphk 9195707Sphk /* 100baseTX-FDX */ 9295707Sphk { BMCR_S100|BMCR_FDX, ANAR_CSMA|ANAR_TX_FD, 9395707Sphk 0, }, 9495707Sphk 9595707Sphk /* 1000baseX */ 9695707Sphk { BMCR_S1000, ANAR_CSMA, 9795707Sphk 0, }, 9895707Sphk 9995707Sphk /* 1000baseX-FDX */ 10095707Sphk { BMCR_S1000|BMCR_FDX, ANAR_CSMA, 10195707Sphk 0, }, 10295707Sphk 10395707Sphk /* 1000baseT */ 10495707Sphk { BMCR_S1000, ANAR_CSMA, 10595707Sphk GTCR_ADV_1000THDX }, 10695707Sphk 10795707Sphk /* 1000baseT-FDX */ 10895707Sphk { BMCR_S1000, ANAR_CSMA, 10995707Sphk GTCR_ADV_1000TFDX }, 11095707Sphk}; 11195707Sphk 11295707Sphkvoid 11395707Sphkmii_phy_setmedia(struct mii_softc *sc) 11495707Sphk{ 11595707Sphk struct mii_data *mii = sc->mii_pdata; 11695707Sphk struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 11795707Sphk int bmcr, anar, gtcr; 11895707Sphk 11995707Sphk if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { 12095707Sphk if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0) 12196026Sphk (void) mii_phy_auto(sc); 12295707Sphk return; 12395707Sphk } 12495707Sphk 12595707Sphk /* 12695707Sphk * Table index is stored in the media entry. 12795707Sphk */ 12895707Sphk 12995718Sphk KASSERT(ife->ifm_data >=0 && ife->ifm_data < MII_NMEDIA, 13095718Sphk ("invalid ife->ifm_data (0x%x) in mii_phy_setmedia", 13195718Sphk ife->ifm_data)); 13295707Sphk 13395707Sphk anar = mii_media_table[ife->ifm_data].mm_anar; 13495707Sphk bmcr = mii_media_table[ife->ifm_data].mm_bmcr; 13595707Sphk gtcr = mii_media_table[ife->ifm_data].mm_gtcr; 13695707Sphk 13795707Sphk if (mii->mii_media.ifm_media & IFM_ETH_MASTER) { 13895707Sphk switch (IFM_SUBTYPE(ife->ifm_media)) { 13995707Sphk case IFM_1000_T: 14095707Sphk gtcr |= GTCR_MAN_MS|GTCR_ADV_MS; 14195707Sphk break; 14295707Sphk 14395707Sphk default: 14495707Sphk panic("mii_phy_setmedia: MASTER on wrong media"); 14595707Sphk } 14695707Sphk } 14795707Sphk 14895707Sphk if (ife->ifm_media & IFM_LOOP) 14995707Sphk bmcr |= BMCR_LOOP; 15095707Sphk 15195707Sphk PHY_WRITE(sc, MII_ANAR, anar); 15295707Sphk PHY_WRITE(sc, MII_BMCR, bmcr); 15395707Sphk if (sc->mii_flags & MIIF_HAVE_GTCR) 15495707Sphk PHY_WRITE(sc, MII_100T2CR, gtcr); 15595707Sphk} 15695707Sphk 15750120Swpaulint 15896026Sphkmii_phy_auto(struct mii_softc *sc) 15950120Swpaul{ 16050120Swpaul 16196026Sphk /* 16296026Sphk * Check for 1000BASE-X. Autonegotiation is a bit 16396026Sphk * different on such devices. 16496026Sphk */ 16596026Sphk if (sc->mii_flags & MIIF_IS_1000X) { 16696026Sphk uint16_t anar = 0; 16795718Sphk 16896026Sphk if (sc->mii_extcapabilities & EXTSR_1000XFDX) 16996026Sphk anar |= ANAR_X_FD; 17096026Sphk if (sc->mii_extcapabilities & EXTSR_1000XHDX) 17196026Sphk anar |= ANAR_X_HD; 17295718Sphk 17396026Sphk if (sc->mii_flags & MIIF_DOPAUSE) { 17496026Sphk /* XXX Asymmetric vs. symmetric? */ 17596026Sphk anar |= ANLPAR_X_PAUSE_TOWARDS; 17696026Sphk } 17795718Sphk 17896026Sphk PHY_WRITE(sc, MII_ANAR, anar); 17996026Sphk } else { 18096026Sphk uint16_t anar; 18195718Sphk 18296026Sphk anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | 18396026Sphk ANAR_CSMA; 18496026Sphk if (sc->mii_flags & MIIF_DOPAUSE) 18596026Sphk anar |= ANAR_FC; 18696026Sphk PHY_WRITE(sc, MII_ANAR, anar); 18796026Sphk if (sc->mii_flags & MIIF_HAVE_GTCR) { 18896026Sphk uint16_t gtcr = 0; 18995718Sphk 19096026Sphk if (sc->mii_extcapabilities & EXTSR_1000TFDX) 19196026Sphk gtcr |= GTCR_ADV_1000TFDX; 19296026Sphk if (sc->mii_extcapabilities & EXTSR_1000THDX) 19396026Sphk gtcr |= GTCR_ADV_1000THDX; 19495718Sphk 19596026Sphk PHY_WRITE(sc, MII_100T2CR, gtcr); 19695718Sphk } 19750120Swpaul } 19896026Sphk PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); 19950120Swpaul return (EJUSTRETURN); 20050120Swpaul} 20150120Swpaul 20284140Sjlemonint 20395718Sphkmii_phy_tick(struct mii_softc *sc) 20484140Sjlemon{ 20584140Sjlemon struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur; 20684140Sjlemon struct ifnet *ifp = sc->mii_pdata->mii_ifp; 20784140Sjlemon int reg; 20884140Sjlemon 20995718Sphk /* Just bail now if the interface is down. */ 21084140Sjlemon if ((ifp->if_flags & IFF_UP) == 0) 21184140Sjlemon return (EJUSTRETURN); 21284140Sjlemon 21384140Sjlemon /* 21484140Sjlemon * If we're not doing autonegotiation, we don't need to do 21584140Sjlemon * any extra work here. However, we need to check the link 21684140Sjlemon * status so we can generate an announcement if the status 21784140Sjlemon * changes. 21884140Sjlemon */ 21984140Sjlemon if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) 22084140Sjlemon return (0); 22184140Sjlemon 22295718Sphk /* Read the status register twice; BMSR_LINK is latch-low. */ 22384140Sjlemon reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 22495718Sphk if (reg & BMSR_LINK) { 22595718Sphk /* 22695718Sphk * See above. 22795718Sphk */ 22884140Sjlemon return (0); 22995718Sphk } 23084140Sjlemon 23184140Sjlemon /* 23295718Sphk * Only retry autonegotiation every N seconds. 23384140Sjlemon */ 234128870Sandre if (sc->mii_anegticks == 0) { 23596027Sphk sc->mii_anegticks = 17; 236128870Sandre return (0); 237128870Sandre } 238128870Sandre if (++sc->mii_ticks <= sc->mii_anegticks) 23984140Sjlemon return (EJUSTRETURN); 24084140Sjlemon 24184140Sjlemon sc->mii_ticks = 0; 24284140Sjlemon mii_phy_reset(sc); 24396026Sphk mii_phy_auto(sc); 24484140Sjlemon return (0); 24584140Sjlemon} 24684140Sjlemon 24750120Swpaulvoid 24895718Sphkmii_phy_reset(struct mii_softc *sc) 24950120Swpaul{ 25050120Swpaul int reg, i; 25150120Swpaul 25295718Sphk if (sc->mii_flags & MIIF_NOISOLATE) 25350120Swpaul reg = BMCR_RESET; 25450120Swpaul else 25550120Swpaul reg = BMCR_RESET | BMCR_ISO; 25695718Sphk PHY_WRITE(sc, MII_BMCR, reg); 25750120Swpaul 25850120Swpaul /* Wait 100ms for it to complete. */ 25950120Swpaul for (i = 0; i < 100; i++) { 26095718Sphk reg = PHY_READ(sc, MII_BMCR); 26150120Swpaul if ((reg & BMCR_RESET) == 0) 26250120Swpaul break; 26350120Swpaul DELAY(1000); 26450120Swpaul } 26550120Swpaul 26695718Sphk if (sc->mii_inst != 0 && ((sc->mii_flags & MIIF_NOISOLATE) == 0)) 26795718Sphk PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 26850120Swpaul} 26950120Swpaul 27084140Sjlemonvoid 27195722Sphkmii_phy_down(struct mii_softc *sc) 27284140Sjlemon{ 27395722Sphk 27495722Sphk} 27595722Sphk 27695722Sphkvoid 27795722Sphkmii_phy_update(struct mii_softc *sc, int cmd) 27895722Sphk{ 27984140Sjlemon struct mii_data *mii = sc->mii_pdata; 28084140Sjlemon 28195722Sphk if (sc->mii_media_active != mii->mii_media_active || 28295722Sphk cmd == MII_MEDIACHG) { 28384140Sjlemon MIIBUS_STATCHG(sc->mii_dev); 28495705Sphk sc->mii_media_active = mii->mii_media_active; 28584140Sjlemon } 28695705Sphk if (sc->mii_media_status != mii->mii_media_status) { 28784140Sjlemon MIIBUS_LINKCHG(sc->mii_dev); 28895705Sphk sc->mii_media_status = mii->mii_media_status; 28984140Sjlemon } 29084140Sjlemon} 29184140Sjlemon 29250120Swpaul/* 29350120Swpaul * Given an ifmedia word, return the corresponding ANAR value. 29450120Swpaul */ 29550120Swpaulint 29650120Swpaulmii_anar(media) 29750120Swpaul int media; 29850120Swpaul{ 29950120Swpaul int rv; 30050120Swpaul 30150120Swpaul switch (media & (IFM_TMASK|IFM_NMASK|IFM_FDX)) { 30250120Swpaul case IFM_ETHER|IFM_10_T: 30350120Swpaul rv = ANAR_10|ANAR_CSMA; 30450120Swpaul break; 30550120Swpaul case IFM_ETHER|IFM_10_T|IFM_FDX: 30650120Swpaul rv = ANAR_10_FD|ANAR_CSMA; 30750120Swpaul break; 30850120Swpaul case IFM_ETHER|IFM_100_TX: 30950120Swpaul rv = ANAR_TX|ANAR_CSMA; 31050120Swpaul break; 31150120Swpaul case IFM_ETHER|IFM_100_TX|IFM_FDX: 31250120Swpaul rv = ANAR_TX_FD|ANAR_CSMA; 31350120Swpaul break; 31450120Swpaul case IFM_ETHER|IFM_100_T4: 31550120Swpaul rv = ANAR_T4|ANAR_CSMA; 31650120Swpaul break; 31750120Swpaul default: 31850120Swpaul rv = 0; 31950120Swpaul break; 32050120Swpaul } 32150120Swpaul 32250120Swpaul return (rv); 32350120Swpaul} 32450120Swpaul 32550120Swpaul/* 32650120Swpaul * Given a BMCR value, return the corresponding ifmedia word. 32750120Swpaul */ 32850120Swpaulint 32950120Swpaulmii_media_from_bmcr(bmcr) 33050120Swpaul int bmcr; 33150120Swpaul{ 33250120Swpaul int rv = IFM_ETHER; 33350120Swpaul 33450120Swpaul if (bmcr & BMCR_S100) 33550120Swpaul rv |= IFM_100_TX; 33650120Swpaul else 33750120Swpaul rv |= IFM_10_T; 33850120Swpaul if (bmcr & BMCR_FDX) 33950120Swpaul rv |= IFM_FDX; 34050120Swpaul 34150120Swpaul return (rv); 34250120Swpaul} 34350120Swpaul 34450120Swpaul/* 34550120Swpaul * Initialize generic PHY media based on BMSR, called when a PHY is 34650120Swpaul * attached. We expect to be set up to print a comma-separated list 34750120Swpaul * of media names. Does not print a newline. 34850120Swpaul */ 34950120Swpaulvoid 35095667Sphkmii_add_media(struct mii_softc *sc) 35150120Swpaul{ 35250120Swpaul const char *sep = ""; 35395667Sphk struct mii_data *mii; 35450120Swpaul 35595667Sphk mii = device_get_softc(sc->mii_dev); 35695707Sphk if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) { 35795665Sphk printf("no media present"); 35895665Sphk return; 35995665Sphk } 36095665Sphk 36150120Swpaul#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) 36250120Swpaul#define PRINT(s) printf("%s%s", sep, s); sep = ", " 36350120Swpaul 36495707Sphk if (sc->mii_capabilities & BMSR_10THDX) { 36595707Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst), 0); 36650120Swpaul PRINT("10baseT"); 36750120Swpaul } 36895707Sphk if (sc->mii_capabilities & BMSR_10TFDX) { 36995707Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst), 37050120Swpaul BMCR_FDX); 37150120Swpaul PRINT("10baseT-FDX"); 37250120Swpaul } 37395707Sphk if (sc->mii_capabilities & BMSR_100TXHDX) { 37495707Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst), 37550120Swpaul BMCR_S100); 37650120Swpaul PRINT("100baseTX"); 37750120Swpaul } 37895707Sphk if (sc->mii_capabilities & BMSR_100TXFDX) { 37995707Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst), 38050120Swpaul BMCR_S100|BMCR_FDX); 38150120Swpaul PRINT("100baseTX-FDX"); 38250120Swpaul } 38395707Sphk if (sc->mii_capabilities & BMSR_100T4) { 38450120Swpaul /* 38550120Swpaul * XXX How do you enable 100baseT4? I assume we set 38650120Swpaul * XXX BMCR_S100 and then assume the PHYs will take 38750120Swpaul * XXX watever action is necessary to switch themselves 38850120Swpaul * XXX into T4 mode. 38950120Swpaul */ 39095707Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst), 39150120Swpaul BMCR_S100); 39250120Swpaul PRINT("100baseT4"); 39350120Swpaul } 39495707Sphk if (sc->mii_capabilities & BMSR_ANEG) { 39595707Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 39650120Swpaul BMCR_AUTOEN); 39750120Swpaul PRINT("auto"); 39850120Swpaul } 39995667Sphk 40095667Sphk 40195667Sphk 40250120Swpaul#undef ADD 40350120Swpaul#undef PRINT 40450120Swpaul} 40595718Sphk 40695718Sphk/* 40795718Sphk * Initialize generic PHY media based on BMSR, called when a PHY is 40895718Sphk * attached. We expect to be set up to print a comma-separated list 40995718Sphk * of media names. Does not print a newline. 41095718Sphk */ 41195718Sphkvoid 41295718Sphkmii_phy_add_media(struct mii_softc *sc) 41395718Sphk{ 41495718Sphk struct mii_data *mii = sc->mii_pdata; 41595718Sphk const char *sep = ""; 41695718Sphk 41795718Sphk#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) 41895718Sphk#define PRINT(s) printf("%s%s", sep, s); sep = ", " 41995718Sphk 42095718Sphk if ((sc->mii_flags & MIIF_NOISOLATE) == 0) 42195718Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), 42295718Sphk MII_MEDIA_NONE); 42395718Sphk 42495718Sphk /* 42595718Sphk * There are different interpretations for the bits in 42695718Sphk * HomePNA PHYs. And there is really only one media type 42795718Sphk * that is supported. 42895718Sphk */ 42995718Sphk if (sc->mii_flags & MIIF_IS_HPNA) { 43095718Sphk if (sc->mii_capabilities & BMSR_10THDX) { 43195718Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0, 43295718Sphk sc->mii_inst), 43395718Sphk MII_MEDIA_10_T); 43495718Sphk PRINT("HomePNA1"); 43595718Sphk } 43695718Sphk return; 43795718Sphk } 43895718Sphk 43995718Sphk if (sc->mii_capabilities & BMSR_10THDX) { 44095718Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst), 44195718Sphk MII_MEDIA_10_T); 44295718Sphk PRINT("10baseT"); 44395718Sphk } 44495718Sphk if (sc->mii_capabilities & BMSR_10TFDX) { 44595718Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst), 44695718Sphk MII_MEDIA_10_T_FDX); 44795718Sphk PRINT("10baseT-FDX"); 44895718Sphk } 44995718Sphk if (sc->mii_capabilities & BMSR_100TXHDX) { 45095718Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst), 45195718Sphk MII_MEDIA_100_TX); 45295718Sphk PRINT("100baseTX"); 45395718Sphk } 45495718Sphk if (sc->mii_capabilities & BMSR_100TXFDX) { 45595718Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst), 45695718Sphk MII_MEDIA_100_TX_FDX); 45795718Sphk PRINT("100baseTX-FDX"); 45895718Sphk } 45995718Sphk if (sc->mii_capabilities & BMSR_100T4) { 46095718Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst), 46195718Sphk MII_MEDIA_100_T4); 46295718Sphk PRINT("100baseT4"); 46395718Sphk } 46495718Sphk 46595718Sphk if (sc->mii_extcapabilities & EXTSR_MEDIAMASK) { 46695718Sphk /* 46795718Sphk * XXX Right now only handle 1000SX and 1000TX. Need 46895718Sphk * XXX to handle 1000LX and 1000CX some how. 46995718Sphk * 47095718Sphk * Note since it can take 5 seconds to auto-negotiate 47195718Sphk * a gigabit link, we make anegticks 10 seconds for 47295718Sphk * all the gigabit media types. 47395718Sphk */ 47495718Sphk if (sc->mii_extcapabilities & EXTSR_1000XHDX) { 47596027Sphk sc->mii_anegticks = 17; 47695718Sphk sc->mii_flags |= MIIF_IS_1000X; 47795718Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, 0, 47895718Sphk sc->mii_inst), MII_MEDIA_1000_X); 47995718Sphk PRINT("1000baseSX"); 48095718Sphk } 48195718Sphk if (sc->mii_extcapabilities & EXTSR_1000XFDX) { 48296027Sphk sc->mii_anegticks = 17; 48395718Sphk sc->mii_flags |= MIIF_IS_1000X; 48495718Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, 48595718Sphk sc->mii_inst), MII_MEDIA_1000_X_FDX); 48695718Sphk PRINT("1000baseSX-FDX"); 48795718Sphk } 48895718Sphk 48995718Sphk /* 49095718Sphk * 1000baseT media needs to be able to manipulate 49195718Sphk * master/slave mode. We set IFM_ETH_MASTER in 49295718Sphk * the "don't care mask" and filter it out when 49395718Sphk * the media is set. 49495718Sphk * 49595718Sphk * All 1000baseT PHYs have a 1000baseT control register. 49695718Sphk */ 49795718Sphk if (sc->mii_extcapabilities & EXTSR_1000THDX) { 49896027Sphk sc->mii_anegticks = 17; 49995718Sphk sc->mii_flags |= MIIF_HAVE_GTCR; 50095718Sphk mii->mii_media.ifm_mask |= IFM_ETH_MASTER; 50195718Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, 50295718Sphk sc->mii_inst), MII_MEDIA_1000_T); 50395718Sphk PRINT("1000baseT"); 50495718Sphk } 50595718Sphk if (sc->mii_extcapabilities & EXTSR_1000TFDX) { 50696027Sphk sc->mii_anegticks = 17; 50795718Sphk sc->mii_flags |= MIIF_HAVE_GTCR; 50895718Sphk mii->mii_media.ifm_mask |= IFM_ETH_MASTER; 50995718Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, 51095718Sphk sc->mii_inst), MII_MEDIA_1000_T_FDX); 51195718Sphk PRINT("1000baseT-FDX"); 51295718Sphk } 51395718Sphk } 51495718Sphk 51595718Sphk if (sc->mii_capabilities & BMSR_ANEG) { 51695718Sphk ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 51795718Sphk MII_NMEDIA); /* intentionally invalid index */ 51895718Sphk PRINT("auto"); 51995718Sphk } 52095718Sphk#undef ADD 52195718Sphk#undef PRINT 52295718Sphk} 52395718Sphk 52495722Sphkint 52595722Sphkmii_phy_detach(device_t dev) 52695722Sphk{ 52795722Sphk struct mii_softc *sc; 52895722Sphk 52995722Sphk sc = device_get_softc(dev); 53095722Sphk mii_phy_down(sc); 53195722Sphk sc->mii_dev = NULL; 53295722Sphk LIST_REMOVE(sc, mii_list); 53395722Sphk 53495722Sphk return(0); 53595722Sphk} 53695724Sphk 53795724Sphkconst struct mii_phydesc * 53895724Sphkmii_phy_match(const struct mii_attach_args *ma, const struct mii_phydesc *mpd) 53995724Sphk{ 54095724Sphk 54195724Sphk for (; mpd->mpd_name != NULL; mpd++) { 54295724Sphk if (MII_OUI(ma->mii_id1, ma->mii_id2) == mpd->mpd_oui && 54395724Sphk MII_MODEL(ma->mii_id2) == mpd->mpd_model) 54495724Sphk return (mpd); 54595724Sphk } 54695724Sphk return (NULL); 54795724Sphk} 548