Module Name: src Committed By: msaitoh Date: Thu Nov 14 09:06:21 UTC 2019
Modified Files: src/sys/dev/mii: ipgphy.c Log Message: - Use auto-negotiation when forcing 1000BASE-T. - Add XXX comment for strange pause setting code. I suspect this is wrong. - On my environments, 1000BASE-T half duplex doesn't work, so we might remove IFM_1000T_HDX from this device in future. To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/sys/dev/mii/ipgphy.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/mii/ipgphy.c diff -u src/sys/dev/mii/ipgphy.c:1.3 src/sys/dev/mii/ipgphy.c:1.4 --- src/sys/dev/mii/ipgphy.c:1.3 Thu Nov 14 09:00:23 2019 +++ src/sys/dev/mii/ipgphy.c Thu Nov 14 09:06:21 2019 @@ -32,7 +32,7 @@ * Driver for the IC Plus IP1000A/IP1001 10/100/1000 PHY. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ipgphy.c,v 1.3 2019/11/14 09:00:23 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ipgphy.c,v 1.4 2019/11/14 09:06:21 msaitoh Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -60,7 +60,7 @@ CFATTACH_DECL_NEW(ipgphy, sizeof(struct static int ipgphy_service(struct mii_softc *, struct mii_data *, int); static void ipgphy_status(struct mii_softc *); -static int ipgphy_mii_phy_auto(struct mii_softc *); +static int ipgphy_mii_phy_auto(struct mii_softc *, u_int); static void ipgphy_load_dspcode(struct mii_softc *); static void ipgphy_reset(struct mii_softc *); @@ -126,7 +126,7 @@ static int ipgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { struct ifmedia_entry *ife = mii->mii_media.ifm_cur; - uint16_t gig, reg, speed; + uint16_t reg, speed; switch (cmd) { case MII_POLLSTAT: @@ -154,16 +154,13 @@ ipgphy_service(struct mii_softc *sc, str switch (IFM_SUBTYPE(ife->ifm_media)) { case IFM_AUTO: - (void)ipgphy_mii_phy_auto(sc); - goto done; - break; - case IFM_1000_T: /* - * XXX - * Manual 1000baseT setting doesn't seem to work. + * This device is required to do auto negotiation + * on 1000BASE-T. */ - speed = BMCR_S1000; + (void)ipgphy_mii_phy_auto(sc, ife->ifm_media); + goto done; break; case IFM_100_TX: @@ -178,26 +175,11 @@ ipgphy_service(struct mii_softc *sc, str return EINVAL; } - if (((ife->ifm_media & IFM_GMASK) & IFM_FDX) != 0) { + if ((ife->ifm_media & IFM_FDX) != 0) speed |= BMCR_FDX; - gig = GTCR_ADV_1000TFDX; - } else - gig = GTCR_ADV_1000THDX; PHY_WRITE(sc, MII_100T2CR, 0); PHY_WRITE(sc, MII_BMCR, speed); - - if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) - break; - - PHY_WRITE(sc, MII_100T2CR, gig); - PHY_WRITE(sc, MII_BMCR, speed); - - if (mii->mii_media.ifm_media & IFM_ETH_MASTER) - gig |= GTCR_MAN_MS | GTCR_ADV_MS; - - PHY_WRITE(sc, MII_100T2CR, gig); - done: break; @@ -211,7 +193,8 @@ done: return 0; /* Only used for autonegotiation. */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { + if ((IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) && + (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)) { sc->mii_ticks = 0; break; } @@ -242,7 +225,7 @@ done: break; sc->mii_ticks = 0; - ipgphy_mii_phy_auto(sc); + ipgphy_mii_phy_auto(sc, ife->ifm_media); break; } @@ -320,26 +303,36 @@ ipgphy_status(struct mii_softc *sc) } static int -ipgphy_mii_phy_auto(struct mii_softc *sc) +ipgphy_mii_phy_auto(struct mii_softc *sc, u_int media) { uint16_t reg = 0; + u_int subtype = IFM_SUBTYPE(media); + /* XXX Is it requreid ? */ if (sc->mii_mpd_model == MII_MODEL_xxICPLUS_IP1001) { PHY_READ(sc, MII_ANAR, ®); reg &= ~(ANAR_PAUSE_SYM | ANAR_PAUSE_ASYM); reg |= ANAR_NP; } - reg |= ANAR_10 | ANAR_10_FD | ANAR_TX | ANAR_TX_FD; + if (subtype == IFM_AUTO) + reg |= ANAR_10 | ANAR_10_FD | ANAR_TX | ANAR_TX_FD; if (sc->mii_flags & MIIF_DOPAUSE) reg |= ANAR_PAUSE_SYM | ANAR_PAUSE_ASYM; PHY_WRITE(sc, MII_ANAR, reg | ANAR_CSMA); - reg = GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX; - if (sc->mii_mpd_model != MII_MODEL_xxICPLUS_IP1001) - reg |= GTCR_ADV_MS; + if (subtype == IFM_AUTO) + reg = GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX; + else if (subtype == IFM_1000_T) { + if ((media & IFM_FDX) != 0) + reg = GTCR_ADV_1000TFDX; + else + reg = GTCR_ADV_1000THDX; + } else + reg = 0; + PHY_WRITE(sc, MII_100T2CR, reg); PHY_WRITE(sc, MII_BMCR, BMCR_FDX | BMCR_AUTOEN | BMCR_STARTNEG);