diff options
-rw-r--r-- | sys/dev/mii/inphy.c | 27 | ||||
-rw-r--r-- | sys/dev/mii/mii.h | 2 | ||||
-rw-r--r-- | sys/dev/mii/mii_physubr.c | 244 | ||||
-rw-r--r-- | sys/dev/mii/miivar.h | 1 | ||||
-rw-r--r-- | sys/dev/mii/nsgphy.c | 255 | ||||
-rw-r--r-- | sys/dev/mii/nsgphyreg.h | 4 | ||||
-rw-r--r-- | sys/dev/nge/if_nge.c | 4 |
7 files changed, 247 insertions, 290 deletions
diff --git a/sys/dev/mii/inphy.c b/sys/dev/mii/inphy.c index 58e070f..6ad444a 100644 --- a/sys/dev/mii/inphy.c +++ b/sys/dev/mii/inphy.c @@ -144,7 +144,7 @@ inphy_attach(device_t dev) sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; device_printf(dev, " "); - mii_add_media(sc); + mii_phy_add_media(sc); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); @@ -192,27 +192,7 @@ inphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - switch (IFM_SUBTYPE(ife->ifm_media)) { - case IFM_AUTO: - /* - * If we're already in auto mode, just return. - */ - if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) - return (0); - (void) mii_phy_auto(sc, 0); - break; - case IFM_100_T4: - /* - * XXX Not supported as a manual setting right now. - */ - return (EINVAL); - default: - /* - * BMCR data is stored in the ifmedia entry. - */ - PHY_WRITE(sc, MII_ANAR, mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); - } + mii_phy_setmedia(sc); break; case MII_TICK: @@ -235,6 +215,7 @@ static void inphy_status(struct mii_softc *sc) { struct mii_data *mii = sc->mii_pdata; + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmsr, bmcr, scr; mii->mii_media_status = IFM_AVALID; @@ -268,5 +249,5 @@ inphy_status(struct mii_softc *sc) if (scr & SCR_FDX) mii->mii_media_active |= IFM_FDX; } else - mii->mii_media_active |= mii_media_from_bmcr(bmcr); + mii->mii_media_active = ife->ifm_media; } diff --git a/sys/dev/mii/mii.h b/sys/dev/mii/mii.h index d37fb5f..963c226 100644 --- a/sys/dev/mii/mii.h +++ b/sys/dev/mii/mii.h @@ -92,7 +92,7 @@ * info available in register 15, but 802.3 section 22.2.4.3 also * states that that all 1000 Mb/s capable PHYs will set this bit to 1. */ -#if 1 +#if 0 #define BMSR_MEDIAMASK (BMSR_100T4|BMSR_100TXFDX|BMSR_100TXHDX|BMSR_10TFDX| \ BMSR_10THDX|BMSR_ANEG) diff --git a/sys/dev/mii/mii_physubr.c b/sys/dev/mii/mii_physubr.c index 2bc17b0..c2b7a11 100644 --- a/sys/dev/mii/mii_physubr.c +++ b/sys/dev/mii/mii_physubr.c @@ -1,7 +1,7 @@ /* $NetBSD: mii_physubr.c,v 1.5 1999/08/03 19:41:49 drochner Exp $ */ /*- - * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. + * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -127,10 +127,9 @@ mii_phy_setmedia(struct mii_softc *sc) * Table index is stored in the media entry. */ -#ifdef DIAGNOSTIC - if (ife->ifm_data < 0 || ife->ifm_data >= MII_NMEDIA) - panic("mii_phy_setmedia"); -#endif + KASSERT(ife->ifm_data >=0 && ife->ifm_data < MII_NMEDIA, + ("invalid ife->ifm_data (0x%x) in mii_phy_setmedia", + ife->ifm_data)); anar = mii_media_table[ife->ifm_data].mm_anar; bmcr = mii_media_table[ife->ifm_data].mm_bmcr; @@ -157,29 +156,57 @@ mii_phy_setmedia(struct mii_softc *sc) } int -mii_phy_auto(mii, waitfor) - struct mii_softc *mii; - int waitfor; +mii_phy_auto(struct mii_softc *sc, int waitfor) { int bmsr, i; - if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) { - PHY_WRITE(mii, MII_ANAR, - BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA); - PHY_WRITE(mii, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); + if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) { + /* + * Check for 1000BASE-X. Autonegotiation is a bit + * different on such devices. + */ + if (sc->mii_flags & MIIF_IS_1000X) { + uint16_t anar = 0; + + if (sc->mii_extcapabilities & EXTSR_1000XFDX) + anar |= ANAR_X_FD; + if (sc->mii_extcapabilities & EXTSR_1000XHDX) + anar |= ANAR_X_HD; + + if (sc->mii_flags & MIIF_DOPAUSE) { + /* XXX Asymmetric vs. symmetric? */ + anar |= ANLPAR_X_PAUSE_TOWARDS; + } + + PHY_WRITE(sc, MII_ANAR, anar); + } else { + uint16_t anar; + + anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | + ANAR_CSMA; + if (sc->mii_flags & MIIF_DOPAUSE) + anar |= ANAR_FC; + PHY_WRITE(sc, MII_ANAR, anar); + if (sc->mii_flags & MIIF_HAVE_GTCR) { + uint16_t gtcr = 0; + + if (sc->mii_extcapabilities & EXTSR_1000TFDX) + gtcr |= GTCR_ADV_1000TFDX; + if (sc->mii_extcapabilities & EXTSR_1000THDX) + gtcr |= GTCR_ADV_1000THDX; + + PHY_WRITE(sc, MII_100T2CR, gtcr); + } + } + PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); } if (waitfor) { /* Wait 500ms for it to complete. */ for (i = 0; i < 500; i++) { - if ((bmsr = PHY_READ(mii, MII_BMSR)) & BMSR_ACOMP) + if ((bmsr = PHY_READ(sc, MII_BMSR)) & BMSR_ACOMP) return (0); DELAY(1000); -#if 0 - if ((bmsr & BMSR_ACOMP) == 0) - printf("%s: autonegotiation failed to complete\n", - mii->mii_dev.dv_xname); -#endif } /* @@ -195,9 +222,9 @@ mii_phy_auto(mii, waitfor) * the tick handler driving autonegotiation. Don't want 500ms * delays all the time while the system is running! */ - if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) { - mii->mii_flags |= MIIF_DOINGAUTO; - mii->mii_auto_ch = timeout(mii_phy_auto_timeout, mii, hz >> 1); + if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) { + sc->mii_flags |= MIIF_DOINGAUTO; + sc->mii_auto_ch = timeout(mii_phy_auto_timeout, sc, hz >> 1); } return (EJUSTRETURN); } @@ -213,37 +240,33 @@ mii_phy_auto_stop(sc) } void -mii_phy_auto_timeout(arg) - void *arg; +mii_phy_auto_timeout(void *arg) { - struct mii_softc *mii = arg; + struct mii_softc *sc = arg; int s, bmsr; - s = splnet(); - mii->mii_flags &= ~MIIF_DOINGAUTO; - bmsr = PHY_READ(mii, MII_BMSR); #if 0 - if ((bmsr & BMSR_ACOMP) == 0) - printf("%s: autonegotiation failed to complete\n", - sc->sc_dev.dv_xname); + if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0) + return; #endif + s = splnet(); + sc->mii_flags &= ~MIIF_DOINGAUTO; + bmsr = PHY_READ(sc, MII_BMSR); + /* Update the media status. */ - (void) (*mii->mii_service)(mii, mii->mii_pdata, MII_POLLSTAT); + (void) (*sc->mii_service)(sc, sc->mii_pdata, MII_POLLSTAT); splx(s); } int -mii_phy_tick(sc) - struct mii_softc *sc; +mii_phy_tick(struct mii_softc *sc) { struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur; struct ifnet *ifp = sc->mii_pdata->mii_ifp; int reg; - /* - * Is the interface even up? - */ + /* Just bail now if the interface is down. */ if ((ifp->if_flags & IFF_UP) == 0) return (EJUSTRETURN); @@ -256,18 +279,21 @@ mii_phy_tick(sc) if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) return (0); - /* - * check for link. - * Read the status register twice; BMSR_LINK is latch-low. - */ + /* Read the status register twice; BMSR_LINK is latch-low. */ reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); - if (reg & BMSR_LINK) + if (reg & BMSR_LINK) { + /* + * See above. + */ return (0); + } /* - * Only retry autonegotiation every 5 seconds. + * Only retry autonegotiation every N seconds. */ - if (++sc->mii_ticks != 5) + if (sc->mii_anegticks == 0) + sc->mii_anegticks = 5; + if (++sc->mii_ticks != sc->mii_anegticks) return (EJUSTRETURN); sc->mii_ticks = 0; @@ -283,27 +309,26 @@ mii_phy_tick(sc) } void -mii_phy_reset(mii) - struct mii_softc *mii; +mii_phy_reset(struct mii_softc *sc) { int reg, i; - if (mii->mii_flags & MIIF_NOISOLATE) + if (sc->mii_flags & MIIF_NOISOLATE) reg = BMCR_RESET; else reg = BMCR_RESET | BMCR_ISO; - PHY_WRITE(mii, MII_BMCR, reg); + PHY_WRITE(sc, MII_BMCR, reg); /* Wait 100ms for it to complete. */ for (i = 0; i < 100; i++) { - reg = PHY_READ(mii, MII_BMCR); + reg = PHY_READ(sc, MII_BMCR); if ((reg & BMCR_RESET) == 0) break; DELAY(1000); } - if (mii->mii_inst != 0 && ((mii->mii_flags & MIIF_NOISOLATE) == 0)) - PHY_WRITE(mii, MII_BMCR, reg | BMCR_ISO); + if (sc->mii_inst != 0 && ((sc->mii_flags & MIIF_NOISOLATE) == 0)) + PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); } void @@ -436,3 +461,122 @@ mii_add_media(struct mii_softc *sc) #undef ADD #undef PRINT } + +/* + * Initialize generic PHY media based on BMSR, called when a PHY is + * attached. We expect to be set up to print a comma-separated list + * of media names. Does not print a newline. + */ +void +mii_phy_add_media(struct mii_softc *sc) +{ + struct mii_data *mii = sc->mii_pdata; + const char *sep = ""; + +#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) +#define PRINT(s) printf("%s%s", sep, s); sep = ", " + + if ((sc->mii_flags & MIIF_NOISOLATE) == 0) + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), + MII_MEDIA_NONE); + + /* + * There are different interpretations for the bits in + * HomePNA PHYs. And there is really only one media type + * that is supported. + */ + if (sc->mii_flags & MIIF_IS_HPNA) { + if (sc->mii_capabilities & BMSR_10THDX) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0, + sc->mii_inst), + MII_MEDIA_10_T); + PRINT("HomePNA1"); + } + return; + } + + if (sc->mii_capabilities & BMSR_10THDX) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst), + MII_MEDIA_10_T); + PRINT("10baseT"); + } + if (sc->mii_capabilities & BMSR_10TFDX) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst), + MII_MEDIA_10_T_FDX); + PRINT("10baseT-FDX"); + } + if (sc->mii_capabilities & BMSR_100TXHDX) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst), + MII_MEDIA_100_TX); + PRINT("100baseTX"); + } + if (sc->mii_capabilities & BMSR_100TXFDX) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst), + MII_MEDIA_100_TX_FDX); + PRINT("100baseTX-FDX"); + } + if (sc->mii_capabilities & BMSR_100T4) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst), + MII_MEDIA_100_T4); + PRINT("100baseT4"); + } + + if (sc->mii_extcapabilities & EXTSR_MEDIAMASK) { + /* + * XXX Right now only handle 1000SX and 1000TX. Need + * XXX to handle 1000LX and 1000CX some how. + * + * Note since it can take 5 seconds to auto-negotiate + * a gigabit link, we make anegticks 10 seconds for + * all the gigabit media types. + */ + if (sc->mii_extcapabilities & EXTSR_1000XHDX) { + sc->mii_anegticks = 10; + sc->mii_flags |= MIIF_IS_1000X; + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, 0, + sc->mii_inst), MII_MEDIA_1000_X); + PRINT("1000baseSX"); + } + if (sc->mii_extcapabilities & EXTSR_1000XFDX) { + sc->mii_anegticks = 10; + sc->mii_flags |= MIIF_IS_1000X; + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, + sc->mii_inst), MII_MEDIA_1000_X_FDX); + PRINT("1000baseSX-FDX"); + } + + /* + * 1000baseT media needs to be able to manipulate + * master/slave mode. We set IFM_ETH_MASTER in + * the "don't care mask" and filter it out when + * the media is set. + * + * All 1000baseT PHYs have a 1000baseT control register. + */ + if (sc->mii_extcapabilities & EXTSR_1000THDX) { + sc->mii_anegticks = 10; + sc->mii_flags |= MIIF_HAVE_GTCR; + mii->mii_media.ifm_mask |= IFM_ETH_MASTER; + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, + sc->mii_inst), MII_MEDIA_1000_T); + PRINT("1000baseT"); + } + if (sc->mii_extcapabilities & EXTSR_1000TFDX) { + sc->mii_anegticks = 10; + sc->mii_flags |= MIIF_HAVE_GTCR; + mii->mii_media.ifm_mask |= IFM_ETH_MASTER; + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, + sc->mii_inst), MII_MEDIA_1000_T_FDX); + PRINT("1000baseT-FDX"); + } + } + + if (sc->mii_capabilities & BMSR_ANEG) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), + MII_NMEDIA); /* intentionally invalid index */ + PRINT("auto"); + } +#undef ADD +#undef PRINT +} + diff --git a/sys/dev/mii/miivar.h b/sys/dev/mii/miivar.h index 69668b0..bc214d9 100644 --- a/sys/dev/mii/miivar.h +++ b/sys/dev/mii/miivar.h @@ -197,6 +197,7 @@ void mii_tick(struct mii_data *); void mii_pollstat(struct mii_data *); int mii_phy_probe(device_t, device_t *, ifm_change_cb_t, ifm_stat_cb_t); void mii_add_media(struct mii_softc *); +void mii_phy_add_media(struct mii_softc *); int mii_media_from_bmcr(int); diff --git a/sys/dev/mii/nsgphy.c b/sys/dev/mii/nsgphy.c index adae9fb..0ee59ea 100644 --- a/sys/dev/mii/nsgphy.c +++ b/sys/dev/mii/nsgphy.c @@ -2,6 +2,12 @@ * Copyright (c) 2001 Wind River Systems * Copyright (c) 2001 * Bill Paul <wpaul@bsdi.com>. All rights reserved. + * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -97,7 +103,6 @@ DRIVER_MODULE(nsgphy, miibus, nsgphy_driver, nsgphy_devclass, 0, 0); static int nsgphy_service(struct mii_softc *, struct mii_data *,int); static void nsgphy_status(struct mii_softc *); -static int nsgphy_mii_phy_auto(struct mii_softc *, int); extern void mii_phy_auto_timeout(void *); static int @@ -127,7 +132,6 @@ nsgphy_attach(device_t dev) struct mii_softc *sc; struct mii_attach_args *ma; struct mii_data *mii; - const char *sep = ""; sc = device_get_softc(dev); ma = device_get_ivars(dev); @@ -139,48 +143,17 @@ nsgphy_attach(device_t dev) sc->mii_phy = ma->mii_phyno; sc->mii_service = nsgphy_service; sc->mii_pdata = mii; + sc->mii_anegticks = 5; - sc->mii_flags |= MIIF_NOISOLATE; mii->mii_instance++; -#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) -#define PRINT(s) printf("%s%s", sep, s); sep = ", " - - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), - BMCR_ISO); -#if 0 - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), - BMCR_LOOP|BMCR_S100); -#endif - - mii_phy_reset(sc); - - device_printf(dev, " "); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst), - BMCR_S1000|BMCR_FDX); - PRINT("1000baseTX-FDX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst), - BMCR_S1000); - PRINT("1000baseTX"); sc->mii_capabilities = (PHY_READ(sc, MII_BMSR) | (BMSR_10TFDX|BMSR_10THDX)) & ma->mii_capmask; if (sc->mii_capabilities & BMSR_EXTSTAT) sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst), - BMCR_S100|BMCR_FDX); - PRINT("100baseTX-FDX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst), BMCR_S100); - PRINT("100baseTX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst), - BMCR_S10|BMCR_FDX); - PRINT("10baseT-FDX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst), BMCR_S10); - PRINT("10baseT"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0); - PRINT("auto"); + + mii_phy_add_media(sc); printf("\n"); -#undef ADD -#undef PRINT MIIBUS_MEDIAINIT(sc->mii_dev); return(0); @@ -234,59 +207,7 @@ nsgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - - switch (IFM_SUBTYPE(ife->ifm_media)) { - case IFM_AUTO: -#ifdef foo - /* - * If we're already in auto mode, just return. - */ - if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) - return (0); -#endif - (void) nsgphy_mii_phy_auto(sc, 0); - break; - case IFM_1000_T: - if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) { - PHY_WRITE(sc, MII_BMCR, - BMCR_FDX|BMCR_SPEED1); - } else { - PHY_WRITE(sc, MII_BMCR, - BMCR_SPEED1); - } - PHY_WRITE(sc, MII_ANAR, ANAR_CSMA); - - /* - * When setting the link manually, one side must - * be the master and the other the slave. However - * ifmedia doesn't give us a good way to specify - * this, so we fake it by using one of the LINK - * flags. If LINK0 is set, we program the PHY to - * be a master, otherwise it's a slave. - */ - if ((mii->mii_ifp->if_flags & IFF_LINK0)) { - PHY_WRITE(sc, MII_100T2CR, - GTCR_MAN_MS|GTCR_ADV_MS); - } else { - PHY_WRITE(sc, MII_100T2CR, GTCR_MAN_MS); - } - break; - case IFM_100_T4: - /* - * XXX Not supported as a manual setting right now. - */ - return (EINVAL); - case IFM_NONE: - PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN); - break; - default: - /* - * BMCR data is stored in the ifmedia entry. - */ - PHY_WRITE(sc, MII_ANAR, mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); - break; - } + mii_phy_setmedia(sc); break; case MII_TICK: @@ -296,39 +217,8 @@ nsgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if (IFM_INST(ife->ifm_media) != sc->mii_inst) return (0); - /* - * Is the interface even up? - */ - if ((mii->mii_ifp->if_flags & IFF_UP) == 0) + if (mii_phy_tick(sc) == EJUSTRETURN) return (0); - - /* - * Only used for autonegotiation. - */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) - break; - - /* - * Check to see if we have link. - */ - reg = PHY_READ(sc, NSGPHY_MII_PHYSUP); - if (reg & NSGPHY_PHYSUP_LNKSTS) - break; - - /* - * Only retry autonegotiation every 5 seconds. - * Actually, for gigE PHYs, we should wait longer, since - * 5 seconds is the mimimum time the documentation - * says to wait for a 1000mbps link to be established. - */ - if (++sc->mii_ticks != 10) - return (0); - - sc->mii_ticks = 0; - - mii_phy_reset(sc); - if (nsgphy_mii_phy_auto(sc, 0) == EJUSTRETURN) - return(0); break; } @@ -344,19 +234,25 @@ static void nsgphy_status(struct mii_softc *sc) { struct mii_data *mii = sc->mii_pdata; - int bmsr, bmcr, physup, anlpar, gstat; + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; + int bmsr, bmcr, physup, gtsr; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; - bmsr = PHY_READ(sc, MII_BMSR); + bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); physup = PHY_READ(sc, NSGPHY_MII_PHYSUP); - if (physup & NSGPHY_PHYSUP_LNKSTS) + if (physup & PHY_SUP_LINK) mii->mii_media_status |= IFM_ACTIVE; bmcr = PHY_READ(sc, MII_BMCR); + if (bmcr & BMCR_ISO) { + mii->mii_media_active |= IFM_NONE; + mii->mii_media_status = 0; + return; + } if (bmcr & BMCR_LOOP) mii->mii_media_active |= IFM_LOOP; @@ -371,100 +267,29 @@ nsgphy_status(struct mii_softc *sc) mii->mii_media_active |= IFM_NONE; return; } - anlpar = PHY_READ(sc, MII_ANLPAR); - gstat = PHY_READ(sc, MII_100T2SR); - if (gstat & GTSR_LP_1000TFDX) - mii->mii_media_active |= IFM_1000_T|IFM_FDX; - else if (gstat & GTSR_LP_1000THDX) - mii->mii_media_active |= IFM_1000_T|IFM_HDX; - else if (anlpar & ANLPAR_T4) - mii->mii_media_active |= IFM_100_T4; - else if (anlpar & ANLPAR_TX_FD) - mii->mii_media_active |= IFM_100_TX|IFM_FDX; - else if (anlpar & ANLPAR_TX) - mii->mii_media_active |= IFM_100_TX; - else if (anlpar & ANLPAR_10_FD) - mii->mii_media_active |= IFM_10_T|IFM_FDX; - else if (anlpar & ANLPAR_10) - mii->mii_media_active |= IFM_10_T|IFM_HDX; - else - mii->mii_media_active |= IFM_NONE; - return; - } - - switch(bmcr & (BMCR_SPEED1|BMCR_SPEED0)) { - case BMCR_S1000: - mii->mii_media_active |= IFM_1000_T; - break; - case BMCR_S100: - mii->mii_media_active |= IFM_100_TX; - break; - case BMCR_S10: - mii->mii_media_active |= IFM_10_T; - break; - default: - break; - } - - if (bmcr & BMCR_FDX) - mii->mii_media_active |= IFM_FDX; - else - mii->mii_media_active |= IFM_HDX; - return; -} + switch (physup & (PHY_SUP_SPEED1|PHY_SUP_SPEED0)) { + case PHY_SUP_SPEED1: + mii->mii_media_active |= IFM_1000_T; + gtsr = PHY_READ(sc, MII_100T2SR); + if (gtsr & GTSR_MS_RES) + mii->mii_media_active |= IFM_ETH_MASTER; + break; + case PHY_SUP_SPEED0: + mii->mii_media_active |= IFM_100_TX; + break; -static int -nsgphy_mii_phy_auto(struct mii_softc *mii, int waitfor) -{ - int bmsr, ktcr = 0, i; - - if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) { - mii_phy_reset(mii); - PHY_WRITE(mii, MII_BMCR, 0); - DELAY(1000); - ktcr = PHY_READ(mii, MII_100T2CR); - PHY_WRITE(mii, MII_100T2CR, ktcr | - (GTCR_ADV_1000TFDX|GTCR_ADV_1000THDX)); - ktcr = PHY_READ(mii, MII_100T2CR); - DELAY(1000); - PHY_WRITE(mii, MII_ANAR, - BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA); - DELAY(1000); - PHY_WRITE(mii, MII_BMCR, - BMCR_AUTOEN | BMCR_STARTNEG); - } + case 0: + mii->mii_media_active |= IFM_10_T; + break; - if (waitfor) { - /* Wait 500ms for it to complete. */ - for (i = 0; i < 500; i++) { - if ((bmsr = PHY_READ(mii, MII_BMSR)) & BMSR_ACOMP) - return (0); - DELAY(1000); -#if 0 - if ((bmsr & BMSR_ACOMP) == 0) - printf("%s: autonegotiation failed to complete\n", - mii->mii_dev.dv_xname); -#endif + default: + mii->mii_media_active |= IFM_NONE; + mii->mii_media_status = 0; } - - /* - * Don't need to worry about clearing MIIF_DOINGAUTO. - * If that's set, a timeout is pending, and it will - * clear the flag. - */ - return (EIO); - } - - /* - * Just let it finish asynchronously. This is for the benefit of - * the tick handler driving autonegotiation. Don't want 500ms - * delays all the time while the system is running! - */ - if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) { - mii->mii_flags |= MIIF_DOINGAUTO; - mii->mii_auto_ch = timeout(mii_phy_auto_timeout, mii, hz >> 1); - } - return (EJUSTRETURN); + if (physup & PHY_SUP_DUPLEX) + mii->mii_media_active |= IFM_FDX; + } else + mii->mii_media_active = ife->ifm_media; } diff --git a/sys/dev/mii/nsgphyreg.h b/sys/dev/mii/nsgphyreg.h index 0c6ef4b..c7680f1 100644 --- a/sys/dev/mii/nsgphyreg.h +++ b/sys/dev/mii/nsgphyreg.h @@ -54,10 +54,14 @@ #define NSGPHY_STRAPOPT_SPDSEL (NSGPHY_STRAPOPT_SPEED1|NSGPHY_STRAPOPT_SPEED0) #define NSGPHY_MII_PHYSUP 0x11 /* PHY support/current status */ +#define PHY_SUP_SPEED1 0x0010 /* speed bit 1 */ +#define PHY_SUP_SPEED0 0x0008 /* speed bit 1 */ #define NSGPHY_PHYSUP_SPEED1 0x0010 /* speed status */ #define NSGPHY_PHYSUP_SPEED0 0x0008 /* speed status */ #define NSGPHY_PHYSUP_SPDSTS (NSGPHY_PHYSUP_SPEED1|NSGPHY_PHYSUP_SPEED0) #define NSGPHY_PHYSUP_LNKSTS 0x0004 /* link status */ +#define PHY_SUP_LINK 0x0004 /* link status */ +#define PHY_SUP_DUPLEX 0x0002 /* 1 == full-duplex */ #define NSGPHY_PHYSUP_DUPSTS 0x0002 /* duplex status 1 == full */ #define NSGPHY_PHYSUP_10BT 0x0001 /* 10baseT resolved */ diff --git a/sys/dev/nge/if_nge.c b/sys/dev/nge/if_nge.c index 53bd1f0..2b5f169 100644 --- a/sys/dev/nge/if_nge.c +++ b/sys/dev/nge/if_nge.c @@ -1980,10 +1980,12 @@ static void nge_stop(sc) ifp->if_flags |= IFF_UP; ifm = mii->mii_media.ifm_cur; mtmp = ifm->ifm_media; - ifm->ifm_media = IFM_ETHER|IFM_NONE; +#if 0 + ifm->ifm_media = IFM_ETHER|IFM_AUTO; mii_mediachg(mii); ifm->ifm_media = mtmp; ifp->if_flags = itmp; +#endif sc->nge_link = 0; |