diff options
author | Poul-Henning Kamp <phk@FreeBSD.org> | 2002-04-29 11:57:30 +0000 |
---|---|---|
committer | Poul-Henning Kamp <phk@FreeBSD.org> | 2002-04-29 11:57:30 +0000 |
commit | 78c8c3db4bca4f44d8a16e63de177324d2063069 (patch) | |
tree | ab00a27fad6535ee94d5573484470b55ed8fe2c5 /sys/dev/mii/nsgphy.c | |
parent | f7bf276ff5c4afb3521b2b88eb6fbf58c55d7b1b (diff) | |
download | src-78c8c3db4bca4f44d8a16e63de177324d2063069.tar.gz src-78c8c3db4bca4f44d8a16e63de177324d2063069.zip |
Move a lot closer to NetBSDs MII support for GigE.
Move fxp and nge drivers over to use the new stuff.
Notes
Notes:
svn path=/head/; revision=95718
Diffstat (limited to 'sys/dev/mii/nsgphy.c')
-rw-r--r-- | sys/dev/mii/nsgphy.c | 255 |
1 files changed, 40 insertions, 215 deletions
diff --git a/sys/dev/mii/nsgphy.c b/sys/dev/mii/nsgphy.c index adae9fbf730a..0ee59ea600cd 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; } |