Index: projects/ifnet/sys/dev/mii/acphy.c =================================================================== --- projects/ifnet/sys/dev/mii/acphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/acphy.c (revision 282026) @@ -1,244 +1,244 @@ /*- * Copyright (c) 1998, 1999 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 * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (c) 1997 Manuel Bouyer. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Driver for Altima AC101 10/100 PHY */ #include #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" static int acphy_probe(device_t); static int acphy_attach(device_t); static device_method_t acphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, acphy_probe), DEVMETHOD(device_attach, acphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t acphy_devclass; static driver_t acphy_driver = { "acphy", acphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(acphy, miibus, acphy_driver, acphy_devclass, 0, 0); -static int acphy_service(struct mii_softc *, struct mii_data *, int); -static void acphy_reset(struct mii_softc *); -static void acphy_status(struct mii_softc *); +static int acphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void acphy_reset(struct mii_softc *, if_media_t); +static void acphy_status(struct mii_softc *, if_media_t); static const struct mii_phydesc acphys[] = { MII_PHY_DESC(ALTIMA, AC101), MII_PHY_DESC(ALTIMA, AC101L), /* XXX This is reported to work, but it's not from any data sheet. */ MII_PHY_DESC(ALTIMA, ACXXX), MII_PHY_END }; static const struct mii_phy_funcs acphy_funcs = { acphy_service, acphy_status, acphy_reset }; static int acphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, acphys, BUS_PROBE_DEFAULT)); } static int acphy_attach(device_t dev) { struct mii_softc *sc; sc = device_get_softc(dev); mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &acphy_funcs, 0); - PHY_RESET(sc); + PHY_RESET(sc, 0); sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask; device_printf(dev, " "); -#define ADD(m) ifmedia_add(&sc->mii_pdata->mii_media, (m), 0, NULL) if ((PHY_READ(sc, MII_ACPHY_MCTL) & AC_MCTL_FX_SEL) != 0) { sc->mii_flags |= MIIF_HAVEFIBER; - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, 0, sc->mii_inst)); + mii_phy_add_media(sc->mii_pdata, IFM_MAKEWORD(IFM_ETHER, + IFM_100_FX, 0, sc->mii_inst)); printf("100baseFX, "); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, IFM_FDX, sc->mii_inst)); + mii_phy_add_media(sc->mii_pdata, IFM_MAKEWORD(IFM_ETHER, + IFM_100_FX, IFM_FDX, sc->mii_inst)); printf("100baseFX-FDX, "); } -#undef ADD - mii_phy_add_media(sc); + mii_phy_generic_media(sc); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); return (0); } static int -acphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +acphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { int reg; switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: /* Wake & deisolate up if necessary */ reg = PHY_READ(sc, MII_BMCR); if (reg & (BMCR_ISO | BMCR_PDOWN)) PHY_WRITE(sc, MII_BMCR, reg & ~(BMCR_ISO | BMCR_PDOWN)); - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; case MII_TICK: /* * This PHY's autonegotiation doesn't need to be kicked. */ break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -acphy_status(struct mii_softc *sc) +acphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmsr, bmcr, diag; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (bmsr & BMSR_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; if (bmcr & BMCR_AUTOEN) { if ((bmsr & BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } diag = PHY_READ(sc, MII_ACPHY_DIAG); if (diag & AC_DIAG_SPEED) mii->mii_media_active |= IFM_100_TX; else mii->mii_media_active |= IFM_10_T; if (diag & AC_DIAG_DUPLEX) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; } else - mii->mii_media_active = ife->ifm_media; + mii->mii_media_active = media; } static void -acphy_reset(struct mii_softc *sc) +acphy_reset(struct mii_softc *sc, if_media_t media) { - mii_phy_reset(sc); + mii_phy_reset(sc, media); PHY_WRITE(sc, MII_ACPHY_INT, 0); } Index: projects/ifnet/sys/dev/mii/amphy.c =================================================================== --- projects/ifnet/sys/dev/mii/amphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/amphy.c (revision 282026) @@ -1,209 +1,209 @@ /*- * Copyright (c) 1997, 1998, 1999 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * driver for AMD AM79c873 PHYs * This driver also works for Davicom DM910{1,2} PHYs, which appear * to be AM79c873 workalikes. */ #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" static int amphy_probe(device_t); static int amphy_attach(device_t); static device_method_t amphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, amphy_probe), DEVMETHOD(device_attach, amphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t amphy_devclass; static driver_t amphy_driver = { "amphy", amphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(amphy, miibus, amphy_driver, amphy_devclass, 0, 0); -static int amphy_service(struct mii_softc *, struct mii_data *, int); -static void amphy_status(struct mii_softc *); +static int amphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void amphy_status(struct mii_softc *, if_media_t); static const struct mii_phydesc amphys[] = { MII_PHY_DESC(xxDAVICOM, DM9102), MII_PHY_DESC(xxDAVICOM, DM9101), MII_PHY_DESC(yyDAVICOM, DM9101), MII_PHY_END }; static const struct mii_phy_funcs amphy_funcs = { amphy_service, amphy_status, mii_phy_reset }; static int amphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, amphys, BUS_PROBE_DEFAULT)); } static int amphy_attach(device_t dev) { mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &hy_funcs, 1); return (0); } static int -amphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +amphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; case MII_TICK: if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -amphy_status(struct mii_softc *sc) +amphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmsr, bmcr, par, anlpar; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (bmsr & BMSR_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; if (bmcr & BMCR_AUTOEN) { /* * The PAR status bits are only valid if autonegotiation * has completed (or it's disabled). */ if ((bmsr & BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } if (PHY_READ(sc, MII_ANER) & ANER_LPAN) { anlpar = PHY_READ(sc, MII_ANAR) & PHY_READ(sc, MII_ANLPAR); if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; else if (anlpar & ANLPAR_T4) mii->mii_media_active |= IFM_100_T4|IFM_HDX; else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX|IFM_HDX; 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; } /* * Link partner is not capable of autonegotiation. */ par = PHY_READ(sc, MII_AMPHY_DSCSR); if (par & DSCSR_100FDX) mii->mii_media_active |= IFM_100_TX|IFM_FDX; else if (par & DSCSR_100HDX) mii->mii_media_active |= IFM_100_TX|IFM_HDX; else if (par & DSCSR_10FDX) mii->mii_media_active |= IFM_10_T|IFM_HDX; else if (par & DSCSR_10HDX) mii->mii_media_active |= IFM_10_T|IFM_HDX; if ((mii->mii_media_active & IFM_FDX) != 0) mii->mii_media_active |= mii_phy_flowstatus(sc); } else - mii->mii_media_active = ife->ifm_media; + mii->mii_media_active = media; } Index: projects/ifnet/sys/dev/mii/atphy.c =================================================================== --- projects/ifnet/sys/dev/mii/atphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/atphy.c (revision 282026) @@ -1,366 +1,365 @@ /*- * Copyright (c) 2008, Pyun YongHyeon * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Driver for the Attansic/Atheros F1 10/100/1000 PHY. */ #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" static int atphy_probe(device_t); static int atphy_attach(device_t); static device_method_t atphy_methods[] = { /* Device interface. */ DEVMETHOD(device_probe, atphy_probe), DEVMETHOD(device_attach, atphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t atphy_devclass; static driver_t atphy_driver = { "atphy", atphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(atphy, miibus, atphy_driver, atphy_devclass, 0, 0); -static int atphy_service(struct mii_softc *, struct mii_data *, int); -static void atphy_status(struct mii_softc *); -static void atphy_reset(struct mii_softc *); -static uint16_t atphy_anar(struct ifmedia_entry *); -static int atphy_setmedia(struct mii_softc *, int); +static int atphy_service(struct mii_softc *, struct mii_data *, mii_cmd_t, + if_media_t); +static void atphy_status(struct mii_softc *, if_media_t); +static void atphy_reset(struct mii_softc *, if_media_t); +static uint16_t atphy_anar(if_media_t); +static int atphy_setmedia(struct mii_softc *, if_media_t); static const struct mii_phydesc atphys[] = { MII_PHY_DESC(xxATHEROS, F1), MII_PHY_DESC(xxATHEROS, F1_7), MII_PHY_DESC(xxATHEROS, AR8021), MII_PHY_DESC(xxATHEROS, F2), MII_PHY_END }; static const struct mii_phy_funcs atphy_funcs = { atphy_service, atphy_status, atphy_reset }; static int atphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, atphys, BUS_PROBE_DEFAULT)); } static int atphy_attach(device_t dev) { mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &atphy_funcs, 1); return (0); } static int -atphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +atphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; uint16_t anar, bmcr, bmsr; switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO || - IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) { - atphy_setmedia(sc, ife->ifm_media); + if (IFM_SUBTYPE(media) == IFM_AUTO || + IFM_SUBTYPE(media) == IFM_1000_T) { + atphy_setmedia(sc, media); break; } bmcr = 0; - switch (IFM_SUBTYPE(ife->ifm_media)) { + switch (IFM_SUBTYPE(media)) { case IFM_100_TX: bmcr = BMCR_S100; break; case IFM_10_T: bmcr = BMCR_S10; break; case IFM_NONE: bmcr = PHY_READ(sc, MII_BMCR); /* * XXX * Due to an unknown reason powering down PHY resulted * in unexpected results such as inaccessibility of * hardware of freshly rebooted system. Disable * powering down PHY until I got more information for * Attansic/Atheros PHY hardwares. */ PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_ISO); goto done; default: return (EINVAL); } - anar = atphy_anar(ife); - if ((ife->ifm_media & IFM_FDX) != 0) { + anar = atphy_anar(media); + if ((media & IFM_FDX) != 0) { bmcr |= BMCR_FDX; - if ((ife->ifm_media & IFM_FLOW) != 0 || + if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0) anar |= ANAR_PAUSE_TOWARDS; } if ((sc->mii_extcapabilities & (EXTSR_1000TFDX | EXTSR_1000THDX)) != 0) PHY_WRITE(sc, MII_100T2CR, 0); PHY_WRITE(sc, MII_ANAR, anar | ANAR_CSMA); /* * Reset the PHY so all changes take effect. */ PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG); done: break; case MII_TICK: /* * Only used for autonegotiation. */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { + if (IFM_SUBTYPE(media) != IFM_AUTO) { sc->mii_ticks = 0; break; } /* * Check for link. * Read the status register twice; BMSR_LINK is latch-low. */ bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (bmsr & BMSR_LINK) { sc->mii_ticks = 0; break; } /* Announce link loss right after it happens. */ if (sc->mii_ticks++ == 0) break; if (sc->mii_ticks <= sc->mii_anegticks) return (0); sc->mii_ticks = 0; - atphy_setmedia(sc, ife->ifm_media); + atphy_setmedia(sc, media); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -atphy_status(struct mii_softc *sc) +atphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; uint32_t bmsr, bmcr, ssr; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if ((bmsr & BMSR_LINK) != 0) mii->mii_media_status |= IFM_ACTIVE; bmcr = PHY_READ(sc, MII_BMCR); if ((bmcr & BMCR_ISO) != 0) { mii->mii_media_active |= IFM_NONE; mii->mii_media_status = 0; return; } if ((bmcr & BMCR_LOOP) != 0) mii->mii_media_active |= IFM_LOOP; ssr = PHY_READ(sc, ATPHY_SSR); if ((ssr & ATPHY_SSR_SPD_DPLX_RESOLVED) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } switch (ssr & ATPHY_SSR_SPEED_MASK) { case ATPHY_SSR_1000MBS: mii->mii_media_active |= IFM_1000_T; /* * atphy(4) has a valid link so reset mii_ticks. * Resetting mii_ticks is needed in order to * detect link loss after auto-negotiation. */ sc->mii_ticks = 0; break; case ATPHY_SSR_100MBS: mii->mii_media_active |= IFM_100_TX; sc->mii_ticks = 0; break; case ATPHY_SSR_10MBS: mii->mii_media_active |= IFM_10_T; sc->mii_ticks = 0; break; default: mii->mii_media_active |= IFM_NONE; return; } if ((ssr & ATPHY_SSR_DUPLEX) != 0) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) && (PHY_READ(sc, MII_100T2SR) & GTSR_MS_RES) != 0) mii->mii_media_active |= IFM_ETH_MASTER; } static void -atphy_reset(struct mii_softc *sc) +atphy_reset(struct mii_softc *sc, if_media_t media) { - struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur; uint32_t reg; int i; /* Take PHY out of power down mode. */ PHY_WRITE(sc, 29, 0x29); PHY_WRITE(sc, 30, 0); reg = PHY_READ(sc, ATPHY_SCR); /* Enable automatic crossover. */ reg |= ATPHY_SCR_AUTO_X_MODE; /* Disable power down. */ reg &= ~ATPHY_SCR_MAC_PDOWN; /* Enable CRS on Tx. */ reg |= ATPHY_SCR_ASSERT_CRS_ON_TX; /* Auto correction for reversed cable polarity. */ reg |= ATPHY_SCR_POLARITY_REVERSAL; PHY_WRITE(sc, ATPHY_SCR, reg); /* Workaround F1 bug to reset phy. */ - atphy_setmedia(sc, ife == NULL ? IFM_AUTO : ife->ifm_media); + atphy_setmedia(sc, media); for (i = 0; i < 1000; i++) { DELAY(1); if ((PHY_READ(sc, MII_BMCR) & BMCR_RESET) == 0) break; } } static uint16_t -atphy_anar(struct ifmedia_entry *ife) +atphy_anar(if_media_t media) { uint16_t anar; anar = 0; - switch (IFM_SUBTYPE(ife->ifm_media)) { + switch (IFM_SUBTYPE(media)) { case IFM_AUTO: anar |= ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10; return (anar); case IFM_1000_T: return (anar); case IFM_100_TX: anar |= ANAR_TX; break; case IFM_10_T: anar |= ANAR_10; break; default: return (0); } - if ((ife->ifm_media & IFM_FDX) != 0) { - if (IFM_SUBTYPE(ife->ifm_media) == IFM_100_TX) + if ((media & IFM_FDX) != 0) { + if (IFM_SUBTYPE(media) == IFM_100_TX) anar |= ANAR_TX_FD; else anar |= ANAR_10_FD; } return (anar); } static int -atphy_setmedia(struct mii_softc *sc, int media) +atphy_setmedia(struct mii_softc *sc, if_media_t media) { uint16_t anar; anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; if ((IFM_SUBTYPE(media) == IFM_AUTO || (media & IFM_FDX) != 0) && ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0)) anar |= ANAR_PAUSE_TOWARDS; PHY_WRITE(sc, MII_ANAR, anar); if ((sc->mii_extcapabilities & (EXTSR_1000TFDX | EXTSR_1000THDX)) != 0) PHY_WRITE(sc, MII_100T2CR, GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX); else if (sc->mii_mpd_model == MII_MODEL_xxATHEROS_F1) { /* * AR8132 has 10/100 PHY and the PHY uses the same * model number of F1 gigabit PHY. The PHY has no * ability to establish gigabit link so explicitly * disable 1000baseT configuration for the PHY. * Otherwise, there is a case that atphy(4) could * not establish a link against gigabit link partner * unless the link partner supports down-shifting. */ PHY_WRITE(sc, MII_100T2CR, 0); } PHY_WRITE(sc, MII_BMCR, BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG); return (EJUSTRETURN); } Index: projects/ifnet/sys/dev/mii/axphy.c =================================================================== --- projects/ifnet/sys/dev/mii/axphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/axphy.c (revision 282026) @@ -1,177 +1,177 @@ /*- * Copyright (c) 2009, M. Warner Losh * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * driver for internal phy in the AX88x9x chips. */ #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include "miibus_if.h" static int axphy_probe(device_t dev); static int axphy_attach(device_t dev); static device_method_t axphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, axphy_probe), DEVMETHOD(device_attach, axphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t axphy_devclass; static driver_t axphy_driver = { "axphy", axphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(axphy, miibus, axphy_driver, axphy_devclass, 0, 0); -static int axphy_service(struct mii_softc *, struct mii_data *, int); -static void axphy_status(struct mii_softc *); +static int axphy_service(struct mii_softc *, struct mii_data *, mii_cmd_t, + if_media_t); +static void axphy_status(struct mii_softc *, if_media_t); static const struct mii_phydesc axphys[] = { MII_PHY_DESC(xxASIX, AX88X9X), MII_PHY_END }; static const struct mii_phy_funcs axphy_funcs = { axphy_service, axphy_status, mii_phy_reset }; static int axphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, axphys, BUS_PROBE_DEFAULT)); } static int axphy_attach(device_t dev) { struct mii_softc *sc; sc = device_get_softc(dev); mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, &axphy_funcs, 1); - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, (IFM_ETHER | IFM_AUTO)); return (0); } static int -axphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +axphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; case MII_TICK: if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -axphy_status(struct mii_softc *sc) +axphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmsr, bmcr; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (bmsr & BMSR_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; if (bmcr & BMCR_AUTOEN) { if ((bmsr & BMSR_ACOMP) == 0) { mii->mii_media_active |= IFM_NONE; return; } #if 0 scr = PHY_READ(sc, MII_AXPHY_SCR); if (scr & SCR_S100) mii->mii_media_active |= IFM_100_TX; else mii->mii_media_active |= IFM_10_T; if (scr & SCR_FDX) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; #endif } else - mii->mii_media_active = ife->ifm_media; + mii->mii_media_active = media; } Index: projects/ifnet/sys/dev/mii/bmtphy.c =================================================================== --- projects/ifnet/sys/dev/mii/bmtphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/bmtphy.c (revision 282026) @@ -1,256 +1,255 @@ /*- * 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 * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1997 Manuel Bouyer. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * from: NetBSD: bmtphy.c,v 1.8 2002/07/03 06:25:50 simonb Exp * */ #include __FBSDID("$FreeBSD$"); /* * Driver for the Broadcom BCM5201/BCM5202 "Mini-Theta" PHYs. This also * drives the PHY on the 3Com 3c905C. The 3c905C's PHY is described in * the 3c905C data sheet. */ #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" static int bmtphy_probe(device_t); static int bmtphy_attach(device_t); static device_method_t bmtphy_methods[] = { /* Device interface */ DEVMETHOD(device_probe, bmtphy_probe), DEVMETHOD(device_attach, bmtphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t bmtphy_devclass; static driver_t bmtphy_driver = { "bmtphy", bmtphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(bmtphy, miibus, bmtphy_driver, bmtphy_devclass, 0, 0); -static int bmtphy_service(struct mii_softc *, struct mii_data *, int); -static void bmtphy_status(struct mii_softc *); -static void bmtphy_reset(struct mii_softc *); +static int bmtphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void bmtphy_status(struct mii_softc *, if_media_t); +static void bmtphy_reset(struct mii_softc *, if_media_t); static const struct mii_phydesc bmtphys_dp[] = { MII_PHY_DESC(xxBROADCOM, BCM4401), MII_PHY_DESC(xxBROADCOM, BCM5201), MII_PHY_DESC(xxBROADCOM, BCM5214), MII_PHY_DESC(xxBROADCOM, BCM5221), MII_PHY_DESC(xxBROADCOM, BCM5222), MII_PHY_END }; static const struct mii_phydesc bmtphys_lp[] = { MII_PHY_DESC(xxBROADCOM, 3C905B), MII_PHY_DESC(xxBROADCOM, 3C905C), MII_PHY_END }; static const struct mii_phy_funcs bmtphy_funcs = { bmtphy_service, bmtphy_status, bmtphy_reset }; static int bmtphy_probe(device_t dev) { int rval; /* Let exphy(4) take precedence for these. */ rval = mii_phy_dev_probe(dev, bmtphys_lp, BUS_PROBE_LOW_PRIORITY); if (rval <= 0) return (rval); return (mii_phy_dev_probe(dev, bmtphys_dp, BUS_PROBE_DEFAULT)); } static int bmtphy_attach(device_t dev) { mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &bmtphy_funcs, 1); return (0); } static int -bmtphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +bmtphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; case MII_TICK: if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -bmtphy_status(struct mii_softc *sc) +bmtphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii; - struct ifmedia_entry *ife; int bmsr, bmcr, aux_csr; mii = sc->mii_pdata; - ife = mii->mii_media.ifm_cur; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (bmsr & BMSR_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; if (bmcr & BMCR_AUTOEN) { /* * The media status bits are only valid if autonegotiation * has completed (or it's disabled). */ if ((bmsr & BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } aux_csr = PHY_READ(sc, MII_BMTPHY_AUX_CSR); if (aux_csr & AUX_CSR_SPEED) mii->mii_media_active |= IFM_100_TX; else mii->mii_media_active |= IFM_10_T; if (aux_csr & AUX_CSR_FDX) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; } else - mii->mii_media_active = ife->ifm_media; + mii->mii_media_active = media; } static void -bmtphy_reset(struct mii_softc *sc) +bmtphy_reset(struct mii_softc *sc, if_media_t media) { u_int16_t data; - mii_phy_reset(sc); + mii_phy_reset(sc, media); if (sc->mii_mpd_model == MII_MODEL_xxBROADCOM_BCM5221) { /* Enable shadow register mode. */ data = PHY_READ(sc, 0x1f); PHY_WRITE(sc, 0x1f, data | 0x0080); /* Enable APD (Auto PowerDetect). */ data = PHY_READ(sc, MII_BMTPHY_AUX2); PHY_WRITE(sc, MII_BMTPHY_AUX2, data | 0x0020); /* Enable clocks across APD for Auto-MDIX functionality. */ data = PHY_READ(sc, MII_BMTPHY_INTR); PHY_WRITE(sc, MII_BMTPHY_INTR, data | 0x0004); /* Disable shadow register mode. */ data = PHY_READ(sc, 0x1f); PHY_WRITE(sc, 0x1f, data & ~0x0080); } } Index: projects/ifnet/sys/dev/mii/brgphy.c =================================================================== --- projects/ifnet/sys/dev/mii/brgphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/brgphy.c (revision 282026) @@ -1,1087 +1,1087 @@ /*- * Copyright (c) 2000 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Driver for the Broadcom BCM54xx/57xx 1000baseTX PHY. */ #include #include #include #include /* XXXGL: if_b[cg]ereg.h contamination */ #include /* XXXGL: if_b[cg]ereg.h contamination */ #include #include #include #include -#include #include +#include /* XXXGL: if_b[cg]ereg.h contamination */ #include #include #include #include "miidevs.h" #include #include #include #include #include #include #include "miibus_if.h" static int brgphy_probe(device_t); static int brgphy_attach(device_t); struct brgphy_softc { struct mii_softc mii_sc; int serdes_flags; /* Keeps track of the serdes type used */ #define BRGPHY_5706S 0x0001 #define BRGPHY_5708S 0x0002 #define BRGPHY_NOANWAIT 0x0004 #define BRGPHY_5709S 0x0008 int bce_phy_flags; /* PHY flags transferred from the MAC driver */ }; static device_method_t brgphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, brgphy_probe), DEVMETHOD(device_attach, brgphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t brgphy_devclass; static driver_t brgphy_driver = { "brgphy", brgphy_methods, sizeof(struct brgphy_softc) }; DRIVER_MODULE(brgphy, miibus, brgphy_driver, brgphy_devclass, 0, 0); -static int brgphy_service(struct mii_softc *, struct mii_data *, int); -static void brgphy_setmedia(struct mii_softc *, int); -static void brgphy_status(struct mii_softc *); -static void brgphy_mii_phy_auto(struct mii_softc *, int); -static void brgphy_reset(struct mii_softc *); +static int brgphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void brgphy_setmedia(struct mii_softc *, if_media_t); +static void brgphy_status(struct mii_softc *, if_media_t); +static void brgphy_mii_phy_auto(struct mii_softc *, if_media_t); +static void brgphy_reset(struct mii_softc *, if_media_t); static void brgphy_enable_loopback(struct mii_softc *); static void bcm5401_load_dspcode(struct mii_softc *); static void bcm5411_load_dspcode(struct mii_softc *); static void bcm54k2_load_dspcode(struct mii_softc *); static void brgphy_fixup_5704_a0_bug(struct mii_softc *); static void brgphy_fixup_adc_bug(struct mii_softc *); static void brgphy_fixup_adjust_trim(struct mii_softc *); static void brgphy_fixup_ber_bug(struct mii_softc *); static void brgphy_fixup_crc_bug(struct mii_softc *); static void brgphy_fixup_jitter_bug(struct mii_softc *); static void brgphy_ethernet_wirespeed(struct mii_softc *); static void brgphy_jumbo_settings(struct mii_softc *, u_long); static const struct mii_phydesc brgphys[] = { MII_PHY_DESC(BROADCOM, BCM5400), MII_PHY_DESC(BROADCOM, BCM5401), MII_PHY_DESC(BROADCOM, BCM5411), MII_PHY_DESC(BROADCOM, BCM54K2), MII_PHY_DESC(BROADCOM, BCM5701), MII_PHY_DESC(BROADCOM, BCM5703), MII_PHY_DESC(BROADCOM, BCM5704), MII_PHY_DESC(BROADCOM, BCM5705), MII_PHY_DESC(BROADCOM, BCM5706), MII_PHY_DESC(BROADCOM, BCM5714), MII_PHY_DESC(BROADCOM, BCM5421), MII_PHY_DESC(BROADCOM, BCM5750), MII_PHY_DESC(BROADCOM, BCM5752), MII_PHY_DESC(BROADCOM, BCM5780), MII_PHY_DESC(BROADCOM, BCM5708C), MII_PHY_DESC(BROADCOM2, BCM5482), MII_PHY_DESC(BROADCOM2, BCM5708S), MII_PHY_DESC(BROADCOM2, BCM5709C), MII_PHY_DESC(BROADCOM2, BCM5709S), MII_PHY_DESC(BROADCOM2, BCM5709CAX), MII_PHY_DESC(BROADCOM2, BCM5722), MII_PHY_DESC(BROADCOM2, BCM5755), MII_PHY_DESC(BROADCOM2, BCM5754), MII_PHY_DESC(BROADCOM2, BCM5761), MII_PHY_DESC(BROADCOM2, BCM5784), #ifdef notyet /* better handled by ukphy(4) until WARs are implemented */ MII_PHY_DESC(BROADCOM2, BCM5785), #endif MII_PHY_DESC(BROADCOM3, BCM5717C), MII_PHY_DESC(BROADCOM3, BCM5719C), MII_PHY_DESC(BROADCOM3, BCM5720C), MII_PHY_DESC(BROADCOM3, BCM57765), MII_PHY_DESC(BROADCOM3, BCM57780), MII_PHY_DESC(BROADCOM4, BCM5725C), MII_PHY_DESC(xxBROADCOM_ALT1, BCM5906), MII_PHY_END }; static const struct mii_phy_funcs brgphy_funcs = { brgphy_service, brgphy_status, brgphy_reset }; static const struct hs21_type { const uint32_t id; const char *prod; } hs21_type_lists[] = { { 0x57081021, "IBM eServer BladeCenter HS21" }, { 0x57081011, "IBM eServer BladeCenter HS21 -[8853PAU]-" }, }; static int detect_hs21(struct bce_softc *bce_sc) { char *sysenv; int found, i; found = 0; sysenv = kern_getenv("smbios.system.product"); if (sysenv == NULL) return (found); for (i = 0; i < nitems(hs21_type_lists); i++) { if (bce_sc->bce_chipid == hs21_type_lists[i].id && strncmp(sysenv, hs21_type_lists[i].prod, strlen(hs21_type_lists[i].prod)) == 0) { found++; break; } } freeenv(sysenv); return (found); } /* Search for our PHY in the list of known PHYs */ static int brgphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, brgphys, BUS_PROBE_DEFAULT)); } /* Attach the PHY to the MII bus */ static int brgphy_attach(device_t dev) { struct brgphy_softc *bsc; struct bge_softc *bge_sc = NULL; struct bce_softc *bce_sc = NULL; struct mii_softc *sc; bsc = device_get_softc(dev); sc = &bsc->mii_sc; mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, &brgphy_funcs, 0); bsc->serdes_flags = 0; /* Find the MAC driver associated with this PHY. */ if (mii_dev_mac_match(dev, "bge")) bge_sc = mii_dev_mac_softc(dev); else if (mii_dev_mac_match(dev, "bce")) bce_sc = mii_dev_mac_softc(dev); /* Handle any special cases based on the PHY ID */ switch (sc->mii_mpd_oui) { case MII_OUI_BROADCOM: switch (sc->mii_mpd_model) { case MII_MODEL_BROADCOM_BCM5706: case MII_MODEL_BROADCOM_BCM5714: /* * The 5464 PHY used in the 5706 supports both copper * and fiber interfaces over GMII. Need to check the * shadow registers to see which mode is actually * in effect, and therefore whether we have 5706C or * 5706S. */ PHY_WRITE(sc, BRGPHY_MII_SHADOW_1C, BRGPHY_SHADOW_1C_MODE_CTRL); if (PHY_READ(sc, BRGPHY_MII_SHADOW_1C) & BRGPHY_SHADOW_1C_ENA_1000X) { bsc->serdes_flags |= BRGPHY_5706S; sc->mii_flags |= MIIF_HAVEFIBER; } break; } break; case MII_OUI_BROADCOM2: switch (sc->mii_mpd_model) { case MII_MODEL_BROADCOM2_BCM5708S: bsc->serdes_flags |= BRGPHY_5708S; sc->mii_flags |= MIIF_HAVEFIBER; break; case MII_MODEL_BROADCOM2_BCM5709S: /* * XXX * 5720S and 5709S shares the same PHY id. * Assume 5720S PHY if parent device is bge(4). */ if (bge_sc != NULL) bsc->serdes_flags |= BRGPHY_5708S; else bsc->serdes_flags |= BRGPHY_5709S; sc->mii_flags |= MIIF_HAVEFIBER; break; } break; } - PHY_RESET(sc); + PHY_RESET(sc, 0); /* Read the PHY's capabilities. */ sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask; if (sc->mii_capabilities & BMSR_EXTSTAT) sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); device_printf(dev, " "); /* Add the supported media types */ if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { - mii_phy_add_media(sc); + mii_phy_generic_media(sc); printf("\n"); } else { sc->mii_anegticks = MII_ANEGTICKS_GIGE; - ifmedia_add(&sc->mii_pdata->mii_media, - IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst), - 0, NULL); + mii_phy_add_media(sc->mii_pdata, IFM_MAKEWORD(IFM_ETHER, + IFM_1000_SX, IFM_FDX, sc->mii_inst)); printf("1000baseSX-FDX, "); /* * 2.5G support is a software enabled feature * on the 5708S and 5709S. */ if (bce_sc && (bce_sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)) { - ifmedia_add(&sc->mii_pdata->mii_media, + mii_phy_add_media(sc->mii_pdata, IFM_MAKEWORD(IFM_ETHER, IFM_2500_SX, IFM_FDX, - sc->mii_inst), 0, NULL); + sc->mii_inst)); printf("2500baseSX-FDX, "); } else if ((bsc->serdes_flags & BRGPHY_5708S) && bce_sc && (detect_hs21(bce_sc) != 0)) { /* * There appears to be certain silicon revision * in IBM HS21 blades that is having issues with * this driver wating for the auto-negotiation to * complete. This happens with a specific chip id * only and when the 1000baseSX-FDX is the only * mode. Workaround this issue since it's unlikely * to be ever addressed. */ printf("auto-neg workaround, "); bsc->serdes_flags |= BRGPHY_NOANWAIT; } - ifmedia_add(&sc->mii_pdata->mii_media, IFM_MAKEWORD(IFM_ETHER, - IFM_AUTO, 0, sc->mii_inst), 0, NULL); + mii_phy_add_media(sc->mii_pdata, IFM_MAKEWORD(IFM_ETHER, + IFM_AUTO, 0, sc->mii_inst)); printf("auto\n"); } MIIBUS_MEDIAINIT(sc->mii_dev); return (0); } static int -brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +brgphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int val; switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: /* Todo: Why is this here? Is it really needed? */ - PHY_RESET(sc); /* XXX hardware bug work-around */ + PHY_RESET(sc, media); /* XXX hardware bug work-around */ - switch (IFM_SUBTYPE(ife->ifm_media)) { + switch (IFM_SUBTYPE(media)) { case IFM_AUTO: - brgphy_mii_phy_auto(sc, ife->ifm_media); + brgphy_mii_phy_auto(sc, media); break; case IFM_2500_SX: case IFM_1000_SX: case IFM_1000_T: case IFM_100_TX: case IFM_10_T: - brgphy_setmedia(sc, ife->ifm_media); + brgphy_setmedia(sc, media); break; default: return (EINVAL); } break; case MII_TICK: /* Bail if autoneg isn't in process. */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { + if (IFM_SUBTYPE(media) != IFM_AUTO) { sc->mii_ticks = 0; break; } /* * Check to see if we have link. If we do, we don't * need to restart the autonegotiation process. */ val = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (val & BMSR_LINK) { sc->mii_ticks = 0; /* Reset autoneg timer. */ break; } /* Announce link loss right after it happens. */ if (sc->mii_ticks++ == 0) break; /* Only retry autonegotiation every mii_anegticks seconds. */ if (sc->mii_ticks <= sc->mii_anegticks) break; /* Retry autonegotiation */ sc->mii_ticks = 0; - brgphy_mii_phy_auto(sc, ife->ifm_media); + brgphy_mii_phy_auto(sc, media); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* * Callback if something changed. Note that we need to poke * the DSP on the Broadcom PHYs if the media changes. */ if (sc->mii_media_active != mii->mii_media_active || sc->mii_media_status != mii->mii_media_status || cmd == MII_MEDIACHG) { switch (sc->mii_mpd_oui) { case MII_OUI_BROADCOM: switch (sc->mii_mpd_model) { case MII_MODEL_BROADCOM_BCM5400: bcm5401_load_dspcode(sc); break; case MII_MODEL_BROADCOM_BCM5401: if (sc->mii_mpd_rev == 1 || sc->mii_mpd_rev == 3) bcm5401_load_dspcode(sc); break; case MII_MODEL_BROADCOM_BCM5411: bcm5411_load_dspcode(sc); break; case MII_MODEL_BROADCOM_BCM54K2: bcm54k2_load_dspcode(sc); break; } break; } } mii_phy_update(sc, cmd); return (0); } /****************************************************************************/ /* Sets the PHY link speed. */ /* */ /* Returns: */ /* None */ /****************************************************************************/ static void -brgphy_setmedia(struct mii_softc *sc, int media) +brgphy_setmedia(struct mii_softc *sc, if_media_t media) { int bmcr = 0, gig; switch (IFM_SUBTYPE(media)) { case IFM_2500_SX: break; case IFM_1000_SX: case IFM_1000_T: bmcr = BRGPHY_S1000; break; case IFM_100_TX: bmcr = BRGPHY_S100; break; case IFM_10_T: default: bmcr = BRGPHY_S10; break; } if ((media & IFM_FDX) != 0) { bmcr |= BRGPHY_BMCR_FDX; gig = BRGPHY_1000CTL_AFD; } else { gig = BRGPHY_1000CTL_AHD; } /* Force loopback to disconnect PHY from Ethernet medium. */ brgphy_enable_loopback(sc); PHY_WRITE(sc, BRGPHY_MII_1000CTL, 0); PHY_WRITE(sc, BRGPHY_MII_ANAR, BRGPHY_SEL_TYPE); if (IFM_SUBTYPE(media) != IFM_1000_T && IFM_SUBTYPE(media) != IFM_1000_SX) { PHY_WRITE(sc, BRGPHY_MII_BMCR, bmcr); return; } if (IFM_SUBTYPE(media) == IFM_1000_T) { gig |= BRGPHY_1000CTL_MSE; if ((media & IFM_ETH_MASTER) != 0) gig |= BRGPHY_1000CTL_MSC; } PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig); PHY_WRITE(sc, BRGPHY_MII_BMCR, bmcr | BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG); } /****************************************************************************/ /* Set the media status based on the PHY settings. */ /* */ /* Returns: */ /* None */ /****************************************************************************/ static void -brgphy_status(struct mii_softc *sc) +brgphy_status(struct mii_softc *sc, if_media_t media) { struct brgphy_softc *bsc = (struct brgphy_softc *)sc; struct mii_data *mii = sc->mii_pdata; int aux, bmcr, bmsr, val, xstat; u_int flowstat; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, BRGPHY_MII_BMSR) | PHY_READ(sc, BRGPHY_MII_BMSR); bmcr = PHY_READ(sc, BRGPHY_MII_BMCR); if (bmcr & BRGPHY_BMCR_LOOP) { mii->mii_media_active |= IFM_LOOP; } if ((bmcr & BRGPHY_BMCR_AUTOEN) && (bmsr & BRGPHY_BMSR_ACOMP) == 0 && (bsc->serdes_flags & BRGPHY_NOANWAIT) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { /* * NB: reading the ANAR, ANLPAR or 1000STS after the AUXSTS * wedges at least the PHY of BCM5704 (but not others). */ flowstat = mii_phy_flowstatus(sc); xstat = PHY_READ(sc, BRGPHY_MII_1000STS); aux = PHY_READ(sc, BRGPHY_MII_AUXSTS); /* If copper link is up, get the negotiated speed/duplex. */ if (aux & BRGPHY_AUXSTS_LINK) { mii->mii_media_status |= IFM_ACTIVE; switch (aux & BRGPHY_AUXSTS_AN_RES) { case BRGPHY_RES_1000FD: mii->mii_media_active |= IFM_1000_T | IFM_FDX; break; case BRGPHY_RES_1000HD: mii->mii_media_active |= IFM_1000_T | IFM_HDX; break; case BRGPHY_RES_100FD: mii->mii_media_active |= IFM_100_TX | IFM_FDX; break; case BRGPHY_RES_100T4: mii->mii_media_active |= IFM_100_T4; break; case BRGPHY_RES_100HD: mii->mii_media_active |= IFM_100_TX | IFM_HDX; break; case BRGPHY_RES_10FD: mii->mii_media_active |= IFM_10_T | IFM_FDX; break; case BRGPHY_RES_10HD: mii->mii_media_active |= IFM_10_T | IFM_HDX; break; default: mii->mii_media_active |= IFM_NONE; break; } if ((mii->mii_media_active & IFM_FDX) != 0) mii->mii_media_active |= flowstat; if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T && (xstat & BRGPHY_1000STS_MSR) != 0) mii->mii_media_active |= IFM_ETH_MASTER; } } else { /* Todo: Add support for flow control. */ /* If serdes link is up, get the negotiated speed/duplex. */ if (bmsr & BRGPHY_BMSR_LINK) { mii->mii_media_status |= IFM_ACTIVE; } /* Check the link speed/duplex based on the PHY type. */ if (bsc->serdes_flags & BRGPHY_5706S) { mii->mii_media_active |= IFM_1000_SX; /* If autoneg enabled, read negotiated duplex settings */ if (bmcr & BRGPHY_BMCR_AUTOEN) { val = PHY_READ(sc, BRGPHY_SERDES_ANAR) & PHY_READ(sc, BRGPHY_SERDES_ANLPAR); if (val & BRGPHY_SERDES_ANAR_FDX) mii->mii_media_active |= IFM_FDX; else mii->mii_media_active |= IFM_HDX; } } else if (bsc->serdes_flags & BRGPHY_5708S) { PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG_PG0); xstat = PHY_READ(sc, BRGPHY_5708S_PG0_1000X_STAT1); /* Check for MRBE auto-negotiated speed results. */ switch (xstat & BRGPHY_5708S_PG0_1000X_STAT1_SPEED_MASK) { case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_10: mii->mii_media_active |= IFM_10_FL; break; case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_100: mii->mii_media_active |= IFM_100_FX; break; case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_1G: mii->mii_media_active |= IFM_1000_SX; break; case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_25G: mii->mii_media_active |= IFM_2500_SX; break; } /* Check for MRBE auto-negotiated duplex results. */ if (xstat & BRGPHY_5708S_PG0_1000X_STAT1_FDX) mii->mii_media_active |= IFM_FDX; else mii->mii_media_active |= IFM_HDX; } else if (bsc->serdes_flags & BRGPHY_5709S) { /* Select GP Status Block of the AN MMD, get autoneg results. */ PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_GP_STATUS); xstat = PHY_READ(sc, BRGPHY_GP_STATUS_TOP_ANEG_STATUS); /* Restore IEEE0 block (assumed in all brgphy(4) code). */ PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_COMBO_IEEE0); /* Check for MRBE auto-negotiated speed results. */ switch (xstat & BRGPHY_GP_STATUS_TOP_ANEG_SPEED_MASK) { case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_10: mii->mii_media_active |= IFM_10_FL; break; case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_100: mii->mii_media_active |= IFM_100_FX; break; case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_1G: mii->mii_media_active |= IFM_1000_SX; break; case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_25G: mii->mii_media_active |= IFM_2500_SX; break; } /* Check for MRBE auto-negotiated duplex results. */ if (xstat & BRGPHY_GP_STATUS_TOP_ANEG_FDX) mii->mii_media_active |= IFM_FDX; else mii->mii_media_active |= IFM_HDX; } } } static void brgphy_mii_phy_auto(struct mii_softc *sc, int media) { int anar, ktcr = 0; - PHY_RESET(sc); + PHY_RESET(sc, media); if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0) anar |= BRGPHY_ANAR_PC | BRGPHY_ANAR_ASP; PHY_WRITE(sc, BRGPHY_MII_ANAR, anar); ktcr = BRGPHY_1000CTL_AFD | BRGPHY_1000CTL_AHD; if (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5701) ktcr |= BRGPHY_1000CTL_MSE | BRGPHY_1000CTL_MSC; PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr); PHY_READ(sc, BRGPHY_MII_1000CTL); } else { anar = BRGPHY_SERDES_ANAR_FDX | BRGPHY_SERDES_ANAR_HDX; if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0) anar |= BRGPHY_SERDES_ANAR_BOTH_PAUSE; PHY_WRITE(sc, BRGPHY_SERDES_ANAR, anar); } PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG); PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00); } /* Enable loopback to force the link down. */ static void brgphy_enable_loopback(struct mii_softc *sc) { int i; PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_LOOP); for (i = 0; i < 15000; i++) { if (!(PHY_READ(sc, BRGPHY_MII_BMSR) & BRGPHY_BMSR_LINK)) break; DELAY(10); } } /* Turn off tap power management on 5401. */ static void bcm5401_load_dspcode(struct mii_softc *sc) { static const struct { int reg; uint16_t val; } dspcode[] = { { BRGPHY_MII_AUXCTL, 0x0c20 }, { BRGPHY_MII_DSP_ADDR_REG, 0x0012 }, { BRGPHY_MII_DSP_RW_PORT, 0x1804 }, { BRGPHY_MII_DSP_ADDR_REG, 0x0013 }, { BRGPHY_MII_DSP_RW_PORT, 0x1204 }, { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, { BRGPHY_MII_DSP_RW_PORT, 0x0132 }, { BRGPHY_MII_DSP_ADDR_REG, 0x8006 }, { BRGPHY_MII_DSP_RW_PORT, 0x0232 }, { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, { BRGPHY_MII_DSP_RW_PORT, 0x0a20 }, { 0, 0 }, }; int i; for (i = 0; dspcode[i].reg != 0; i++) PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); DELAY(40); } static void bcm5411_load_dspcode(struct mii_softc *sc) { static const struct { int reg; uint16_t val; } dspcode[] = { { 0x1c, 0x8c23 }, { 0x1c, 0x8ca3 }, { 0x1c, 0x8c23 }, { 0, 0 }, }; int i; for (i = 0; dspcode[i].reg != 0; i++) PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); } void bcm54k2_load_dspcode(struct mii_softc *sc) { static const struct { int reg; uint16_t val; } dspcode[] = { { 4, 0x01e1 }, { 9, 0x0300 }, { 0, 0 }, }; int i; for (i = 0; dspcode[i].reg != 0; i++) PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); } static void brgphy_fixup_5704_a0_bug(struct mii_softc *sc) { static const struct { int reg; uint16_t val; } dspcode[] = { { 0x1c, 0x8d68 }, { 0x1c, 0x8d68 }, { 0, 0 }, }; int i; for (i = 0; dspcode[i].reg != 0; i++) PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); } static void brgphy_fixup_adc_bug(struct mii_softc *sc) { static const struct { int reg; uint16_t val; } dspcode[] = { { BRGPHY_MII_AUXCTL, 0x0c00 }, { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, { BRGPHY_MII_DSP_RW_PORT, 0x2aaa }, { 0, 0 }, }; int i; for (i = 0; dspcode[i].reg != 0; i++) PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); } static void brgphy_fixup_adjust_trim(struct mii_softc *sc) { static const struct { int reg; uint16_t val; } dspcode[] = { { BRGPHY_MII_AUXCTL, 0x0c00 }, { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, { BRGPHY_MII_DSP_RW_PORT, 0x110b }, { BRGPHY_MII_TEST1, 0x0014 }, { BRGPHY_MII_AUXCTL, 0x0400 }, { 0, 0 }, }; int i; for (i = 0; dspcode[i].reg != 0; i++) PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); } static void brgphy_fixup_ber_bug(struct mii_softc *sc) { static const struct { int reg; uint16_t val; } dspcode[] = { { BRGPHY_MII_AUXCTL, 0x0c00 }, { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, { BRGPHY_MII_DSP_RW_PORT, 0x310b }, { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, { BRGPHY_MII_DSP_RW_PORT, 0x9506 }, { BRGPHY_MII_DSP_ADDR_REG, 0x401f }, { BRGPHY_MII_DSP_RW_PORT, 0x14e2 }, { BRGPHY_MII_AUXCTL, 0x0400 }, { 0, 0 }, }; int i; for (i = 0; dspcode[i].reg != 0; i++) PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); } static void brgphy_fixup_crc_bug(struct mii_softc *sc) { static const struct { int reg; uint16_t val; } dspcode[] = { { BRGPHY_MII_DSP_RW_PORT, 0x0a75 }, { 0x1c, 0x8c68 }, { 0x1c, 0x8d68 }, { 0x1c, 0x8c68 }, { 0, 0 }, }; int i; for (i = 0; dspcode[i].reg != 0; i++) PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); } static void brgphy_fixup_jitter_bug(struct mii_softc *sc) { static const struct { int reg; uint16_t val; } dspcode[] = { { BRGPHY_MII_AUXCTL, 0x0c00 }, { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, { BRGPHY_MII_DSP_RW_PORT, 0x010b }, { BRGPHY_MII_AUXCTL, 0x0400 }, { 0, 0 }, }; int i; for (i = 0; dspcode[i].reg != 0; i++) PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); } static void brgphy_fixup_disable_early_dac(struct mii_softc *sc) { uint32_t val; PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x0f08); val = PHY_READ(sc, BRGPHY_MII_DSP_RW_PORT); val &= ~(1 << 8); PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, val); } static void brgphy_ethernet_wirespeed(struct mii_softc *sc) { uint32_t val; /* Enable Ethernet@WireSpeed. */ PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007); val = PHY_READ(sc, BRGPHY_MII_AUXCTL); PHY_WRITE(sc, BRGPHY_MII_AUXCTL, val | (1 << 15) | (1 << 4)); } static void brgphy_jumbo_settings(struct mii_softc *sc, u_long mtu) { uint32_t val; /* Set or clear jumbo frame settings in the PHY. */ if (mtu > ETHER_MAX_LEN) { if (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5401) { /* BCM5401 PHY cannot read-modify-write. */ PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x4c20); } else { PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7); val = PHY_READ(sc, BRGPHY_MII_AUXCTL); PHY_WRITE(sc, BRGPHY_MII_AUXCTL, val | BRGPHY_AUXCTL_LONG_PKT); } val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL); PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, val | BRGPHY_PHY_EXTCTL_HIGH_LA); } else { PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7); val = PHY_READ(sc, BRGPHY_MII_AUXCTL); PHY_WRITE(sc, BRGPHY_MII_AUXCTL, val & ~(BRGPHY_AUXCTL_LONG_PKT | 0x7)); val = PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL); PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, val & ~BRGPHY_PHY_EXTCTL_HIGH_LA); } } static void -brgphy_reset(struct mii_softc *sc) +brgphy_reset(struct mii_softc *sc, if_media_t media) { struct bge_softc *bge_sc = NULL; struct bce_softc *bce_sc = NULL; u_int mtu; int i, val; /* * Perform a reset. Note that at least some Broadcom PHYs default to * being powered down as well as isolated after a reset but don't work * if one or both of these bits are cleared. However, they just work * fine if both bits remain set, so we don't use mii_phy_reset() here. */ PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_RESET); /* Wait 100ms for it to complete. */ for (i = 0; i < 100; i++) { if ((PHY_READ(sc, BRGPHY_MII_BMCR) & BRGPHY_BMCR_RESET) == 0) break; DELAY(1000); } /* Handle any PHY specific procedures following the reset. */ switch (sc->mii_mpd_oui) { case MII_OUI_BROADCOM: switch (sc->mii_mpd_model) { case MII_MODEL_BROADCOM_BCM5400: bcm5401_load_dspcode(sc); break; case MII_MODEL_BROADCOM_BCM5401: if (sc->mii_mpd_rev == 1 || sc->mii_mpd_rev == 3) bcm5401_load_dspcode(sc); break; case MII_MODEL_BROADCOM_BCM5411: bcm5411_load_dspcode(sc); break; case MII_MODEL_BROADCOM_BCM54K2: bcm54k2_load_dspcode(sc); break; } break; case MII_OUI_BROADCOM3: switch (sc->mii_mpd_model) { case MII_MODEL_BROADCOM3_BCM5717C: case MII_MODEL_BROADCOM3_BCM5719C: case MII_MODEL_BROADCOM3_BCM5720C: case MII_MODEL_BROADCOM3_BCM57765: return; } break; case MII_OUI_BROADCOM4: return; } mtu = MIIBUS_READVAR(sc->mii_dev, MIIVAR_MTU); /* Find the driver associated with this PHY. */ if (mii_phy_mac_match(sc, "bge")) bge_sc = mii_phy_mac_softc(sc); else if (mii_phy_mac_match(sc, "bce")) bce_sc = mii_phy_mac_softc(sc); if (bge_sc) { /* Fix up various bugs */ if (bge_sc->bge_phy_flags & BGE_PHY_5704_A0_BUG) brgphy_fixup_5704_a0_bug(sc); if (bge_sc->bge_phy_flags & BGE_PHY_ADC_BUG) brgphy_fixup_adc_bug(sc); if (bge_sc->bge_phy_flags & BGE_PHY_ADJUST_TRIM) brgphy_fixup_adjust_trim(sc); if (bge_sc->bge_phy_flags & BGE_PHY_BER_BUG) brgphy_fixup_ber_bug(sc); if (bge_sc->bge_phy_flags & BGE_PHY_CRC_BUG) brgphy_fixup_crc_bug(sc); if (bge_sc->bge_phy_flags & BGE_PHY_JITTER_BUG) brgphy_fixup_jitter_bug(sc); if (bge_sc->bge_flags & BGE_FLAG_JUMBO) brgphy_jumbo_settings(sc, mtu); if ((bge_sc->bge_phy_flags & BGE_PHY_NO_WIRESPEED) == 0) brgphy_ethernet_wirespeed(sc); /* Enable Link LED on Dell boxes */ if (bge_sc->bge_phy_flags & BGE_PHY_NO_3LED) { PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL) & ~BRGPHY_PHY_EXTCTL_3_LED); } /* Adjust output voltage (From Linux driver) */ if (bge_sc->bge_asicrev == BGE_ASICREV_BCM5906) PHY_WRITE(sc, BRGPHY_MII_EPHY_PTEST, 0x12); } else if (bce_sc) { if (BCE_CHIP_NUM(bce_sc) == BCE_CHIP_NUM_5708 && (bce_sc->bce_phy_flags & BCE_PHY_SERDES_FLAG)) { /* Store autoneg capabilities/results in digital block (Page 0) */ PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG3_PG2); PHY_WRITE(sc, BRGPHY_5708S_PG2_DIGCTL_3_0, BRGPHY_5708S_PG2_DIGCTL_3_0_USE_IEEE); PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG_PG0); /* Enable fiber mode and autodetection */ PHY_WRITE(sc, BRGPHY_5708S_PG0_1000X_CTL1, PHY_READ(sc, BRGPHY_5708S_PG0_1000X_CTL1) | BRGPHY_5708S_PG0_1000X_CTL1_AUTODET_EN | BRGPHY_5708S_PG0_1000X_CTL1_FIBER_MODE); /* Enable parallel detection */ PHY_WRITE(sc, BRGPHY_5708S_PG0_1000X_CTL2, PHY_READ(sc, BRGPHY_5708S_PG0_1000X_CTL2) | BRGPHY_5708S_PG0_1000X_CTL2_PAR_DET_EN); /* Advertise 2.5G support through next page during autoneg */ if (bce_sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG) PHY_WRITE(sc, BRGPHY_5708S_ANEG_NXT_PG_XMIT1, PHY_READ(sc, BRGPHY_5708S_ANEG_NXT_PG_XMIT1) | BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G); /* Increase TX signal amplitude */ if ((BCE_CHIP_ID(bce_sc) == BCE_CHIP_ID_5708_A0) || (BCE_CHIP_ID(bce_sc) == BCE_CHIP_ID_5708_B0) || (BCE_CHIP_ID(bce_sc) == BCE_CHIP_ID_5708_B1)) { PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_TX_MISC_PG5); PHY_WRITE(sc, BRGPHY_5708S_PG5_TXACTL1, PHY_READ(sc, BRGPHY_5708S_PG5_TXACTL1) & ~0x30); PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG_PG0); } /* Backplanes use special driver/pre-driver/pre-emphasis values. */ if ((bce_sc->bce_shared_hw_cfg & BCE_SHARED_HW_CFG_PHY_BACKPLANE) && (bce_sc->bce_port_hw_cfg & BCE_PORT_HW_CFG_CFG_TXCTL3_MASK)) { PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_TX_MISC_PG5); PHY_WRITE(sc, BRGPHY_5708S_PG5_TXACTL3, bce_sc->bce_port_hw_cfg & BCE_PORT_HW_CFG_CFG_TXCTL3_MASK); PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG_PG0); } } else if (BCE_CHIP_NUM(bce_sc) == BCE_CHIP_NUM_5709 && (bce_sc->bce_phy_flags & BCE_PHY_SERDES_FLAG)) { /* Select the SerDes Digital block of the AN MMD. */ PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_SERDES_DIG); val = PHY_READ(sc, BRGPHY_SERDES_DIG_1000X_CTL1); val &= ~BRGPHY_SD_DIG_1000X_CTL1_AUTODET; val |= BRGPHY_SD_DIG_1000X_CTL1_FIBER; PHY_WRITE(sc, BRGPHY_SERDES_DIG_1000X_CTL1, val); /* Select the Over 1G block of the AN MMD. */ PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_OVER_1G); /* Enable autoneg "Next Page" to advertise 2.5G support. */ val = PHY_READ(sc, BRGPHY_OVER_1G_UNFORMAT_PG1); if (bce_sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG) val |= BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G; else val &= ~BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G; PHY_WRITE(sc, BRGPHY_OVER_1G_UNFORMAT_PG1, val); /* Select the Multi-Rate Backplane Ethernet block of the AN MMD. */ PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_MRBE); /* Enable MRBE speed autoneg. */ val = PHY_READ(sc, BRGPHY_MRBE_MSG_PG5_NP); val |= BRGPHY_MRBE_MSG_PG5_NP_MBRE | BRGPHY_MRBE_MSG_PG5_NP_T2; PHY_WRITE(sc, BRGPHY_MRBE_MSG_PG5_NP, val); /* Select the Clause 73 User B0 block of the AN MMD. */ PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_CL73_USER_B0); /* Enable MRBE speed autoneg. */ PHY_WRITE(sc, BRGPHY_CL73_USER_B0_MBRE_CTL1, BRGPHY_CL73_USER_B0_MBRE_CTL1_NP_AFT_BP | BRGPHY_CL73_USER_B0_MBRE_CTL1_STA_MGR | BRGPHY_CL73_USER_B0_MBRE_CTL1_ANEG); /* Restore IEEE0 block (assumed in all brgphy(4) code). */ PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_COMBO_IEEE0); } else if (BCE_CHIP_NUM(bce_sc) == BCE_CHIP_NUM_5709) { if ((BCE_CHIP_REV(bce_sc) == BCE_CHIP_REV_Ax) || (BCE_CHIP_REV(bce_sc) == BCE_CHIP_REV_Bx)) brgphy_fixup_disable_early_dac(sc); brgphy_jumbo_settings(sc, mtu); brgphy_ethernet_wirespeed(sc); } else { brgphy_fixup_ber_bug(sc); brgphy_jumbo_settings(sc, mtu); brgphy_ethernet_wirespeed(sc); } } } Index: projects/ifnet/sys/dev/mii/ciphy.c =================================================================== --- projects/ifnet/sys/dev/mii/ciphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/ciphy.c (revision 282026) @@ -1,369 +1,369 @@ /*- * Copyright (c) 2004 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Driver for the Cicada/Vitesse CS/VSC8xxx 10/100/1000 copper PHY. */ #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" #include static int ciphy_probe(device_t); static int ciphy_attach(device_t); static device_method_t ciphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, ciphy_probe), DEVMETHOD(device_attach, ciphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t ciphy_devclass; static driver_t ciphy_driver = { "ciphy", ciphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(ciphy, miibus, ciphy_driver, ciphy_devclass, 0, 0); -static int ciphy_service(struct mii_softc *, struct mii_data *, int); -static void ciphy_status(struct mii_softc *); -static void ciphy_reset(struct mii_softc *); +static int ciphy_service(struct mii_softc *, struct mii_data *, mii_cmd_t, + if_media_t); +static void ciphy_status(struct mii_softc *, if_media_t); +static void ciphy_reset(struct mii_softc *, if_media_t); static void ciphy_fixup(struct mii_softc *); static const struct mii_phydesc ciphys[] = { MII_PHY_DESC(xxCICADA, CS8201), MII_PHY_DESC(xxCICADA, CS8201A), MII_PHY_DESC(xxCICADA, CS8201B), MII_PHY_DESC(xxCICADA, CS8204), MII_PHY_DESC(xxCICADA, VSC8211), MII_PHY_DESC(xxCICADA, VSC8221), MII_PHY_DESC(xxCICADA, CS8244), MII_PHY_DESC(xxVITESSE, VSC8601), MII_PHY_DESC(xxVITESSE, VSC8641), MII_PHY_END }; static const struct mii_phy_funcs ciphy_funcs = { ciphy_service, ciphy_status, ciphy_reset }; static int ciphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, ciphys, BUS_PROBE_DEFAULT)); } static int ciphy_attach(device_t dev) { mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, &ciphy_funcs, 1); return (0); } static int -ciphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +ciphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int reg, speed, gig; switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: ciphy_fixup(sc); /* XXX hardware bug work-around */ - switch (IFM_SUBTYPE(ife->ifm_media)) { + switch (IFM_SUBTYPE(media)) { case IFM_AUTO: #ifdef foo /* * If we're already in auto mode, just return. */ if (PHY_READ(sc, CIPHY_MII_BMCR) & CIPHY_BMCR_AUTOEN) return (0); #endif - (void)mii_phy_auto(sc); + (void)mii_phy_auto(sc, media); break; case IFM_1000_T: speed = CIPHY_S1000; goto setit; case IFM_100_TX: speed = CIPHY_S100; goto setit; case IFM_10_T: speed = CIPHY_S10; setit: - if ((ife->ifm_media & IFM_FDX) != 0) { + if ((media & IFM_FDX) != 0) { speed |= CIPHY_BMCR_FDX; gig = CIPHY_1000CTL_AFD; } else gig = CIPHY_1000CTL_AHD; - if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) { + if (IFM_SUBTYPE(media) == IFM_1000_T) { gig |= CIPHY_1000CTL_MSE; - if ((ife->ifm_media & IFM_ETH_MASTER) != 0) + if ((media & IFM_ETH_MASTER) != 0) gig |= CIPHY_1000CTL_MSC; speed |= CIPHY_BMCR_AUTOEN | CIPHY_BMCR_STARTNEG; } else gig = 0; PHY_WRITE(sc, CIPHY_MII_1000CTL, gig); PHY_WRITE(sc, CIPHY_MII_BMCR, speed); PHY_WRITE(sc, CIPHY_MII_ANAR, CIPHY_SEL_TYPE); break; case IFM_NONE: PHY_WRITE(sc, MII_BMCR, BMCR_ISO | BMCR_PDOWN); break; default: return (EINVAL); } break; case MII_TICK: /* * Only used for autonegotiation. */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + if (IFM_SUBTYPE(media) != IFM_AUTO) break; /* * Check to see if we have link. If we do, we don't * need to restart the autonegotiation process. Read * the BMSR twice in case it's latched. */ reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (reg & BMSR_LINK) break; /* Announce link loss right after it happens. */ if (++sc->mii_ticks == 0) break; /* * Only retry autonegotiation every mii_anegticks seconds. */ if (sc->mii_ticks <= sc->mii_anegticks) break; sc->mii_ticks = 0; - mii_phy_auto(sc); + mii_phy_auto(sc, media); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* * Callback if something changed. Note that we need to poke * apply fixups for certain PHY revs. */ if (sc->mii_media_active != mii->mii_media_active || sc->mii_media_status != mii->mii_media_status || cmd == MII_MEDIACHG) { ciphy_fixup(sc); } mii_phy_update(sc, cmd); return (0); } static void -ciphy_status(struct mii_softc *sc) +ciphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; int bmsr, bmcr; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (bmsr & BMSR_LINK) mii->mii_media_status |= IFM_ACTIVE; bmcr = PHY_READ(sc, CIPHY_MII_BMCR); if (bmcr & CIPHY_BMCR_LOOP) mii->mii_media_active |= IFM_LOOP; if (bmcr & CIPHY_BMCR_AUTOEN) { if ((bmsr & CIPHY_BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } } bmsr = PHY_READ(sc, CIPHY_MII_AUXCSR); switch (bmsr & CIPHY_AUXCSR_SPEED) { case CIPHY_SPEED10: mii->mii_media_active |= IFM_10_T; break; case CIPHY_SPEED100: mii->mii_media_active |= IFM_100_TX; break; case CIPHY_SPEED1000: mii->mii_media_active |= IFM_1000_T; break; default: device_printf(sc->mii_dev, "unknown PHY speed %x\n", bmsr & CIPHY_AUXCSR_SPEED); break; } if (bmsr & CIPHY_AUXCSR_FDX) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) && (PHY_READ(sc, CIPHY_MII_1000STS) & CIPHY_1000STS_MSR) != 0) mii->mii_media_active |= IFM_ETH_MASTER; } static void -ciphy_reset(struct mii_softc *sc) +ciphy_reset(struct mii_softc *sc, if_media_t media) { - mii_phy_reset(sc); + mii_phy_reset(sc, media); DELAY(1000); } #define PHY_SETBIT(x, y, z) \ PHY_WRITE(x, y, (PHY_READ(x, y) | (z))) #define PHY_CLRBIT(x, y, z) \ PHY_WRITE(x, y, (PHY_READ(x, y) & ~(z))) static void ciphy_fixup(struct mii_softc *sc) { uint16_t model; uint16_t status, speed; uint16_t val; model = MII_MODEL(PHY_READ(sc, CIPHY_MII_PHYIDR2)); status = PHY_READ(sc, CIPHY_MII_AUXCSR); speed = status & CIPHY_AUXCSR_SPEED; if (mii_phy_mac_match(sc, "nfe")) { /* need to set for 2.5V RGMII for NVIDIA adapters */ val = PHY_READ(sc, CIPHY_MII_ECTL1); val &= ~(CIPHY_ECTL1_IOVOL | CIPHY_ECTL1_INTSEL); val |= (CIPHY_IOVOL_2500MV | CIPHY_INTSEL_RGMII); PHY_WRITE(sc, CIPHY_MII_ECTL1, val); /* From Linux. */ val = PHY_READ(sc, CIPHY_MII_AUXCSR); val |= CIPHY_AUXCSR_MDPPS; PHY_WRITE(sc, CIPHY_MII_AUXCSR, val); val = PHY_READ(sc, CIPHY_MII_10BTCSR); val |= CIPHY_10BTCSR_ECHO; PHY_WRITE(sc, CIPHY_MII_10BTCSR, val); } switch (model) { case MII_MODEL_xxCICADA_CS8204: case MII_MODEL_xxCICADA_CS8201: /* Turn off "aux mode" (whatever that means) */ PHY_SETBIT(sc, CIPHY_MII_AUXCSR, CIPHY_AUXCSR_MDPPS); /* * Work around speed polling bug in VT3119/VT3216 * when using MII in full duplex mode. */ if ((speed == CIPHY_SPEED10 || speed == CIPHY_SPEED100) && (status & CIPHY_AUXCSR_FDX)) { PHY_SETBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); } else { PHY_CLRBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); } /* Enable link/activity LED blink. */ PHY_SETBIT(sc, CIPHY_MII_LED, CIPHY_LED_LINKACTBLINK); break; case MII_MODEL_xxCICADA_CS8201A: case MII_MODEL_xxCICADA_CS8201B: /* * Work around speed polling bug in VT3119/VT3216 * when using MII in full duplex mode. */ if ((speed == CIPHY_SPEED10 || speed == CIPHY_SPEED100) && (status & CIPHY_AUXCSR_FDX)) { PHY_SETBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); } else { PHY_CLRBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); } break; case MII_MODEL_xxCICADA_VSC8211: case MII_MODEL_xxCICADA_VSC8221: case MII_MODEL_xxCICADA_CS8244: case MII_MODEL_xxVITESSE_VSC8601: case MII_MODEL_xxVITESSE_VSC8641: break; default: device_printf(sc->mii_dev, "unknown CICADA PHY model %x\n", model); break; } } Index: projects/ifnet/sys/dev/mii/e1000phy.c =================================================================== --- projects/ifnet/sys/dev/mii/e1000phy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/e1000phy.c (revision 282026) @@ -1,499 +1,499 @@ /*- * Principal Author: Parag Patel * Copyright (c) 2001 * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Additional Copyright (c) 2001 by Traakan Software under same licence. * Secondary Author: Matthew Jacob */ #include __FBSDID("$FreeBSD$"); /* * driver for the Marvell 88E1000 series external 1000/100/10-BT PHY. */ /* * Support added for the Marvell 88E1011 (Alaska) 1000/100/10baseTX and * 1000baseSX PHY. * Nathan Binkert * Jung-uk Kim */ #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" static int e1000phy_probe(device_t); static int e1000phy_attach(device_t); static device_method_t e1000phy_methods[] = { /* device interface */ DEVMETHOD(device_probe, e1000phy_probe), DEVMETHOD(device_attach, e1000phy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t e1000phy_devclass; static driver_t e1000phy_driver = { "e1000phy", e1000phy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(e1000phy, miibus, e1000phy_driver, e1000phy_devclass, 0, 0); -static int e1000phy_service(struct mii_softc *, struct mii_data *, int); -static void e1000phy_status(struct mii_softc *); -static void e1000phy_reset(struct mii_softc *); -static int e1000phy_mii_phy_auto(struct mii_softc *, int); +static int e1000phy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void e1000phy_status(struct mii_softc *, if_media_t); +static void e1000phy_reset(struct mii_softc *, if_media_t); +static int e1000phy_mii_phy_auto(struct mii_softc *, if_media_t); static const struct mii_phydesc e1000phys[] = { MII_PHY_DESC(MARVELL, E1000), MII_PHY_DESC(MARVELL, E1011), MII_PHY_DESC(MARVELL, E1000_3), MII_PHY_DESC(MARVELL, E1000_5), MII_PHY_DESC(MARVELL, E1111), MII_PHY_DESC(xxMARVELL, E1000), MII_PHY_DESC(xxMARVELL, E1011), MII_PHY_DESC(xxMARVELL, E1000_3), MII_PHY_DESC(xxMARVELL, E1000S), MII_PHY_DESC(xxMARVELL, E1000_5), MII_PHY_DESC(xxMARVELL, E1101), MII_PHY_DESC(xxMARVELL, E3082), MII_PHY_DESC(xxMARVELL, E1112), MII_PHY_DESC(xxMARVELL, E1149), MII_PHY_DESC(xxMARVELL, E1111), MII_PHY_DESC(xxMARVELL, E1116), MII_PHY_DESC(xxMARVELL, E1116R), MII_PHY_DESC(xxMARVELL, E1116R_29), MII_PHY_DESC(xxMARVELL, E1118), MII_PHY_DESC(xxMARVELL, E1145), MII_PHY_DESC(xxMARVELL, E1149R), MII_PHY_DESC(xxMARVELL, E3016), MII_PHY_DESC(xxMARVELL, PHYG65G), MII_PHY_END }; static const struct mii_phy_funcs e1000phy_funcs = { e1000phy_service, e1000phy_status, e1000phy_reset }; static int e1000phy_probe(device_t dev) { return (mii_phy_dev_probe(dev, e1000phys, BUS_PROBE_DEFAULT)); } static int e1000phy_attach(device_t dev) { struct mii_softc *sc; sc = device_get_softc(dev); mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &e1000phy_funcs, 0); if (mii_dev_mac_match(dev, "msk") && (sc->mii_flags & MIIF_MACPRIV0) != 0) sc->mii_flags |= MIIF_PHYPRIV0; switch (sc->mii_mpd_model) { case MII_MODEL_xxMARVELL_E1011: case MII_MODEL_xxMARVELL_E1112: if (PHY_READ(sc, E1000_ESSR) & E1000_ESSR_FIBER_LINK) sc->mii_flags |= MIIF_HAVEFIBER; break; case MII_MODEL_xxMARVELL_E1149: case MII_MODEL_xxMARVELL_E1149R: /* * Some 88E1149 PHY's page select is initialized to * point to other bank instead of copper/fiber bank * which in turn resulted in wrong registers were * accessed during PHY operation. It is believed that * page 0 should be used for copper PHY so reinitialize * E1000_EADR to select default copper PHY. If parent * device know the type of PHY(either copper or fiber), * that information should be used to select default * type of PHY. */ PHY_WRITE(sc, E1000_EADR, 0); break; } - PHY_RESET(sc); + PHY_RESET(sc, 0); sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask; if (sc->mii_capabilities & BMSR_EXTSTAT) { sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); if ((sc->mii_extcapabilities & (EXTSR_1000TFDX | EXTSR_1000THDX)) != 0) sc->mii_flags |= MIIF_HAVE_GTCR; } device_printf(dev, " "); - mii_phy_add_media(sc); + mii_phy_generic_media(sc); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); return (0); } static void -e1000phy_reset(struct mii_softc *sc) +e1000phy_reset(struct mii_softc *sc, if_media_t media) { uint16_t reg, page; reg = PHY_READ(sc, E1000_SCR); if ((sc->mii_flags & MIIF_HAVEFIBER) != 0) { reg &= ~E1000_SCR_AUTO_X_MODE; PHY_WRITE(sc, E1000_SCR, reg); if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1112) { /* Select 1000BASE-X only mode. */ page = PHY_READ(sc, E1000_EADR); PHY_WRITE(sc, E1000_EADR, 2); reg = PHY_READ(sc, E1000_SCR); reg &= ~E1000_SCR_MODE_MASK; reg |= E1000_SCR_MODE_1000BX; PHY_WRITE(sc, E1000_SCR, reg); if ((sc->mii_flags & MIIF_PHYPRIV0) != 0) { /* Set SIGDET polarity low for SFP module. */ PHY_WRITE(sc, E1000_EADR, 1); reg = PHY_READ(sc, E1000_SCR); reg |= E1000_SCR_FIB_SIGDET_POLARITY; PHY_WRITE(sc, E1000_SCR, reg); } PHY_WRITE(sc, E1000_EADR, page); } } else { switch (sc->mii_mpd_model) { case MII_MODEL_xxMARVELL_E1111: case MII_MODEL_xxMARVELL_E1112: case MII_MODEL_xxMARVELL_E1116: case MII_MODEL_xxMARVELL_E1116R_29: case MII_MODEL_xxMARVELL_E1118: case MII_MODEL_xxMARVELL_E1149: case MII_MODEL_xxMARVELL_E1149R: case MII_MODEL_xxMARVELL_PHYG65G: /* Disable energy detect mode. */ reg &= ~E1000_SCR_EN_DETECT_MASK; reg |= E1000_SCR_AUTO_X_MODE; if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1116 || sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1116R_29) reg &= ~E1000_SCR_POWER_DOWN; reg |= E1000_SCR_ASSERT_CRS_ON_TX; break; case MII_MODEL_xxMARVELL_E3082: reg |= (E1000_SCR_AUTO_X_MODE >> 1); reg |= E1000_SCR_ASSERT_CRS_ON_TX; break; case MII_MODEL_xxMARVELL_E3016: reg |= E1000_SCR_AUTO_MDIX; reg &= ~(E1000_SCR_EN_DETECT | E1000_SCR_SCRAMBLER_DISABLE); reg |= E1000_SCR_LPNP; /* XXX Enable class A driver for Yukon FE+ A0. */ PHY_WRITE(sc, 0x1C, PHY_READ(sc, 0x1C) | 0x0001); break; default: reg &= ~E1000_SCR_AUTO_X_MODE; reg |= E1000_SCR_ASSERT_CRS_ON_TX; break; } if (sc->mii_mpd_model != MII_MODEL_xxMARVELL_E3016) { /* Auto correction for reversed cable polarity. */ reg &= ~E1000_SCR_POLARITY_REVERSAL; } PHY_WRITE(sc, E1000_SCR, reg); if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1116 || sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1116R_29 || sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1149 || sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1149R) { PHY_WRITE(sc, E1000_EADR, 2); reg = PHY_READ(sc, E1000_SCR); reg |= E1000_SCR_RGMII_POWER_UP; PHY_WRITE(sc, E1000_SCR, reg); PHY_WRITE(sc, E1000_EADR, 0); } } switch (sc->mii_mpd_model) { case MII_MODEL_xxMARVELL_E3082: case MII_MODEL_xxMARVELL_E1112: case MII_MODEL_xxMARVELL_E1118: break; case MII_MODEL_xxMARVELL_E1116: case MII_MODEL_xxMARVELL_E1116R_29: page = PHY_READ(sc, E1000_EADR); /* Select page 3, LED control register. */ PHY_WRITE(sc, E1000_EADR, 3); PHY_WRITE(sc, E1000_SCR, E1000_SCR_LED_LOS(1) | /* Link/Act */ E1000_SCR_LED_INIT(8) | /* 10Mbps */ E1000_SCR_LED_STAT1(7) | /* 100Mbps */ E1000_SCR_LED_STAT0(7)); /* 1000Mbps */ /* Set blink rate. */ PHY_WRITE(sc, E1000_IER, E1000_PULSE_DUR(E1000_PULSE_170MS) | E1000_BLINK_RATE(E1000_BLINK_84MS)); PHY_WRITE(sc, E1000_EADR, page); break; case MII_MODEL_xxMARVELL_E3016: /* LED2 -> ACT, LED1 -> LINK, LED0 -> SPEED. */ PHY_WRITE(sc, 0x16, 0x0B << 8 | 0x05 << 4 | 0x04); /* Integrated register calibration workaround. */ PHY_WRITE(sc, 0x1D, 17); PHY_WRITE(sc, 0x1E, 0x3F60); break; default: /* Force TX_CLK to 25MHz clock. */ reg = PHY_READ(sc, E1000_ESCR); reg |= E1000_ESCR_TX_CLK_25; PHY_WRITE(sc, E1000_ESCR, reg); break; } /* Reset the PHY so all changes take effect. */ reg = PHY_READ(sc, E1000_CR); reg |= E1000_CR_RESET; PHY_WRITE(sc, E1000_CR, reg); } static int -e1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +e1000phy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; uint16_t speed, gig; int reg; switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { - e1000phy_mii_phy_auto(sc, ife->ifm_media); + if (IFM_SUBTYPE(media) == IFM_AUTO) { + e1000phy_mii_phy_auto(sc, media); break; } speed = 0; - switch (IFM_SUBTYPE(ife->ifm_media)) { + switch (IFM_SUBTYPE(media)) { case IFM_1000_T: if ((sc->mii_flags & MIIF_HAVE_GTCR) == 0) return (EINVAL); speed = E1000_CR_SPEED_1000; break; case IFM_1000_SX: if ((sc->mii_extcapabilities & (EXTSR_1000XFDX | EXTSR_1000XHDX)) == 0) return (EINVAL); speed = E1000_CR_SPEED_1000; break; case IFM_100_TX: speed = E1000_CR_SPEED_100; break; case IFM_10_T: speed = E1000_CR_SPEED_10; break; case IFM_NONE: reg = PHY_READ(sc, E1000_CR); PHY_WRITE(sc, E1000_CR, reg | E1000_CR_ISOLATE | E1000_CR_POWER_DOWN); goto done; default: return (EINVAL); } - if ((ife->ifm_media & IFM_FDX) != 0) { + if ((media & IFM_FDX) != 0) { speed |= E1000_CR_FULL_DUPLEX; gig = E1000_1GCR_1000T_FD; } else gig = E1000_1GCR_1000T; reg = PHY_READ(sc, E1000_CR); reg &= ~E1000_CR_AUTO_NEG_ENABLE; PHY_WRITE(sc, E1000_CR, reg | E1000_CR_RESET); - if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) { + if (IFM_SUBTYPE(media) == IFM_1000_T) { gig |= E1000_1GCR_MS_ENABLE; - if ((ife->ifm_media & IFM_ETH_MASTER) != 0) + if ((media & IFM_ETH_MASTER) != 0) gig |= E1000_1GCR_MS_VALUE; } else if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0) gig = 0; PHY_WRITE(sc, E1000_1GCR, gig); PHY_WRITE(sc, E1000_AR, E1000_AR_SELECTOR_FIELD); PHY_WRITE(sc, E1000_CR, speed | E1000_CR_RESET); done: break; case MII_TICK: /* * Only used for autonegotiation. */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { + if (IFM_SUBTYPE(media) != IFM_AUTO) { sc->mii_ticks = 0; break; } /* * check for link. * 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) { sc->mii_ticks = 0; break; } /* Announce link loss right after it happens. */ if (sc->mii_ticks++ == 0) break; if (sc->mii_ticks <= sc->mii_anegticks) break; sc->mii_ticks = 0; - PHY_RESET(sc); - e1000phy_mii_phy_auto(sc, ife->ifm_media); + PHY_RESET(sc, media); + e1000phy_mii_phy_auto(sc, media); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -e1000phy_status(struct mii_softc *sc) +e1000phy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; int bmcr, bmsr, ssr; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, E1000_SR) | PHY_READ(sc, E1000_SR); bmcr = PHY_READ(sc, E1000_CR); ssr = PHY_READ(sc, E1000_SSR); if (bmsr & E1000_SR_LINK_STATUS) mii->mii_media_status |= IFM_ACTIVE; if (bmcr & E1000_CR_LOOPBACK) mii->mii_media_active |= IFM_LOOP; if ((bmcr & E1000_CR_AUTO_NEG_ENABLE) != 0 && (ssr & E1000_SSR_SPD_DPLX_RESOLVED) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { switch (ssr & E1000_SSR_SPEED) { case E1000_SSR_1000MBS: mii->mii_media_active |= IFM_1000_T; break; case E1000_SSR_100MBS: mii->mii_media_active |= IFM_100_TX; break; case E1000_SSR_10MBS: mii->mii_media_active |= IFM_10_T; break; default: mii->mii_media_active |= IFM_NONE; return; } } else { /* * Some fiber PHY(88E1112) does not seem to set resolved * speed so always assume we've got IFM_1000_SX. */ mii->mii_media_active |= IFM_1000_SX; } if (ssr & E1000_SSR_DUPLEX) { mii->mii_media_active |= IFM_FDX; if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) mii->mii_media_active |= mii_phy_flowstatus(sc); } else mii->mii_media_active |= IFM_HDX; if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) { if (((PHY_READ(sc, E1000_1GSR) | PHY_READ(sc, E1000_1GSR)) & E1000_1GSR_MS_CONFIG_RES) != 0) mii->mii_media_active |= IFM_ETH_MASTER; } } static int -e1000phy_mii_phy_auto(struct mii_softc *sc, int media) +e1000phy_mii_phy_auto(struct mii_softc *sc, if_media_t media) { uint16_t reg; if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { reg = PHY_READ(sc, E1000_AR); reg &= ~(E1000_AR_PAUSE | E1000_AR_ASM_DIR); reg |= E1000_AR_10T | E1000_AR_10T_FD | E1000_AR_100TX | E1000_AR_100TX_FD; if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0) reg |= E1000_AR_PAUSE | E1000_AR_ASM_DIR; PHY_WRITE(sc, E1000_AR, reg | E1000_AR_SELECTOR_FIELD); } else PHY_WRITE(sc, E1000_AR, E1000_FA_1000X_FD | E1000_FA_1000X); if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0) { reg = 0; if ((sc->mii_extcapabilities & EXTSR_1000TFDX) != 0) reg |= E1000_1GCR_1000T_FD; if ((sc->mii_extcapabilities & EXTSR_1000THDX) != 0) reg |= E1000_1GCR_1000T; PHY_WRITE(sc, E1000_1GCR, reg); } PHY_WRITE(sc, E1000_CR, E1000_CR_AUTO_NEG_ENABLE | E1000_CR_RESTART_AUTO_NEG); return (EJUSTRETURN); } Index: projects/ifnet/sys/dev/mii/gentbi.c =================================================================== --- projects/ifnet/sys/dev/mii/gentbi.c (revision 282025) +++ projects/ifnet/sys/dev/mii/gentbi.c (revision 282026) @@ -1,261 +1,261 @@ /* $NetBSD: gentbi.c,v 1.15 2006/03/29 07:05:24 thorpej Exp $ */ /*- * 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 * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1997 Manuel Bouyer. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Driver for generic ten-bit (1000BASE-SX) interfaces, built into * many Gigabit Ethernet chips. * * All we have to do here is correctly report speed and duplex. */ #include __FBSDID("$FreeBSD$"); /* * Driver for generic unknown ten-bit interfaces(1000BASE-{LX,SX} * fiber interfaces). */ #include #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include "miibus_if.h" static int gentbi_probe(device_t); static int gentbi_attach(device_t); static device_method_t gentbi_methods[] = { /* device interface */ DEVMETHOD(device_probe, gentbi_probe), DEVMETHOD(device_attach, gentbi_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t gentbi_devclass; static driver_t gentbi_driver = { "gentbi", gentbi_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(gentbi, miibus, gentbi_driver, gentbi_devclass, 0, 0); -static int gentbi_service(struct mii_softc *, struct mii_data *, int); -static void gentbi_status(struct mii_softc *); +static int gentbi_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void gentbi_status(struct mii_softc *, if_media_t); static const struct mii_phy_funcs gentbi_funcs = { gentbi_service, gentbi_status, mii_phy_reset }; static int gentbi_probe(device_t dev) { device_t parent; struct mii_attach_args *ma; int bmsr, extsr; parent = device_get_parent(dev); ma = device_get_ivars(dev); /* * We match as a generic TBI if: * * - There is no media in the BMSR. * - EXTSR has only 1000X. */ bmsr = MIIBUS_READREG(parent, ma->mii_phyno, MII_BMSR); if ((bmsr & BMSR_EXTSTAT) == 0 || (bmsr & BMSR_MEDIAMASK) != 0) return (ENXIO); extsr = MIIBUS_READREG(parent, ma->mii_phyno, MII_EXTSR); if (extsr & (EXTSR_1000TFDX|EXTSR_1000THDX)) return (ENXIO); if (extsr & (EXTSR_1000XFDX|EXTSR_1000XHDX)) { /* * We think this is a generic TBI. Return a match * priority higher than ukphy, but lower than what * specific drivers will return. */ device_set_desc(dev, "Generic ten-bit interface"); return (BUS_PROBE_LOW_PRIORITY); } return (ENXIO); } static int gentbi_attach(device_t dev) { struct mii_softc *sc; sc = device_get_softc(dev); mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &gentbi_funcs, 0); - PHY_RESET(sc); + PHY_RESET(sc, 0); /* * Mask out all media in the BMSR. We only are really interested * in "auto". */ sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask & ~BMSR_MEDIAMASK; if (sc->mii_capabilities & BMSR_EXTSTAT) sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); device_printf(dev, " "); - mii_phy_add_media(sc); + mii_phy_generic_media(sc); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); return (0); } static int -gentbi_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +gentbi_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; case MII_TICK: if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -gentbi_status(struct mii_softc *sc) +gentbi_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmsr, bmcr, anlpar; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (bmsr & BMSR_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; if (bmcr & BMCR_AUTOEN) { /* * The media status bits are only valid if autonegotiation * has completed (or it's disabled). */ if ((bmsr & BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } /* * The media is always 1000baseSX. Check the ANLPAR to * see if we're doing full-duplex. */ mii->mii_media_active |= IFM_1000_SX; anlpar = PHY_READ(sc, MII_ANLPAR); if ((sc->mii_extcapabilities & EXTSR_1000XFDX) != 0 && (anlpar & ANLPAR_X_FD) != 0) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; } else - mii->mii_media_active = ife->ifm_media; + mii->mii_media_active = media; } Index: projects/ifnet/sys/dev/mii/icsphy.c =================================================================== --- projects/ifnet/sys/dev/mii/icsphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/icsphy.c (revision 282026) @@ -1,239 +1,239 @@ /* $NetBSD: icsphy.c,v 1.41 2006/11/16 21:24:07 christos Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 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 * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1997 Manuel Bouyer. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * driver for Integrated Circuit Systems' ICS1889-1893 ethernet 10/100 PHY * datasheet from www.icst.com */ #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" static int icsphy_probe(device_t dev); static int icsphy_attach(device_t dev); static device_method_t icsphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, icsphy_probe), DEVMETHOD(device_attach, icsphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t icsphy_devclass; static driver_t icsphy_driver = { "icsphy", icsphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(icsphy, miibus, icsphy_driver, icsphy_devclass, 0, 0); -static int icsphy_service(struct mii_softc *, struct mii_data *, int); -static void icsphy_status(struct mii_softc *); -static void icsphy_reset(struct mii_softc *); +static int icsphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void icsphy_status(struct mii_softc *, if_media_t); +static void icsphy_reset(struct mii_softc *, if_media_t); static const struct mii_phydesc icsphys[] = { MII_PHY_DESC(ICS, 1889), MII_PHY_DESC(ICS, 1890), MII_PHY_DESC(ICS, 1892), MII_PHY_DESC(ICS, 1893), MII_PHY_END }; static const struct mii_phy_funcs icsphy_funcs = { icsphy_service, icsphy_status, icsphy_reset }; static int icsphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, icsphys, BUS_PROBE_DEFAULT)); } static int icsphy_attach(device_t dev) { mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, &icsphy_funcs, 1); return (0); } static int -icsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +icsphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; case MII_TICK: if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -icsphy_status(struct mii_softc *sc) +icsphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmcr, qpr; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; /* * Don't get link from the BMSR. It's available in the QPR, * and we have to read it twice to unlatch it anyhow. This * gives us fewer register reads. */ qpr = PHY_READ(sc, MII_ICSPHY_QPR); /* unlatch */ qpr = PHY_READ(sc, MII_ICSPHY_QPR); /* real value */ if (qpr & QPR_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; if (bmcr & BMCR_AUTOEN) { if ((qpr & QPR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } if (qpr & QPR_SPEED) mii->mii_media_active |= IFM_100_TX; else mii->mii_media_active |= IFM_10_T; if (qpr & QPR_FDX) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; } else - mii->mii_media_active = ife->ifm_media; + mii->mii_media_active = media; } static void -icsphy_reset(struct mii_softc *sc) +icsphy_reset(struct mii_softc *sc, if_media_t media) { - mii_phy_reset(sc); + mii_phy_reset(sc, media); /* set powerdown feature */ switch (sc->mii_mpd_model) { case MII_MODEL_ICS_1890: case MII_MODEL_ICS_1893: PHY_WRITE(sc, MII_ICSPHY_ECR2, ECR2_100AUTOPWRDN); break; case MII_MODEL_ICS_1892: PHY_WRITE(sc, MII_ICSPHY_ECR2, ECR2_10AUTOPWRDN|ECR2_100AUTOPWRDN); break; default: /* 1889 have no ECR2 */ break; } /* * There is no description that the reset do auto-negotiation in the * data sheet. */ PHY_WRITE(sc, MII_BMCR, BMCR_S100|BMCR_STARTNEG|BMCR_FDX); } Index: projects/ifnet/sys/dev/mii/ip1000phy.c =================================================================== --- projects/ifnet/sys/dev/mii/ip1000phy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/ip1000phy.c (revision 282026) @@ -1,355 +1,355 @@ /*- * Copyright (c) 2006, Pyun YongHyeon * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); /* * Driver for the IC Plus IP1000A/IP1001 10/100/1000 PHY. */ #include #include #include #include #include /* XXXGL: if_stgereg.h contamination */ #include /* XXXGL: if_stgereg.h contamination */ #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" #include #include static int ip1000phy_probe(device_t); static int ip1000phy_attach(device_t); static device_method_t ip1000phy_methods[] = { /* device interface */ DEVMETHOD(device_probe, ip1000phy_probe), DEVMETHOD(device_attach, ip1000phy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t ip1000phy_devclass; static driver_t ip1000phy_driver = { "ip1000phy", ip1000phy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(ip1000phy, miibus, ip1000phy_driver, ip1000phy_devclass, 0, 0); -static int ip1000phy_service(struct mii_softc *, struct mii_data *, int); -static void ip1000phy_status(struct mii_softc *); -static void ip1000phy_reset(struct mii_softc *); -static int ip1000phy_mii_phy_auto(struct mii_softc *, int); +static int ip1000phy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void ip1000phy_status(struct mii_softc *, if_media_t); +static void ip1000phy_reset(struct mii_softc *, if_media_t); +static int ip1000phy_mii_phy_auto(struct mii_softc *, if_media_t); static const struct mii_phydesc ip1000phys[] = { MII_PHY_DESC(xxICPLUS, IP1000A), MII_PHY_DESC(xxICPLUS, IP1001), MII_PHY_END }; static const struct mii_phy_funcs ip1000phy_funcs = { ip1000phy_service, ip1000phy_status, ip1000phy_reset }; static int ip1000phy_probe(device_t dev) { return (mii_phy_dev_probe(dev, ip1000phys, BUS_PROBE_DEFAULT)); } static int ip1000phy_attach(device_t dev) { struct mii_attach_args *ma; u_int flags; ma = device_get_ivars(dev); flags = MIIF_NOISOLATE | MIIF_NOMANPAUSE; if (MII_MODEL(ma->mii_id2) == MII_MODEL_xxICPLUS_IP1000A && mii_dev_mac_match(dev, "stge") && (miibus_get_flags(dev) & MIIF_MACPRIV0) != 0) flags |= MIIF_PHYPRIV0; mii_phy_dev_attach(dev, flags, &ip1000phy_funcs, 1); return (0); } static int -ip1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +ip1000phy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; uint32_t gig, reg, speed; switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - PHY_RESET(sc); - switch (IFM_SUBTYPE(ife->ifm_media)) { + PHY_RESET(sc, media); + switch (IFM_SUBTYPE(media)) { case IFM_AUTO: - (void)ip1000phy_mii_phy_auto(sc, ife->ifm_media); + (void)ip1000phy_mii_phy_auto(sc, media); goto done; case IFM_1000_T: /* * XXX * Manual 1000baseT setting doesn't seem to work. */ speed = IP1000PHY_BMCR_1000; break; case IFM_100_TX: speed = IP1000PHY_BMCR_100; break; case IFM_10_T: speed = IP1000PHY_BMCR_10; break; default: return (EINVAL); } - if ((ife->ifm_media & IFM_FDX) != 0) { + if ((media & IFM_FDX) != 0) { speed |= IP1000PHY_BMCR_FDX; gig = IP1000PHY_1000CR_1000T_FDX; } else gig = IP1000PHY_1000CR_1000T; - if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) { + if (IFM_SUBTYPE(media) == IFM_1000_T) { gig |= IP1000PHY_1000CR_MASTER | IP1000PHY_1000CR_MANUAL; - if ((ife->ifm_media & IFM_ETH_MASTER) != 0) + if ((media & IFM_ETH_MASTER) != 0) gig |= IP1000PHY_1000CR_MMASTER; } else gig = 0; PHY_WRITE(sc, IP1000PHY_MII_1000CR, gig); PHY_WRITE(sc, IP1000PHY_MII_BMCR, speed); done: break; case MII_TICK: /* * Only used for autonegotiation. */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { + if (IFM_SUBTYPE(media) != IFM_AUTO) { sc->mii_ticks = 0; break; } /* * check for link. */ reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (reg & BMSR_LINK) { sc->mii_ticks = 0; break; } /* Announce link loss right after it happens */ if (sc->mii_ticks++ == 0) break; /* * Only retry autonegotiation every mii_anegticks seconds. */ if (sc->mii_ticks <= sc->mii_anegticks) break; sc->mii_ticks = 0; - ip1000phy_mii_phy_auto(sc, ife->ifm_media); + ip1000phy_mii_phy_auto(sc, media); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -ip1000phy_status(struct mii_softc *sc) +ip1000phy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; uint32_t bmsr, bmcr, stat; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, IP1000PHY_MII_BMSR) | PHY_READ(sc, IP1000PHY_MII_BMSR); if ((bmsr & IP1000PHY_BMSR_LINK) != 0) mii->mii_media_status |= IFM_ACTIVE; bmcr = PHY_READ(sc, IP1000PHY_MII_BMCR); if ((bmcr & IP1000PHY_BMCR_LOOP) != 0) mii->mii_media_active |= IFM_LOOP; if ((bmcr & IP1000PHY_BMCR_AUTOEN) != 0) { if ((bmsr & IP1000PHY_BMSR_ANEGCOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } } if (sc->mii_mpd_model == MII_MODEL_xxICPLUS_IP1001) { stat = PHY_READ(sc, IP1000PHY_LSR); switch (stat & IP1000PHY_LSR_SPEED_MASK) { case IP1000PHY_LSR_SPEED_10: mii->mii_media_active |= IFM_10_T; break; case IP1000PHY_LSR_SPEED_100: mii->mii_media_active |= IFM_100_TX; break; case IP1000PHY_LSR_SPEED_1000: mii->mii_media_active |= IFM_1000_T; break; default: mii->mii_media_active |= IFM_NONE; return; } if ((stat & IP1000PHY_LSR_FULL_DUPLEX) != 0) mii->mii_media_active |= IFM_FDX; else mii->mii_media_active |= IFM_HDX; } else { stat = PHY_READ(sc, STGE_PhyCtrl); switch (PC_LinkSpeed(stat)) { case PC_LinkSpeed_Down: mii->mii_media_active |= IFM_NONE; return; case PC_LinkSpeed_10: mii->mii_media_active |= IFM_10_T; break; case PC_LinkSpeed_100: mii->mii_media_active |= IFM_100_TX; break; case PC_LinkSpeed_1000: mii->mii_media_active |= IFM_1000_T; break; default: mii->mii_media_active |= IFM_NONE; return; } if ((stat & PC_PhyDuplexStatus) != 0) mii->mii_media_active |= IFM_FDX; else mii->mii_media_active |= IFM_HDX; } if ((mii->mii_media_active & IFM_FDX) != 0) mii->mii_media_active |= mii_phy_flowstatus(sc); if ((mii->mii_media_active & IFM_1000_T) != 0) { stat = PHY_READ(sc, IP1000PHY_MII_1000SR); if ((stat & IP1000PHY_1000SR_MASTER) != 0) mii->mii_media_active |= IFM_ETH_MASTER; } } static int -ip1000phy_mii_phy_auto(struct mii_softc *sc, int media) +ip1000phy_mii_phy_auto(struct mii_softc *sc, if_media_t media) { uint32_t reg; reg = 0; if (sc->mii_mpd_model == MII_MODEL_xxICPLUS_IP1001) { reg = PHY_READ(sc, IP1000PHY_MII_ANAR); reg &= ~(IP1000PHY_ANAR_PAUSE | IP1000PHY_ANAR_APAUSE); reg |= IP1000PHY_ANAR_NP; } reg |= IP1000PHY_ANAR_10T | IP1000PHY_ANAR_10T_FDX | IP1000PHY_ANAR_100TX | IP1000PHY_ANAR_100TX_FDX; if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0) reg |= IP1000PHY_ANAR_PAUSE | IP1000PHY_ANAR_APAUSE; PHY_WRITE(sc, IP1000PHY_MII_ANAR, reg | IP1000PHY_ANAR_CSMA); reg = IP1000PHY_1000CR_1000T | IP1000PHY_1000CR_1000T_FDX; if (sc->mii_mpd_model != MII_MODEL_xxICPLUS_IP1001) reg |= IP1000PHY_1000CR_MASTER; PHY_WRITE(sc, IP1000PHY_MII_1000CR, reg); PHY_WRITE(sc, IP1000PHY_MII_BMCR, (IP1000PHY_BMCR_FDX | IP1000PHY_BMCR_AUTOEN | IP1000PHY_BMCR_STARTNEG)); return (EJUSTRETURN); } static void ip1000phy_load_dspcode(struct mii_softc *sc) { PHY_WRITE(sc, 31, 0x0001); PHY_WRITE(sc, 27, 0x01e0); PHY_WRITE(sc, 31, 0x0002); PHY_WRITE(sc, 27, 0xeb8e); PHY_WRITE(sc, 31, 0x0000); PHY_WRITE(sc, 30, 0x005e); PHY_WRITE(sc, 9, 0x0700); DELAY(50); } static void -ip1000phy_reset(struct mii_softc *sc) +ip1000phy_reset(struct mii_softc *sc, if_media_t media) { uint32_t reg; - mii_phy_reset(sc); + mii_phy_reset(sc, media); /* clear autoneg/full-duplex as we don't want it after reset */ reg = PHY_READ(sc, IP1000PHY_MII_BMCR); reg &= ~(IP1000PHY_BMCR_AUTOEN | IP1000PHY_BMCR_FDX); PHY_WRITE(sc, MII_BMCR, reg); if ((sc->mii_flags & MIIF_PHYPRIV0) != 0) ip1000phy_load_dspcode(sc); } Index: projects/ifnet/sys/dev/mii/jmphy.c =================================================================== --- projects/ifnet/sys/dev/mii/jmphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/jmphy.c (revision 282026) @@ -1,342 +1,342 @@ /*- * Copyright (c) 2008, Pyun YongHyeon * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Driver for the JMicron JMP211 10/100/1000, JMP202 10/100 PHY. */ #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" static int jmphy_probe(device_t); static int jmphy_attach(device_t); -static void jmphy_reset(struct mii_softc *); -static uint16_t jmphy_anar(struct ifmedia_entry *); -static int jmphy_setmedia(struct mii_softc *, struct ifmedia_entry *); +static uint16_t jmphy_anar(if_media_t); +static int jmphy_setmedia(struct mii_softc *, if_media_t); static device_method_t jmphy_methods[] = { /* Device interface. */ DEVMETHOD(device_probe, jmphy_probe), DEVMETHOD(device_attach, jmphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t jmphy_devclass; static driver_t jmphy_driver = { "jmphy", jmphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(jmphy, miibus, jmphy_driver, jmphy_devclass, 0, 0); -static int jmphy_service(struct mii_softc *, struct mii_data *, int); -static void jmphy_status(struct mii_softc *); +static int jmphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void jmphy_status(struct mii_softc *, if_media_t); +static void jmphy_reset(struct mii_softc *, if_media_t); static const struct mii_phydesc jmphys[] = { MII_PHY_DESC(JMICRON, JMP202), MII_PHY_DESC(JMICRON, JMP211), MII_PHY_END }; static const struct mii_phy_funcs jmphy_funcs = { jmphy_service, jmphy_status, jmphy_reset }; static int jmphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, jmphys, BUS_PROBE_DEFAULT)); } static int jmphy_attach(device_t dev) { u_int flags; flags = 0; if (mii_dev_mac_match(dev, "jme") && (miibus_get_flags(dev) & MIIF_MACPRIV0) != 0) flags |= MIIF_PHYPRIV0; mii_phy_dev_attach(dev, flags, &jmphy_funcs, 1); return (0); } static int -jmphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +jmphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - if (jmphy_setmedia(sc, ife) != EJUSTRETURN) + if (jmphy_setmedia(sc, media) != EJUSTRETURN) return (EINVAL); break; case MII_TICK: /* * Only used for autonegotiation. */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { + if (IFM_SUBTYPE(media) != IFM_AUTO) { sc->mii_ticks = 0; break; } /* Check for link. */ if ((PHY_READ(sc, JMPHY_SSR) & JMPHY_SSR_LINK_UP) != 0) { sc->mii_ticks = 0; break; } /* Announce link loss right after it happens. */ if (sc->mii_ticks++ == 0) break; if (sc->mii_ticks <= sc->mii_anegticks) return (0); sc->mii_ticks = 0; - (void)jmphy_setmedia(sc, ife); + (void)jmphy_setmedia(sc, media); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -jmphy_status(struct mii_softc *sc) +jmphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; int bmcr, ssr; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; ssr = PHY_READ(sc, JMPHY_SSR); if ((ssr & JMPHY_SSR_LINK_UP) != 0) mii->mii_media_status |= IFM_ACTIVE; bmcr = PHY_READ(sc, MII_BMCR); if ((bmcr & BMCR_ISO) != 0) { mii->mii_media_active |= IFM_NONE; mii->mii_media_status = 0; return; } if ((bmcr & BMCR_LOOP) != 0) mii->mii_media_active |= IFM_LOOP; if ((ssr & JMPHY_SSR_SPD_DPLX_RESOLVED) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } switch ((ssr & JMPHY_SSR_SPEED_MASK)) { case JMPHY_SSR_SPEED_1000: mii->mii_media_active |= IFM_1000_T; /* * jmphy(4) got a valid link so reset mii_ticks. * Resetting mii_ticks is needed in order to * detect link loss after auto-negotiation. */ sc->mii_ticks = 0; break; case JMPHY_SSR_SPEED_100: mii->mii_media_active |= IFM_100_TX; sc->mii_ticks = 0; break; case JMPHY_SSR_SPEED_10: mii->mii_media_active |= IFM_10_T; sc->mii_ticks = 0; break; default: mii->mii_media_active |= IFM_NONE; return; } if ((ssr & JMPHY_SSR_DUPLEX) != 0) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) { if ((PHY_READ(sc, MII_100T2SR) & GTSR_MS_RES) != 0) mii->mii_media_active |= IFM_ETH_MASTER; } } static void -jmphy_reset(struct mii_softc *sc) +jmphy_reset(struct mii_softc *sc, if_media_t media) { uint16_t t2cr, val; int i; /* Disable sleep mode. */ PHY_WRITE(sc, JMPHY_TMCTL, PHY_READ(sc, JMPHY_TMCTL) & ~JMPHY_TMCTL_SLEEP_ENB); PHY_WRITE(sc, MII_BMCR, BMCR_RESET | BMCR_AUTOEN); for (i = 0; i < 1000; i++) { DELAY(1); if ((PHY_READ(sc, MII_BMCR) & BMCR_RESET) == 0) break; } /* Perform vendor recommended PHY calibration. */ if ((sc->mii_flags & MIIF_PHYPRIV0) != 0) { /* Select PHY test mode 1. */ t2cr = PHY_READ(sc, MII_100T2CR); t2cr &= ~GTCR_TEST_MASK; t2cr |= 0x2000; PHY_WRITE(sc, MII_100T2CR, t2cr); /* Apply calibration patch. */ PHY_WRITE(sc, JMPHY_SPEC_ADDR, JMPHY_SPEC_ADDR_READ | JMPHY_EXT_COMM_2); val = PHY_READ(sc, JMPHY_SPEC_DATA); val &= ~0x0002; val |= 0x0010 | 0x0001; PHY_WRITE(sc, JMPHY_SPEC_DATA, val); PHY_WRITE(sc, JMPHY_SPEC_ADDR, JMPHY_SPEC_ADDR_WRITE | JMPHY_EXT_COMM_2); /* XXX 20ms to complete recalibration. */ DELAY(20 * 1000); PHY_READ(sc, MII_100T2CR); PHY_WRITE(sc, JMPHY_SPEC_ADDR, JMPHY_SPEC_ADDR_READ | JMPHY_EXT_COMM_2); val = PHY_READ(sc, JMPHY_SPEC_DATA); val &= ~(0x0001 | 0x0002 | 0x0010); PHY_WRITE(sc, JMPHY_SPEC_DATA, val); PHY_WRITE(sc, JMPHY_SPEC_ADDR, JMPHY_SPEC_ADDR_WRITE | JMPHY_EXT_COMM_2); /* Disable PHY test mode. */ PHY_READ(sc, MII_100T2CR); t2cr &= ~GTCR_TEST_MASK; PHY_WRITE(sc, MII_100T2CR, t2cr); } } static uint16_t -jmphy_anar(struct ifmedia_entry *ife) +jmphy_anar(if_media_t media) { uint16_t anar; anar = 0; - switch (IFM_SUBTYPE(ife->ifm_media)) { + switch (IFM_SUBTYPE(media)) { case IFM_AUTO: anar |= ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10; break; case IFM_1000_T: break; case IFM_100_TX: anar |= ANAR_TX | ANAR_TX_FD; break; case IFM_10_T: anar |= ANAR_10 | ANAR_10_FD; break; default: break; } return (anar); } static int -jmphy_setmedia(struct mii_softc *sc, struct ifmedia_entry *ife) +jmphy_setmedia(struct mii_softc *sc, if_media_t media) { uint16_t anar, bmcr, gig; gig = 0; bmcr = PHY_READ(sc, MII_BMCR); - switch (IFM_SUBTYPE(ife->ifm_media)) { + switch (IFM_SUBTYPE(media)) { case IFM_AUTO: gig |= GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX; break; case IFM_1000_T: gig |= GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX; break; case IFM_100_TX: case IFM_10_T: break; case IFM_NONE: PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_ISO | BMCR_PDOWN); return (EJUSTRETURN); default: return (EINVAL); } - anar = jmphy_anar(ife); - if ((IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO || - (ife->ifm_media & IFM_FDX) != 0) && - ((ife->ifm_media & IFM_FLOW) != 0 || + anar = jmphy_anar(media); + if ((IFM_SUBTYPE(media) == IFM_AUTO || + (media & IFM_FDX) != 0) && + ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0)) anar |= ANAR_PAUSE_TOWARDS; if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0) { - if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) { + if (IFM_SUBTYPE(media) == IFM_1000_T) { gig |= GTCR_MAN_MS; - if ((ife->ifm_media & IFM_ETH_MASTER) != 0) + if ((media & IFM_ETH_MASTER) != 0) gig |= GTCR_ADV_MS; } PHY_WRITE(sc, MII_100T2CR, gig); } PHY_WRITE(sc, MII_ANAR, anar | ANAR_CSMA); PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_AUTOEN | BMCR_STARTNEG); return (EJUSTRETURN); } Index: projects/ifnet/sys/dev/mii/lxtphy.c =================================================================== --- projects/ifnet/sys/dev/mii/lxtphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/lxtphy.c (revision 282026) @@ -1,267 +1,266 @@ /* OpenBSD: lxtphy.c,v 1.5 2000/08/26 20:04:17 nate Exp */ /* NetBSD: lxtphy.c,v 1.19 2000/02/02 23:34:57 thorpej Exp */ /*- * Copyright (c) 1998, 1999 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 * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (c) 1997 Manuel Bouyer. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * driver for Level One's LXT-970 ethernet 10/100 PHY * datasheet from www.level1.com */ #include #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" static int lxtphy_probe(device_t); static int lxtphy_attach(device_t); static device_method_t lxtphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, lxtphy_probe), DEVMETHOD(device_attach, lxtphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t lxtphy_devclass; static driver_t lxtphy_driver = { "lxtphy", lxtphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(lxtphy, miibus, lxtphy_driver, lxtphy_devclass, 0, 0); -static int lxtphy_service(struct mii_softc *, struct mii_data *, int); -static void lxtphy_status(struct mii_softc *); -static void lxtphy_reset(struct mii_softc *); +static int lxtphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void lxtphy_status(struct mii_softc *, if_media_t); +static void lxtphy_reset(struct mii_softc *, if_media_t); static void lxtphy_set_tp(struct mii_softc *); static void lxtphy_set_fx(struct mii_softc *); static const struct mii_phydesc lxtphys[] = { MII_PHY_DESC(xxLEVEL1, LXT970), MII_PHY_END }; static const struct mii_phy_funcs lxtphy_funcs = { lxtphy_service, lxtphy_status, lxtphy_reset }; static int lxtphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, lxtphys, BUS_PROBE_DEFAULT)); } static int lxtphy_attach(device_t dev) { struct mii_softc *sc; sc = device_get_softc(dev); mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &lxtphy_funcs, 0); - PHY_RESET(sc); + PHY_RESET(sc, 0); sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask; device_printf(dev, " "); -#define ADD(m) ifmedia_add(&sc->mii_pdata->mii_media, (m), 0, NULL) - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, 0, sc->mii_inst)); + mii_phy_add_media(sc->mii_pdata, + IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, 0, sc->mii_inst)); printf("100baseFX, "); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, IFM_FDX, sc->mii_inst)); + mii_phy_add_media(sc->mii_pdata, + IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, IFM_FDX, sc->mii_inst)); printf("100baseFX-FDX, "); -#undef ADD - mii_phy_add_media(sc); + mii_phy_generic_media(sc); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); return (0); } static int -lxtphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +lxtphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - if (IFM_SUBTYPE(ife->ifm_media) == IFM_100_FX) + if (IFM_SUBTYPE(media) == IFM_100_FX) lxtphy_set_fx(sc); else lxtphy_set_tp(sc); - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; case MII_TICK: if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -lxtphy_status(struct mii_softc *sc) +lxtphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmcr, bmsr, csr; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; /* * Get link status from the CSR; we need to read the CSR * for media type anyhow, and the link status in the CSR * doens't latch, so fewer register reads are required. */ csr = PHY_READ(sc, MII_LXTPHY_CSR); if (csr & CSR_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; if (bmcr & BMCR_AUTOEN) { bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if ((bmsr & BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } if (csr & CSR_SPEED) mii->mii_media_active |= IFM_100_TX; else mii->mii_media_active |= IFM_10_T; if (csr & CSR_DUPLEX) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; } else - mii->mii_media_active = ife->ifm_media; + mii->mii_media_active = media; } static void -lxtphy_reset(struct mii_softc *sc) +lxtphy_reset(struct mii_softc *sc, if_media_t media) { - mii_phy_reset(sc); + mii_phy_reset(sc, media); PHY_WRITE(sc, MII_LXTPHY_IER, PHY_READ(sc, MII_LXTPHY_IER) & ~IER_INTEN); } static void lxtphy_set_tp(struct mii_softc *sc) { int cfg; cfg = PHY_READ(sc, MII_LXTPHY_CONFIG); cfg &= ~CONFIG_100BASEFX; PHY_WRITE(sc, MII_LXTPHY_CONFIG, cfg); } static void lxtphy_set_fx(struct mii_softc *sc) { int cfg; cfg = PHY_READ(sc, MII_LXTPHY_CONFIG); cfg |= CONFIG_100BASEFX; PHY_WRITE(sc, MII_LXTPHY_CONFIG, cfg); } Index: projects/ifnet/sys/dev/mii/micphy.c =================================================================== --- projects/ifnet/sys/dev/mii/micphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/micphy.c (revision 282026) @@ -1,216 +1,215 @@ /*- * Copyright (c) 2014 Ruslan Bukin * All rights reserved. * * This software was developed by SRI International and the University of * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) * ("CTSRD"), as part of the DARPA CRASH research programme. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Micrel KSZ9021 Gigabit Ethernet Transceiver */ #include #include #include #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include "miibus_if.h" #include #include #include #include #define MII_KSZPHY_EXTREG 0x0b #define KSZPHY_EXTREG_WRITE (1 << 15) #define MII_KSZPHY_EXTREG_WRITE 0x0c #define MII_KSZPHY_EXTREG_READ 0x0d #define MII_KSZPHY_CLK_CONTROL_PAD_SKEW 0x104 #define MII_KSZPHY_RX_DATA_PAD_SKEW 0x105 #define MII_KSZPHY_TX_DATA_PAD_SKEW 0x106 #define PS_TO_REG(p) ((p) / 200) static int micphy_probe(device_t); static int micphy_attach(device_t); static int micphy_service(struct mii_softc *, struct mii_data *, int); static device_method_t micphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, micphy_probe), DEVMETHOD(device_attach, micphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t micphy_devclass; static driver_t micphy_driver = { "micphy", micphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(micphy, miibus, micphy_driver, micphy_devclass, 0, 0); static const struct mii_phydesc micphys[] = { MII_PHY_DESC(MICREL, KSZ9021), MII_PHY_END }; static const struct mii_phy_funcs micphy_funcs = { micphy_service, ukphy_status, mii_phy_reset }; static void micphy_write(struct mii_softc *sc, uint32_t reg, uint32_t val) { PHY_WRITE(sc, MII_KSZPHY_EXTREG, KSZPHY_EXTREG_WRITE | reg); PHY_WRITE(sc, MII_KSZPHY_EXTREG_WRITE, val); } static int ksz9021_load_values(struct mii_softc *sc, phandle_t node, uint32_t reg, char *field1, char *field2, char *field3, char *field4) { pcell_t dts_value[1]; int len; int val; val = 0; if ((len = OF_getproplen(node, field1)) > 0) { OF_getencprop(node, field1, dts_value, len); val = PS_TO_REG(dts_value[0]); } if ((len = OF_getproplen(node, field2)) > 0) { OF_getencprop(node, field2, dts_value, len); val |= PS_TO_REG(dts_value[0]) << 4; } if ((len = OF_getproplen(node, field3)) > 0) { OF_getencprop(node, field3, dts_value, len); val |= PS_TO_REG(dts_value[0]) << 8; } if ((len = OF_getproplen(node, field4)) > 0) { OF_getencprop(node, field4, dts_value, len); val |= PS_TO_REG(dts_value[0]) << 12; } micphy_write(sc, reg, val); return (0); } static int micphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, micphys, BUS_PROBE_DEFAULT)); } static int micphy_attach(device_t dev) { struct mii_softc *sc; phandle_t node; device_t miibus; device_t parent; sc = device_get_softc(dev); mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &micphy_funcs, 1); - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); miibus = device_get_parent(dev); parent = device_get_parent(miibus); if ((node = ofw_bus_get_node(parent)) == -1) return (ENXIO); ksz9021_load_values(sc, node, MII_KSZPHY_CLK_CONTROL_PAD_SKEW, "txen-skew-ps", "txc-skew-ps", "rxdv-skew-ps", "rxc-skew-ps"); ksz9021_load_values(sc, node, MII_KSZPHY_RX_DATA_PAD_SKEW, "rxd0-skew-ps", "rxd1-skew-ps", "rxd2-skew-ps", "rxd3-skew-ps"); ksz9021_load_values(sc, node, MII_KSZPHY_TX_DATA_PAD_SKEW, "txd0-skew-ps", "txd1-skew-ps", "txd2-skew-ps", "txd3-skew-ps"); return (0); } static int micphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; case MII_TICK: if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } Index: projects/ifnet/sys/dev/mii/mii.c =================================================================== --- projects/ifnet/sys/dev/mii/mii.c (revision 282025) +++ projects/ifnet/sys/dev/mii/mii.c (revision 282026) @@ -1,635 +1,624 @@ /* $NetBSD: mii.c,v 1.12 1999/08/03 19:41:49 drochner Exp $ */ /*- * Copyright (c) 1998 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 * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * MII bus layer, glues MII-capable network interface drivers to sharable * PHY drivers. This exports an interface compatible with BSD/OS 3.0's, * plus some NetBSD extensions. */ #include #include #include #include #include #include -#include #include #include #include MODULE_VERSION(miibus, 1); #include "miibus_if.h" static device_attach_t miibus_attach; static bus_child_location_str_t miibus_child_location_str; static bus_child_pnpinfo_str_t miibus_child_pnpinfo_str; static device_detach_t miibus_detach; static bus_hinted_child_t miibus_hinted_child; static bus_print_child_t miibus_print_child; static device_probe_t miibus_probe; static bus_read_ivar_t miibus_read_ivar; static miibus_readreg_t miibus_readreg; static miibus_statchg_t miibus_statchg; static miibus_writereg_t miibus_writereg; static miibus_readvar_t miibus_readvar; static miibus_mediainit_t miibus_mediainit; static unsigned char mii_bitreverse(unsigned char x); static device_method_t miibus_methods[] = { /* device interface */ DEVMETHOD(device_probe, miibus_probe), DEVMETHOD(device_attach, miibus_attach), DEVMETHOD(device_detach, miibus_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), /* bus interface */ DEVMETHOD(bus_print_child, miibus_print_child), DEVMETHOD(bus_read_ivar, miibus_read_ivar), DEVMETHOD(bus_child_pnpinfo_str, miibus_child_pnpinfo_str), DEVMETHOD(bus_child_location_str, miibus_child_location_str), DEVMETHOD(bus_hinted_child, miibus_hinted_child), /* MII interface */ DEVMETHOD(miibus_readreg, miibus_readreg), DEVMETHOD(miibus_writereg, miibus_writereg), DEVMETHOD(miibus_statchg, miibus_statchg), DEVMETHOD(miibus_readvar, miibus_readvar), DEVMETHOD(miibus_mediainit, miibus_mediainit), DEVMETHOD_END }; devclass_t miibus_devclass; driver_t miibus_driver = { "miibus", miibus_methods, sizeof(struct mii_data) }; struct miibus_ivars { - ifm_change_cb_t ifmedia_upd; - ifm_stat_cb_t ifmedia_sts; u_int mii_flags; u_int mii_offset; }; static int miibus_probe(device_t dev) { device_set_desc(dev, "MII bus"); return (BUS_PROBE_SPECIFIC); } static int miibus_attach(device_t dev) { - struct miibus_ivars *ivars; struct mii_attach_args *ma; struct mii_data *mii; device_t *children; int i, nchildren; mii = device_get_softc(dev); if (device_get_children(dev, &children, &nchildren) == 0) { for (i = 0; i < nchildren; i++) { ma = device_get_ivars(children[i]); ma->mii_data = mii; } free(children, M_TEMP); } if (nchildren == 0) { device_printf(dev, "cannot get children\n"); return (ENXIO); } - ivars = device_get_ivars(dev); - ifmedia_init(&mii->mii_media, IFM_IMASK, ivars->ifmedia_upd, - ivars->ifmedia_sts); LIST_INIT(&mii->mii_phys); return (bus_generic_attach(dev)); } static int miibus_detach(device_t dev) { struct mii_data *mii; bus_generic_detach(dev); mii = device_get_softc(dev); - ifmedia_removeall(&mii->mii_media); return (0); } static int miibus_print_child(device_t dev, device_t child) { struct mii_attach_args *ma; int retval; ma = device_get_ivars(child); retval = bus_print_child_header(dev, child); retval += printf(" PHY %d", ma->mii_phyno); retval += bus_print_child_footer(dev, child); return (retval); } static int miibus_read_ivar(device_t dev, device_t child __unused, int which, uintptr_t *result) { struct miibus_ivars *ivars; /* * NB: this uses the instance variables of the miibus rather than * its PHY children. */ ivars = device_get_ivars(dev); switch (which) { case MIIBUS_IVAR_FLAGS: *result = ivars->mii_flags; break; default: return (ENOENT); } return (0); } static int miibus_child_pnpinfo_str(device_t dev __unused, device_t child, char *buf, size_t buflen) { struct mii_attach_args *ma; ma = device_get_ivars(child); snprintf(buf, buflen, "oui=0x%x model=0x%x rev=0x%x", MII_OUI(ma->mii_id1, ma->mii_id2), MII_MODEL(ma->mii_id2), MII_REV(ma->mii_id2)); return (0); } static int miibus_child_location_str(device_t dev __unused, device_t child, char *buf, size_t buflen) { struct mii_attach_args *ma; ma = device_get_ivars(child); snprintf(buf, buflen, "phyno=%d", ma->mii_phyno); return (0); } static void miibus_hinted_child(device_t dev, const char *name, int unit) { struct miibus_ivars *ivars; struct mii_attach_args *args, *ma; device_t *children, phy; int i, nchildren; u_int val; if (resource_int_value(name, unit, "phyno", &val) != 0) return; if (device_get_children(dev, &children, &nchildren) != 0) return; ma = NULL; for (i = 0; i < nchildren; i++) { args = device_get_ivars(children[i]); if (args->mii_phyno == val) { ma = args; break; } } free(children, M_TEMP); /* * Don't add a PHY that was automatically identified by having media * in its BMSR twice, only allow to alter its attach arguments. */ if (ma == NULL) { ma = malloc(sizeof(struct mii_attach_args), M_DEVBUF, M_NOWAIT); if (ma == NULL) return; phy = device_add_child(dev, name, unit); if (phy == NULL) { free(ma, M_DEVBUF); return; } ivars = device_get_ivars(dev); ma->mii_phyno = val; ma->mii_offset = ivars->mii_offset++; ma->mii_id1 = 0; ma->mii_id2 = 0; ma->mii_capmask = BMSR_DEFCAPMASK; device_set_ivars(phy, ma); } if (resource_int_value(name, unit, "id1", &val) == 0) ma->mii_id1 = val; if (resource_int_value(name, unit, "id2", &val) == 0) ma->mii_id2 = val; if (resource_int_value(name, unit, "capmask", &val) == 0) ma->mii_capmask = val; } /* * The miibus just relays most devmethods to the parent. */ static int miibus_readreg(device_t dev, int phy, int reg) { return (MIIBUS_READREG(device_get_parent(dev), phy, reg)); } static int miibus_writereg(device_t dev, int phy, int reg, int data) { return (MIIBUS_WRITEREG(device_get_parent(dev), phy, reg, data)); } static void miibus_statchg(device_t dev) { MIIBUS_STATCHG(device_get_parent(dev)); } static uint64_t miibus_readvar(device_t dev, int var) { return (MIIBUS_READVAR(device_get_parent(dev), var)); } static void miibus_mediainit(device_t dev) { - struct mii_data *mii; - struct ifmedia_entry *m; - int media = 0; + struct mii_data *mii; + int i; /* Poke the parent in case it has any media of its own to add. */ MIIBUS_MEDIAINIT(device_get_parent(dev)); + /* + * Prefer (IFM_ETHER | IFM_AUTO), but if not found set the last + * media word set by phys. + */ mii = device_get_softc(dev); - LIST_FOREACH(m, &mii->mii_media.ifm_list, ifm_list) { - media = m->ifm_media; - if (media == (IFM_ETHER | IFM_AUTO)) + for (i = 0; mii->mii_mediae[i + 1] != 0; i++) + if (mii->mii_mediae[i] == (IFM_ETHER | IFM_AUTO)) break; - } - ifmedia_set(&mii->mii_media, media); + mii->mii_media = mii->mii_mediae[i]; } /* * Helper function used by network interface drivers, attaches the miibus and * the PHYs to the network interface driver parent. */ int -mii_attach(device_t dev, device_t *miibus, ifm_change_cb_t ifmedia_upd, - ifm_stat_cb_t ifmedia_sts, int capmask, int phyloc, int offloc, int flags) +mii_attach(device_t dev, device_t *miibus, int capmask, int phyloc, int offloc, + int flags) { struct miibus_ivars *ivars; struct mii_attach_args *args, ma; device_t *children, phy; int bmsr, first, i, nchildren, phymax, phymin, rv; uint32_t phymask; if (phyloc != MII_PHY_ANY && offloc != MII_OFFSET_ANY) { printf("%s: phyloc and offloc specified\n", __func__); return (EINVAL); } if (offloc != MII_OFFSET_ANY && (offloc < 0 || offloc >= MII_NPHY)) { printf("%s: invalid offloc %d\n", __func__, offloc); return (EINVAL); } if (phyloc == MII_PHY_ANY) { phymin = 0; phymax = MII_NPHY - 1; } else { if (phyloc < 0 || phyloc >= MII_NPHY) { printf("%s: invalid phyloc %d\n", __func__, phyloc); return (EINVAL); } phymin = phymax = phyloc; } first = 0; if (*miibus == NULL) { first = 1; ivars = malloc(sizeof(*ivars), M_DEVBUF, M_NOWAIT); if (ivars == NULL) return (ENOMEM); - ivars->ifmedia_upd = ifmedia_upd; - ivars->ifmedia_sts = ifmedia_sts; ivars->mii_flags = flags; *miibus = device_add_child(dev, "miibus", -1); if (*miibus == NULL) { rv = ENXIO; goto fail; } device_set_ivars(*miibus, ivars); } else { ivars = device_get_ivars(*miibus); - if (ivars->ifmedia_upd != ifmedia_upd || - ivars->ifmedia_sts != ifmedia_sts || - ivars->mii_flags != flags) { + if (ivars->mii_flags != flags) { printf("%s: non-matching invariant\n", __func__); return (EINVAL); } /* * Assignment of the attach arguments mii_data for the first * pass is done in miibus_attach(), i.e. once the miibus softc * has been allocated. */ ma.mii_data = device_get_softc(*miibus); } ma.mii_capmask = capmask; if (resource_int_value(device_get_name(*miibus), device_get_unit(*miibus), "phymask", &phymask) != 0) phymask = 0xffffffff; if (device_get_children(*miibus, &children, &nchildren) != 0) { children = NULL; nchildren = 0; } ivars->mii_offset = 0; for (ma.mii_phyno = phymin; ma.mii_phyno <= phymax; ma.mii_phyno++) { /* * Make sure we haven't already configured a PHY at this * address. This allows mii_attach() to be called * multiple times. */ for (i = 0; i < nchildren; i++) { args = device_get_ivars(children[i]); if (args->mii_phyno == ma.mii_phyno) { /* * Yes, there is already something * configured at this address. */ goto skip; } } /* * Check to see if there is a PHY at this address. Note, * many braindead PHYs report 0/0 in their ID registers, * so we test for media in the BMSR. */ bmsr = MIIBUS_READREG(dev, ma.mii_phyno, MII_BMSR); if (bmsr == 0 || bmsr == 0xffff || (bmsr & (BMSR_EXTSTAT | BMSR_MEDIAMASK)) == 0) { /* Assume no PHY at this address. */ continue; } /* * There is a PHY at this address. If we were given an * `offset' locator, skip this PHY if it doesn't match. */ if (offloc != MII_OFFSET_ANY && offloc != ivars->mii_offset) goto skip; /* * Skip this PHY if it's not included in the phymask hint. */ if ((phymask & (1 << ma.mii_phyno)) == 0) goto skip; /* * Extract the IDs. Braindead PHYs will be handled by * the `ukphy' driver, as we have no ID information to * match on. */ ma.mii_id1 = MIIBUS_READREG(dev, ma.mii_phyno, MII_PHYIDR1); ma.mii_id2 = MIIBUS_READREG(dev, ma.mii_phyno, MII_PHYIDR2); ma.mii_offset = ivars->mii_offset; args = malloc(sizeof(struct mii_attach_args), M_DEVBUF, M_NOWAIT); if (args == NULL) goto skip; bcopy((char *)&ma, (char *)args, sizeof(ma)); phy = device_add_child(*miibus, NULL, -1); if (phy == NULL) { free(args, M_DEVBUF); goto skip; } device_set_ivars(phy, args); skip: ivars->mii_offset++; } free(children, M_TEMP); if (first != 0) { rv = device_set_driver(*miibus, &miibus_driver); if (rv != 0) goto fail; bus_enumerate_hinted_children(*miibus); rv = device_get_children(*miibus, &children, &nchildren); if (rv != 0) goto fail; free(children, M_TEMP); if (nchildren == 0) { rv = ENXIO; goto fail; } rv = bus_generic_attach(dev); if (rv != 0) goto fail; /* Attaching of the PHY drivers is done in miibus_attach(). */ return (0); } rv = bus_generic_attach(*miibus); if (rv != 0) goto fail; return (0); fail: if (*miibus != NULL) device_delete_child(dev, *miibus); free(ivars, M_DEVBUF); if (first != 0) *miibus = NULL; return (rv); } /* - * Media changed; notify all PHYs. + * Media changed; notify all PHYs. This function is called from drivers + * ifop_media_change method, which propagates media parameter to this + * layer. */ int -mii_mediachg(struct mii_data *mii) +mii_mediachg(struct mii_data *mii, if_media_t media) { struct mii_softc *child; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int rv; mii->mii_media_status = 0; mii->mii_media_active = IFM_NONE; LIST_FOREACH(child, &mii->mii_phys, mii_list) { /* * If the media indicates a different PHY instance, * isolate this one. */ - if (IFM_INST(ife->ifm_media) != child->mii_inst) { + if (IFM_INST(media) != child->mii_inst) { if ((child->mii_flags & MIIF_NOISOLATE) != 0) { device_printf(child->mii_dev, "%s: " "can't handle non-zero PHY instance %d\n", __func__, child->mii_inst); continue; } PHY_WRITE(child, MII_BMCR, PHY_READ(child, MII_BMCR) | BMCR_ISO); continue; } - rv = PHY_SERVICE(child, mii, MII_MEDIACHG); + rv = PHY_SERVICE(child, mii, MII_MEDIACHG, media); if (rv) return (rv); } + mii->mii_media = media; return (0); } /* * Call the PHY tick routines, used during autonegotiation. */ void mii_tick(struct mii_data *mii) { struct mii_softc *child; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; LIST_FOREACH(child, &mii->mii_phys, mii_list) { /* * If this PHY instance isn't currently selected, just skip * it. */ - if (IFM_INST(ife->ifm_media) != child->mii_inst) + if (IFM_INST(mii->mii_media) != child->mii_inst) continue; - (void)PHY_SERVICE(child, mii, MII_TICK); + (void)PHY_SERVICE(child, mii, MII_TICK, mii->mii_media); } } /* * Get media status from PHYs. */ void mii_pollstat(struct mii_data *mii) { struct mii_softc *child; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; mii->mii_media_status = 0; mii->mii_media_active = IFM_NONE; LIST_FOREACH(child, &mii->mii_phys, mii_list) { /* * If we're not polling this PHY instance, just skip it. */ - if (IFM_INST(ife->ifm_media) != child->mii_inst) + if (IFM_INST(mii->mii_media) != child->mii_inst) continue; - (void)PHY_SERVICE(child, mii, MII_POLLSTAT); + (void)PHY_SERVICE(child, mii, MII_POLLSTAT, mii->mii_media); } } static unsigned char mii_bitreverse(unsigned char x) { static unsigned const char nibbletab[16] = { 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; return ((nibbletab[x & 15] << 4) | nibbletab[x >> 4]); } u_int mii_oui(u_int id1, u_int id2) { u_int h; h = (id1 << 6) | (id2 >> 10); return ((mii_bitreverse(h >> 16) << 16) | (mii_bitreverse((h >> 8) & 0xff) << 8) | mii_bitreverse(h & 0xff)); } int mii_phy_mac_match(struct mii_softc *mii, const char *name) { return (strcmp(device_get_name(device_get_parent(mii->mii_dev)), name) == 0); } int mii_dev_mac_match(device_t parent, const char *name) { return (strcmp(device_get_name(device_get_parent( device_get_parent(parent))), name) == 0); } void * mii_phy_mac_softc(struct mii_softc *mii) { return (device_get_softc(device_get_parent(mii->mii_dev))); } void * mii_dev_mac_softc(device_t parent) { return (device_get_softc(device_get_parent(device_get_parent(parent)))); } Index: projects/ifnet/sys/dev/mii/mii_physubr.c =================================================================== --- projects/ifnet/sys/dev/mii/mii_physubr.c (revision 282025) +++ projects/ifnet/sys/dev/mii/mii_physubr.c (revision 282026) @@ -1,674 +1,675 @@ /* $NetBSD: mii_physubr.c,v 1.5 1999/08/03 19:41:49 drochner Exp $ */ /*- * 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 * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Subroutines common to all PHYs. */ #include #include #include #include #include #include #include -#include #include #include #include #include "miibus_if.h" /* * * An array of structures to map MII media types to BMCR/ANAR settings. */ enum { MII_MEDIA_NONE = 0, MII_MEDIA_10_T, MII_MEDIA_10_T_FDX, MII_MEDIA_100_T4, MII_MEDIA_100_TX, MII_MEDIA_100_TX_FDX, MII_MEDIA_1000_X, MII_MEDIA_1000_X_FDX, MII_MEDIA_1000_T, MII_MEDIA_1000_T_FDX, MII_NMEDIA, }; static const struct mii_media { u_int mm_bmcr; /* BMCR settings for this media */ u_int mm_anar; /* ANAR settings for this media */ u_int mm_gtcr; /* 100base-T2 or 1000base-T CR */ } mii_media_table[MII_NMEDIA] = { /* None */ { BMCR_ISO, ANAR_CSMA, 0, }, /* 10baseT */ { BMCR_S10, ANAR_CSMA|ANAR_10, 0, }, /* 10baseT-FDX */ { BMCR_S10|BMCR_FDX, ANAR_CSMA|ANAR_10_FD, 0, }, /* 100baseT4 */ { BMCR_S100, ANAR_CSMA|ANAR_T4, 0, }, /* 100baseTX */ { BMCR_S100, ANAR_CSMA|ANAR_TX, 0, }, /* 100baseTX-FDX */ { BMCR_S100|BMCR_FDX, ANAR_CSMA|ANAR_TX_FD, 0, }, /* 1000baseX */ { BMCR_S1000, ANAR_CSMA, 0, }, /* 1000baseX-FDX */ { BMCR_S1000|BMCR_FDX, ANAR_CSMA, 0, }, /* 1000baseT */ { BMCR_S1000, ANAR_CSMA, GTCR_ADV_1000THDX }, /* 1000baseT-FDX */ { BMCR_S1000, ANAR_CSMA, GTCR_ADV_1000TFDX }, }; void -mii_phy_setmedia(struct mii_softc *sc) +mii_phy_setmedia(struct mii_softc *sc, if_media_t media) { - struct mii_data *mii = sc->mii_pdata; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmcr, anar, gtcr; int index = -1; - switch (IFM_SUBTYPE(ife->ifm_media)) { + switch (IFM_SUBTYPE(media)) { case IFM_AUTO: /* * Force renegotiation if MIIF_DOPAUSE or MIIF_FORCEANEG. * The former is necessary as we might switch from flow- * control advertisement being off to on or vice versa. */ if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0 || (sc->mii_flags & (MIIF_DOPAUSE | MIIF_FORCEANEG)) != 0) - (void)mii_phy_auto(sc); + (void)mii_phy_auto(sc, media); return; case IFM_NONE: index = MII_MEDIA_NONE; break; case IFM_HPNA_1: index = MII_MEDIA_10_T; break; case IFM_10_T: - switch (IFM_OPTIONS(ife->ifm_media)) { + switch (IFM_OPTIONS(media)) { case 0: index = MII_MEDIA_10_T; break; case IFM_FDX: case (IFM_FDX | IFM_FLOW): index = MII_MEDIA_10_T_FDX; break; }; break; case IFM_100_TX: case IFM_100_FX: - switch (IFM_OPTIONS(ife->ifm_media)) { + switch (IFM_OPTIONS(media)) { case 0: index = MII_MEDIA_100_TX; break; case IFM_FDX: case (IFM_FDX | IFM_FLOW): index = MII_MEDIA_100_TX_FDX; break; } break; case IFM_100_T4: index = MII_MEDIA_100_T4; break; case IFM_1000_SX: - switch (IFM_OPTIONS(ife->ifm_media)) { + switch (IFM_OPTIONS(media)) { case 0: index = MII_MEDIA_1000_X; break; case IFM_FDX: case (IFM_FDX | IFM_FLOW): index = MII_MEDIA_1000_X_FDX; break; } break; case IFM_1000_T: - switch (IFM_OPTIONS(ife->ifm_media)) { + switch (IFM_OPTIONS(media)) { case 0: case IFM_ETH_MASTER: index = MII_MEDIA_1000_T; break; case IFM_FDX: case (IFM_FDX | IFM_ETH_MASTER): case (IFM_FDX | IFM_FLOW): case (IFM_FDX | IFM_FLOW | IFM_ETH_MASTER): index = MII_MEDIA_1000_T_FDX; break; } break; } KASSERT(index != -1, ("%s: failed to map media word %d", - __func__, ife->ifm_media)); + __func__, media)); anar = mii_media_table[index].mm_anar; bmcr = mii_media_table[index].mm_bmcr; gtcr = mii_media_table[index].mm_gtcr; - if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) { + if (IFM_SUBTYPE(media) == IFM_1000_T) { gtcr |= GTCR_MAN_MS; - if ((ife->ifm_media & IFM_ETH_MASTER) != 0) + if ((media & IFM_ETH_MASTER) != 0) gtcr |= GTCR_ADV_MS; } - if ((ife->ifm_media & IFM_FDX) != 0 && - ((ife->ifm_media & IFM_FLOW) != 0 || + if ((media & IFM_FDX) != 0 && ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0)) { if ((sc->mii_flags & MIIF_IS_1000X) != 0) anar |= ANAR_X_PAUSE_TOWARDS; else { anar |= ANAR_FC; /* XXX Only 1000BASE-T has PAUSE_ASYM? */ if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0 && (sc->mii_extcapabilities & (EXTSR_1000THDX | EXTSR_1000TFDX)) != 0) anar |= ANAR_X_PAUSE_ASYM; } } PHY_WRITE(sc, MII_ANAR, anar); PHY_WRITE(sc, MII_BMCR, bmcr); if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0) PHY_WRITE(sc, MII_100T2CR, gtcr); } int -mii_phy_auto(struct mii_softc *sc) +mii_phy_auto(struct mii_softc *sc, if_media_t media) { - struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur; int anar, gtcr; /* * Check for 1000BASE-X. Autonegotiation is a bit * different on such devices. */ if ((sc->mii_flags & MIIF_IS_1000X) != 0) { anar = 0; if ((sc->mii_extcapabilities & EXTSR_1000XFDX) != 0) anar |= ANAR_X_FD; if ((sc->mii_extcapabilities & EXTSR_1000XHDX) != 0) anar |= ANAR_X_HD; - if ((ife->ifm_media & IFM_FLOW) != 0 || + if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0) anar |= ANAR_X_PAUSE_TOWARDS; PHY_WRITE(sc, MII_ANAR, anar); } else { anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; - if ((ife->ifm_media & IFM_FLOW) != 0 || + if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0) { if ((sc->mii_capabilities & (BMSR_10TFDX | BMSR_100TXFDX)) != 0) anar |= ANAR_FC; /* XXX Only 1000BASE-T has PAUSE_ASYM? */ if (((sc->mii_flags & MIIF_HAVE_GTCR) != 0) && (sc->mii_extcapabilities & (EXTSR_1000THDX | EXTSR_1000TFDX)) != 0) anar |= ANAR_X_PAUSE_ASYM; } PHY_WRITE(sc, MII_ANAR, anar); if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0) { gtcr = 0; if ((sc->mii_extcapabilities & EXTSR_1000TFDX) != 0) gtcr |= GTCR_ADV_1000TFDX; if ((sc->mii_extcapabilities & EXTSR_1000THDX) != 0) gtcr |= GTCR_ADV_1000THDX; PHY_WRITE(sc, MII_100T2CR, gtcr); } } PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); return (EJUSTRETURN); } int mii_phy_tick(struct mii_softc *sc) { - struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur; + if_media_t media = sc->mii_pdata->mii_media; int reg; /* * If we're not doing autonegotiation, we don't need to do * any extra work here. However, we need to check the link * status so we can generate an announcement if the status * changes. */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { + if (IFM_SUBTYPE(media) != IFM_AUTO) { sc->mii_ticks = 0; /* reset autonegotiation timer. */ return (0); } /* 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) != 0) { sc->mii_ticks = 0; /* reset autonegotiation timer. */ /* See above. */ return (0); } /* Announce link loss right after it happens */ if (sc->mii_ticks++ == 0) return (0); /* XXX: use default value if phy driver did not set mii_anegticks */ if (sc->mii_anegticks == 0) sc->mii_anegticks = MII_ANEGTICKS_GIGE; /* Only retry autonegotiation every mii_anegticks ticks. */ if (sc->mii_ticks <= sc->mii_anegticks) return (EJUSTRETURN); sc->mii_ticks = 0; - PHY_RESET(sc); - mii_phy_auto(sc); + PHY_RESET(sc, media); + mii_phy_auto(sc, media); return (0); } void -mii_phy_reset(struct mii_softc *sc) +mii_phy_reset(struct mii_softc *sc, if_media_t media) { - struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur; int i, reg; if ((sc->mii_flags & MIIF_NOISOLATE) != 0) reg = BMCR_RESET; else reg = BMCR_RESET | BMCR_ISO; PHY_WRITE(sc, MII_BMCR, reg); /* Wait 100ms for it to complete. */ for (i = 0; i < 100; i++) { reg = PHY_READ(sc, MII_BMCR); if ((reg & BMCR_RESET) == 0) break; DELAY(1000); } /* NB: a PHY may default to being powered down and/or isolated. */ reg &= ~(BMCR_PDOWN | BMCR_ISO); if ((sc->mii_flags & MIIF_NOISOLATE) == 0 && - ((ife == NULL && sc->mii_inst != 0) || - (ife != NULL && IFM_INST(ife->ifm_media) != sc->mii_inst))) + ((media == 0 && sc->mii_inst != 0) || + (media != 0 && IFM_INST(media) != sc->mii_inst))) reg |= BMCR_ISO; if (PHY_READ(sc, MII_BMCR) != reg) PHY_WRITE(sc, MII_BMCR, reg); } void -mii_phy_update(struct mii_softc *sc, int cmd) +mii_phy_update(struct mii_softc *sc, mii_cmd_t cmd) { struct mii_data *mii = sc->mii_pdata; if (sc->mii_media_active != mii->mii_media_active || sc->mii_media_status != mii->mii_media_status || cmd == MII_MEDIACHG) { MIIBUS_STATCHG(sc->mii_dev); sc->mii_media_active = mii->mii_media_active; sc->mii_media_status = mii->mii_media_status; } } /* + * Add one more media to array of supported mediae. + */ +void +mii_phy_add_media(struct mii_data *mii, if_media_t media) +{ + + KASSERT(mii->mii_index < MII_MAX_MEDIAE, + ("%s: mediae array overflow", __func__)); + mii->mii_mediae[mii->mii_index++] = media; +} + +/* * 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) +mii_phy_generic_media(struct mii_softc *sc) { struct mii_data *mii = sc->mii_pdata; const char *sep = ""; int fdx = 0; if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 && (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) { printf("no media present"); return; } /* * Set the autonegotiation timer for 10/100 media. Gigabit media is * handled below. */ sc->mii_anegticks = MII_ANEGTICKS; -#define ADD(m) ifmedia_add(&mii->mii_media, (m), 0, NULL) +#define ADD(t, s, o, i) mii_phy_add_media(mii, IFM_MAKEWORD((t), (s), (o), (i))) #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)); + ADD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst); PRINT("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) != 0) { if ((sc->mii_capabilities & BMSR_10THDX) != 0) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0, - sc->mii_inst)); + ADD(IFM_ETHER, IFM_HPNA_1, 0, sc->mii_inst); PRINT("HomePNA1"); } return; } if ((sc->mii_capabilities & BMSR_10THDX) != 0) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst)); + ADD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst); PRINT("10baseT"); } if ((sc->mii_capabilities & BMSR_10TFDX) != 0) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst)); + ADD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst); PRINT("10baseT-FDX"); if ((sc->mii_flags & MIIF_DOPAUSE) != 0 && (sc->mii_flags & MIIF_NOMANPAUSE) == 0) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, - IFM_FDX | IFM_FLOW, sc->mii_inst)); + ADD(IFM_ETHER, IFM_10_T, IFM_FDX | IFM_FLOW, + sc->mii_inst); PRINT("10baseT-FDX-flow"); } fdx = 1; } if ((sc->mii_capabilities & BMSR_100TXHDX) != 0) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst)); + ADD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst); PRINT("100baseTX"); } if ((sc->mii_capabilities & BMSR_100TXFDX) != 0) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst)); + ADD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst); PRINT("100baseTX-FDX"); if ((sc->mii_flags & MIIF_DOPAUSE) != 0 && (sc->mii_flags & MIIF_NOMANPAUSE) == 0) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, - IFM_FDX | IFM_FLOW, sc->mii_inst)); + ADD(IFM_ETHER, IFM_100_TX, IFM_FDX | IFM_FLOW, + sc->mii_inst); PRINT("100baseTX-FDX-flow"); } fdx = 1; } if ((sc->mii_capabilities & BMSR_100T4) != 0) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst)); + ADD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst); PRINT("100baseT4"); } if ((sc->mii_extcapabilities & EXTSR_MEDIAMASK) != 0) { /* * XXX Right now only handle 1000SX and 1000TX. Need * XXX to handle 1000LX and 1000CX somehow. */ if ((sc->mii_extcapabilities & EXTSR_1000XHDX) != 0) { sc->mii_anegticks = MII_ANEGTICKS_GIGE; sc->mii_flags |= MIIF_IS_1000X; - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, 0, - sc->mii_inst)); + ADD(IFM_ETHER, IFM_1000_SX, 0, sc->mii_inst); PRINT("1000baseSX"); } if ((sc->mii_extcapabilities & EXTSR_1000XFDX) != 0) { sc->mii_anegticks = MII_ANEGTICKS_GIGE; sc->mii_flags |= MIIF_IS_1000X; - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, - sc->mii_inst)); + ADD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst); PRINT("1000baseSX-FDX"); if ((sc->mii_flags & MIIF_DOPAUSE) != 0 && (sc->mii_flags & MIIF_NOMANPAUSE) == 0) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, - IFM_FDX | IFM_FLOW, sc->mii_inst)); + ADD(IFM_ETHER, IFM_1000_SX, IFM_FDX | IFM_FLOW, + sc->mii_inst); PRINT("1000baseSX-FDX-flow"); } fdx = 1; } /* * 1000baseT media needs to be able to manipulate * master/slave mode. * * All 1000baseT PHYs have a 1000baseT control register. */ if ((sc->mii_extcapabilities & EXTSR_1000THDX) != 0) { sc->mii_anegticks = MII_ANEGTICKS_GIGE; sc->mii_flags |= MIIF_HAVE_GTCR; - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, - sc->mii_inst)); + ADD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst); PRINT("1000baseT"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, - IFM_ETH_MASTER, sc->mii_inst)); + ADD(IFM_ETHER, IFM_1000_T, IFM_ETH_MASTER, + sc->mii_inst); PRINT("1000baseT-master"); } if ((sc->mii_extcapabilities & EXTSR_1000TFDX) != 0) { sc->mii_anegticks = MII_ANEGTICKS_GIGE; sc->mii_flags |= MIIF_HAVE_GTCR; - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, - sc->mii_inst)); + ADD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst); PRINT("1000baseT-FDX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, - IFM_FDX | IFM_ETH_MASTER, sc->mii_inst)); + ADD(IFM_ETHER, IFM_1000_T, IFM_FDX | IFM_ETH_MASTER, + sc->mii_inst); PRINT("1000baseT-FDX-master"); if ((sc->mii_flags & MIIF_DOPAUSE) != 0 && (sc->mii_flags & MIIF_NOMANPAUSE) == 0) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, - IFM_FDX | IFM_FLOW, sc->mii_inst)); + ADD(IFM_ETHER, IFM_1000_T, IFM_FDX | IFM_FLOW, + sc->mii_inst); PRINT("1000baseT-FDX-flow"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, + ADD(IFM_ETHER, IFM_1000_T, IFM_FDX | IFM_FLOW | IFM_ETH_MASTER, - sc->mii_inst)); + sc->mii_inst); PRINT("1000baseT-FDX-flow-master"); } fdx = 1; } } if ((sc->mii_capabilities & BMSR_ANEG) != 0) { /* intentionally invalid index */ - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst)); + ADD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst); PRINT("auto"); if (fdx != 0 && (sc->mii_flags & MIIF_DOPAUSE) != 0) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, IFM_FLOW, - sc->mii_inst)); + ADD(IFM_ETHER, IFM_AUTO, IFM_FLOW, sc->mii_inst); PRINT("auto-flow"); } } #undef ADD #undef PRINT } int mii_phy_detach(device_t dev) { struct mii_softc *sc; sc = device_get_softc(dev); sc->mii_dev = NULL; LIST_REMOVE(sc, mii_list); return (0); } const struct mii_phydesc * mii_phy_match_gen(const struct mii_attach_args *ma, const struct mii_phydesc *mpd, size_t len) { for (; mpd->mpd_name != NULL; mpd = (const struct mii_phydesc *)((const char *)mpd + len)) { if (MII_OUI(ma->mii_id1, ma->mii_id2) == mpd->mpd_oui && MII_MODEL(ma->mii_id2) == mpd->mpd_model) return (mpd); } return (NULL); } const struct mii_phydesc * mii_phy_match(const struct mii_attach_args *ma, const struct mii_phydesc *mpd) { return (mii_phy_match_gen(ma, mpd, sizeof(struct mii_phydesc))); } int mii_phy_dev_probe(device_t dev, const struct mii_phydesc *mpd, int mrv) { mpd = mii_phy_match(device_get_ivars(dev), mpd); if (mpd != NULL) { device_set_desc(dev, mpd->mpd_name); return (mrv); } return (ENXIO); } void mii_phy_dev_attach(device_t dev, u_int flags, const struct mii_phy_funcs *mpf, int add_media) { struct mii_softc *sc; struct mii_attach_args *ma; struct mii_data *mii; sc = device_get_softc(dev); ma = device_get_ivars(dev); sc->mii_dev = device_get_parent(dev); mii = ma->mii_data; LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); sc->mii_flags = flags | miibus_get_flags(dev); sc->mii_mpd_oui = MII_OUI(ma->mii_id1, ma->mii_id2); sc->mii_mpd_model = MII_MODEL(ma->mii_id2); sc->mii_mpd_rev = MII_REV(ma->mii_id2); sc->mii_capmask = ma->mii_capmask; sc->mii_inst = mii->mii_instance++; sc->mii_phy = ma->mii_phyno; sc->mii_offset = ma->mii_offset; sc->mii_funcs = mpf; sc->mii_pdata = mii; if (bootverbose) device_printf(dev, "OUI 0x%06x, model 0x%04x, rev. %d\n", sc->mii_mpd_oui, sc->mii_mpd_model, sc->mii_mpd_rev); if (add_media == 0) return; - PHY_RESET(sc); + PHY_RESET(sc, IFM_ETHER | IFM_AUTO); sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask; if (sc->mii_capabilities & BMSR_EXTSTAT) sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); + device_printf(dev, " "); - mii_phy_add_media(sc); + mii_phy_generic_media(sc); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); } /* * Return the flow control status flag from MII_ANAR & MII_ANLPAR. */ u_int mii_phy_flowstatus(struct mii_softc *sc) { int anar, anlpar; if ((sc->mii_flags & MIIF_DOPAUSE) == 0) return (0); anar = PHY_READ(sc, MII_ANAR); anlpar = PHY_READ(sc, MII_ANLPAR); /* * Check for 1000BASE-X. Autonegotiation is a bit * different on such devices. */ if ((sc->mii_flags & MIIF_IS_1000X) != 0) { anar <<= 3; anlpar <<= 3; } if ((anar & ANAR_PAUSE_SYM) != 0 && (anlpar & ANLPAR_PAUSE_SYM) != 0) return (IFM_FLOW | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE); if ((anar & ANAR_PAUSE_SYM) == 0) { if ((anar & ANAR_PAUSE_ASYM) != 0 && (anlpar & ANLPAR_PAUSE_TOWARDS) != 0) return (IFM_FLOW | IFM_ETH_TXPAUSE); else return (0); } if ((anar & ANAR_PAUSE_ASYM) == 0) { if ((anlpar & ANLPAR_PAUSE_SYM) != 0) return (IFM_FLOW | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE); else return (0); } switch ((anlpar & ANLPAR_PAUSE_TOWARDS)) { case ANLPAR_PAUSE_NONE: return (0); case ANLPAR_PAUSE_ASYM: return (IFM_FLOW | IFM_ETH_RXPAUSE); default: return (IFM_FLOW | IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE); } /* NOTREACHED */ } Index: projects/ifnet/sys/dev/mii/miivar.h =================================================================== --- projects/ifnet/sys/dev/mii/miivar.h (revision 282025) +++ projects/ifnet/sys/dev/mii/miivar.h (revision 282026) @@ -1,254 +1,281 @@ /* $NetBSD: miivar.h,v 1.8 1999/04/23 04:24:32 thorpej Exp $ */ /*- * Copyright (c) 1998, 1999 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 * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _DEV_MII_MIIVAR_H_ #define _DEV_MII_MIIVAR_H_ #include /* - * Media Independent Interface data structure defintions + * Media Independent Interface data structure definitions. */ -struct mii_softc; - /* - * A network interface driver has one of these structures in its softc. - * It is the interface from the network interface driver to the MII - * layer. + * This is the interface from the network interface driver to the MII + * layer. A NIC driver grabs the structure via device_get_softc(miibus). */ struct mii_data { - struct ifmedia mii_media; /* media information */ + /* + * Current media word. Matches the one that if_media.c stores. + * Modified by mii_mediachg(). Most functions descent from + * mii_mediachg(), and carry requested media word as argument, + * however some require it to be saved in softc. + */ + if_media_t mii_media; /* * For network interfaces with multiple PHYs, a list of all * PHYs is required so they can all be notified when a media * request is made. */ LIST_HEAD(mii_listhead, mii_softc) mii_phys; u_int mii_instance; /* * PHY driver fills this in with active media status. */ u_int mii_media_status; u_int mii_media_active; + + /* + * The number of MII_MAX_MEDIAE was taken quite carelessly. + * The mii_physubr.c can add at maximum 20 mediae per phy. + * Some phys (acphy) can a couple of extra mediae on top of + * that. However, there could be several phys per miibus(4). + * On the other hand, all known NICs that may have several + * phys, are quite old and their twisted pair phy can run + * at maximum of 100 Mbit/s. + * We could allocate this array dynamically, but looks like + * miibus(4) enabled drivers are now legacy, so a more simple + * static design was chosen. + */ +#define MII_MAX_MEDIAE 30 + u_int mii_index; + if_media_t mii_mediae[MII_MAX_MEDIAE + 1]; }; typedef struct mii_data mii_data_t; /* + * Requests that can be made to the downcall. + */ +typedef enum { + MII_TICK = 1, /* once-per-second tick */ + MII_MEDIACHG, /* user changed media; perform the switch */ + MII_POLLSTAT, /* user requested media status; fill it in */ +} mii_cmd_t; + +struct mii_softc; + +/* * Functions provided by the PHY to perform various functions. */ struct mii_phy_funcs { - int (*pf_service)(struct mii_softc *, struct mii_data *, int); - void (*pf_status)(struct mii_softc *); - void (*pf_reset)(struct mii_softc *); + int (*pf_service)(struct mii_softc *, struct mii_data *, mii_cmd_t, + if_media_t media); + void (*pf_status)(struct mii_softc *, if_media_t); + void (*pf_reset)(struct mii_softc *, if_media_t); }; /* - * Requests that can be made to the downcall. - */ -#define MII_TICK 1 /* once-per-second tick */ -#define MII_MEDIACHG 2 /* user changed media; perform the switch */ -#define MII_POLLSTAT 3 /* user requested media status; fill it in */ - -/* * Each PHY driver's softc has one of these as the first member. * XXX This would be better named "phy_softc", but this is the name * XXX BSDI used, and we would like to have the same interface. */ struct mii_softc { device_t mii_dev; /* generic device glue */ LIST_ENTRY(mii_softc) mii_list; /* entry on parent's PHY list */ uint32_t mii_mpd_oui; /* the PHY's OUI (MII_OUI())*/ uint32_t mii_mpd_model; /* the PHY's model (MII_MODEL())*/ uint32_t mii_mpd_rev; /* the PHY's revision (MII_REV())*/ u_int mii_capmask; /* capability mask for BMSR */ u_int mii_phy; /* our MII address */ u_int mii_offset; /* first PHY, second PHY, etc. */ u_int mii_inst; /* instance for ifmedia */ /* Our PHY functions. */ const struct mii_phy_funcs *mii_funcs; struct mii_data *mii_pdata; /* pointer to parent's mii_data */ u_int mii_flags; /* misc. flags; see below */ u_int mii_capabilities; /* capabilities from BMSR */ u_int mii_extcapabilities; /* extended capabilities */ u_int mii_ticks; /* MII_TICK counter */ u_int mii_anegticks; /* ticks before retrying aneg */ u_int mii_media_active; /* last active media */ u_int mii_media_status; /* last active status */ }; typedef struct mii_softc mii_softc_t; /* mii_flags */ #define MIIF_INITDONE 0x00000001 /* has been initialized (mii_data) */ #define MIIF_NOISOLATE 0x00000002 /* do not isolate the PHY */ #if 0 #define MIIF_NOLOOP 0x00000004 /* no loopback capability */ #endif #define MIIF_DOINGAUTO 0x00000008 /* doing autonegotiation (mii_softc) */ #define MIIF_AUTOTSLEEP 0x00000010 /* use tsleep(), not callout() */ #define MIIF_HAVEFIBER 0x00000020 /* from parent: has fiber interface */ #define MIIF_HAVE_GTCR 0x00000040 /* has 100base-T2/1000base-T CR */ #define MIIF_IS_1000X 0x00000080 /* is a 1000BASE-X device */ #define MIIF_DOPAUSE 0x00000100 /* advertise PAUSE capability */ #define MIIF_IS_HPNA 0x00000200 /* is a HomePNA device */ #define MIIF_FORCEANEG 0x00000400 /* force auto-negotiation */ #define MIIF_NOMANPAUSE 0x00100000 /* no manual PAUSE selection */ #define MIIF_FORCEPAUSE 0x00200000 /* force PAUSE advertisement */ #define MIIF_MACPRIV0 0x01000000 /* private to the MAC driver */ #define MIIF_MACPRIV1 0x02000000 /* private to the MAC driver */ #define MIIF_MACPRIV2 0x04000000 /* private to the MAC driver */ #define MIIF_PHYPRIV0 0x10000000 /* private to the PHY driver */ #define MIIF_PHYPRIV1 0x20000000 /* private to the PHY driver */ #define MIIF_PHYPRIV2 0x40000000 /* private to the PHY driver */ /* Default mii_anegticks values */ #define MII_ANEGTICKS 5 #define MII_ANEGTICKS_GIGE 17 #define MIIF_INHERIT_MASK (MIIF_NOISOLATE|MIIF_NOLOOP|MIIF_AUTOTSLEEP) /* * Special `locators' passed to mii_attach(). If one of these is not * an `any' value, we look for *that* PHY and configure it. If both * are not `any', that is an error, and mii_attach() will fail. */ #define MII_OFFSET_ANY -1 #define MII_PHY_ANY -1 /* * Used to attach a PHY to a parent. */ struct mii_attach_args { struct mii_data *mii_data; /* pointer to parent data */ u_int mii_phyno; /* MII address */ u_int mii_offset; /* first PHY, second PHY, etc. */ uint32_t mii_id1; /* PHY ID register 1 */ uint32_t mii_id2; /* PHY ID register 2 */ u_int mii_capmask; /* capability mask for BMSR */ }; typedef struct mii_attach_args mii_attach_args_t; /* * Used to match a PHY. */ struct mii_phydesc { uint32_t mpd_oui; /* the PHY's OUI */ uint32_t mpd_model; /* the PHY's model */ const char *mpd_name; /* the PHY's name */ }; #define MII_PHY_DESC(a, b) { MII_OUI_ ## a, MII_MODEL_ ## a ## _ ## b, \ MII_STR_ ## a ## _ ## b } #define MII_PHY_END { 0, 0, NULL } #ifdef _KERNEL #define PHY_READ(p, r) \ MIIBUS_READREG((p)->mii_dev, (p)->mii_phy, (r)) #define PHY_WRITE(p, r, v) \ MIIBUS_WRITEREG((p)->mii_dev, (p)->mii_phy, (r), (v)) -#define PHY_SERVICE(p, d, o) \ - (*(p)->mii_funcs->pf_service)((p), (d), (o)) +#define PHY_SERVICE(p, d, o, m) \ + (*(p)->mii_funcs->pf_service)((p), (d), (o), (m)) -#define PHY_STATUS(p) \ - (*(p)->mii_funcs->pf_status)(p) +#define PHY_STATUS(p, m) \ + (*(p)->mii_funcs->pf_status)((p), (m)) -#define PHY_RESET(p) \ - (*(p)->mii_funcs->pf_reset)(p) +#define PHY_RESET(p, m) \ + (*(p)->mii_funcs->pf_reset)((p), (m)) enum miibus_device_ivars { MIIBUS_IVAR_FLAGS }; /* * Simplified accessors for miibus */ #define MIIBUS_ACCESSOR(var, ivar, type) \ __BUS_ACCESSOR(miibus, var, MIIBUS, ivar, type) MIIBUS_ACCESSOR(flags, FLAGS, u_int) extern devclass_t miibus_devclass; extern driver_t miibus_driver; -int mii_attach(device_t, device_t *, ifm_change_cb_t, ifm_stat_cb_t, - int, int, int, int); -int mii_mediachg(struct mii_data *); +int mii_attach(device_t, device_t *, int, int, int, int); +int mii_mediachg(struct mii_data *, if_media_t); void mii_tick(struct mii_data *); void mii_pollstat(struct mii_data *); -void mii_phy_add_media(struct mii_softc *); +void mii_phy_add_media(struct mii_data *, if_media_t); +void mii_phy_generic_media(struct mii_softc *); -int mii_phy_auto(struct mii_softc *); +int mii_phy_auto(struct mii_softc *, if_media_t); int mii_phy_detach(device_t dev); u_int mii_phy_flowstatus(struct mii_softc *); -void mii_phy_reset(struct mii_softc *); -void mii_phy_setmedia(struct mii_softc *sc); -void mii_phy_update(struct mii_softc *, int); +void mii_phy_reset(struct mii_softc *, if_media_t); +void mii_phy_setmedia(struct mii_softc *, if_media_t); +void mii_phy_update(struct mii_softc *, mii_cmd_t); int mii_phy_tick(struct mii_softc *); int mii_phy_mac_match(struct mii_softc *, const char *); int mii_dev_mac_match(device_t, const char *); void *mii_phy_mac_softc(struct mii_softc *); void *mii_dev_mac_softc(device_t); const struct mii_phydesc * mii_phy_match(const struct mii_attach_args *ma, const struct mii_phydesc *mpd); const struct mii_phydesc * mii_phy_match_gen(const struct mii_attach_args *ma, const struct mii_phydesc *mpd, size_t endlen); int mii_phy_dev_probe(device_t dev, const struct mii_phydesc *mpd, int mrv); void mii_phy_dev_attach(device_t dev, u_int flags, const struct mii_phy_funcs *mpf, int add_media); -void ukphy_status(struct mii_softc *); +void ukphy_status(struct mii_softc *, if_media_t); u_int mii_oui(u_int, u_int); #define MII_OUI(id1, id2) mii_oui(id1, id2) #define MII_MODEL(id2) (((id2) & IDR2_MODEL) >> 4) #define MII_REV(id2) ((id2) & IDR2_REV) /* Arguments for miibus_readvar(). */ enum { MIIVAR_MTU, }; + +/* miibus(4) uses some bits of if_media_t for its own cookies. */ +#define MII_MEDIA_MASK (IFM_IMASK | IFM_FLAG0 | IFM_FLAG1 | IFM_FLAG2) #endif /* _KERNEL */ #endif /* _DEV_MII_MIIVAR_H_ */ Index: projects/ifnet/sys/dev/mii/mlphy.c =================================================================== --- projects/ifnet/sys/dev/mii/mlphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/mlphy.c (revision 282026) @@ -1,359 +1,353 @@ /*- * Copyright (c) 1997, 1998, 1999 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); /* * driver for Micro Linear 6692 PHYs * * The Micro Linear 6692 is a strange beast, and dealing with it using * this code framework is tricky. The 6692 is actually a 100Mbps-only * device, which means that a second PHY is required to support 10Mbps * modes. However, even though the 6692 does not support 10Mbps modes, * it can still advertise them when performing autonegotiation. If a * 10Mbps mode is negotiated, we must program the registers of the * companion PHY accordingly in addition to programming the registers * of the 6692. * * This device also does not have vendor/device ID registers. */ #include #include #include #include #include #include #include -#include #include #include #include #include "miibus_if.h" #define ML_STATE_AUTO_SELF 1 #define ML_STATE_AUTO_OTHER 2 struct mlphy_softc { struct mii_softc ml_mii; device_t ml_dev; int ml_state; int ml_linked; }; static int mlphy_probe(device_t); static int mlphy_attach(device_t); static device_method_t mlphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, mlphy_probe), DEVMETHOD(device_attach, mlphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t mlphy_devclass; static driver_t mlphy_driver = { "mlphy", mlphy_methods, sizeof(struct mlphy_softc) }; DRIVER_MODULE(mlphy, miibus, mlphy_driver, mlphy_devclass, 0, 0); static struct mii_softc *mlphy_find_other(struct mlphy_softc *); -static int mlphy_service(struct mii_softc *, struct mii_data *, int); -static void mlphy_reset(struct mii_softc *); -static void mlphy_status(struct mii_softc *); +static int mlphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void mlphy_reset(struct mii_softc *, if_media_t); +static void mlphy_status(struct mii_softc *, if_media_t); static const struct mii_phy_funcs mlphy_funcs = { mlphy_service, mlphy_status, mlphy_reset }; static int mlphy_probe(dev) device_t dev; { struct mii_attach_args *ma; ma = device_get_ivars(dev); /* * Micro Linear PHY reports oui == 0 model == 0 */ if (MII_OUI(ma->mii_id1, ma->mii_id2) != 0 || MII_MODEL(ma->mii_id2) != 0) return (ENXIO); /* * Make sure the parent is a `tl'. So far, I have only * encountered the 6692 on an Olicom card with a ThunderLAN * controller chip. */ if (!mii_dev_mac_match(dev, "tl")) return (ENXIO); device_set_desc(dev, "Micro Linear 6692 media interface"); return (BUS_PROBE_DEFAULT); } static int -mlphy_attach(dev) - device_t dev; +mlphy_attach(device_t dev) { struct mlphy_softc *msc; struct mii_softc *sc; msc = device_get_softc(dev); sc = &msc->ml_mii; msc->ml_dev = dev; mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &mlphy_funcs, 0); - PHY_RESET(sc); + PHY_RESET(sc, 0); sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask; /* Let the companion PHY (if any) only handle the media we don't. */ sc->mii_capmask = ~sc->mii_capabilities; device_printf(dev, " "); - mii_phy_add_media(sc); + mii_phy_generic_media(sc); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); return (0); } static struct mii_softc * mlphy_find_other(struct mlphy_softc *msc) { device_t *devlist; struct mii_softc *retval; int i, devs; retval = NULL; if (device_get_children(msc->ml_mii.mii_dev, &devlist, &devs) != 0) return (NULL); for (i = 0; i < devs; i++) { if (devlist[i] != msc->ml_dev) { retval = device_get_softc(devlist[i]); break; } } free(devlist, M_TEMP); return (retval); } static int -mlphy_service(xsc, mii, cmd) - struct mii_softc *xsc; - struct mii_data *mii; - int cmd; +mlphy_service(struct mii_softc *xsc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; struct mii_softc *other = NULL; struct mlphy_softc *msc = (struct mlphy_softc *)xsc; struct mii_softc *sc = (struct mii_softc *)&msc->ml_mii; int other_inst, reg; /* * See if there's another PHY on this bus with us. * If so, we may need it for 10Mbps modes. */ other = mlphy_find_other(msc); switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - switch (IFM_SUBTYPE(ife->ifm_media)) { + switch (IFM_SUBTYPE(media)) { case IFM_AUTO: /* * For autonegotiation, reset and isolate the * companion PHY (if any) and then do NWAY * autonegotiation ourselves. */ msc->ml_state = ML_STATE_AUTO_SELF; if (other != NULL) { - PHY_RESET(other); + PHY_RESET(other, media); PHY_WRITE(other, MII_BMCR, BMCR_ISO); } - (void)mii_phy_auto(sc); + (void)mii_phy_auto(sc, media); msc->ml_linked = 0; return (0); case IFM_10_T: case IFM_100_TX: /* * For 10baseT and 100baseTX modes, reset and isolate * the companion PHY (if any), then program ourselves * accordingly. */ if (other != NULL) { - PHY_RESET(other); + PHY_RESET(other, media); PHY_WRITE(other, MII_BMCR, BMCR_ISO); } - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); msc->ml_state = 0; break; default: return (EINVAL); } break; case MII_TICK: /* * Only used for autonegotiation. */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + if (IFM_SUBTYPE(media) != IFM_AUTO) break; /* * Check to see if we have link. If we do, we don't * need to restart the autonegotiation process. Read * the BMSR twice in case it's latched. * If we're in a 10Mbps mode, check the link of the * 10Mbps PHY. Sometimes the Micro Linear PHY's * linkstat bit will clear while the linkstat bit of * the companion PHY will remain set. */ if (msc->ml_state == ML_STATE_AUTO_OTHER) { reg = PHY_READ(other, MII_BMSR) | PHY_READ(other, MII_BMSR); } else { reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); } if (reg & BMSR_LINK) { if (!msc->ml_linked) { msc->ml_linked = 1; - PHY_STATUS(sc); + PHY_STATUS(sc, media); } break; } /* * Only retry autonegotiation every 5 seconds. */ if (++sc->mii_ticks <= MII_ANEGTICKS) break; sc->mii_ticks = 0; msc->ml_linked = 0; mii->mii_media_active = IFM_NONE; - PHY_RESET(sc); + PHY_RESET(sc, media); msc->ml_state = ML_STATE_AUTO_SELF; if (other != NULL) { - PHY_RESET(other); + PHY_RESET(other, media); PHY_WRITE(other, MII_BMCR, BMCR_ISO); } - mii_phy_auto(sc); + mii_phy_auto(sc, media); return (0); } /* Update the media status. */ if (msc->ml_state == ML_STATE_AUTO_OTHER) { other_inst = other->mii_inst; other->mii_inst = sc->mii_inst; - if (IFM_INST(ife->ifm_media) == other->mii_inst) - (void)PHY_SERVICE(other, mii, MII_POLLSTAT); + if (IFM_INST(media) == other->mii_inst) + (void)PHY_SERVICE(other, mii, MII_POLLSTAT, media); other->mii_inst = other_inst; sc->mii_media_active = other->mii_media_active; sc->mii_media_status = other->mii_media_status; } else - ukphy_status(sc); + ukphy_status(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } /* * The Micro Linear PHY comes out of reset with the 'autoneg * enable' bit set, which we don't want. */ static void -mlphy_reset(sc) - struct mii_softc *sc; +mlphy_reset(struct mii_softc *sc, if_media_t media) { int reg; - mii_phy_reset(sc); + mii_phy_reset(sc, media); reg = PHY_READ(sc, MII_BMCR); reg &= ~BMCR_AUTOEN; PHY_WRITE(sc, MII_BMCR, reg); } /* * If we negotiate a 10Mbps mode, we need to check for an alternate * PHY and make sure it's enabled and set correctly. */ static void -mlphy_status(sc) - struct mii_softc *sc; +mlphy_status(struct mii_softc *sc, if_media_t media) { struct mlphy_softc *msc = (struct mlphy_softc *)sc; struct mii_data *mii = msc->ml_mii.mii_pdata; struct mii_softc *other = NULL; /* See if there's another PHY on the bus with us. */ other = mlphy_find_other(msc); if (other == NULL) return; - ukphy_status(sc); + ukphy_status(sc, media); if (IFM_SUBTYPE(mii->mii_media_active) != IFM_10_T) { msc->ml_state = ML_STATE_AUTO_SELF; - PHY_RESET(other); + PHY_RESET(other, media); PHY_WRITE(other, MII_BMCR, BMCR_ISO); } if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T) { msc->ml_state = ML_STATE_AUTO_OTHER; - PHY_RESET(&msc->ml_mii); + PHY_RESET(&msc->ml_mii, media); PHY_WRITE(&msc->ml_mii, MII_BMCR, BMCR_ISO); - PHY_RESET(other); - mii_phy_auto(other); + PHY_RESET(other, media); + mii_phy_auto(other, media); } } Index: projects/ifnet/sys/dev/mii/nsgphy.c =================================================================== --- projects/ifnet/sys/dev/mii/nsgphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/nsgphy.c (revision 282026) @@ -1,246 +1,246 @@ /*- * Copyright (c) 2001 Wind River Systems * Copyright (c) 2001 * Bill Paul . 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 * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Driver for the National Semiconductor DP83861, DP83865 and DP83891 * 10/100/1000 PHYs. * Datasheet available at: http://www.national.com/ds/DP/DP83861.pdf * and at: http://www.national.com/ds/DP/DP83865.pdf * * The DP83891 is the older NS GigE PHY which isn't being sold * anymore. The DP83861 is its replacement, which is an 'enhanced' * firmware driven component. The major difference between the * two is that the DP83891 can't generate interrupts, while the * 83861 can (probably it wasn't originally designed to do this, but * it can now thanks to firmware updates). The DP83861 also allows * access to its internal RAM via indirect register access. The * DP83865 is an ultra low power version of the DP83861 and DP83891. */ #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" static int nsgphy_probe(device_t); static int nsgphy_attach(device_t); static device_method_t nsgphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, nsgphy_probe), DEVMETHOD(device_attach, nsgphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t nsgphy_devclass; static driver_t nsgphy_driver = { "nsgphy", nsgphy_methods, sizeof(struct mii_softc) }; 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_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void nsgphy_status(struct mii_softc *, if_media_t); static const struct mii_phydesc nsgphys[] = { MII_PHY_DESC(xxNATSEMI, DP83861), MII_PHY_DESC(xxNATSEMI, DP83865), MII_PHY_DESC(xxNATSEMI, DP83891), MII_PHY_END }; static const struct mii_phy_funcs nsgphy_funcs = { nsgphy_service, nsgphy_status, mii_phy_reset }; static int nsgphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, nsgphys, BUS_PROBE_DEFAULT)); } static int nsgphy_attach(device_t dev) { struct mii_softc *sc; sc = device_get_softc(dev); mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &nsgphy_funcs, 0); - PHY_RESET(sc); + PHY_RESET(sc, 0); /* * NB: the PHY has the 10BASE-T BMSR bits hard-wired to 0, * even though it supports 10BASE-T. */ sc->mii_capabilities = (PHY_READ(sc, MII_BMSR) | BMSR_10TFDX | BMSR_10THDX) & sc->mii_capmask; /* * Note that as documented manual 1000BASE-T modes of DP83865 only * work together with other National Semiconductor PHYs. */ if (sc->mii_capabilities & BMSR_EXTSTAT) sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); - mii_phy_add_media(sc); + mii_phy_generic_media(sc); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); return (0); } static int -nsgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +nsgphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; case MII_TICK: if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -nsgphy_status(struct mii_softc *sc) +nsgphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; - 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) | PHY_READ(sc, MII_BMSR); physup = PHY_READ(sc, NSGPHY_MII_PHYSUP); 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; if (bmcr & BMCR_AUTOEN) { /* * The media status bits are only valid if autonegotiation * has completed (or it's disabled). */ if ((bmsr & BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; 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; case 0: mii->mii_media_active |= IFM_10_T; break; default: mii->mii_media_active |= IFM_NONE; mii->mii_media_status = 0; return; } if (physup & PHY_SUP_DUPLEX) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; } else - mii->mii_media_active = ife->ifm_media; + mii->mii_media_active = media; } Index: projects/ifnet/sys/dev/mii/nsphy.c =================================================================== --- projects/ifnet/sys/dev/mii/nsphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/nsphy.c (revision 282026) @@ -1,324 +1,323 @@ /* $NetBSD: nsphy.c,v 1.18 1999/07/14 23:57:36 thorpej Exp $ */ /*- * Copyright (c) 1998, 1999 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 * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (c) 1997 Manuel Bouyer. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * driver for National Semiconductor's DP83840A ethernet 10/100 PHY * Data Sheet available from www.national.com */ #include #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" static int nsphy_probe(device_t); static int nsphy_attach(device_t); static device_method_t nsphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, nsphy_probe), DEVMETHOD(device_attach, nsphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t nsphy_devclass; static driver_t nsphy_driver = { "nsphy", nsphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(nsphy, miibus, nsphy_driver, nsphy_devclass, 0, 0); -static int nsphy_service(struct mii_softc *, struct mii_data *, int); -static void nsphy_status(struct mii_softc *); -static void nsphy_reset(struct mii_softc *); +static int nsphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void nsphy_status(struct mii_softc *, if_media_t); +static void nsphy_reset(struct mii_softc *, if_media_t); static const struct mii_phydesc nsphys[] = { MII_PHY_DESC(xxNATSEMI, DP83840), MII_PHY_END }; static const struct mii_phy_funcs nsphy_funcs = { nsphy_service, nsphy_status, nsphy_reset }; static int nsphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, nsphys, BUS_PROBE_DEFAULT)); } static int nsphy_attach(device_t dev) { u_int flags; flags = MIIF_NOMANPAUSE; /* * Am79C971 wedge when isolating all of their external PHYs. */ if (mii_dev_mac_match(dev,"pcn")) flags |= MIIF_NOISOLATE; mii_phy_dev_attach(dev, flags, &nsphy_funcs, 1); return (0); } static int -nsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +nsphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { int reg; switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: reg = PHY_READ(sc, MII_NSPHY_PCR); /* * Set up the PCR to use LED4 to indicate full-duplex * in both 10baseT and 100baseTX modes. */ reg |= PCR_LED4MODE; /* * Make sure Carrier Integrity Monitor function is * disabled (normal for Node operation, but sometimes * it's not set?!) */ reg |= PCR_CIMDIS; /* * Make sure "force link good" is set to normal mode. * It's only intended for debugging. */ reg |= PCR_FLINK100; /* * Mystery bits which are supposedly `reserved', * but we seem to need to set them when the PHY * is connected to some interfaces: * * 0x0400 is needed for fxp * (Intel EtherExpress Pro 10+/100B, 82557 chip) * (nsphy with a DP83840 chip) * 0x0100 may be needed for some other card */ reg |= 0x0100 | 0x0400; if (mii_phy_mac_match(sc, "fxp")) PHY_WRITE(sc, MII_NSPHY_PCR, reg); - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; case MII_TICK: if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -nsphy_status(struct mii_softc *sc) +nsphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmsr, bmcr, par, anlpar; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (bmsr & BMSR_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; if (bmcr & BMCR_AUTOEN) { /* * The PAR status bits are only valid if autonegotiation * has completed (or it's disabled). */ if ((bmsr & BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } /* * Argh. The PAR doesn't seem to indicate duplex mode * properly! Determine media based on link partner's * advertised capabilities. */ if (PHY_READ(sc, MII_ANER) & ANER_LPAN) { anlpar = PHY_READ(sc, MII_ANAR) & PHY_READ(sc, MII_ANLPAR); if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; else if (anlpar & ANLPAR_T4) mii->mii_media_active |= IFM_100_T4|IFM_HDX; else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX|IFM_HDX; 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; if ((mii->mii_media_active & IFM_FDX) != 0) mii->mii_media_active |= mii_phy_flowstatus(sc); return; } /* * Link partner is not capable of autonegotiation. * We will never be in full-duplex mode if this is * the case, so reading the PAR is OK. */ par = PHY_READ(sc, MII_NSPHY_PAR); if (par & PAR_10) mii->mii_media_active |= IFM_10_T; else mii->mii_media_active |= IFM_100_TX; mii->mii_media_active |= IFM_HDX; } else - mii->mii_media_active = ife->ifm_media; + mii->mii_media_active = media; } static void -nsphy_reset(struct mii_softc *sc) +nsphy_reset(struct mii_softc *sc, if_media_t media) { - struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur; int reg, i; if (sc->mii_flags & MIIF_NOISOLATE) reg = BMCR_RESET; else reg = BMCR_RESET | BMCR_ISO; PHY_WRITE(sc, MII_BMCR, reg); /* * It is best to allow a little time for the reset to settle * in before we start polling the BMCR again. Notably, the * DP83840A manuals state that there should be a 500us delay * between asserting software reset and attempting MII serial * operations. Be conservative. */ DELAY(1000); /* * Wait another 2s for it to complete. * This is only a little overkill as under normal circumstances * the PHY can take up to 1s to complete reset. * This is also a bit odd because after a reset, the BMCR will * clear the reset bit and simply reports 0 even though the reset * is not yet complete. */ for (i = 0; i < 1000; i++) { reg = PHY_READ(sc, MII_BMCR); if (reg != 0 && (reg & BMCR_RESET) == 0) break; DELAY(2000); } if ((sc->mii_flags & MIIF_NOISOLATE) == 0) { - if ((ife == NULL && sc->mii_inst != 0) || - (ife != NULL && IFM_INST(ife->ifm_media) != sc->mii_inst)) + if ((media == 0 && sc->mii_inst != 0) || + (media != 0 && IFM_INST(media) != sc->mii_inst)) PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); } } Index: projects/ifnet/sys/dev/mii/nsphyter.c =================================================================== --- projects/ifnet/sys/dev/mii/nsphyter.c (revision 282025) +++ projects/ifnet/sys/dev/mii/nsphyter.c (revision 282026) @@ -1,262 +1,261 @@ /* $NetBSD: nsphyter.c,v 1.28 2008/01/20 07:58:19 msaitoh Exp $ */ /*- * 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 * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (c) 1997 Manuel Bouyer. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Driver for the National Semiconductor's DP83843, DP83847 and DP83849 * `PHYTER' Ethernet 10/100 PHYs * Data Sheets are available from http://www.national.com * * We also support the DP83815 `MacPHYTER' internal PHY since, for our * purposes, they are compatible. */ #include #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" static device_probe_t nsphyter_probe; static device_attach_t nsphyter_attach; static device_method_t nsphyter_methods[] = { /* device interface */ DEVMETHOD(device_probe, nsphyter_probe), DEVMETHOD(device_attach, nsphyter_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t nsphyter_devclass; static driver_t nsphyter_driver = { "nsphyter", nsphyter_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(nsphyter, miibus, nsphyter_driver, nsphyter_devclass, 0, 0); -static int nsphyter_service(struct mii_softc *, struct mii_data *, int); -static void nsphyter_status(struct mii_softc *); -static void nsphyter_reset(struct mii_softc *); +static int nsphyter_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void nsphyter_status(struct mii_softc *, if_media_t); +static void nsphyter_reset(struct mii_softc *, if_media_t); static const struct mii_phydesc nsphyters[] = { MII_PHY_DESC(xxNATSEMI, DP83815), MII_PHY_DESC(xxNATSEMI, DP83843), MII_PHY_DESC(xxNATSEMI, DP83847), MII_PHY_DESC(xxNATSEMI, DP83849), MII_PHY_END }; static const struct mii_phy_funcs nsphyter_funcs = { nsphyter_service, nsphyter_status, nsphyter_reset }; static int nsphyter_probe(device_t dev) { return (mii_phy_dev_probe(dev, nsphyters, BUS_PROBE_DEFAULT)); } static int nsphyter_attach(device_t dev) { mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &nsphyter_funcs, 1); return (0); } static int -nsphyter_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +nsphyter_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; case MII_TICK: if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -nsphyter_status(struct mii_softc *sc) +nsphyter_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmsr, bmcr, physts; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); physts = PHY_READ(sc, MII_NSPHYTER_PHYSTS); if ((physts & PHYSTS_LINK) != 0) mii->mii_media_status |= IFM_ACTIVE; bmcr = PHY_READ(sc, MII_BMCR); if ((bmcr & BMCR_ISO) != 0) { mii->mii_media_active |= IFM_NONE; mii->mii_media_status = 0; return; } if ((bmcr & BMCR_LOOP) != 0) mii->mii_media_active |= IFM_LOOP; if ((bmcr & BMCR_AUTOEN) != 0) { /* * The media status bits are only valid if autonegotiation * has completed (or it's disabled). */ if ((bmsr & BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } if ((physts & PHYSTS_SPEED10) != 0) mii->mii_media_active |= IFM_10_T; else mii->mii_media_active |= IFM_100_TX; if ((physts & PHYSTS_DUPLEX) != 0) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; } else - mii->mii_media_active = ife->ifm_media; + mii->mii_media_active = media; } static void -nsphyter_reset(struct mii_softc *sc) +nsphyter_reset(struct mii_softc *sc, if_media_t media) { - struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur; int reg, i; if ((sc->mii_flags & MIIF_NOISOLATE) != 0) reg = BMCR_RESET; else reg = BMCR_RESET | BMCR_ISO; PHY_WRITE(sc, MII_BMCR, reg); /* * It is best to allow a little time for the reset to settle * in before we start polling the BMCR again. Notably, the * DP8384{3,7} manuals state that there should be a 500us delay * between asserting software reset and attempting MII serial * operations. Be conservative. Also, a DP83815 can get into * a bad state on cable removal and reinsertion if we do not * delay here. */ DELAY(1000); /* * Wait another 2s for it to complete. * This is only a little overkill as under normal circumstances * the PHY can take up to 1s to complete reset. * This is also a bit odd because after a reset, the BMCR will * clear the reset bit and simply reports 0 even though the reset * is not yet complete. */ for (i = 0; i < 1000; i++) { reg = PHY_READ(sc, MII_BMCR); if (reg != 0 && (reg & BMCR_RESET) == 0) break; DELAY(2000); } if ((sc->mii_flags & MIIF_NOISOLATE) == 0) { - if ((ife == NULL && sc->mii_inst != 0) || - (ife != NULL && IFM_INST(ife->ifm_media) != sc->mii_inst)) + if ((media == 0 && sc->mii_inst != 0) || + (media != 0 && IFM_INST(media) != sc->mii_inst)) PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); } } Index: projects/ifnet/sys/dev/mii/pnaphy.c =================================================================== --- projects/ifnet/sys/dev/mii/pnaphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/pnaphy.c (revision 282026) @@ -1,147 +1,147 @@ /*- * Copyright (c) 2000 Berkeley Software Design, Inc. * Copyright (c) 1997, 1998, 1999, 2000 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * driver for homePNA PHYs * This is really just a stub that allows us to identify homePNA-based * transceicers and display the link status. MII-based homePNA PHYs * only support one media type and no autonegotiation. If we were * really clever, we could tweak some of the vendor-specific registers * to optimize the link. */ #include #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include "miibus_if.h" static int pnaphy_probe(device_t); static int pnaphy_attach(device_t); static device_method_t pnaphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, pnaphy_probe), DEVMETHOD(device_attach, pnaphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t pnaphy_devclass; static driver_t pnaphy_driver = { "pnaphy", pnaphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(pnaphy, miibus, pnaphy_driver, pnaphy_devclass, 0, 0); -static int pnaphy_service(struct mii_softc *, struct mii_data *,int); +static int pnaphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); static const struct mii_phydesc pnaphys[] = { MII_PHY_DESC(yyAMD, 79c901home), MII_PHY_END }; static const struct mii_phy_funcs pnaphy_funcs = { pnaphy_service, ukphy_status, mii_phy_reset }; static int pnaphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, pnaphys, BUS_PROBE_DEFAULT)); } static int pnaphy_attach(device_t dev) { mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_IS_HPNA | MIIF_NOMANPAUSE, &pnaphy_funcs, 1); return (0); } static int -pnaphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +pnaphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - switch (IFM_SUBTYPE(ife->ifm_media)) { + switch (IFM_SUBTYPE(media)) { case IFM_HPNA_1: - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; default: return (EINVAL); } break; case MII_TICK: if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T) mii->mii_media_active = IFM_ETHER | IFM_HPNA_1; /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } Index: projects/ifnet/sys/dev/mii/qsphy.c =================================================================== --- projects/ifnet/sys/dev/mii/qsphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/qsphy.c (revision 282026) @@ -1,223 +1,224 @@ /* OpenBSD: qsphy.c,v 1.6 2000/08/26 20:04:18 nate Exp */ /* NetBSD: qsphy.c,v 1.19 2000/02/02 23:34:57 thorpej Exp */ /*- * Copyright (c) 1998, 1999 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 * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (c) 1997 Manuel Bouyer. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * driver for Quality Semiconductor's QS6612 ethernet 10/100 PHY * datasheet from www.qualitysemi.com */ #include #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" static int qsphy_probe(device_t); static int qsphy_attach(device_t); static device_method_t qsphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, qsphy_probe), DEVMETHOD(device_attach, qsphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t qsphy_devclass; static driver_t qsphy_driver = { "qsphy", qsphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(qsphy, miibus, qsphy_driver, qsphy_devclass, 0, 0); -static int qsphy_service(struct mii_softc *, struct mii_data *, int); -static void qsphy_reset(struct mii_softc *); -static void qsphy_status(struct mii_softc *); +static int qsphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void qsphy_reset(struct mii_softc *, if_media_t); +static void qsphy_status(struct mii_softc *, if_media_t); static const struct mii_phydesc qsphys[] = { MII_PHY_DESC(xxQUALSEMI, QS6612), MII_PHY_END }; static const struct mii_phy_funcs qsphy_funcs = { qsphy_service, qsphy_status, qsphy_reset }; static int qsphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, qsphys, BUS_PROBE_DEFAULT)); } static int qsphy_attach(device_t dev) { mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &qsphy_funcs, 1); return (0); } static int -qsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +qsphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; case MII_TICK: /* * This PHY's autonegotiation doesn't need to be kicked. */ break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -qsphy_status(struct mii_softc *sc) +qsphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; int bmsr, bmcr, pctl; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (bmsr & BMSR_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; pctl = PHY_READ(sc, MII_QSPHY_PCTL); switch (pctl & PCTL_OPMASK) { case PCTL_10_T: mii->mii_media_active |= IFM_10_T|IFM_HDX; break; case PCTL_10_T_FDX: mii->mii_media_active |= IFM_10_T|IFM_FDX; break; case PCTL_100_TX: mii->mii_media_active |= IFM_100_TX|IFM_HDX; break; case PCTL_100_TX_FDX: mii->mii_media_active |= IFM_100_TX|IFM_FDX; break; case PCTL_100_T4: mii->mii_media_active |= IFM_100_T4|IFM_HDX; break; case PCTL_AN: mii->mii_media_active |= IFM_NONE; break; default: /* Erg... this shouldn't happen. */ mii->mii_media_active |= IFM_NONE; break; } if ((mii->mii_media_active & IFM_FDX) != 0) mii->mii_media_active |= mii_phy_flowstatus(sc); } static void -qsphy_reset(struct mii_softc *sc) +qsphy_reset(struct mii_softc *sc, if_media_t media) { - mii_phy_reset(sc); + mii_phy_reset(sc, media); PHY_WRITE(sc, MII_QSPHY_IMASK, 0); } Index: projects/ifnet/sys/dev/mii/rdcphy.c =================================================================== --- projects/ifnet/sys/dev/mii/rdcphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/rdcphy.c (revision 282026) @@ -1,234 +1,231 @@ /*- * Copyright (c) 2010, Pyun YongHyeon * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Driver for the RDC Semiconductor R6040 10/100 PHY. */ #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" static device_probe_t rdcphy_probe; static device_attach_t rdcphy_attach; struct rdcphy_softc { struct mii_softc mii_sc; int mii_link_tick; #define RDCPHY_MANNEG_TICK 3 }; static device_method_t rdcphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, rdcphy_probe), DEVMETHOD(device_attach, rdcphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t rdcphy_devclass; static driver_t rdcphy_driver = { "rdcphy", rdcphy_methods, sizeof(struct rdcphy_softc) }; DRIVER_MODULE(rdcphy, miibus, rdcphy_driver, rdcphy_devclass, 0, 0); -static int rdcphy_service(struct mii_softc *, struct mii_data *, int); -static void rdcphy_status(struct mii_softc *); +static int rdcphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void rdcphy_status(struct mii_softc *, if_media_t); static const struct mii_phydesc rdcphys[] = { MII_PHY_DESC(RDC, R6040), MII_PHY_END }; static const struct mii_phy_funcs rdcphy_funcs = { rdcphy_service, rdcphy_status, mii_phy_reset }; static int rdcphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, rdcphys, BUS_PROBE_DEFAULT)); } static int rdcphy_attach(device_t dev) { mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &rdcphy_funcs, 1); return (0); } static int -rdcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +rdcphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { struct rdcphy_softc *rsc; - struct ifmedia_entry *ife; rsc = (struct rdcphy_softc *)sc; - ife = mii->mii_media.ifm_cur; switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - mii_phy_setmedia(sc); - switch (IFM_SUBTYPE(ife->ifm_media)) { + mii_phy_setmedia(sc, media); + switch (IFM_SUBTYPE(media)) { case IFM_100_TX: case IFM_10_T: /* * Report fake lost link event to parent * driver. This will stop MAC of parent * driver and make it possible to reconfigure * MAC after completion of link establishment. * Note, the parent MAC seems to require * restarting MAC when underlying any PHY * configuration was changed even if the * resolved speed/duplex was not changed at * all. */ mii->mii_media_status = 0; mii->mii_media_active = IFM_ETHER | IFM_NONE; rsc->mii_link_tick = RDCPHY_MANNEG_TICK; /* Immediately report link down. */ mii_phy_update(sc, MII_MEDIACHG); return (0); default: break; } break; case MII_TICK: if (mii_phy_tick(sc) == EJUSTRETURN) return (0); - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { + if (IFM_SUBTYPE(media) != IFM_AUTO) { /* * It seems the PHY hardware does not correctly * report link status changes when manual link * configuration is in progress. It is also * possible for the PHY to complete establishing * a link within one second such that mii(4) * did not notice the link change. To workaround * the issue, emulate lost link event and wait * for 3 seconds when manual link configuration * is in progress. 3 seconds would be long * enough to absorb transient link flips. */ if (rsc->mii_link_tick > 0) { rsc->mii_link_tick--; return (0); } } break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -rdcphy_status(struct mii_softc *sc) +rdcphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii; - struct ifmedia_entry *ife; int bmsr, bmcr, physts; mii = sc->mii_pdata; - ife = mii->mii_media.ifm_cur; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); physts = PHY_READ(sc, MII_RDCPHY_STATUS); if ((physts & STATUS_LINK_UP) != 0) mii->mii_media_status |= IFM_ACTIVE; bmcr = PHY_READ(sc, MII_BMCR); if ((bmcr & BMCR_ISO) != 0) { mii->mii_media_active |= IFM_NONE; mii->mii_media_status = 0; return; } if ((bmcr & BMCR_LOOP) != 0) mii->mii_media_active |= IFM_LOOP; if ((bmcr & BMCR_AUTOEN) != 0) { if ((bmsr & BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } } switch (physts & STATUS_SPEED_MASK) { case STATUS_SPEED_100: mii->mii_media_active |= IFM_100_TX; break; case STATUS_SPEED_10: mii->mii_media_active |= IFM_10_T; break; default: mii->mii_media_active |= IFM_NONE; return; } if ((physts & STATUS_FULL_DUPLEX) != 0) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; } Index: projects/ifnet/sys/dev/mii/rgephy.c =================================================================== --- projects/ifnet/sys/dev/mii/rgephy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/rgephy.c (revision 282026) @@ -1,550 +1,549 @@ /*- * Copyright (c) 2003 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Driver for the RealTek 8169S/8110S/8211B/8211C internal 10/100/1000 PHY. */ #include #include #include #include /* XXXGL: rgephyreg.h contamination */ #include /* XXXGL: rgephyreg.h contamination */ #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" #include #include static int rgephy_probe(device_t); static int rgephy_attach(device_t); static device_method_t rgephy_methods[] = { /* device interface */ DEVMETHOD(device_probe, rgephy_probe), DEVMETHOD(device_attach, rgephy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t rgephy_devclass; static driver_t rgephy_driver = { "rgephy", rgephy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(rgephy, miibus, rgephy_driver, rgephy_devclass, 0, 0); -static int rgephy_service(struct mii_softc *, struct mii_data *, int); -static void rgephy_status(struct mii_softc *); -static int rgephy_mii_phy_auto(struct mii_softc *, int); -static void rgephy_reset(struct mii_softc *); +static int rgephy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void rgephy_status(struct mii_softc *, if_media_t); +static int rgephy_mii_phy_auto(struct mii_softc *, if_media_t); +static void rgephy_reset(struct mii_softc *, if_media_t); static int rgephy_linkup(struct mii_softc *); static void rgephy_loop(struct mii_softc *); static void rgephy_load_dspcode(struct mii_softc *); static const struct mii_phydesc rgephys[] = { MII_PHY_DESC(REALTEK, RTL8169S), MII_PHY_DESC(REALTEK, RTL8251), MII_PHY_END }; static const struct mii_phy_funcs rgephy_funcs = { rgephy_service, rgephy_status, rgephy_reset }; static int rgephy_probe(device_t dev) { return (mii_phy_dev_probe(dev, rgephys, BUS_PROBE_DEFAULT)); } static int rgephy_attach(device_t dev) { struct mii_softc *sc; u_int flags; sc = device_get_softc(dev); flags = 0; if (mii_dev_mac_match(dev, "re")) flags |= MIIF_PHYPRIV0; mii_phy_dev_attach(dev, flags, &rgephy_funcs, 0); /* RTL8169S do not report auto-sense; add manually. */ sc->mii_capabilities = (PHY_READ(sc, MII_BMSR) | BMSR_ANEG) & sc->mii_capmask; if (sc->mii_capabilities & BMSR_EXTSTAT) sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); device_printf(dev, " "); - mii_phy_add_media(sc); + mii_phy_generic_media(sc); printf("\n"); - /* - * Allow IFM_FLAG0 to be set indicating that auto-negotiation with - * manual configuration, which is used to work around issues with - * certain setups by default, should not be triggered as it may in - * turn cause harm in some edge cases. - */ - sc->mii_pdata->mii_media.ifm_mask |= IFM_FLAG0; - PHY_RESET(sc); + PHY_RESET(sc, sc->mii_pdata->mii_media); MIIBUS_MEDIAINIT(sc->mii_dev); return (0); } static int -rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +rgephy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int speed, gig, anar; switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - PHY_RESET(sc); /* XXX hardware bug work-around */ + PHY_RESET(sc, media); /* XXX hardware bug work-around */ anar = PHY_READ(sc, RGEPHY_MII_ANAR); anar &= ~(RGEPHY_ANAR_PC | RGEPHY_ANAR_ASP | RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX | RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10); - switch (IFM_SUBTYPE(ife->ifm_media)) { + switch (IFM_SUBTYPE(media)) { case IFM_AUTO: #ifdef foo /* * If we're already in auto mode, just return. */ if (PHY_READ(sc, RGEPHY_MII_BMCR) & RGEPHY_BMCR_AUTOEN) return (0); #endif - (void)rgephy_mii_phy_auto(sc, ife->ifm_media); + (void)rgephy_mii_phy_auto(sc, media); break; case IFM_1000_T: speed = RGEPHY_S1000; goto setit; case IFM_100_TX: speed = RGEPHY_S100; anar |= RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX; goto setit; case IFM_10_T: + /* + * Allow IFM_FLAG0 to be set indicating that + * auto-negotiation with manual configuration, + * which is used to work around issues with certain + * setups by default, should not be triggered as it + * may in turn cause harm in some edge cases. + */ speed = RGEPHY_S10; anar |= RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10; setit: - if ((ife->ifm_media & IFM_FLOW) != 0 && - (mii->mii_media.ifm_media & IFM_FLAG0) != 0) + if ((media & IFM_FLOW) != 0 && (media & IFM_FLAG0) != 0) return (EINVAL); - if ((ife->ifm_media & IFM_FDX) != 0) { + if ((media & IFM_FDX) != 0) { speed |= RGEPHY_BMCR_FDX; gig = RGEPHY_1000CTL_AFD; anar &= ~(RGEPHY_ANAR_TX | RGEPHY_ANAR_10); - if ((ife->ifm_media & IFM_FLOW) != 0 || + if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0) anar |= RGEPHY_ANAR_PC | RGEPHY_ANAR_ASP; } else { gig = RGEPHY_1000CTL_AHD; anar &= ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_10_FD); } - if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) { + if (IFM_SUBTYPE(media) == IFM_1000_T) { gig |= RGEPHY_1000CTL_MSE; - if ((ife->ifm_media & IFM_ETH_MASTER) != 0) + if ((media & IFM_ETH_MASTER) != 0) gig |= RGEPHY_1000CTL_MSC; } else { gig = 0; anar &= ~RGEPHY_ANAR_ASP; } - if ((mii->mii_media.ifm_media & IFM_FLAG0) == 0) + if ((media & IFM_FLAG0) == 0) speed |= RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG; rgephy_loop(sc); PHY_WRITE(sc, RGEPHY_MII_1000CTL, gig); PHY_WRITE(sc, RGEPHY_MII_ANAR, anar); PHY_WRITE(sc, RGEPHY_MII_BMCR, speed); break; case IFM_NONE: PHY_WRITE(sc, MII_BMCR, BMCR_ISO | BMCR_PDOWN); break; default: return (EINVAL); } break; case MII_TICK: /* * Only used for autonegotiation. */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { + if (IFM_SUBTYPE(media) != IFM_AUTO) { sc->mii_ticks = 0; break; } /* * Check to see if we have link. If we do, we don't * need to restart the autonegotiation process. */ if (rgephy_linkup(sc) != 0) { sc->mii_ticks = 0; break; } /* Announce link loss right after it happens. */ if (sc->mii_ticks++ == 0) break; /* Only retry autonegotiation every mii_anegticks seconds. */ if (sc->mii_ticks <= sc->mii_anegticks) return (0); sc->mii_ticks = 0; - rgephy_mii_phy_auto(sc, ife->ifm_media); + rgephy_mii_phy_auto(sc, media); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* * Callback if something changed. Note that we need to poke * the DSP on the RealTek PHYs if the media changes. * */ if (sc->mii_media_active != mii->mii_media_active || sc->mii_media_status != mii->mii_media_status || cmd == MII_MEDIACHG) { rgephy_load_dspcode(sc); } mii_phy_update(sc, cmd); return (0); } static int rgephy_linkup(struct mii_softc *sc) { int linkup; uint16_t reg; linkup = 0; if ((sc->mii_flags & MIIF_PHYPRIV0) == 0 && sc->mii_mpd_rev >= RGEPHY_8211B) { if (sc->mii_mpd_rev == RGEPHY_8211F) { reg = PHY_READ(sc, RGEPHY_F_MII_SSR); if (reg & RGEPHY_F_SSR_LINK) linkup++; } else { reg = PHY_READ(sc, RGEPHY_MII_SSR); if (reg & RGEPHY_SSR_LINK) linkup++; } } else { reg = PHY_READ(sc, RL_GMEDIASTAT); if (reg & RL_GMEDIASTAT_LINK) linkup++; } return (linkup); } static void -rgephy_status(struct mii_softc *sc) +rgephy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; int bmsr, bmcr; uint16_t ssr; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; if (rgephy_linkup(sc) != 0) mii->mii_media_status |= IFM_ACTIVE; bmsr = PHY_READ(sc, RGEPHY_MII_BMSR); bmcr = PHY_READ(sc, RGEPHY_MII_BMCR); if (bmcr & RGEPHY_BMCR_ISO) { mii->mii_media_active |= IFM_NONE; mii->mii_media_status = 0; return; } if (bmcr & RGEPHY_BMCR_LOOP) mii->mii_media_active |= IFM_LOOP; if (bmcr & RGEPHY_BMCR_AUTOEN) { if ((bmsr & RGEPHY_BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } } if ((sc->mii_flags & MIIF_PHYPRIV0) == 0 && sc->mii_mpd_rev >= RGEPHY_8211B) { if (sc->mii_mpd_rev == RGEPHY_8211F) { ssr = PHY_READ(sc, RGEPHY_F_MII_SSR); switch (ssr & RGEPHY_F_SSR_SPD_MASK) { case RGEPHY_F_SSR_S1000: mii->mii_media_active |= IFM_1000_T; break; case RGEPHY_F_SSR_S100: mii->mii_media_active |= IFM_100_TX; break; case RGEPHY_F_SSR_S10: mii->mii_media_active |= IFM_10_T; break; default: mii->mii_media_active |= IFM_NONE; break; } if (ssr & RGEPHY_F_SSR_FDX) mii->mii_media_active |= IFM_FDX; else mii->mii_media_active |= IFM_HDX; } else { ssr = PHY_READ(sc, RGEPHY_MII_SSR); switch (ssr & RGEPHY_SSR_SPD_MASK) { case RGEPHY_SSR_S1000: mii->mii_media_active |= IFM_1000_T; break; case RGEPHY_SSR_S100: mii->mii_media_active |= IFM_100_TX; break; case RGEPHY_SSR_S10: mii->mii_media_active |= IFM_10_T; break; default: mii->mii_media_active |= IFM_NONE; break; } if (ssr & RGEPHY_SSR_FDX) mii->mii_media_active |= IFM_FDX; else mii->mii_media_active |= IFM_HDX; } } else { bmsr = PHY_READ(sc, RL_GMEDIASTAT); if (bmsr & RL_GMEDIASTAT_1000MBPS) mii->mii_media_active |= IFM_1000_T; else if (bmsr & RL_GMEDIASTAT_100MBPS) mii->mii_media_active |= IFM_100_TX; else if (bmsr & RL_GMEDIASTAT_10MBPS) mii->mii_media_active |= IFM_10_T; else mii->mii_media_active |= IFM_NONE; if (bmsr & RL_GMEDIASTAT_FDX) mii->mii_media_active |= IFM_FDX; else mii->mii_media_active |= IFM_HDX; } if ((mii->mii_media_active & IFM_FDX) != 0) mii->mii_media_active |= mii_phy_flowstatus(sc); if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) && (PHY_READ(sc, RGEPHY_MII_1000STS) & RGEPHY_1000STS_MSR) != 0) mii->mii_media_active |= IFM_ETH_MASTER; } static int -rgephy_mii_phy_auto(struct mii_softc *sc, int media) +rgephy_mii_phy_auto(struct mii_softc *sc, if_media_t media) { int anar; rgephy_loop(sc); - PHY_RESET(sc); + PHY_RESET(sc, media); anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0) anar |= RGEPHY_ANAR_PC | RGEPHY_ANAR_ASP; PHY_WRITE(sc, RGEPHY_MII_ANAR, anar); DELAY(1000); PHY_WRITE(sc, RGEPHY_MII_1000CTL, RGEPHY_1000CTL_AHD | RGEPHY_1000CTL_AFD); DELAY(1000); PHY_WRITE(sc, RGEPHY_MII_BMCR, RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG); DELAY(100); return (EJUSTRETURN); } static void rgephy_loop(struct mii_softc *sc) { int i; if (sc->mii_mpd_model != MII_MODEL_REALTEK_RTL8251 && sc->mii_mpd_rev < RGEPHY_8211B) { PHY_WRITE(sc, RGEPHY_MII_BMCR, RGEPHY_BMCR_PDOWN); DELAY(1000); } for (i = 0; i < 15000; i++) { if (!(PHY_READ(sc, RGEPHY_MII_BMSR) & RGEPHY_BMSR_LINK)) { #if 0 device_printf(sc->mii_dev, "looped %d\n", i); #endif break; } DELAY(10); } } #define PHY_SETBIT(x, y, z) \ PHY_WRITE(x, y, (PHY_READ(x, y) | (z))) #define PHY_CLRBIT(x, y, z) \ PHY_WRITE(x, y, (PHY_READ(x, y) & ~(z))) /* * Initialize RealTek PHY per the datasheet. The DSP in the PHYs of * existing revisions of the 8169S/8110S chips need to be tuned in * order to reliably negotiate a 1000Mbps link. This is only needed * for rev 0 and rev 1 of the PHY. Later versions work without * any fixups. */ static void rgephy_load_dspcode(struct mii_softc *sc) { int val; if (sc->mii_mpd_model == MII_MODEL_REALTEK_RTL8251 || sc->mii_mpd_rev >= RGEPHY_8211B) return; PHY_WRITE(sc, 31, 0x0001); PHY_WRITE(sc, 21, 0x1000); PHY_WRITE(sc, 24, 0x65C7); PHY_CLRBIT(sc, 4, 0x0800); val = PHY_READ(sc, 4) & 0xFFF; PHY_WRITE(sc, 4, val); PHY_WRITE(sc, 3, 0x00A1); PHY_WRITE(sc, 2, 0x0008); PHY_WRITE(sc, 1, 0x1020); PHY_WRITE(sc, 0, 0x1000); PHY_SETBIT(sc, 4, 0x0800); PHY_CLRBIT(sc, 4, 0x0800); val = (PHY_READ(sc, 4) & 0xFFF) | 0x7000; PHY_WRITE(sc, 4, val); PHY_WRITE(sc, 3, 0xFF41); PHY_WRITE(sc, 2, 0xDE60); PHY_WRITE(sc, 1, 0x0140); PHY_WRITE(sc, 0, 0x0077); val = (PHY_READ(sc, 4) & 0xFFF) | 0xA000; PHY_WRITE(sc, 4, val); PHY_WRITE(sc, 3, 0xDF01); PHY_WRITE(sc, 2, 0xDF20); PHY_WRITE(sc, 1, 0xFF95); PHY_WRITE(sc, 0, 0xFA00); val = (PHY_READ(sc, 4) & 0xFFF) | 0xB000; PHY_WRITE(sc, 4, val); PHY_WRITE(sc, 3, 0xFF41); PHY_WRITE(sc, 2, 0xDE20); PHY_WRITE(sc, 1, 0x0140); PHY_WRITE(sc, 0, 0x00BB); val = (PHY_READ(sc, 4) & 0xFFF) | 0xF000; PHY_WRITE(sc, 4, val); PHY_WRITE(sc, 3, 0xDF01); PHY_WRITE(sc, 2, 0xDF20); PHY_WRITE(sc, 1, 0xFF95); PHY_WRITE(sc, 0, 0xBF00); PHY_SETBIT(sc, 4, 0x0800); PHY_CLRBIT(sc, 4, 0x0800); PHY_WRITE(sc, 31, 0x0000); DELAY(40); } static void -rgephy_reset(struct mii_softc *sc) +rgephy_reset(struct mii_softc *sc, if_media_t media) { uint16_t pcr, ssr; switch (sc->mii_mpd_rev) { case RGEPHY_8211F: pcr = PHY_READ(sc, RGEPHY_F_MII_PCR1); if ((pcr & RGEPHY_F_PCR1_MDI_MM) != 0) { pcr &= ~RGEPHY_F_PCR1_MDI_MM; PHY_WRITE(sc, RGEPHY_F_MII_PCR1, pcr); } break; case RGEPHY_8211C: if ((sc->mii_flags & MIIF_PHYPRIV0) == 0) { /* RTL8211C(L) */ ssr = PHY_READ(sc, RGEPHY_MII_SSR); if ((ssr & RGEPHY_SSR_ALDPS) != 0) { ssr &= ~RGEPHY_SSR_ALDPS; PHY_WRITE(sc, RGEPHY_MII_SSR, ssr); } } /* FALLTHROUGH */ default: if (sc->mii_mpd_rev >= RGEPHY_8211B) { pcr = PHY_READ(sc, RGEPHY_MII_PCR); if ((pcr & RGEPHY_PCR_MDIX_AUTO) == 0) { pcr &= ~RGEPHY_PCR_MDI_MASK; pcr |= RGEPHY_PCR_MDIX_AUTO; PHY_WRITE(sc, RGEPHY_MII_PCR, pcr); } } break; } - mii_phy_reset(sc); + mii_phy_reset(sc, media); DELAY(1000); rgephy_load_dspcode(sc); } Index: projects/ifnet/sys/dev/mii/rlphy.c =================================================================== --- projects/ifnet/sys/dev/mii/rlphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/rlphy.c (revision 282026) @@ -1,260 +1,260 @@ /*- * Copyright (c) 1997, 1998, 1999 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * driver for RealTek 8139 internal PHYs */ #include #include #include #include /* XXXGL: if_rlreg.h contamination */ #include /* XXXGL: if_rlreg.h contamination */ #include #include #include #include /* XXXGL: if_rlreg.h contamination */ -#include #include #include #include #include "miidevs.h" #include #include #include "miibus_if.h" static int rlphy_probe(device_t); static int rlphy_attach(device_t); static device_method_t rlphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, rlphy_probe), DEVMETHOD(device_attach, rlphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t rlphy_devclass; static driver_t rlphy_driver = { "rlphy", rlphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(rlphy, miibus, rlphy_driver, rlphy_devclass, 0, 0); -static int rlphy_service(struct mii_softc *, struct mii_data *, int); -static void rlphy_status(struct mii_softc *); +static int rlphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void rlphy_status(struct mii_softc *, if_media_t); /* * RealTek internal PHYs don't have vendor/device ID registers; * re(4) and rl(4) fake up a return value of all zeros. */ static const struct mii_phydesc rlintphys[] = { { 0, 0, "RealTek internal media interface" }, MII_PHY_END }; static const struct mii_phydesc rlphys[] = { MII_PHY_DESC(yyREALTEK, RTL8201L), MII_PHY_DESC(REALTEK, RTL8201E), MII_PHY_DESC(xxICPLUS, IP101), MII_PHY_END }; static const struct mii_phy_funcs rlphy_funcs = { rlphy_service, rlphy_status, mii_phy_reset }; static int rlphy_probe(device_t dev) { int rv; rv = mii_phy_dev_probe(dev, rlphys, BUS_PROBE_DEFAULT); if (rv <= 0) return (rv); if (mii_dev_mac_match(dev, "rl") || mii_dev_mac_match(dev, "re")) return (mii_phy_dev_probe(dev, rlintphys, BUS_PROBE_DEFAULT)); return (ENXIO); } static int rlphy_attach(device_t dev) { /* * The RealTek PHY can never be isolated. */ mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, &rlphy_funcs, 1); return (0); } static int -rlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +rlphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; case MII_TICK: /* * The RealTek PHY's autonegotiation doesn't need to be * kicked; it continues in the background. */ break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -rlphy_status(struct mii_softc *phy) +rlphy_status(struct mii_softc *phy, if_media_t media) { struct mii_data *mii = phy->mii_pdata; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmsr, bmcr, anlpar; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(phy, MII_BMSR) | PHY_READ(phy, MII_BMSR); if (bmsr & BMSR_LINK) mii->mii_media_status |= IFM_ACTIVE; bmcr = PHY_READ(phy, 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; if (bmcr & BMCR_AUTOEN) { /* * NWay autonegotiation takes the highest-order common * bit of the ANAR and ANLPAR (i.e. best media advertised * both by us and our link partner). */ if ((bmsr & BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } if ((anlpar = PHY_READ(phy, MII_ANAR) & PHY_READ(phy, MII_ANLPAR))) { if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; else if (anlpar & ANLPAR_T4) mii->mii_media_active |= IFM_100_T4|IFM_HDX; else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX|IFM_HDX; 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; if ((mii->mii_media_active & IFM_FDX) != 0) mii->mii_media_active |= mii_phy_flowstatus(phy); return; } /* * If the other side doesn't support NWAY, then the * best we can do is determine if we have a 10Mbps or * 100Mbps link. There's no way to know if the link * is full or half duplex, so we default to half duplex * and hope that the user is clever enough to manually * change the media settings if we're wrong. */ /* * The RealTek PHY supports non-NWAY link speed * detection, however it does not report the link * detection results via the ANLPAR or BMSR registers. * (What? RealTek doesn't do things the way everyone * else does? I'm just shocked, shocked I tell you.) * To determine the link speed, we have to do one * of two things: * * - If this is a standalone RealTek RTL8201(L) or * workalike PHY, we can determine the link speed by * testing bit 0 in the magic, vendor-specific register * at offset 0x19. * * - If this is a RealTek MAC with integrated PHY, we * can test the 'SPEED10' bit of the MAC's media status * register. */ if (!(phy->mii_mpd_model == 0 && phy->mii_mpd_rev == 0)) { if (PHY_READ(phy, 0x0019) & 0x01) mii->mii_media_active |= IFM_100_TX; else mii->mii_media_active |= IFM_10_T; } else { if (PHY_READ(phy, RL_MEDIASTAT) & RL_MEDIASTAT_SPEED10) mii->mii_media_active |= IFM_10_T; else mii->mii_media_active |= IFM_100_TX; } mii->mii_media_active |= IFM_HDX; } else - mii->mii_media_active = ife->ifm_media; + mii->mii_media_active = media; } Index: projects/ifnet/sys/dev/mii/rlswitch.c =================================================================== --- projects/ifnet/sys/dev/mii/rlswitch.c (revision 282025) +++ projects/ifnet/sys/dev/mii/rlswitch.c (revision 282026) @@ -1,396 +1,395 @@ /*- * Copyright (c) 1997, 1998, 1999 * Bill Paul . All rights reserved. * Copyright (c) 2006 Bernd Walter. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * driver for RealTek 8305 pseudo PHYs */ #include #include #include #include #include #include #include /* XXXGL: if_rlreg.h contamination */ -#include #include #include #include #include "miidevs.h" #include #include #include "miibus_if.h" //#define RL_DEBUG #define RL_VLAN static int rlswitch_probe(device_t); static int rlswitch_attach(device_t); static device_method_t rlswitch_methods[] = { /* device interface */ DEVMETHOD(device_probe, rlswitch_probe), DEVMETHOD(device_attach, rlswitch_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t rlswitch_devclass; static driver_t rlswitch_driver = { "rlswitch", rlswitch_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(rlswitch, miibus, rlswitch_driver, rlswitch_devclass, 0, 0); static int rlswitch_service(struct mii_softc *, struct mii_data *, int); static void rlswitch_status(struct mii_softc *); #ifdef RL_DEBUG static void rlswitch_phydump(device_t dev); #endif static const struct mii_phydesc rlswitches[] = { MII_PHY_DESC(REALTEK, RTL8305SC), MII_PHY_END }; static const struct mii_phy_funcs rlswitch_funcs = { rlswitch_service, rlswitch_status, mii_phy_reset }; static int rlswitch_probe(device_t dev) { int rv; rv = mii_phy_dev_probe(dev, rlswitches, BUS_PROBE_DEFAULT); if (rv <= 0) return (rv); return (ENXIO); } static int rlswitch_attach(device_t dev) { struct mii_softc *sc; sc = device_get_softc(dev); /* * We handle all pseudo PHYs in a single instance. */ mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, &rlswitch_funcs, 0); sc->mii_capabilities = BMSR_100TXFDX & sc->mii_capmask; device_printf(dev, " "); - mii_phy_add_media(sc); + mii_phy_generic_media(sc); printf("\n"); #ifdef RL_DEBUG rlswitch_phydump(dev); #endif #ifdef RL_VLAN int val; /* Global Control 0 */ val = 0; val |= 0 << 10; /* enable 802.1q VLAN Tag support */ val |= 0 << 9; /* enable VLAN ingress filtering */ val |= 1 << 8; /* disable VLAN tag admit control */ val |= 1 << 6; /* internal use */ val |= 1 << 5; /* internal use */ val |= 1 << 4; /* internal use */ val |= 1 << 3; /* internal use */ val |= 1 << 1; /* reserved */ MIIBUS_WRITEREG(sc->mii_dev, 0, 16, val); /* Global Control 2 */ val = 0; val |= 1 << 15; /* reserved */ val |= 0 << 14; /* enable 1552 Bytes support */ val |= 1 << 13; /* enable broadcast input drop */ val |= 1 << 12; /* forward reserved control frames */ val |= 1 << 11; /* disable forwarding unicast frames to other VLAN's */ val |= 1 << 10; /* disable forwarding ARP broadcasts to other VLAN's */ val |= 1 << 9; /* enable 48 pass 1 */ val |= 0 << 8; /* enable VLAN */ val |= 1 << 7; /* reserved */ val |= 1 << 6; /* enable defer */ val |= 1 << 5; /* 43ms LED blink time */ val |= 3 << 3; /* 16:1 queue weight */ val |= 1 << 2; /* disable broadcast storm control */ val |= 1 << 1; /* enable power-on LED blinking */ val |= 1 << 0; /* reserved */ MIIBUS_WRITEREG(sc->mii_dev, 0, 18, val); /* Port 0 Control Register 0 */ val = 0; val |= 1 << 15; /* reserved */ val |= 1 << 11; /* drop received packets with wrong VLAN tag */ val |= 1 << 10; /* disable 802.1p priority classification */ val |= 1 << 9; /* disable diffserv priority classification */ val |= 1 << 6; /* internal use */ val |= 3 << 4; /* internal use */ val |= 1 << 3; /* internal use */ val |= 1 << 2; /* internal use */ val |= 1 << 0; /* remove VLAN tags on output */ MIIBUS_WRITEREG(sc->mii_dev, 0, 22, val); /* Port 1 Control Register 0 */ val = 0; val |= 1 << 15; /* reserved */ val |= 1 << 11; /* drop received packets with wrong VLAN tag */ val |= 1 << 10; /* disable 802.1p priority classification */ val |= 1 << 9; /* disable diffserv priority classification */ val |= 1 << 6; /* internal use */ val |= 3 << 4; /* internal use */ val |= 1 << 3; /* internal use */ val |= 1 << 2; /* internal use */ val |= 1 << 0; /* remove VLAN tags on output */ MIIBUS_WRITEREG(sc->mii_dev, 1, 22, val); /* Port 2 Control Register 0 */ val = 0; val |= 1 << 15; /* reserved */ val |= 1 << 11; /* drop received packets with wrong VLAN tag */ val |= 1 << 10; /* disable 802.1p priority classification */ val |= 1 << 9; /* disable diffserv priority classification */ val |= 1 << 6; /* internal use */ val |= 3 << 4; /* internal use */ val |= 1 << 3; /* internal use */ val |= 1 << 2; /* internal use */ val |= 1 << 0; /* remove VLAN tags on output */ MIIBUS_WRITEREG(sc->mii_dev, 2, 22, val); /* Port 3 Control Register 0 */ val = 0; val |= 1 << 15; /* reserved */ val |= 1 << 11; /* drop received packets with wrong VLAN tag */ val |= 1 << 10; /* disable 802.1p priority classification */ val |= 1 << 9; /* disable diffserv priority classification */ val |= 1 << 6; /* internal use */ val |= 3 << 4; /* internal use */ val |= 1 << 3; /* internal use */ val |= 1 << 2; /* internal use */ val |= 1 << 0; /* remove VLAN tags on output */ MIIBUS_WRITEREG(sc->mii_dev, 3, 22, val); /* Port 4 (system port) Control Register 0 */ val = 0; val |= 1 << 15; /* reserved */ val |= 0 << 11; /* don't drop received packets with wrong VLAN tag */ val |= 1 << 10; /* disable 802.1p priority classification */ val |= 1 << 9; /* disable diffserv priority classification */ val |= 1 << 6; /* internal use */ val |= 3 << 4; /* internal use */ val |= 1 << 3; /* internal use */ val |= 1 << 2; /* internal use */ val |= 2 << 0; /* add VLAN tags for untagged packets on output */ MIIBUS_WRITEREG(sc->mii_dev, 4, 22, val); /* Port 0 Control Register 1 and VLAN A */ val = 0; val |= 0x0 << 12; /* Port 0 VLAN Index */ val |= 1 << 11; /* internal use */ val |= 1 << 10; /* internal use */ val |= 1 << 9; /* internal use */ val |= 1 << 7; /* internal use */ val |= 1 << 6; /* internal use */ val |= 0x11 << 0; /* VLAN A membership */ MIIBUS_WRITEREG(sc->mii_dev, 0, 24, val); /* Port 0 Control Register 2 and VLAN A */ val = 0; val |= 1 << 15; /* internal use */ val |= 1 << 14; /* internal use */ val |= 1 << 13; /* internal use */ val |= 1 << 12; /* internal use */ val |= 0x100 << 0; /* VLAN A ID */ MIIBUS_WRITEREG(sc->mii_dev, 0, 25, val); /* Port 1 Control Register 1 and VLAN B */ val = 0; val |= 0x1 << 12; /* Port 1 VLAN Index */ val |= 1 << 11; /* internal use */ val |= 1 << 10; /* internal use */ val |= 1 << 9; /* internal use */ val |= 1 << 7; /* internal use */ val |= 1 << 6; /* internal use */ val |= 0x12 << 0; /* VLAN B membership */ MIIBUS_WRITEREG(sc->mii_dev, 1, 24, val); /* Port 1 Control Register 2 and VLAN B */ val = 0; val |= 1 << 15; /* internal use */ val |= 1 << 14; /* internal use */ val |= 1 << 13; /* internal use */ val |= 1 << 12; /* internal use */ val |= 0x101 << 0; /* VLAN B ID */ MIIBUS_WRITEREG(sc->mii_dev, 1, 25, val); /* Port 2 Control Register 1 and VLAN C */ val = 0; val |= 0x2 << 12; /* Port 2 VLAN Index */ val |= 1 << 11; /* internal use */ val |= 1 << 10; /* internal use */ val |= 1 << 9; /* internal use */ val |= 1 << 7; /* internal use */ val |= 1 << 6; /* internal use */ val |= 0x14 << 0; /* VLAN C membership */ MIIBUS_WRITEREG(sc->mii_dev, 2, 24, val); /* Port 2 Control Register 2 and VLAN C */ val = 0; val |= 1 << 15; /* internal use */ val |= 1 << 14; /* internal use */ val |= 1 << 13; /* internal use */ val |= 1 << 12; /* internal use */ val |= 0x102 << 0; /* VLAN C ID */ MIIBUS_WRITEREG(sc->mii_dev, 2, 25, val); /* Port 3 Control Register 1 and VLAN D */ val = 0; val |= 0x3 << 12; /* Port 3 VLAN Index */ val |= 1 << 11; /* internal use */ val |= 1 << 10; /* internal use */ val |= 1 << 9; /* internal use */ val |= 1 << 7; /* internal use */ val |= 1 << 6; /* internal use */ val |= 0x18 << 0; /* VLAN D membership */ MIIBUS_WRITEREG(sc->mii_dev, 3, 24, val); /* Port 3 Control Register 2 and VLAN D */ val = 0; val |= 1 << 15; /* internal use */ val |= 1 << 14; /* internal use */ val |= 1 << 13; /* internal use */ val |= 1 << 12; /* internal use */ val |= 0x103 << 0; /* VLAN D ID */ MIIBUS_WRITEREG(sc->mii_dev, 3, 25, val); /* Port 4 Control Register 1 and VLAN E */ val = 0; val |= 0x0 << 12; /* Port 4 VLAN Index */ val |= 1 << 11; /* internal use */ val |= 1 << 10; /* internal use */ val |= 1 << 9; /* internal use */ val |= 1 << 7; /* internal use */ val |= 1 << 6; /* internal use */ val |= 0 << 0; /* VLAN E membership */ MIIBUS_WRITEREG(sc->mii_dev, 4, 24, val); /* Port 4 Control Register 2 and VLAN E */ val = 0; val |= 1 << 15; /* internal use */ val |= 1 << 14; /* internal use */ val |= 1 << 13; /* internal use */ val |= 1 << 12; /* internal use */ val |= 0x104 << 0; /* VLAN E ID */ MIIBUS_WRITEREG(sc->mii_dev, 4, 25, val); #endif #ifdef RL_DEBUG rlswitch_phydump(dev); #endif MIIBUS_MEDIAINIT(sc->mii_dev); return (0); } static int rlswitch_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: break; case MII_TICK: break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ // mii_phy_update(sc, cmd); return (0); } static void rlswitch_status(struct mii_softc *phy) { struct mii_data *mii = phy->mii_pdata; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; mii->mii_media_status |= IFM_ACTIVE; mii->mii_media_active |= IFM_100_TX | IFM_FDX | mii_phy_flowstatus(phy); } #ifdef RL_DEBUG static void rlswitch_phydump(device_t dev) { int phy, reg, val; struct mii_softc *sc; sc = device_get_softc(dev); device_printf(dev, "rlswitchphydump\n"); for (phy = 0; phy <= 5; phy++) { printf("PHY%i:", phy); for (reg = 0; reg <= 31; reg++) { val = MIIBUS_READREG(sc->mii_dev, phy, reg); printf(" 0x%x", val); } printf("\n"); } } #endif Index: projects/ifnet/sys/dev/mii/smcphy.c =================================================================== --- projects/ifnet/sys/dev/mii/smcphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/smcphy.c (revision 282026) @@ -1,263 +1,261 @@ /*- * Copyright (c) 2006 Benno Rice. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Driver for the SEEQ 80220 and 84220. * (Originally developed for the internal PHY on the SMSC LAN91C111.) */ #include #include #include #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include "miibus_if.h" static int smcphy_probe(device_t); static int smcphy_attach(device_t); -static int smcphy_service(struct mii_softc *, struct mii_data *, int); -static void smcphy_reset(struct mii_softc *); -static void smcphy_auto(struct mii_softc *, int); -static void smcphy_status(struct mii_softc *); +static int smcphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void smcphy_reset(struct mii_softc *, if_media_t); +static void smcphy_auto(struct mii_softc *, if_media_t); +static void smcphy_status(struct mii_softc *, if_media_t); static device_method_t smcphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, smcphy_probe), DEVMETHOD(device_attach, smcphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t smcphy_devclass; static driver_t smcphy_driver = { "smcphy", smcphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(smcphy, miibus, smcphy_driver, smcphy_devclass, 0, 0); static const struct mii_phydesc smcphys[] = { MII_PHY_DESC(SEEQ, 80220), MII_PHY_DESC(SEEQ, 84220), MII_PHY_END }; static const struct mii_phy_funcs smcphy80220_funcs = { smcphy_service, smcphy_status, mii_phy_reset }; static const struct mii_phy_funcs smcphy_funcs = { smcphy_service, smcphy_status, smcphy_reset }; static int smcphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, smcphys, BUS_PROBE_DEFAULT)); } static int smcphy_attach(device_t dev) { struct mii_softc *sc; struct mii_attach_args *ma; const struct mii_phy_funcs *mpf; sc = device_get_softc(dev); ma = device_get_ivars(dev); if (MII_MODEL(ma->mii_id2) == MII_MODEL_SEEQ_80220) mpf = &smcphy80220_funcs; else mpf = &smcphy_funcs; mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, mpf, 1); - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, (IFM_ETHER | IFM_AUTO)); return (0); } static int -smcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +smcphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { - struct ifmedia_entry *ife; int reg; - ife = mii->mii_media.ifm_cur; - switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - switch (IFM_SUBTYPE(ife->ifm_media)) { + switch (IFM_SUBTYPE(media)) { case IFM_AUTO: - smcphy_auto(sc, ife->ifm_media); + smcphy_auto(sc, media); break; default: - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; } break; case MII_TICK: - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { + if (IFM_SUBTYPE(media) != IFM_AUTO) { break; } /* I have no idea why BMCR_ISO gets set. */ reg = PHY_READ(sc, MII_BMCR); if (reg & BMCR_ISO) { PHY_WRITE(sc, MII_BMCR, reg & ~BMCR_ISO); } reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (reg & BMSR_LINK) { sc->mii_ticks = 0; break; } if (++sc->mii_ticks <= MII_ANEGTICKS) { break; } sc->mii_ticks = 0; - PHY_RESET(sc); - smcphy_auto(sc, ife->ifm_media); + PHY_RESET(sc, media); + smcphy_auto(sc, media); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -smcphy_reset(struct mii_softc *sc) +smcphy_reset(struct mii_softc *sc, if_media_t media) { u_int bmcr; int timeout; PHY_WRITE(sc, MII_BMCR, BMCR_RESET); for (timeout = 2; timeout > 0; timeout--) { DELAY(50000); bmcr = PHY_READ(sc, MII_BMCR); if ((bmcr & BMCR_RESET) == 0) break; } if (bmcr & BMCR_RESET) device_printf(sc->mii_dev, "reset failed\n"); PHY_WRITE(sc, MII_BMCR, 0x3000); /* Mask interrupts, we poll instead. */ PHY_WRITE(sc, 0x1e, 0xffc0); } static void -smcphy_auto(struct mii_softc *sc, int media) +smcphy_auto(struct mii_softc *sc, if_media_t media) { uint16_t anar; anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0) anar |= ANAR_FC; PHY_WRITE(sc, MII_ANAR, anar); /* Apparently this helps. */ anar = PHY_READ(sc, MII_ANAR); PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); } static void -smcphy_status(struct mii_softc *sc) +smcphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii; uint32_t bmcr, bmsr, status; mii = sc->mii_pdata; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if ((bmsr & BMSR_LINK) != 0) mii->mii_media_status |= IFM_ACTIVE; bmcr = PHY_READ(sc, MII_BMCR); if ((bmcr & BMCR_ISO) != 0) { mii->mii_media_active |= IFM_NONE; mii->mii_media_status = 0; return; } if ((bmcr & BMCR_LOOP) != 0) mii->mii_media_active |= IFM_LOOP; if ((bmcr & BMCR_AUTOEN) != 0) { if ((bmsr & BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } } status = PHY_READ(sc, 0x12); if (status & 0x0080) mii->mii_media_active |= IFM_100_TX; else mii->mii_media_active |= IFM_10_T; if (status & 0x0040) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; } Index: projects/ifnet/sys/dev/mii/smscphy.c =================================================================== --- projects/ifnet/sys/dev/mii/smscphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/smscphy.c (revision 282026) @@ -1,225 +1,223 @@ /*- * Copyright (c) 2006 Benno Rice. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Driver for the SMSC LAN8710A */ #include #include #include #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include "miibus_if.h" static int smscphy_probe(device_t); static int smscphy_attach(device_t); -static int smscphy_service(struct mii_softc *, struct mii_data *, int); -static void smscphy_auto(struct mii_softc *, int); -static void smscphy_status(struct mii_softc *); +static int smscphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void smscphy_auto(struct mii_softc *, if_media_t); +static void smscphy_status(struct mii_softc *, if_media_t); static device_method_t smscphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, smscphy_probe), DEVMETHOD(device_attach, smscphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t smscphy_devclass; static driver_t smscphy_driver = { "smscphy", smscphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(smscphy, miibus, smscphy_driver, smscphy_devclass, 0, 0); static const struct mii_phydesc smscphys[] = { MII_PHY_DESC(SMC, LAN8710A), MII_PHY_END }; static const struct mii_phy_funcs smscphy_funcs = { smscphy_service, smscphy_status, mii_phy_reset }; static int smscphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, smscphys, BUS_PROBE_DEFAULT)); } static int smscphy_attach(device_t dev) { struct mii_softc *sc; const struct mii_phy_funcs *mpf; sc = device_get_softc(dev); mpf = &smscphy_funcs; mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, mpf, 1); - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, (IFM_AUTO | IFM_ETHER)); return (0); } static int -smscphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +smscphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { - struct ifmedia_entry *ife; int reg; - ife = mii->mii_media.ifm_cur; - switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - switch (IFM_SUBTYPE(ife->ifm_media)) { + switch (IFM_SUBTYPE(media)) { case IFM_AUTO: - smscphy_auto(sc, ife->ifm_media); + smscphy_auto(sc, media); break; default: - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; } break; case MII_TICK: - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { + if (IFM_SUBTYPE(media) != IFM_AUTO) { break; } /* I have no idea why BMCR_ISO gets set. */ reg = PHY_READ(sc, MII_BMCR); if (reg & BMCR_ISO) { PHY_WRITE(sc, MII_BMCR, reg & ~BMCR_ISO); } reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (reg & BMSR_LINK) { sc->mii_ticks = 0; break; } if (++sc->mii_ticks <= MII_ANEGTICKS) { break; } sc->mii_ticks = 0; - PHY_RESET(sc); - smscphy_auto(sc, ife->ifm_media); + PHY_RESET(sc, media); + smscphy_auto(sc, media); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -smscphy_auto(struct mii_softc *sc, int media) +smscphy_auto(struct mii_softc *sc, if_media_t media) { uint16_t anar; anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0) anar |= ANAR_FC; PHY_WRITE(sc, MII_ANAR, anar); /* Apparently this helps. */ anar = PHY_READ(sc, MII_ANAR); PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); } static void -smscphy_status(struct mii_softc *sc) +smscphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii; uint32_t bmcr, bmsr, status; mii = sc->mii_pdata; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if ((bmsr & BMSR_LINK) != 0) mii->mii_media_status |= IFM_ACTIVE; bmcr = PHY_READ(sc, MII_BMCR); if ((bmcr & BMCR_ISO) != 0) { mii->mii_media_active |= IFM_NONE; mii->mii_media_status = 0; return; } if ((bmcr & BMCR_LOOP) != 0) mii->mii_media_active |= IFM_LOOP; if ((bmcr & BMCR_AUTOEN) != 0) { if ((bmsr & BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } } status = PHY_READ(sc, 0x1F); if (status & 0x0008) mii->mii_media_active |= IFM_100_TX; else mii->mii_media_active |= IFM_10_T; if (status & 0x0010) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; } Index: projects/ifnet/sys/dev/mii/tdkphy.c =================================================================== --- projects/ifnet/sys/dev/mii/tdkphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/tdkphy.c (revision 282026) @@ -1,223 +1,223 @@ /*- * Copyright (c) 2000,2001 Jonathan Chen. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer, * without modification, immediately at the beginning of the file. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Driver for the TDK 78Q2120 MII * * References: * Datasheet for the 78Q2120 - http://www.tsc.tdk.com/lan/78q2120.pdf * Most of this code stolen from ukphy.c */ /* * The TDK 78Q2120 is found on some Xircom X3201 based CardBus cards, * also spotted on some 3C575 cards. It's just like any other normal * phy, except it does auto negotiation in a different way. */ #include #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" static int tdkphy_probe(device_t); static int tdkphy_attach(device_t); static device_method_t tdkphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, tdkphy_probe), DEVMETHOD(device_attach, tdkphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t tdkphy_devclass; static driver_t tdkphy_driver = { "tdkphy", tdkphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(tdkphy, miibus, tdkphy_driver, tdkphy_devclass, 0, 0); -static int tdkphy_service(struct mii_softc *, struct mii_data *, int); -static void tdkphy_status(struct mii_softc *); +static int tdkphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void tdkphy_status(struct mii_softc *, if_media_t); static const struct mii_phydesc tdkphys[] = { MII_PHY_DESC(xxTSC, 78Q2120), MII_PHY_END }; static const struct mii_phy_funcs tdkphy_funcs = { tdkphy_service, tdkphy_status, mii_phy_reset }; static int tdkphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, tdkphys, BUS_PROBE_DEFAULT)); } static int tdkphy_attach(device_t dev) { mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &tdkphy_funcs, 1); return (0); } static int -tdkphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +tdkphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; case MII_TICK: if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); if (sc->mii_pdata->mii_media_active & IFM_FDX) PHY_WRITE(sc, MII_BMCR, PHY_READ(sc, MII_BMCR) | BMCR_FDX); else PHY_WRITE(sc, MII_BMCR, PHY_READ(sc, MII_BMCR) & ~BMCR_FDX); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -tdkphy_status(struct mii_softc *phy) +tdkphy_status(struct mii_softc *phy, if_media_t media) { struct mii_data *mii = phy->mii_pdata; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmsr, bmcr, anlpar, diag; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(phy, MII_BMSR) | PHY_READ(phy, MII_BMSR); if (bmsr & BMSR_LINK) mii->mii_media_status |= IFM_ACTIVE; bmcr = PHY_READ(phy, 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; if (bmcr & BMCR_AUTOEN) { /* * NWay autonegotiation takes the highest-order common * bit of the ANAR and ANLPAR (i.e. best media advertised * both by us and our link partner). */ if ((bmsr & BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } anlpar = PHY_READ(phy, MII_ANAR) & PHY_READ(phy, MII_ANLPAR); /* * ANLPAR doesn't get set on my card, but we check it anyway, * since it is mentioned in the 78Q2120 specs. */ if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; else if (anlpar & ANLPAR_T4) mii->mii_media_active |= IFM_100_T4|IFM_HDX; else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX|IFM_HDX; 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 { /* * ANLPAR isn't set, which leaves two possibilities: * 1) Auto negotiation failed * 2) Auto negotiation completed, but the card forgot * to set ANLPAR. * So we check the MII_DIAG(18) register... */ diag = PHY_READ(phy, MII_DIAG); if (diag & DIAG_NEGFAIL) /* assume 10baseT if no neg */ mii->mii_media_active |= IFM_10_T|IFM_HDX; else { if (diag & DIAG_DUPLEX) mii->mii_media_active |= IFM_FDX; else mii->mii_media_active |= IFM_HDX; if (diag & DIAG_RATE_100) mii->mii_media_active |= IFM_100_TX; else mii->mii_media_active |= IFM_10_T; } } if ((mii->mii_media_active & IFM_FDX) != 0) mii->mii_media_active |= mii_phy_flowstatus(phy); } else - mii->mii_media_active = ife->ifm_media; + mii->mii_media_active = media; } Index: projects/ifnet/sys/dev/mii/tlphy.c =================================================================== --- projects/ifnet/sys/dev/mii/tlphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/tlphy.c (revision 282026) @@ -1,374 +1,371 @@ /* $NetBSD: tlphy.c,v 1.18 1999/05/14 11:40:28 drochner Exp $ */ /*- * Copyright (c) 1998, 1999 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 * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (c) 1997 Manuel Bouyer. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Driver for Texas Instruments's ThunderLAN PHYs */ #include #include #include #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" struct tlphy_softc { struct mii_softc sc_mii; /* generic PHY */ int sc_need_acomp; }; static int tlphy_probe(device_t); static int tlphy_attach(device_t); static device_method_t tlphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, tlphy_probe), DEVMETHOD(device_attach, tlphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t tlphy_devclass; static driver_t tlphy_driver = { "tlphy", tlphy_methods, sizeof(struct tlphy_softc) }; DRIVER_MODULE(tlphy, miibus, tlphy_driver, tlphy_devclass, 0, 0); -static int tlphy_service(struct mii_softc *, struct mii_data *, int); -static int tlphy_auto(struct tlphy_softc *); +static int tlphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static int tlphy_auto(struct tlphy_softc *, if_media_t); static void tlphy_acomp(struct tlphy_softc *); -static void tlphy_status(struct mii_softc *); +static void tlphy_status(struct mii_softc *, if_media_t); static const struct mii_phydesc tlphys[] = { MII_PHY_DESC(TI, TLAN10T), MII_PHY_END }; static const struct mii_phy_funcs tlphy_funcs = { tlphy_service, tlphy_status, mii_phy_reset }; static int tlphy_probe(device_t dev) { if (!mii_dev_mac_match(dev, "tl")) return (ENXIO); return (mii_phy_dev_probe(dev, tlphys, BUS_PROBE_DEFAULT)); } static int tlphy_attach(device_t dev) { device_t *devlist; struct mii_softc *other, *sc_mii; const char *sep = ""; int capmask, devs, i; sc_mii = device_get_softc(dev); mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &tlphy_funcs, 0); /* * Note that if we're on a device that also supports 100baseTX, * we are not going to want to use the built-in 10baseT port, * since there will be another PHY on the MII wired up to the * UTP connector. */ capmask = BMSR_DEFCAPMASK; if (sc_mii->mii_inst && device_get_children(sc_mii->mii_dev, &devlist, &devs) == 0) { for (i = 0; i < devs; i++) { if (devlist[i] != dev) { other = device_get_softc(devlist[i]); capmask &= ~other->mii_capabilities; break; } } free(devlist, M_TEMP); } - PHY_RESET(sc_mii); + PHY_RESET(sc_mii, IFM_NONE); sc_mii->mii_capabilities = PHY_READ(sc_mii, MII_BMSR) & capmask; -#define ADD(m, c) \ - ifmedia_add(&sc_mii->mii_pdata->mii_media, (m), (c), NULL) #define PRINT(s) printf("%s%s", sep, s); sep = ", " if ((sc_mii->mii_flags & (MIIF_MACPRIV0 | MIIF_MACPRIV1)) != 0 && (sc_mii->mii_capabilities & BMSR_MEDIAMASK) != 0) device_printf(dev, " "); if ((sc_mii->mii_flags & MIIF_MACPRIV0) != 0) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_2, 0, sc_mii->mii_inst), - 0); + mii_phy_add_media(sc_mii->mii_pdata, + IFM_MAKEWORD(IFM_ETHER, IFM_10_2, 0, sc_mii->mii_inst)); PRINT("10base2/BNC"); } if ((sc_mii->mii_flags & MIIF_MACPRIV1) != 0) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, sc_mii->mii_inst), - 0); + mii_phy_add_media(sc_mii->mii_pdata, + IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, sc_mii->mii_inst)); PRINT("10base5/AUI"); } if ((sc_mii->mii_capabilities & BMSR_MEDIAMASK) != 0) { printf("%s", sep); - mii_phy_add_media(sc_mii); + mii_phy_generic_media(sc_mii); } if ((sc_mii->mii_flags & (MIIF_MACPRIV0 | MIIF_MACPRIV1)) != 0 && (sc_mii->mii_capabilities & BMSR_MEDIAMASK) != 0) printf("\n"); -#undef ADD #undef PRINT MIIBUS_MEDIAINIT(sc_mii->mii_dev); return (0); } static int -tlphy_service(struct mii_softc *self, struct mii_data *mii, int cmd) +tlphy_service(struct mii_softc *self, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { struct tlphy_softc *sc = (struct tlphy_softc *)self; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int reg; if (sc->sc_need_acomp) tlphy_acomp(sc); switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - switch (IFM_SUBTYPE(ife->ifm_media)) { + switch (IFM_SUBTYPE(media)) { case IFM_AUTO: /* * The ThunderLAN PHY doesn't self-configure after * an autonegotiation cycle, so there's no such * thing as "already in auto mode". */ - (void)tlphy_auto(sc); + (void)tlphy_auto(sc, media); break; case IFM_10_2: case IFM_10_5: PHY_WRITE(&sc->sc_mii, MII_BMCR, 0); PHY_WRITE(&sc->sc_mii, MII_TLPHY_CTRL, CTRL_AUISEL); DELAY(100000); break; default: PHY_WRITE(&sc->sc_mii, MII_TLPHY_CTRL, 0); DELAY(100000); - mii_phy_setmedia(&sc->sc_mii); + mii_phy_setmedia(&sc->sc_mii, media); } break; case MII_TICK: /* * Only used for autonegotiation. */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + if (IFM_SUBTYPE(media) != IFM_AUTO) break; /* * Check to see if we have link. If we do, we don't * need to restart the autonegotiation process. Read * the BMSR twice in case it's latched. * * XXX WHAT ABOUT CHECKING LINK ON THE BNC/AUI?! */ reg = PHY_READ(&sc->sc_mii, MII_BMSR) | PHY_READ(&sc->sc_mii, MII_BMSR); if (reg & BMSR_LINK) break; /* * Only retry autonegotiation every 5 seconds. */ if (++sc->sc_mii.mii_ticks <= MII_ANEGTICKS) break; sc->sc_mii.mii_ticks = 0; - PHY_RESET(&sc->sc_mii); - (void)tlphy_auto(sc); + PHY_RESET(&sc->sc_mii, media); + (void)tlphy_auto(sc, media); return (0); } /* Update the media status. */ - PHY_STATUS(self); + PHY_STATUS(self, media); /* Callback if something changed. */ mii_phy_update(&sc->sc_mii, cmd); return (0); } static void -tlphy_status(struct mii_softc *self) +tlphy_status(struct mii_softc *self, if_media_t media) { struct tlphy_softc *sc = (struct tlphy_softc *)self; struct mii_data *mii = sc->sc_mii.mii_pdata; int bmsr, bmcr, tlctrl; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmcr = PHY_READ(&sc->sc_mii, MII_BMCR); if (bmcr & BMCR_ISO) { mii->mii_media_active |= IFM_NONE; mii->mii_media_status = 0; return; } tlctrl = PHY_READ(&sc->sc_mii, MII_TLPHY_CTRL); if (tlctrl & CTRL_AUISEL) { mii->mii_media_status = 0; - mii->mii_media_active = mii->mii_media.ifm_cur->ifm_media; + mii->mii_media_active = media; return; } bmsr = PHY_READ(&sc->sc_mii, MII_BMSR) | PHY_READ(&sc->sc_mii, MII_BMSR); if (bmsr & BMSR_LINK) mii->mii_media_status |= IFM_ACTIVE; if (bmcr & BMCR_LOOP) mii->mii_media_active |= IFM_LOOP; /* * Grr, braindead ThunderLAN PHY doesn't have any way to * tell which media is actually active. (Note it also * doesn't self-configure after autonegotiation.) We * just have to report what's in the BMCR. */ if (bmcr & BMCR_FDX) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(self); else mii->mii_media_active |= IFM_HDX; mii->mii_media_active |= IFM_10_T; } static int -tlphy_auto(struct tlphy_softc *sc) +tlphy_auto(struct tlphy_softc *sc, if_media_t media) { int error; - switch ((error = mii_phy_auto(&sc->sc_mii))) { + switch ((error = mii_phy_auto(&sc->sc_mii, media))) { case EIO: /* * Just assume we're not in full-duplex mode. * XXX Check link and try AUI/BNC? */ PHY_WRITE(&sc->sc_mii, MII_BMCR, 0); break; case EJUSTRETURN: /* Flag that we need to program when it completes. */ sc->sc_need_acomp = 1; break; default: tlphy_acomp(sc); } return (error); } static void tlphy_acomp(struct tlphy_softc *sc) { int aner, anlpar; sc->sc_need_acomp = 0; /* * Grr, braindead ThunderLAN PHY doesn't self-configure * after autonegotiation. We have to do it ourselves * based on the link partner status. */ aner = PHY_READ(&sc->sc_mii, MII_ANER); if (aner & ANER_LPAN) { anlpar = PHY_READ(&sc->sc_mii, MII_ANLPAR) & PHY_READ(&sc->sc_mii, MII_ANAR); if (anlpar & ANAR_10_FD) { PHY_WRITE(&sc->sc_mii, MII_BMCR, BMCR_FDX); return; } } PHY_WRITE(&sc->sc_mii, MII_BMCR, 0); } Index: projects/ifnet/sys/dev/mii/truephy.c =================================================================== --- projects/ifnet/sys/dev/mii/truephy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/truephy.c (revision 282026) @@ -1,315 +1,315 @@ /*- * Copyright (c) 2007 The DragonFly Project. All rights reserved. * * This code is derived from software contributed to The DragonFly Project * by Sepherosa Ziehau * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name of The DragonFly Project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific, prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $DragonFly: src/sys/dev/netif/mii_layer/truephy.c,v 1.3 2008/02/10 07:29:27 sephe Exp $ * $FreeBSD$ */ #include #include #include #include #include #include #include -#include #include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" #define TRUEPHY_FRAMELEN(mtu) \ (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + (mtu) + ETHER_CRC_LEN) -static int truephy_service(struct mii_softc *, struct mii_data *, int); +static int truephy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); static int truephy_attach(device_t); static int truephy_probe(device_t); -static void truephy_reset(struct mii_softc *); -static void truephy_status(struct mii_softc *); +static void truephy_reset(struct mii_softc *, if_media_t); +static void truephy_status(struct mii_softc *, if_media_t); static device_method_t truephy_methods[] = { /* device interface */ DEVMETHOD(device_probe, truephy_probe), DEVMETHOD(device_attach, truephy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static const struct mii_phydesc truephys[] = { MII_PHY_DESC(AGERE, ET1011), MII_PHY_DESC(AGERE, ET1011C), MII_PHY_END }; static devclass_t truephy_devclass; static driver_t truephy_driver = { "truephy", truephy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(truephy, miibus, truephy_driver, truephy_devclass, 0, 0); static const struct mii_phy_funcs truephy_funcs = { truephy_service, truephy_status, truephy_reset }; static const struct truephy_dsp { uint16_t index; uint16_t data; } truephy_dspcode[] = { { 0x880b, 0x0926 }, /* AfeIfCreg4B1000Msbs */ { 0x880c, 0x0926 }, /* AfeIfCreg4B100Msbs */ { 0x880d, 0x0926 }, /* AfeIfCreg4B10Msbs */ { 0x880e, 0xb4d3 }, /* AfeIfCreg4B1000Lsbs */ { 0x880f, 0xb4d3 }, /* AfeIfCreg4B100Lsbs */ { 0x8810, 0xb4d3 }, /* AfeIfCreg4B10Lsbs */ { 0x8805, 0xb03e }, /* AfeIfCreg3B1000Msbs */ { 0x8806, 0xb03e }, /* AfeIfCreg3B100Msbs */ { 0x8807, 0xff00 }, /* AfeIfCreg3B10Msbs */ { 0x8808, 0xe090 }, /* AfeIfCreg3B1000Lsbs */ { 0x8809, 0xe110 }, /* AfeIfCreg3B100Lsbs */ { 0x880a, 0x0000 }, /* AfeIfCreg3B10Lsbs */ { 0x300d, 1 }, /* DisableNorm */ { 0x280c, 0x0180 }, /* LinkHoldEnd */ { 0x1c21, 0x0002 }, /* AlphaM */ { 0x3821, 6 }, /* FfeLkgTx0 */ { 0x381d, 1 }, /* FfeLkg1g4 */ { 0x381e, 1 }, /* FfeLkg1g5 */ { 0x381f, 1 }, /* FfeLkg1g6 */ { 0x3820, 1 }, /* FfeLkg1g7 */ { 0x8402, 0x01f0 }, /* Btinact */ { 0x800e, 20 }, /* LftrainTime */ { 0x800f, 24 }, /* DvguardTime */ { 0x8010, 46 } /* IdlguardTime */ }; static int truephy_probe(device_t dev) { return (mii_phy_dev_probe(dev, truephys, BUS_PROBE_DEFAULT)); } static int truephy_attach(device_t dev) { struct mii_softc *sc; sc = device_get_softc(dev); mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, &truephy_funcs, 0); - PHY_RESET(sc); + PHY_RESET(sc, 0); sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask; if (sc->mii_capabilities & BMSR_EXTSTAT) { sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); /* No 1000baseT half-duplex support */ sc->mii_extcapabilities &= ~EXTSR_1000THDX; } device_printf(dev, " "); - mii_phy_add_media(sc); + mii_phy_generic_media(sc); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); return (0); } static int -truephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +truephy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmcr; switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { + if (IFM_SUBTYPE(media) != IFM_AUTO) { bmcr = PHY_READ(sc, MII_BMCR) & ~BMCR_AUTOEN; PHY_WRITE(sc, MII_BMCR, bmcr); PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_PDOWN); } - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { + if (IFM_SUBTYPE(media) != IFM_AUTO) { bmcr = PHY_READ(sc, MII_BMCR) & ~BMCR_PDOWN; PHY_WRITE(sc, MII_BMCR, bmcr); - if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) { + if (IFM_SUBTYPE(media) == IFM_1000_T) { PHY_WRITE(sc, MII_BMCR, bmcr | BMCR_AUTOEN | BMCR_STARTNEG); } } break; case MII_TICK: if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -truephy_reset(struct mii_softc *sc) +truephy_reset(struct mii_softc *sc, if_media_t media) { int i; if (sc->mii_mpd_model == MII_MODEL_AGERE_ET1011) { - mii_phy_reset(sc); + mii_phy_reset(sc, media); return; } for (i = 0; i < 2; ++i) { PHY_READ(sc, MII_PHYIDR1); PHY_READ(sc, MII_PHYIDR2); PHY_READ(sc, TRUEPHY_CTRL); PHY_WRITE(sc, TRUEPHY_CTRL, TRUEPHY_CTRL_DIAG | TRUEPHY_CTRL_RSV1); PHY_WRITE(sc, TRUEPHY_INDEX, TRUEPHY_INDEX_MAGIC); PHY_READ(sc, TRUEPHY_DATA); PHY_WRITE(sc, TRUEPHY_CTRL, TRUEPHY_CTRL_RSV1); } PHY_READ(sc, MII_BMCR); PHY_READ(sc, TRUEPHY_CTRL); PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_PDOWN | BMCR_S1000); PHY_WRITE(sc, TRUEPHY_CTRL, TRUEPHY_CTRL_DIAG | TRUEPHY_CTRL_RSV1 | TRUEPHY_CTRL_RSV0); for (i = 0; i < nitems(truephy_dspcode); ++i) { const struct truephy_dsp *dsp = &truephy_dspcode[i]; PHY_WRITE(sc, TRUEPHY_INDEX, dsp->index); PHY_WRITE(sc, TRUEPHY_DATA, dsp->data); PHY_WRITE(sc, TRUEPHY_INDEX, dsp->index); PHY_READ(sc, TRUEPHY_DATA); } PHY_READ(sc, MII_BMCR); PHY_READ(sc, TRUEPHY_CTRL); PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_S1000); PHY_WRITE(sc, TRUEPHY_CTRL, TRUEPHY_CTRL_RSV1); - mii_phy_reset(sc); + mii_phy_reset(sc, media); if (TRUEPHY_FRAMELEN((MIIBUS_READVAR(sc->mii_dev, MIIVAR_MTU)) > 2048)) { int conf; conf = PHY_READ(sc, TRUEPHY_CONF); conf &= ~TRUEPHY_CONF_TXFIFO_MASK; conf |= TRUEPHY_CONF_TXFIFO_24; PHY_WRITE(sc, TRUEPHY_CONF, conf); } } static void -truephy_status(struct mii_softc *sc) +truephy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; int bmsr, bmcr, sr; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; sr = PHY_READ(sc, TRUEPHY_SR); bmcr = PHY_READ(sc, MII_BMCR); bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (bmsr & BMSR_LINK) mii->mii_media_status |= IFM_ACTIVE; if (bmcr & BMCR_AUTOEN) { if ((bmsr & BMSR_ACOMP) == 0) { mii->mii_media_active |= IFM_NONE; return; } } switch (sr & TRUEPHY_SR_SPD_MASK) { case TRUEPHY_SR_SPD_1000T: mii->mii_media_active |= IFM_1000_T; break; case TRUEPHY_SR_SPD_100TX: mii->mii_media_active |= IFM_100_TX; break; case TRUEPHY_SR_SPD_10T: mii->mii_media_active |= IFM_10_T; break; default: /* XXX will this ever happen? */ printf("invalid media SR %#x\n", sr); mii->mii_media_active |= IFM_NONE; return; } if (sr & TRUEPHY_SR_FDX) mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc); else mii->mii_media_active |= IFM_HDX; } Index: projects/ifnet/sys/dev/mii/ukphy.c =================================================================== --- projects/ifnet/sys/dev/mii/ukphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/ukphy.c (revision 282026) @@ -1,158 +1,159 @@ /* $NetBSD: ukphy.c,v 1.2 1999/04/23 04:24:32 thorpej Exp $ */ /*- * Copyright (c) 1998, 1999 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, and by Frank van der Linden. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /*- * Copyright (c) 1997 Manuel Bouyer. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * driver for generic unknown PHYs */ #include #include #include #include #include #include #include -#include #include #include #include #include "miibus_if.h" static int ukphy_probe(device_t); static int ukphy_attach(device_t); static device_method_t ukphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, ukphy_probe), DEVMETHOD(device_attach, ukphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t ukphy_devclass; static driver_t ukphy_driver = { "ukphy", ukphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(ukphy, miibus, ukphy_driver, ukphy_devclass, 0, 0); -static int ukphy_service(struct mii_softc *, struct mii_data *, int); +static int ukphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); static const struct mii_phy_funcs ukphy_funcs = { ukphy_service, ukphy_status, mii_phy_reset }; static int ukphy_probe(device_t dev) { /* * We know something is here, so always match at a low priority. */ device_set_desc(dev, "Generic IEEE 802.3u media interface"); return (BUS_PROBE_GENERIC); } static int ukphy_attach(device_t dev) { struct mii_softc *sc; sc = device_get_softc(dev); mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &ukphy_funcs, 1); - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, (IFM_ETHER | IFM_AUTO)); return (0); } static int -ukphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +ukphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - mii_phy_setmedia(sc); + mii_phy_setmedia(sc, media); break; case MII_TICK: if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } /* Update the media status. */ - PHY_STATUS(sc); + PHY_STATUS(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } Index: projects/ifnet/sys/dev/mii/ukphy_subr.c =================================================================== --- projects/ifnet/sys/dev/mii/ukphy_subr.c (revision 282025) +++ projects/ifnet/sys/dev/mii/ukphy_subr.c (revision 282026) @@ -1,129 +1,127 @@ /* $NetBSD: ukphy_subr.c,v 1.2 1998/11/05 04:08:02 thorpej Exp $ */ /*- * Copyright (c) 1998 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, and by Frank van der Linden. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Subroutines shared by the ukphy driver and other PHY drivers. */ #include #include #include #include #include -#include #include #include #include #include "miibus_if.h" /* * Media status subroutine. If a PHY driver does media detection simply * by decoding the NWay autonegotiation, use this routine. */ void -ukphy_status(struct mii_softc *phy) +ukphy_status(struct mii_softc *phy, if_media_t media) { struct mii_data *mii = phy->mii_pdata; - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int bmsr, bmcr, anlpar, gtcr, gtsr; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(phy, MII_BMSR) | PHY_READ(phy, MII_BMSR); if (bmsr & BMSR_LINK) mii->mii_media_status |= IFM_ACTIVE; bmcr = PHY_READ(phy, 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; if (bmcr & BMCR_AUTOEN) { /* * NWay autonegotiation takes the highest-order common * bit of the ANAR and ANLPAR (i.e. best media advertised * both by us and our link partner). */ if ((bmsr & BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } anlpar = PHY_READ(phy, MII_ANAR) & PHY_READ(phy, MII_ANLPAR); if ((phy->mii_flags & MIIF_HAVE_GTCR) != 0 && (phy->mii_extcapabilities & (EXTSR_1000THDX | EXTSR_1000TFDX)) != 0) { gtcr = PHY_READ(phy, MII_100T2CR); gtsr = PHY_READ(phy, MII_100T2SR); } else gtcr = gtsr = 0; if ((gtcr & GTCR_ADV_1000TFDX) && (gtsr & GTSR_LP_1000TFDX)) mii->mii_media_active |= IFM_1000_T|IFM_FDX; else if ((gtcr & GTCR_ADV_1000THDX) && (gtsr & GTSR_LP_1000THDX)) mii->mii_media_active |= IFM_1000_T|IFM_HDX; else if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; else if (anlpar & ANLPAR_T4) mii->mii_media_active |= IFM_100_T4|IFM_HDX; else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX|IFM_HDX; 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; if ((mii->mii_media_active & IFM_1000_T) != 0 && (gtsr & GTSR_MS_RES) != 0) mii->mii_media_active |= IFM_ETH_MASTER; if ((mii->mii_media_active & IFM_FDX) != 0) mii->mii_media_active |= mii_phy_flowstatus(phy); } else - mii->mii_media_active = ife->ifm_media; + mii->mii_media_active = media; } Index: projects/ifnet/sys/dev/mii/xmphy.c =================================================================== --- projects/ifnet/sys/dev/mii/xmphy.c (revision 282025) +++ projects/ifnet/sys/dev/mii/xmphy.c (revision 282026) @@ -1,274 +1,275 @@ /*- * Copyright (c) 2000 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * driver for the XaQti XMAC II's internal PHY. This is sort of * like a 10/100 PHY, except the only thing we're really autoselecting * here is full/half duplex. Speed is always 1000mbps. */ #include #include #include #include #include #include -#include #include #include #include #include "miidevs.h" #include #include "miibus_if.h" static int xmphy_probe(device_t); static int xmphy_attach(device_t); static device_method_t xmphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, xmphy_probe), DEVMETHOD(device_attach, xmphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD_END }; static devclass_t xmphy_devclass; static driver_t xmphy_driver = { "xmphy", xmphy_methods, sizeof(struct mii_softc) }; DRIVER_MODULE(xmphy, miibus, xmphy_driver, xmphy_devclass, 0, 0); -static int xmphy_service(struct mii_softc *, struct mii_data *, int); -static void xmphy_status(struct mii_softc *); +static int xmphy_service(struct mii_softc *, struct mii_data *, + mii_cmd_t, if_media_t); +static void xmphy_status(struct mii_softc *, if_media_t); static int xmphy_mii_phy_auto(struct mii_softc *); static const struct mii_phydesc xmphys[] = { MII_PHY_DESC(xxJATO, BASEX), MII_PHY_DESC(xxXAQTI, XMACII), MII_PHY_END }; static const struct mii_phy_funcs xmphy_funcs = { xmphy_service, xmphy_status, mii_phy_reset }; static int xmphy_probe(device_t dev) { return (mii_phy_dev_probe(dev, xmphys, BUS_PROBE_DEFAULT)); } static int xmphy_attach(device_t dev) { struct mii_softc *sc; const char *sep = ""; sc = device_get_softc(dev); mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, &xmphy_funcs, 0); sc->mii_anegticks = MII_ANEGTICKS; - PHY_RESET(sc); + PHY_RESET(sc, 0); -#define ADD(m) ifmedia_add(&sc->mii_pdata->mii_media, (m), 0, NULL) #define PRINT(s) printf("%s%s", sep, s); sep = ", " device_printf(dev, " "); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, 0, sc->mii_inst)); + mii_phy_add_media(sc->mii_pdata, + IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, 0, sc->mii_inst)); PRINT("1000baseSX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst)); + mii_phy_add_media(sc->mii_pdata, + IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst)); PRINT("1000baseSX-FDX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst)); + mii_phy_add_media(sc->mii_pdata, + IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst)); PRINT("auto"); printf("\n"); -#undef ADD #undef PRINT MIIBUS_MEDIAINIT(sc->mii_dev); return (0); } static int -xmphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) +xmphy_service(struct mii_softc *sc, struct mii_data *mii, mii_cmd_t cmd, + if_media_t media) { - struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int reg; switch (cmd) { case MII_POLLSTAT: break; case MII_MEDIACHG: - switch (IFM_SUBTYPE(ife->ifm_media)) { + switch (IFM_SUBTYPE(media)) { case IFM_AUTO: #ifdef foo /* * If we're already in auto mode, just return. */ if (PHY_READ(sc, XMPHY_MII_BMCR) & XMPHY_BMCR_AUTOEN) return (0); #endif (void)xmphy_mii_phy_auto(sc); break; case IFM_1000_SX: - PHY_RESET(sc); - if ((ife->ifm_media & IFM_FDX) != 0) { + PHY_RESET(sc, media); + if ((media & IFM_FDX) != 0) { PHY_WRITE(sc, XMPHY_MII_ANAR, XMPHY_ANAR_FDX); PHY_WRITE(sc, XMPHY_MII_BMCR, XMPHY_BMCR_FDX); } else { PHY_WRITE(sc, XMPHY_MII_ANAR, XMPHY_ANAR_HDX); PHY_WRITE(sc, XMPHY_MII_BMCR, 0); } break; default: return (EINVAL); } break; case MII_TICK: /* * Only used for autonegotiation. */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + if (IFM_SUBTYPE(media) != IFM_AUTO) break; /* * Check to see if we have link. If we do, we don't * need to restart the autonegotiation process. Read * the BMSR twice in case it's latched. */ reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (reg & BMSR_LINK) break; /* Only retry autonegotiation every mii_anegticks seconds. */ if (sc->mii_ticks <= sc->mii_anegticks) break; sc->mii_ticks = 0; - PHY_RESET(sc); + PHY_RESET(sc, media); xmphy_mii_phy_auto(sc); return (0); } /* Update the media status. */ - xmphy_status(sc); + xmphy_status(sc, media); /* Callback if something changed. */ mii_phy_update(sc, cmd); return (0); } static void -xmphy_status(struct mii_softc *sc) +xmphy_status(struct mii_softc *sc, if_media_t media) { struct mii_data *mii = sc->mii_pdata; int bmsr, bmcr, anlpar; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; bmsr = PHY_READ(sc, XMPHY_MII_BMSR) | PHY_READ(sc, XMPHY_MII_BMSR); if (bmsr & XMPHY_BMSR_LINK) mii->mii_media_status |= IFM_ACTIVE; /* Do dummy read of extended status register. */ bmcr = PHY_READ(sc, XMPHY_MII_EXTSTS); bmcr = PHY_READ(sc, XMPHY_MII_BMCR); if (bmcr & XMPHY_BMCR_LOOP) mii->mii_media_active |= IFM_LOOP; if (bmcr & XMPHY_BMCR_AUTOEN) { if ((bmsr & XMPHY_BMSR_ACOMP) == 0) { if (bmsr & XMPHY_BMSR_LINK) { mii->mii_media_active |= IFM_1000_SX|IFM_HDX; return; } /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } mii->mii_media_active |= IFM_1000_SX; anlpar = PHY_READ(sc, XMPHY_MII_ANAR) & PHY_READ(sc, XMPHY_MII_ANLPAR); if (anlpar & XMPHY_ANLPAR_FDX) mii->mii_media_active |= IFM_FDX; else mii->mii_media_active |= IFM_HDX; return; } mii->mii_media_active |= IFM_1000_SX; if (bmcr & XMPHY_BMCR_FDX) mii->mii_media_active |= IFM_FDX; else mii->mii_media_active |= IFM_HDX; } static int xmphy_mii_phy_auto(struct mii_softc *mii) { int anar = 0; anar = PHY_READ(mii, XMPHY_MII_ANAR); anar |= XMPHY_ANAR_FDX|XMPHY_ANAR_HDX; PHY_WRITE(mii, XMPHY_MII_ANAR, anar); DELAY(1000); PHY_WRITE(mii, XMPHY_MII_BMCR, XMPHY_BMCR_AUTOEN | XMPHY_BMCR_STARTNEG); return (EJUSTRETURN); }