diff options
Diffstat (limited to 'sys/dev/mii')
-rw-r--r-- | sys/dev/mii/exphy.c | 199 | ||||
-rw-r--r-- | sys/dev/mii/files.mii | 36 | ||||
-rw-r--r-- | sys/dev/mii/icsphy.c | 319 | ||||
-rw-r--r-- | sys/dev/mii/icsphyreg.h | 92 | ||||
-rw-r--r-- | sys/dev/mii/inphy.c | 189 | ||||
-rw-r--r-- | sys/dev/mii/lxtphy.c | 323 | ||||
-rw-r--r-- | sys/dev/mii/lxtphyreg.h | 89 | ||||
-rw-r--r-- | sys/dev/mii/mii.c | 25 | ||||
-rw-r--r-- | sys/dev/mii/mii_physubr.c | 102 | ||||
-rw-r--r-- | sys/dev/mii/miivar.h | 29 | ||||
-rw-r--r-- | sys/dev/mii/nsphy.c | 192 | ||||
-rw-r--r-- | sys/dev/mii/qsphy.c | 200 | ||||
-rw-r--r-- | sys/dev/mii/sqphy.c | 319 | ||||
-rw-r--r-- | sys/dev/mii/sqphyreg.h | 128 | ||||
-rw-r--r-- | sys/dev/mii/tlphy.c | 133 | ||||
-rw-r--r-- | sys/dev/mii/ukphy.c | 274 | ||||
-rw-r--r-- | sys/dev/mii/ukphy_subr.c | 113 |
17 files changed, 2128 insertions, 634 deletions
diff --git a/sys/dev/mii/exphy.c b/sys/dev/mii/exphy.c index 7c062f925ff..8a16211e1ec 100644 --- a/sys/dev/mii/exphy.c +++ b/sys/dev/mii/exphy.c @@ -1,5 +1,5 @@ -/* $OpenBSD: exphy.c,v 1.1 1998/09/10 17:17:33 jason Exp $ */ -/* $NetBSD: exphy.c,v 1.5 1998/08/28 12:50:36 fvdl Exp $ */ +/* $OpenBSD: exphy.c,v 1.2 1998/11/11 19:34:44 jason Exp $ */ +/* $NetBSD: exphy.c,v 1.15 1998/11/05 00:19:32 thorpej Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -85,12 +85,6 @@ #include <dev/mii/miivar.h> #include <dev/mii/miidevs.h> -struct exphy_softc { - struct mii_softc sc_mii; /* generic PHY */ - int sc_capabilities; - int sc_active; -}; - #ifdef __NetBSD__ int exphymatch __P((struct device *, struct cfdata *, void *)); #else @@ -99,7 +93,7 @@ int exphymatch __P((struct device *, void *, void *)); void exphyattach __P((struct device *, struct device *, void *)); struct cfattach exphy_ca = { - sizeof(struct exphy_softc), exphymatch, exphyattach + sizeof(struct mii_softc), exphymatch, exphyattach }; #ifdef __OpenBSD__ @@ -108,18 +102,8 @@ struct cfdriver exphy_cd = { }; #endif -#define EXPHY_READ(sc, reg) \ - (*(sc)->sc_mii.mii_pdata->mii_readreg)((sc)->sc_mii.mii_dev.dv_parent, \ - (sc)->sc_mii.mii_phy, (reg)) - -#define EXPHY_WRITE(sc, reg, val) \ - (*(sc)->sc_mii.mii_pdata->mii_writereg)((sc)->sc_mii.mii_dev.dv_parent, \ - (sc)->sc_mii.mii_phy, (reg), (val)) - int exphy_service __P((struct mii_softc *, struct mii_data *, int)); -void exphy_reset __P((struct exphy_softc *)); -void exphy_auto __P((struct exphy_softc *)); -void exphy_status __P((struct exphy_softc *)); +void exphy_reset __P((struct mii_softc *)); int exphymatch(parent, match, aux) @@ -136,11 +120,17 @@ exphymatch(parent, match, aux) /* * Argh, 3Com PHY reports oui == 0 model == 0! */ - if (MII_OUI(ma->mii_id1, ma->mii_id2) == 0 && - MII_MODEL(ma->mii_id2) == 0) - return (1); + if (MII_OUI(ma->mii_id1, ma->mii_id2) != 0 && + MII_MODEL(ma->mii_id2) != 0) + return (0); - return (0); + /* + * Make sure the parent is an `ex'. + */ + if (strcmp(parent->dv_cfdata->cf_driver->cd_name, "ex") != 0) + return (0); + + return (10); } void @@ -148,17 +138,16 @@ exphyattach(parent, self, aux) struct device *parent, *self; void *aux; { - struct exphy_softc *sc = (struct exphy_softc *)self; + struct mii_softc *sc = (struct mii_softc *)self; struct mii_attach_args *ma = aux; struct mii_data *mii = ma->mii_data; - printf(": 3Com internal media interface, rev. %d\n", - MII_REV(ma->mii_id2)); + printf(": 3Com internal media interface\n"); - sc->sc_mii.mii_inst = mii->mii_instance; - sc->sc_mii.mii_phy = ma->mii_phyno; - sc->sc_mii.mii_service = exphy_service; - sc->sc_mii.mii_pdata = mii; + sc->mii_inst = mii->mii_instance; + sc->mii_phy = ma->mii_phyno; + sc->mii_service = exphy_service; + sc->mii_pdata = mii; /* * The 3Com PHY can never be isolated, so never allow non-zero @@ -166,45 +155,49 @@ exphyattach(parent, self, aux) */ if (mii->mii_instance != 0) { printf("%s: ignoring this PHY, non-zero instance\n", - sc->sc_mii.mii_dev.dv_xname); + sc->mii_dev.dv_xname); return; } + sc->mii_flags |= MIIF_NOISOLATE; #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->sc_mii.mii_inst), +#if 0 /* See above. */ + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), BMCR_ISO); +#endif - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->sc_mii.mii_inst), + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), BMCR_LOOP|BMCR_S100); exphy_reset(sc); - sc->sc_capabilities = EXPHY_READ(sc, MII_BMSR) & ma->mii_capmask; - printf("%s: ", sc->sc_mii.mii_dev.dv_xname); - if ((sc->sc_capabilities & BMSR_MEDIAMASK) == 0) + sc->mii_capabilities = + PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + printf("%s: ", sc->mii_dev.dv_xname); + if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) printf("no media present"); else - mii_add_media(mii, sc->sc_capabilities, sc->sc_mii.mii_inst); + mii_add_media(mii, sc->mii_capabilities, + sc->mii_inst); printf("\n"); #undef ADD } int -exphy_service(self, mii, cmd) - struct mii_softc *self; +exphy_service(sc, mii, cmd) + struct mii_softc *sc; struct mii_data *mii; int cmd; { - struct exphy_softc *sc = (struct exphy_softc *)self; + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; /* * We can't isolate the 3Com PHY, so it has to be the only one! */ - if (IFM_INST(mii->mii_media.ifm_media) != sc->sc_mii.mii_inst) + if (IFM_INST(ife->ifm_media) != sc->mii_inst) panic("exphy_service: can't isolate 3Com PHY"); - switch (cmd) { case MII_POLLSTAT: break; @@ -216,14 +209,14 @@ exphy_service(self, mii, cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - switch (IFM_SUBTYPE(mii->mii_media.ifm_media)) { + switch (IFM_SUBTYPE(ife->ifm_media)) { case IFM_AUTO: /* * If we're already in auto mode, just return. */ - if (EXPHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) + if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) return (0); - exphy_auto(sc); + (void) mii_phy_auto(sc); break; case IFM_100_T4: /* @@ -234,10 +227,9 @@ exphy_service(self, mii, cmd) /* * BMCR data is stored in the ifmedia entry. */ - EXPHY_WRITE(sc, MII_ANAR, - mii_anar(mii->mii_media.ifm_media)); - EXPHY_WRITE(sc, MII_BMCR, - mii->mii_media.ifm_cur->ifm_data); + PHY_WRITE(sc, MII_ANAR, + mii_anar(ife->ifm_media)); + PHY_WRITE(sc, MII_BMCR, ife->ifm_data); } break; @@ -245,7 +237,7 @@ exphy_service(self, mii, cmd) /* * Only used for autonegotiation. */ - if (IFM_SUBTYPE(mii->mii_media.ifm_media) != IFM_AUTO) + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) return (0); /* @@ -262,117 +254,26 @@ exphy_service(self, mii, cmd) } /* Update the media status. */ - exphy_status(sc); + ukphy_status(sc); /* Callback if something changed. */ - if (sc->sc_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - (*mii->mii_statchg)(sc->sc_mii.mii_dev.dv_parent); - sc->sc_active = mii->mii_media_active; + if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { + (*mii->mii_statchg)(sc->mii_dev.dv_parent); + sc->mii_active = mii->mii_media_active; } return (0); } void -exphy_status(sc) - struct exphy_softc *sc; -{ - struct mii_data *mii = sc->sc_mii.mii_pdata; - int bmsr, bmcr, anlpar; - - mii->mii_media_status = IFM_AVALID; - mii->mii_media_active = IFM_ETHER; - - bmsr = EXPHY_READ(sc, MII_BMSR) | EXPHY_READ(sc, MII_BMSR); - if (bmsr & BMSR_LINK) - mii->mii_media_status |= IFM_ACTIVE; - - bmcr = EXPHY_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 3Com PHY uses 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 = EXPHY_READ(sc, MII_ANAR) & EXPHY_READ(sc, MII_ANLPAR); - if (anlpar & ANLPAR_T4) - mii->mii_media_active |= IFM_100_T4; - else if (anlpar & ANLPAR_TX_FD) - mii->mii_media_active |= IFM_100_TX|IFM_FDX; - else if (anlpar & ANLPAR_TX) - mii->mii_media_active |= IFM_100_TX; - else if (anlpar & ANLPAR_10_FD) - mii->mii_media_active |= IFM_10_T|IFM_FDX; - else if (anlpar & ANLPAR_10) - mii->mii_media_active |= IFM_10_T; - else - mii->mii_media_active |= IFM_NONE; - } else { - if (bmcr & BMCR_S100) - mii->mii_media_active |= IFM_100_TX; - else - mii->mii_media_active |= IFM_10_T; - if (bmcr & BMCR_FDX) - mii->mii_media_active |= IFM_FDX; - } -} - -void -exphy_auto(sc) - struct exphy_softc *sc; -{ - int bmsr, i; - - EXPHY_WRITE(sc, MII_ANAR, - BMSR_MEDIA_TO_ANAR(sc->sc_capabilities) | ANAR_CSMA); - EXPHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); - - /* Wait 500ms for it to complete. */ - for (i = 0; i < 500; i++) { - if ((bmsr = EXPHY_READ(sc, MII_BMSR)) & BMSR_ACOMP) - return; - delay(1000); - } -#if 0 - if ((bmsr & BMSR_ACOMP) == 0) - printf("%s: autonegotiation failed to complete\n", - sc->sc_mii.mii_dev.dv_xname); -#endif -} - -void exphy_reset(sc) - struct exphy_softc *sc; + struct mii_softc *sc; { - int reg, i; - - EXPHY_WRITE(sc, MII_BMCR, BMCR_RESET); - /* Wait 100ms for it to complete. */ - for (i = 0; i < 100; i++) { - reg = EXPHY_READ(sc, MII_BMCR); - if ((reg & BMCR_RESET) == 0) - break; - delay(1000); - } + mii_phy_reset(sc); /* * XXX 3Com PHY doesn't set the BMCR properly after * XXX reset, which breaks autonegotiation. */ - EXPHY_WRITE(sc, MII_BMCR, BMCR_S100|BMCR_AUTOEN|BMCR_FDX); + PHY_WRITE(sc, MII_BMCR, BMCR_S100|BMCR_AUTOEN|BMCR_FDX); } diff --git a/sys/dev/mii/files.mii b/sys/dev/mii/files.mii index c8d7e79b420..d7929a20a23 100644 --- a/sys/dev/mii/files.mii +++ b/sys/dev/mii/files.mii @@ -1,24 +1,46 @@ -# $OpenBSD: files.mii,v 1.1 1998/09/10 17:17:33 jason Exp $ -# $NetBSD: files.mii,v 1.7 1998/08/12 08:46:20 thorpej Exp $ +# $OpenBSD: files.mii,v 1.2 1998/11/11 19:34:45 jason Exp $ +# $NetBSD: files.mii,v 1.13 1998/11/05 00:36:48 thorpej Exp $ file dev/mii/mii.c mii -device tlphy +define mii_phy +file dev/mii/mii_physubr.c mii_phy + +define ukphy_subr +file dev/mii/ukphy_subr.c ukphy_subr + +device tlphy: mii_phy attach tlphy at mii file dev/mii/tlphy.c tlphy -device nsphy +device nsphy: mii_phy attach nsphy at mii file dev/mii/nsphy.c nsphy -device qsphy +device qsphy: mii_phy attach qsphy at mii file dev/mii/qsphy.c qsphy -device inphy +device inphy: mii_phy attach inphy at mii file dev/mii/inphy.c inphy -device exphy +device exphy: mii_phy, ukphy_subr attach exphy at mii file dev/mii/exphy.c exphy + +device lxtphy: mii_phy +attach lxtphy at mii +file dev/mii/lxtphy.c lxtphy + +device icsphy: mii_phy +attach icsphy at mii +file dev/mii/icsphy.c icsphy + +device sqphy: mii_phy +attach sqphy at mii +file dev/mii/sqphy.c sqphy + +device ukphy: mii_phy, ukphy_subr +attach ukphy at mii +file dev/mii/ukphy.c ukphy diff --git a/sys/dev/mii/icsphy.c b/sys/dev/mii/icsphy.c new file mode 100644 index 00000000000..8e26627278c --- /dev/null +++ b/sys/dev/mii/icsphy.c @@ -0,0 +1,319 @@ +/* $OpenBSD: icsphy.c,v 1.1 1998/11/11 19:34:45 jason Exp $ */ +/* $NetBSD: icsphy.c,v 1.8 1998/11/05 04:08:01 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. + * + * 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 the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Manuel Bouyer. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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 Integrated Circuit Systems' ICS1890 ethernet 10/100 PHY + * datasheet from www.icst.com + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_media.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> +#include <dev/mii/miidevs.h> + +#include <dev/mii/icsphyreg.h> + +#ifdef __NetBSD__ +int icsphymatch __P((struct device *, struct cfdata *, void *)); +#else +int icsphymatch __P((struct device *, void *, void *)); +#endif +void icsphyattach __P((struct device *, struct device *, void *)); + +struct cfattach icsphy_ca = { + sizeof(struct mii_softc), icsphymatch, icsphyattach +}; + +#ifdef __OpenBSD__ +struct cfdriver icsphy_cd = { + NULL, "icsphy", DV_DULL +}; +#endif + +int icsphy_service __P((struct mii_softc *, struct mii_data *, int)); +void icsphy_reset __P((struct mii_softc *)); +void icsphy_status __P((struct mii_softc *)); + +int +icsphymatch(parent, match, aux) + struct device *parent; +#ifdef __NetBSD__ + struct cfdata *match; +#else + void *match; +#endif + void *aux; +{ + struct mii_attach_args *ma = aux; + + if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_ICS && + MII_MODEL(ma->mii_id2) == MII_MODEL_ICS_1890) + return (10); + + return (0); +} + +void +icsphyattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct mii_softc *sc = (struct mii_softc *)self; + struct mii_attach_args *ma = aux; + struct mii_data *mii = ma->mii_data; + + printf(": %s, rev. %d\n", MII_STR_ICS_1890, + MII_REV(ma->mii_id2)); + + sc->mii_inst = mii->mii_instance; + sc->mii_phy = ma->mii_phyno; + sc->mii_service = icsphy_service; + sc->mii_pdata = mii; + +#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) + + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), + BMCR_ISO); + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), + BMCR_LOOP|BMCR_S100); + + icsphy_reset(sc); + + sc->mii_capabilities = + PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + printf("%s: ", sc->mii_dev.dv_xname); + if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) + printf("no media present"); + else + mii_add_media(mii, sc->mii_capabilities, + sc->mii_inst); + printf("\n"); +#undef ADD +} + +int +icsphy_service(sc, mii, cmd) + struct mii_softc *sc; + struct mii_data *mii; + int cmd; +{ + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; + int reg; + + switch (cmd) { + case MII_POLLSTAT: + /* + * If we're not polling our PHY instance, just return. + */ + if (IFM_INST(ife->ifm_media) != sc->mii_inst) + return (0); + break; + + case MII_MEDIACHG: + /* + * If the media indicates a different PHY instance, + * isolate ourselves. + */ + if (IFM_INST(ife->ifm_media) != sc->mii_inst) { + reg = PHY_READ(sc, MII_BMCR); + PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); + return (0); + } + + /* + * If the interface is not up, don't do anything. + */ + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) + break; + + switch (IFM_SUBTYPE(ife->ifm_media)) { + case IFM_AUTO: + /* + * If we're already in auto mode, just return. + */ + if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) + return (0); + (void) mii_phy_auto(sc); + break; + case IFM_100_T4: + /* + * XXX Not supported as a manual setting right now. + */ + return (EINVAL); + default: + /* + * BMCR data is stored in the ifmedia entry. + */ + PHY_WRITE(sc, MII_ANAR, + mii_anar(ife->ifm_media)); + PHY_WRITE(sc, MII_BMCR, ife->ifm_data); + } + break; + + case MII_TICK: + /* + * If we're not currently selected, just return. + */ + if (IFM_INST(ife->ifm_media) != sc->mii_inst) + return (0); + + /* + * Only used for autonegotiation. + */ + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + return (0); + + /* + * Is the interface even up? + */ + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) + return (0); + + /* + * The ICS1890's autonegotiation doesn't need to be + * kicked; it continues in the background. + */ + break; + } + + /* Update the media status. */ + icsphy_status(sc); + + /* Callback if something changed. */ + if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { + (*mii->mii_statchg)(sc->mii_dev.dv_parent); + sc->mii_active = mii->mii_media_active; + } + return (0); +} + +void +icsphy_status(sc) + struct mii_softc *sc; +{ + struct mii_data *mii = sc->mii_pdata; + 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; + } else + mii->mii_media_active = mii_media_from_bmcr(bmcr); +} + +void +icsphy_reset(sc) + struct mii_softc *sc; +{ + + mii_phy_reset(sc); + PHY_WRITE(sc, MII_ICSPHY_ECR2, ECR2_10TPROT|ECR2_Q10T); +} diff --git a/sys/dev/mii/icsphyreg.h b/sys/dev/mii/icsphyreg.h new file mode 100644 index 00000000000..efa8544ec8e --- /dev/null +++ b/sys/dev/mii/icsphyreg.h @@ -0,0 +1,92 @@ +/* $OpenBSD: icsphyreg.h,v 1.1 1998/11/11 19:34:46 jason Exp $ */ +/* $NetBSD: icsphyreg.h,v 1.1 1998/11/02 23:46:20 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. + * + * 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 the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 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. + */ + +#ifndef _DEV_MII_ICSPHYREG_H_ +#define _DEV_MII_ICSPHYREG_H_ + +/* + * ICS1890 registers. + */ + +#define MII_ICSPHY_ECR 0x10 /* Extended Control Register */ +#define ECR_OVR 0x8000 /* disable command reg overwrites */ +#define ECR_PHYADDR_MASK 0x07c0 /* PHY address mask */ +#define ECR_CTEST 0x0020 /* Stream Cipher Test Mode */ +#define ECR_IECT 0x0004 /* Invalid Error Code Test */ +#define ECR_SSD 0x0001 /* Stream Cipher Disable */ + +#define MII_ICSPHY_QPR 0x11 /* Quick Poll Register */ +#define QPR_SPEED 0x8000 /* 100Mbps */ +#define QPR_FDX 0x4000 /* Full dupled */ +#define QPR_ANB2 0x2000 /* Autoneg monitor bit 2 */ +#define QPR_ANB1 0x1000 /* Autoneg monitor bit 1 */ +#define QPR_ANB0 0x0800 /* Autoneg monitor bit 0 */ +#define QPR_RXERR 0x0400 /* Receive signal lost */ +#define QPR_PLLERR 0x0200 /* PLL error */ +#define QPR_FCARR 0x0100 /* False carrier detected */ +#define QPR_INVALSYM 0x0080 /* Invalid Symbol Detected */ +#define QPR_HALT 0x0040 /* Halt Symbol Detected */ +#define QPR_PREEM 0x0020 /* Two Idle Symbols together */ +#define QPR_ACOMP 0x0010 /* Autonegotiation complete */ +#define QPR_JABBER 0x0004 /* Jabber detected */ +#define QPR_RFAULT 0x0002 /* Remote Fault */ +#define QPR_LINK 0x0001 /* Link */ + +#define MII_ICSPHY_TTR 0x12 /* 10baseT Operations Register */ +#define TTR_RJABBER 0x8000 /* Remote Jabber */ +#define TTR_POLARITY 0x4000 /* Polarity Reversed */ +#define TTR_NOJABBER 0x0020 /* Disable Jabber Check */ +#define TTR_LOOP 0x0010 /* Loopback mode */ +#define TTR_NOAPOLARITY 0x0008 /* Disable auto polarity correction */ +#define TTR_NOSQE 0x0004 /* Disable SQE check */ +#define TTR_NOLINK 0x0002 /* Disable Link check */ +#define TTR_NOSQUELCH 0x0001 /* Disable squelch */ + +#define MII_ICSPHY_ECR2 0x13 /* Extended Control Register 2 */ +#define ECR2_REPEATER 0x8000 /* Repeater Mode */ +#define ECR2_HWSW 0x4000 /* hw/sw config priority */ +#define ECR2_LPRF 0x2000 /* link partner supports rem fault */ +#define ECR2_FORCERF 0x0400 /* Force transmit of rem fault */ +#define ECR2_RFPUP 0x0010 /* Rem fault on power up */ +#define ECR2_Q10T 0x0004 /* Qualified 10baseT data */ +#define ECR2_10TPROT 0x0002 /* 10baseT protect */ +#define ECR2_AUTOPWRDN 0x0001 /* automatic power down */ + +#endif /* _DEV_MII_ICSPHYREG_H_ */ diff --git a/sys/dev/mii/inphy.c b/sys/dev/mii/inphy.c index 70cedb54345..6f43b03fb1a 100644 --- a/sys/dev/mii/inphy.c +++ b/sys/dev/mii/inphy.c @@ -1,5 +1,5 @@ -/* $OpenBSD: inphy.c,v 1.1 1998/09/10 17:17:33 jason Exp $ */ -/* $NetBSD: inphy.c,v 1.3 1998/08/12 20:56:35 thorpej Exp $ */ +/* $OpenBSD: inphy.c,v 1.2 1998/11/11 19:34:46 jason Exp $ */ +/* $NetBSD: inphy.c,v 1.10 1998/11/05 04:08:02 thorpej Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -88,13 +88,6 @@ #include <dev/mii/inphyreg.h> -struct inphy_softc { - struct mii_softc sc_mii; /* generic PHY */ - int sc_capabilities; - int sc_ticks; - int sc_active; -}; - #ifdef __NetBSD__ int inphymatch __P((struct device *, struct cfdata *, void *)); #else @@ -103,7 +96,7 @@ int inphymatch __P((struct device *, void *, void *)); void inphyattach __P((struct device *, struct device *, void *)); struct cfattach inphy_ca = { - sizeof(struct inphy_softc), inphymatch, inphyattach + sizeof(struct mii_softc), inphymatch, inphyattach }; #ifdef __OpenBSD__ @@ -112,18 +105,8 @@ struct cfdriver inphy_cd = { }; #endif -#define INPHY_READ(sc, reg) \ - (*(sc)->sc_mii.mii_pdata->mii_readreg)((sc)->sc_mii.mii_dev.dv_parent, \ - (sc)->sc_mii.mii_phy, (reg)) - -#define INPHY_WRITE(sc, reg, val) \ - (*(sc)->sc_mii.mii_pdata->mii_writereg)((sc)->sc_mii.mii_dev.dv_parent, \ - (sc)->sc_mii.mii_phy, (reg), (val)) - int inphy_service __P((struct mii_softc *, struct mii_data *, int)); -void inphy_reset __P((struct inphy_softc *)); -void inphy_auto __P((struct inphy_softc *)); -void inphy_status __P((struct inphy_softc *)); +void inphy_status __P((struct mii_softc *)); int inphymatch(parent, match, aux) @@ -139,7 +122,7 @@ inphymatch(parent, match, aux) if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_INTEL && MII_MODEL(ma->mii_id2) == MII_MODEL_INTEL_I82555) - return (1); + return (10); return (0); } @@ -149,47 +132,55 @@ inphyattach(parent, self, aux) struct device *parent, *self; void *aux; { - struct inphy_softc *sc = (struct inphy_softc *)self; + struct mii_softc *sc = (struct mii_softc *)self; struct mii_attach_args *ma = aux; struct mii_data *mii = ma->mii_data; printf(": %s, rev. %d\n", MII_STR_INTEL_I82555, MII_REV(ma->mii_id2)); - sc->sc_mii.mii_inst = mii->mii_instance; - sc->sc_mii.mii_phy = ma->mii_phyno; - sc->sc_mii.mii_service = inphy_service; - sc->sc_mii.mii_pdata = mii; + sc->mii_inst = mii->mii_instance; + sc->mii_phy = ma->mii_phyno; + sc->mii_service = inphy_service; + sc->mii_pdata = mii; + + /* + * i82557 wedges if all of its PHYs are isolated! + */ + if (strcmp(parent->dv_cfdata->cf_driver->cd_name, "fxp") == 0 && + mii->mii_instance == 0) + sc->mii_flags |= MIIF_NOISOLATE; #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) -#if 0 - /* Can't do this on the i82557! */ - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->sc_mii.mii_inst), - BMCR_ISO); -#endif - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->sc_mii.mii_inst), + if ((sc->mii_flags & MIIF_NOISOLATE) == 0) + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), + BMCR_ISO); + + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), BMCR_LOOP|BMCR_S100); - inphy_reset(sc); + mii_phy_reset(sc); - sc->sc_capabilities = INPHY_READ(sc, MII_BMSR) & ma->mii_capmask; - printf("%s: ", sc->sc_mii.mii_dev.dv_xname); - if ((sc->sc_capabilities & BMSR_MEDIAMASK) == 0) + sc->mii_capabilities = + PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + printf("%s: ", sc->mii_dev.dv_xname); + if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) printf("no media present"); else - mii_add_media(mii, sc->sc_capabilities, sc->sc_mii.mii_inst); + mii_add_media(mii, sc->mii_capabilities, + sc->mii_inst); printf("\n"); #undef ADD } int -inphy_service(self, mii, cmd) - struct mii_softc *self; +inphy_service(sc, mii, cmd) + struct mii_softc *sc; struct mii_data *mii; int cmd; { - struct inphy_softc *sc = (struct inphy_softc *)self; + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int reg; switch (cmd) { @@ -197,8 +188,7 @@ inphy_service(self, mii, cmd) /* * If we're not polling our PHY instance, just return. */ - if (IFM_INST(mii->mii_media.ifm_media) != - sc->sc_mii.mii_inst) + if (IFM_INST(ife->ifm_media) != sc->mii_inst) return (0); break; @@ -207,10 +197,9 @@ inphy_service(self, mii, cmd) * If the media indicates a different PHY instance, * isolate ourselves. */ - if (IFM_INST(mii->mii_media.ifm_media) != - sc->sc_mii.mii_inst) { - reg = INPHY_READ(sc, MII_BMCR); - INPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); + if (IFM_INST(ife->ifm_media) != sc->mii_inst) { + reg = PHY_READ(sc, MII_BMCR); + PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); return (0); } @@ -220,14 +209,14 @@ inphy_service(self, mii, cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - switch (IFM_SUBTYPE(mii->mii_media.ifm_media)) { + switch (IFM_SUBTYPE(ife->ifm_media)) { case IFM_AUTO: /* * If we're already in auto mode, just return. */ - if (INPHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) + if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) return (0); - inphy_auto(sc); + (void) mii_phy_auto(sc); break; case IFM_100_T4: /* @@ -238,10 +227,9 @@ inphy_service(self, mii, cmd) /* * BMCR data is stored in the ifmedia entry. */ - INPHY_WRITE(sc, MII_ANAR, - mii_anar(mii->mii_media.ifm_media)); - INPHY_WRITE(sc, MII_BMCR, - mii->mii_media.ifm_cur->ifm_data); + PHY_WRITE(sc, MII_ANAR, + mii_anar(ife->ifm_media)); + PHY_WRITE(sc, MII_BMCR, ife->ifm_data); } break; @@ -249,14 +237,13 @@ inphy_service(self, mii, cmd) /* * If we're not currently selected, just return. */ - if (IFM_INST(mii->mii_media.ifm_media) != - sc->sc_mii.mii_inst) + if (IFM_INST(ife->ifm_media) != sc->mii_inst) return (0); /* * Only used for autonegotiation. */ - if (IFM_SUBTYPE(mii->mii_media.ifm_media) != IFM_AUTO) + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) return (0); /* @@ -270,19 +257,20 @@ inphy_service(self, mii, cmd) * need to restart the autonegotiation process. Read * the BMSR twice in case it's latched. */ - reg = INPHY_READ(sc, MII_BMSR) | INPHY_READ(sc, MII_BMSR); + reg = PHY_READ(sc, MII_BMSR) | + PHY_READ(sc, MII_BMSR); if (reg & BMSR_LINK) return (0); /* * Only retry autonegotiation every 5 seconds. */ - if (++sc->sc_ticks != 5) + if (++sc->mii_ticks != 5) return (0); - sc->sc_ticks = 0; - inphy_reset(sc); - inphy_auto(sc); + sc->mii_ticks = 0; + mii_phy_reset(sc); + (void) mii_phy_auto(sc); break; } @@ -290,28 +278,29 @@ inphy_service(self, mii, cmd) inphy_status(sc); /* Callback if something changed. */ - if (sc->sc_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - (*mii->mii_statchg)(sc->sc_mii.mii_dev.dv_parent); - sc->sc_active = mii->mii_media_active; + if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { + (*mii->mii_statchg)(sc->mii_dev.dv_parent); + sc->mii_active = mii->mii_media_active; } return (0); } void inphy_status(sc) - struct inphy_softc *sc; + struct mii_softc *sc; { - struct mii_data *mii = sc->sc_mii.mii_pdata; + struct mii_data *mii = sc->mii_pdata; int bmsr, bmcr, scr; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; - bmsr = INPHY_READ(sc, MII_BMSR) | INPHY_READ(sc, MII_BMSR); + bmsr = PHY_READ(sc, MII_BMSR) | + PHY_READ(sc, MII_BMSR); if (bmsr & BMSR_LINK) mii->mii_media_status |= IFM_ACTIVE; - bmcr = INPHY_READ(sc, MII_BMCR); + bmcr = PHY_READ(sc, MII_BMCR); if (bmcr & BMCR_ISO) { mii->mii_media_active |= IFM_NONE; mii->mii_media_status = 0; @@ -327,7 +316,7 @@ inphy_status(sc) mii->mii_media_active |= IFM_NONE; return; } - scr = INPHY_READ(sc, MII_INPHY_SCR); + scr = PHY_READ(sc, MII_INPHY_SCR); if (scr & SCR_T4) mii->mii_media_active |= IFM_100_T4; else if (scr & SCR_S100) @@ -336,62 +325,6 @@ inphy_status(sc) mii->mii_media_active |= IFM_10_T; if (scr & SCR_FDX) mii->mii_media_active |= IFM_FDX; - } else { - if (bmcr & BMCR_S100) - mii->mii_media_active |= IFM_100_TX; - else - mii->mii_media_active |= IFM_10_T; - if (bmcr & BMCR_FDX) - mii->mii_media_active |= IFM_FDX; - } -} - -void -inphy_auto(sc) - struct inphy_softc *sc; -{ - int bmsr, i; - - INPHY_WRITE(sc, MII_ANAR, - BMSR_MEDIA_TO_ANAR(sc->sc_capabilities) | ANAR_CSMA); - INPHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); - - /* Wait 500ms for it to complete. */ - for (i = 0; i < 500; i++) { - if ((bmsr = INPHY_READ(sc, MII_BMSR)) & BMSR_ACOMP) - return; - delay(1000); - } -#if 0 - if ((bmsr & BMSR_ACOMP) == 0) - printf("%s: autonegotiation failed to complete\n", - sc->sc_mii.mii_dev.dv_xname); -#endif -} - -void -inphy_reset(sc) - struct inphy_softc *sc; -{ - int reg, i; - - /* - * The i82557 wedges if we isolate all of its PHYs! - */ - if (sc->sc_mii.mii_inst == 0) - INPHY_WRITE(sc, MII_BMCR, BMCR_RESET); - else - INPHY_WRITE(sc, MII_BMCR, BMCR_RESET|BMCR_ISO); - - /* Wait 100ms for it to complete. */ - for (i = 0; i < 100; i++) { - reg = INPHY_READ(sc, MII_BMCR); - if ((reg & BMCR_RESET) == 0) - break; - delay(1000); - } - - /* Make sure the PHY is isolated. */ - if (sc->sc_mii.mii_inst != 0) - INPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); + } else + mii->mii_media_active = mii_media_from_bmcr(bmcr); } diff --git a/sys/dev/mii/lxtphy.c b/sys/dev/mii/lxtphy.c new file mode 100644 index 00000000000..5209d172d63 --- /dev/null +++ b/sys/dev/mii/lxtphy.c @@ -0,0 +1,323 @@ +/* $OpenBSD: lxtphy.c,v 1.1 1998/11/11 19:34:46 jason Exp $ */ +/* $NetBSD: lxtphy.c,v 1.9 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. + * + * 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 the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Manuel Bouyer. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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 Level One's LXT-970 ethernet 10/100 PHY + * datasheet from www.level1.com + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_media.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> +#include <dev/mii/miidevs.h> + +#include <dev/mii/lxtphyreg.h> + +#ifdef __NetBSD__ +int lxtphymatch __P((struct device *, struct cfdata *, void *)); +#else +int lxtphymatch __P((struct device *, void *, void *)); +#endif +void lxtphyattach __P((struct device *, struct device *, void *)); + +struct cfattach lxtphy_ca = { + sizeof(struct mii_softc), lxtphymatch, lxtphyattach +}; + +#ifdef __OpenBSD__ +struct cfdriver lxtphy_cd = { + NULL, "lxtphy", DV_DULL +}; +#endif + +int lxtphy_service __P((struct mii_softc *, struct mii_data *, int)); +void lxtphy_status __P((struct mii_softc *)); + +int +lxtphymatch(parent, match, aux) + struct device *parent; +#ifdef __NetBSD__ + struct cfdata *match; +#else + void *match; +#endif + void *aux; +{ + struct mii_attach_args *ma = aux; + + if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_LEVEL1 && + MII_MODEL(ma->mii_id2) == MII_MODEL_LEVEL1_LXT970) + return (10); + + return (0); +} + +void +lxtphyattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct mii_softc *sc = (struct mii_softc *)self; + struct mii_attach_args *ma = aux; + struct mii_data *mii = ma->mii_data; + + printf(": %s, rev. %d\n", MII_STR_LEVEL1_LXT970, + MII_REV(ma->mii_id2)); + + sc->mii_inst = mii->mii_instance; + sc->mii_phy = ma->mii_phyno; + sc->mii_service = lxtphy_service; + sc->mii_pdata = mii; + +#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) + + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), + BMCR_ISO); + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), + BMCR_LOOP|BMCR_S100); + + mii_phy_reset(sc); + + sc->mii_capabilities = + PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + printf("%s: ", sc->mii_dev.dv_xname); + if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) + printf("no media present"); + else + mii_add_media(mii, sc->mii_capabilities, + sc->mii_inst); + printf("\n"); +#undef ADD +} + +int +lxtphy_service(sc, mii, cmd) + struct mii_softc *sc; + struct mii_data *mii; + int cmd; +{ + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; + int reg; + + switch (cmd) { + case MII_POLLSTAT: + /* + * If we're not polling our PHY instance, just return. + */ + if (IFM_INST(ife->ifm_media) != sc->mii_inst) + return (0); + break; + + case MII_MEDIACHG: + /* + * If the media indicates a different PHY instance, + * isolate ourselves. + */ + if (IFM_INST(ife->ifm_media) != sc->mii_inst) { + reg = PHY_READ(sc, MII_BMCR); + PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); + return (0); + } + + /* + * If the interface is not up, don't do anything. + */ + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) + break; + + switch (IFM_SUBTYPE(ife->ifm_media)) { + case IFM_AUTO: + /* + * If we're already in auto mode, just return. + */ + if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) + return (0); + (void) mii_phy_auto(sc); + break; + case IFM_100_T4: + /* + * XXX Not supported as a manual setting right now. + */ + return (EINVAL); + default: + /* + * BMCR data is stored in the ifmedia entry. + */ + PHY_WRITE(sc, MII_ANAR, + mii_anar(ife->ifm_media)); + PHY_WRITE(sc, MII_BMCR, ife->ifm_data); + } + break; + + case MII_TICK: + /* + * If we're not currently selected, just return. + */ + if (IFM_INST(ife->ifm_media) != sc->mii_inst) + return (0); + + /* + * Only used for autonegotiation. + */ + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + return (0); + + /* + * Is the interface even up? + */ + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) + return (0); + + /* + * Check to see if we have link. If we do, we don't + * need to restart the autonegotiation process. Use + * the LXT CSR instead of the BMSR, since the CSR's + * link indication is dynamic, not latched, so only + * one register read is required. + */ + reg = PHY_READ(sc, MII_LXTPHY_CSR); + if (reg & CSR_LINK) + return (0); + + /* + * Only retry autonegotiation every 5 seconds. + */ + if (++sc->mii_ticks != 5) + return (0); + + sc->mii_ticks = 0; + mii_phy_reset(sc); + (void) mii_phy_auto(sc); + break; + } + + /* Update the media status. */ + lxtphy_status(sc); + + /* Callback if something changed. */ + if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { + (*mii->mii_statchg)(sc->mii_dev.dv_parent); + sc->mii_active = mii->mii_media_active; + } + return (0); +} + +void +lxtphy_status(sc) + struct mii_softc *sc; +{ + struct mii_data *mii = sc->mii_pdata; + int bmcr, 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) { + if ((csr & CSR_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; + } else + mii->mii_media_active = mii_media_from_bmcr(bmcr); +} diff --git a/sys/dev/mii/lxtphyreg.h b/sys/dev/mii/lxtphyreg.h new file mode 100644 index 00000000000..f78e454fb73 --- /dev/null +++ b/sys/dev/mii/lxtphyreg.h @@ -0,0 +1,89 @@ +/* $OpenBSD: lxtphyreg.h,v 1.1 1998/11/11 19:34:47 jason Exp $ */ +/* $NetBSD: lxtphyreg.h,v 1.1 1998/10/24 00:33:17 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. + * + * 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 the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 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. + */ + +#ifndef _DEV_MII_LXTPHYREG_H_ +#define _DEV_MII_LXTPHYREG_H_ + +/* + * LXT970 registers. + */ + +#define MII_LXTPHY_MIRROR 0x10 /* Mirror register */ + /* All bits user-defined */ + +#define MII_LXTPHY_IER 0x11 /* Interrupt Enable Register */ +#define IER_MIIDRVLVL 0x0008 /* Rediced MII driver levels */ +#define IER_LNK_CRITERIA 0x0004 /* Enhanced Link Loss Criteria */ +#define IER_INTEN 0x0002 /* Interrupt Enable */ +#define IER_TINT 0x0001 /* Force Interrupt */ + +#define MII_LXTPHY_ISR 0x12 /* Interrupt Status Register */ +#define ISR_MINT 0x8000 /* MII Interrupt Pending */ +#define ISR_XTALOK 0x4000 /* Clocks OK */ + +#define MII_LXTPHY_CONFIG 0x13 /* Configuration Register */ +#define CONFIG_TXMIT_TEST 0x4000 /* 100base-T Transmit Test */ +#define CONFIG_REPEATER 0x2000 /* Repeater Mode */ +#define CONFIG_MDIO_INT 0x1000 /* Enable intr signalling on MDIO */ +#define CONFIG_TPLOOP 0x0800 /* Disable 10base-T Loopback */ +#define CONFIG_SQE 0x0400 /* Enable SQE */ +#define CONFIG_DISJABBER 0x0200 /* Disable Jabber */ +#define CONFIG_DISLINKTEST 0x0100 /* Disable Link Test */ +#define CONFIG_LEDC1 0x0080 /* LEDC configuration */ +#define CONFIG_LEDC0 0x0040 /* ... */ + /* 0 0 LEDC indicates collision */ + /* 0 1 LEDC is off */ + /* 1 0 LEDC indicates activity */ + /* 1 1 LEDC is on */ +#define CONFIG_ADVTXCLK 0x0020 /* Advance TX clock */ +#define CONFIG_5BSYMBOL 0x0010 /* 5-bit Symbol mode */ +#define CONFIG_SCRAMBLER 0x0008 /* Bypass scrambler */ +#define CONFIG_100BASEFX 0x0004 /* 100base-FX */ +#define CONFIG_TXDISCON 0x0001 /* Disconnect TP transmitter */ + +#define MII_LXTPHY_CSR 0x14 /* Chip Status Register */ +#define CSR_LINK 0x2000 /* Link is up */ +#define CSR_DUPLEX 0x1000 /* Full-duplex */ +#define CSR_SPEED 0x0800 /* 100Mbps */ +#define CSR_ACOMP 0x0400 /* Autonegotiation complete */ +#define CSR_PAGERCVD 0x0200 /* Link page received */ +#define CSR_LOWVCC 0x0004 /* Low Voltage Fault */ + +#endif /* _DEV_MII_LXTPHYREG_H_ */ diff --git a/sys/dev/mii/mii.c b/sys/dev/mii/mii.c index 40cc6e12194..1bec2fc803e 100644 --- a/sys/dev/mii/mii.c +++ b/sys/dev/mii/mii.c @@ -1,5 +1,5 @@ -/* $OpenBSD: mii.c,v 1.1 1998/09/10 17:17:33 jason Exp $ */ -/* $NetBSD: mii.c,v 1.7 1998/08/11 00:41:44 thorpej Exp $ */ +/* $OpenBSD: mii.c,v 1.2 1998/11/11 19:34:47 jason Exp $ */ +/* $NetBSD: mii.c,v 1.9 1998/11/05 04:08:02 thorpej Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -131,7 +131,7 @@ mii_print(aux, pnp) struct mii_attach_args *ma = aux; if (pnp != NULL) - printf("PHY oui 0x%x model 0x%x rev 0x%x at %s", + printf("OUI 0x%06x model 0x%04x rev %d at %s", MII_OUI(ma->mii_id1, ma->mii_id2), MII_MODEL(ma->mii_id2), MII_REV(ma->mii_id2), pnp); @@ -197,6 +197,25 @@ mii_anar(media) } /* + * Given a BMCR value, return the corresponding ifmedia word. + */ +int +mii_media_from_bmcr(bmcr) + int bmcr; +{ + int rv = IFM_ETHER; + + if (bmcr & BMCR_S100) + rv |= IFM_100_TX; + else + rv |= IFM_10_T; + if (bmcr & IFM_FDX) + rv |= IFM_FDX; + + return (rv); +} + +/* * Media changed; notify all PHYs. */ int diff --git a/sys/dev/mii/mii_physubr.c b/sys/dev/mii/mii_physubr.c new file mode 100644 index 00000000000..4d7ee6dd5fd --- /dev/null +++ b/sys/dev/mii/mii_physubr.c @@ -0,0 +1,102 @@ +/* $OpenBSD: mii_physubr.c,v 1.1 1998/11/11 19:34:47 jason Exp $ */ +/* $NetBSD: mii_physubr.c,v 1.2 1998/11/04 23:28:15 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. + * + * 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 the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 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. + */ + +/* + * Subroutines common to all PHYs. + */ + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/systm.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_media.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> + +int +mii_phy_auto(mii) + struct mii_softc *mii; +{ + int bmsr, i; + + PHY_WRITE(mii, MII_ANAR, + BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA); + PHY_WRITE(mii, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); + + /* Wait 500ms for it to complete. */ + for (i = 0; i < 500; i++) { + if ((bmsr = PHY_READ(mii, MII_BMSR)) & BMSR_ACOMP) + return (1); + delay(1000); + } +#if 0 + if ((bmsr & BMSR_ACOMP) == 0) + printf("%s: autonegotiation failed to complete\n", + mii->mii_dev.dv_xname); +#endif + return (0); +} + +void +mii_phy_reset(mii) + struct mii_softc *mii; +{ + int reg, i; + + if (mii->mii_flags & MIIF_NOISOLATE) + reg = BMCR_RESET; + else + reg = BMCR_RESET | BMCR_ISO; + PHY_WRITE(mii, MII_BMCR, reg); + + /* Wait 100ms for it to complete. */ + for (i = 0; i < 100; i++) { + reg = PHY_READ(mii, MII_BMCR); + if ((reg & BMCR_RESET) == 0) + break; + delay(1000); + } + + if (mii->mii_inst != 0 && ((mii->mii_flags & MIIF_NOISOLATE) == 0)) + PHY_WRITE(mii, MII_BMCR, reg | BMCR_ISO); +} diff --git a/sys/dev/mii/miivar.h b/sys/dev/mii/miivar.h index e25a1d354f8..be716d91b86 100644 --- a/sys/dev/mii/miivar.h +++ b/sys/dev/mii/miivar.h @@ -1,5 +1,5 @@ -/* $OpenBSD: miivar.h,v 1.1 1998/09/10 17:17:34 jason Exp $ */ -/* $NetBSD: miivar.h,v 1.1 1998/08/10 23:55:18 thorpej Exp $ */ +/* $OpenBSD: miivar.h,v 1.2 1998/11/11 19:34:48 jason Exp $ */ +/* $NetBSD: miivar.h,v 1.7 1998/11/05 04:08:02 thorpej Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -100,7 +100,7 @@ typedef int (*mii_downcall_t) __P((struct mii_softc *, struct mii_data *, int)); /* * Requests that can be made to the downcall. */ -#define MII_TICK 1 +#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 */ @@ -119,9 +119,17 @@ struct mii_softc { mii_downcall_t mii_service; /* our downcall */ struct mii_data *mii_pdata; /* pointer to parent's mii_data */ + + int mii_flags; /* misc. flags; see below */ + int mii_capabilities; /* capabilities from BMSR */ + int mii_ticks; /* MII_TICK counter */ + int mii_active; /* last active media */ }; typedef struct mii_softc mii_softc_t; +/* mii_flags */ +#define MIIF_NOISOLATE 0x0001 /* do not isolate the PHY */ + /* * Used to attach a PHY to a parent. */ @@ -136,12 +144,27 @@ typedef struct mii_attach_args mii_attach_args_t; #ifdef _KERNEL +#define PHY_READ(p, r) \ + (*(p)->mii_pdata->mii_readreg)((p)->mii_dev.dv_parent, \ + (p)->mii_phy, (r)) + +#define PHY_WRITE(p, r, v) \ + (*(p)->mii_pdata->mii_writereg)((p)->mii_dev.dv_parent, \ + (p)->mii_phy, (r), (v)) + int mii_anar __P((int)); int mii_mediachg __P((struct mii_data *)); void mii_tick __P((struct mii_data *)); void mii_pollstat __P((struct mii_data *)); void mii_phy_probe __P((struct device *, struct mii_data *, int)); void mii_add_media __P((struct mii_data *, int, int)); + +int mii_media_from_bmcr __P((int)); + +int mii_phy_auto __P((struct mii_softc *)); +void mii_phy_reset __P((struct mii_softc *)); + +void ukphy_status __P((struct mii_softc *)); #endif /* _KERNEL */ #endif /* _DEV_MII_MIIVAR_H_ */ diff --git a/sys/dev/mii/nsphy.c b/sys/dev/mii/nsphy.c index ee9430df8ae..73eba605f97 100644 --- a/sys/dev/mii/nsphy.c +++ b/sys/dev/mii/nsphy.c @@ -1,5 +1,5 @@ -/* $OpenBSD: nsphy.c,v 1.1 1998/09/10 17:17:34 jason Exp $ */ -/* $NetBSD: nsphy.c,v 1.9 1998/08/14 00:23:26 thorpej Exp $ */ +/* $OpenBSD: nsphy.c,v 1.2 1998/11/11 19:34:48 jason Exp $ */ +/* $NetBSD: nsphy.c,v 1.16 1998/11/05 04:08:02 thorpej Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -88,13 +88,6 @@ #include <dev/mii/nsphyreg.h> -struct nsphy_softc { - struct mii_softc sc_mii; /* generic PHY */ - int sc_capabilities; - int sc_ticks; - int sc_active; -}; - #ifdef __NetBSD__ int nsphymatch __P((struct device *, struct cfdata *, void *)); #else @@ -103,7 +96,7 @@ int nsphymatch __P((struct device *, void *, void *)); void nsphyattach __P((struct device *, struct device *, void *)); struct cfattach nsphy_ca = { - sizeof(struct nsphy_softc), nsphymatch, nsphyattach + sizeof(struct mii_softc), nsphymatch, nsphyattach }; #ifdef __OpenBSD__ @@ -112,18 +105,8 @@ struct cfdriver nsphy_cd = { }; #endif -#define NSPHY_READ(sc, reg) \ - (*(sc)->sc_mii.mii_pdata->mii_readreg)((sc)->sc_mii.mii_dev.dv_parent, \ - (sc)->sc_mii.mii_phy, (reg)) - -#define NSPHY_WRITE(sc, reg, val) \ - (*(sc)->sc_mii.mii_pdata->mii_writereg)((sc)->sc_mii.mii_dev.dv_parent, \ - (sc)->sc_mii.mii_phy, (reg), (val)) - int nsphy_service __P((struct mii_softc *, struct mii_data *, int)); -void nsphy_reset __P((struct nsphy_softc *)); -void nsphy_auto __P((struct nsphy_softc *)); -void nsphy_status __P((struct nsphy_softc *)); +void nsphy_status __P((struct mii_softc *)); int nsphymatch(parent, match, aux) @@ -139,7 +122,7 @@ nsphymatch(parent, match, aux) if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_NATSEMI && MII_MODEL(ma->mii_id2) == MII_MODEL_NATSEMI_DP83840) - return (1); + return (10); return (0); } @@ -150,47 +133,56 @@ nsphyattach(parent, self, aux) struct device *self; void *aux; { - struct nsphy_softc *sc = (struct nsphy_softc *)self; + struct mii_softc *sc = (struct mii_softc *)self; struct mii_attach_args *ma = aux; struct mii_data *mii = ma->mii_data; printf(": %s, rev. %d\n", MII_STR_NATSEMI_DP83840, MII_REV(ma->mii_id2)); - sc->sc_mii.mii_inst = mii->mii_instance; - sc->sc_mii.mii_phy = ma->mii_phyno; - sc->sc_mii.mii_service = nsphy_service; - sc->sc_mii.mii_pdata = mii; + sc->mii_inst = mii->mii_instance; + sc->mii_phy = ma->mii_phyno; + sc->mii_service = nsphy_service; + sc->mii_pdata = mii; + + /* + * i82557 wedges if all of its PHYs are isolated! + */ + if (strcmp(parent->dv_cfdata->cf_driver->cd_name, "fxp") == 0 && + mii->mii_instance == 0) + sc->mii_flags |= MIIF_NOISOLATE; #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) #if 0 /* Can't do this on the i82557! */ - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->sc_mii.mii_inst), + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), BMCR_ISO); #endif - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->sc_mii.mii_inst), + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), BMCR_LOOP|BMCR_S100); - nsphy_reset(sc); + mii_phy_reset(sc); - sc->sc_capabilities = NSPHY_READ(sc, MII_BMSR) & ma->mii_capmask; - printf("%s: ", sc->sc_mii.mii_dev.dv_xname); - if ((sc->sc_capabilities & BMSR_MEDIAMASK) == 0) + sc->mii_capabilities = + PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + printf("%s: ", sc->mii_dev.dv_xname); + if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) printf("no media present"); else - mii_add_media(mii, sc->sc_capabilities, sc->sc_mii.mii_inst); + mii_add_media(mii, sc->mii_capabilities, + sc->mii_inst); printf("\n"); #undef ADD } int -nsphy_service(self, mii, cmd) - struct mii_softc *self; +nsphy_service(sc, mii, cmd) + struct mii_softc *sc; struct mii_data *mii; int cmd; { - struct nsphy_softc *sc = (struct nsphy_softc *)self; + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int reg; switch (cmd) { @@ -198,8 +190,7 @@ nsphy_service(self, mii, cmd) /* * If we're not polling our PHY instance, just return. */ - if (IFM_INST(mii->mii_media.ifm_media) != - sc->sc_mii.mii_inst) + if (IFM_INST(ife->ifm_media) != sc->mii_inst) return (0); break; @@ -208,10 +199,9 @@ nsphy_service(self, mii, cmd) * If the media indicates a different PHY instance, * isolate ourselves. */ - if (IFM_INST(mii->mii_media.ifm_media) != - sc->sc_mii.mii_inst) { - reg = NSPHY_READ(sc, MII_BMCR); - NSPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); + if (IFM_INST(ife->ifm_media) != sc->mii_inst) { + reg = PHY_READ(sc, MII_BMCR); + PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); return (0); } @@ -221,7 +211,7 @@ nsphy_service(self, mii, cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - reg = NSPHY_READ(sc, MII_NSPHY_PCR); + reg = PHY_READ(sc, MII_NSPHY_PCR); /* * Set up the PCR to use LED4 to indicate full-duplex @@ -252,16 +242,16 @@ nsphy_service(self, mii, cmd) reg |= 0x0100 | 0x0400; #endif - NSPHY_WRITE(sc, MII_NSPHY_PCR, reg); + PHY_WRITE(sc, MII_NSPHY_PCR, reg); - switch (IFM_SUBTYPE(mii->mii_media.ifm_media)) { + switch (IFM_SUBTYPE(ife->ifm_media)) { case IFM_AUTO: /* * If we're already in auto mode, just return. */ - if (NSPHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) + if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) return (0); - nsphy_auto(sc); + (void) mii_phy_auto(sc); break; case IFM_100_T4: /* @@ -272,10 +262,9 @@ nsphy_service(self, mii, cmd) /* * BMCR data is stored in the ifmedia entry. */ - NSPHY_WRITE(sc, MII_ANAR, - mii_anar(mii->mii_media.ifm_media)); - NSPHY_WRITE(sc, MII_BMCR, - mii->mii_media.ifm_cur->ifm_data); + PHY_WRITE(sc, MII_ANAR, + mii_anar(ife->ifm_media)); + PHY_WRITE(sc, MII_BMCR, ife->ifm_data); } break; @@ -283,14 +272,13 @@ nsphy_service(self, mii, cmd) /* * If we're not currently selected, just return. */ - if (IFM_INST(mii->mii_media.ifm_media) != - sc->sc_mii.mii_inst) + if (IFM_INST(ife->ifm_media) != sc->mii_inst) return (0); /* * Only used for autonegotiation. */ - if (IFM_SUBTYPE(mii->mii_media.ifm_media) != IFM_AUTO) + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) return (0); /* @@ -304,19 +292,20 @@ nsphy_service(self, mii, cmd) * need to restart the autonegotiation process. Read * the BMSR twice in case it's latched. */ - reg = NSPHY_READ(sc, MII_BMSR) | NSPHY_READ(sc, MII_BMSR); + reg = PHY_READ(sc, MII_BMSR) | + PHY_READ(sc, MII_BMSR); if (reg & BMSR_LINK) return (0); /* * Only retry autonegotiation every 5 seconds. */ - if (++sc->sc_ticks != 5) + if (++sc->mii_ticks != 5) return (0); - sc->sc_ticks = 0; - nsphy_reset(sc); - nsphy_auto(sc); + sc->mii_ticks = 0; + mii_phy_reset(sc); + (void) mii_phy_auto(sc); break; } @@ -324,28 +313,29 @@ nsphy_service(self, mii, cmd) nsphy_status(sc); /* Callback if something changed. */ - if (sc->sc_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - (*mii->mii_statchg)(sc->sc_mii.mii_dev.dv_parent); - sc->sc_active = mii->mii_media_active; + if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { + (*mii->mii_statchg)(sc->mii_dev.dv_parent); + sc->mii_active = mii->mii_media_active; } return (0); } void nsphy_status(sc) - struct nsphy_softc *sc; + struct mii_softc *sc; { - struct mii_data *mii = sc->sc_mii.mii_pdata; + struct mii_data *mii = sc->mii_pdata; int bmsr, bmcr, par, anlpar; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; - bmsr = NSPHY_READ(sc, MII_BMSR) | NSPHY_READ(sc, MII_BMSR); + bmsr = PHY_READ(sc, MII_BMSR) | + PHY_READ(sc, MII_BMSR); if (bmsr & BMSR_LINK) mii->mii_media_status |= IFM_ACTIVE; - bmcr = NSPHY_READ(sc, MII_BMCR); + bmcr = PHY_READ(sc, MII_BMCR); if (bmcr & BMCR_ISO) { mii->mii_media_active |= IFM_NONE; mii->mii_media_status = 0; @@ -371,9 +361,9 @@ nsphy_status(sc) * properly! Determine media based on link partner's * advertised capabilities. */ - if (NSPHY_READ(sc, MII_ANER) & ANER_LPAN) { - anlpar = NSPHY_READ(sc, MII_ANAR) & - NSPHY_READ(sc, MII_ANLPAR); + if (PHY_READ(sc, MII_ANER) & ANER_LPAN) { + anlpar = PHY_READ(sc, MII_ANAR) & + PHY_READ(sc, MII_ANLPAR); if (anlpar & ANLPAR_T4) mii->mii_media_active |= IFM_100_T4; else if (anlpar & ANLPAR_TX_FD) @@ -394,7 +384,7 @@ nsphy_status(sc) * We will never be in full-duplex mode if this is * the case, so reading the PAR is OK. */ - par = NSPHY_READ(sc, MII_NSPHY_PAR); + par = PHY_READ(sc, MII_NSPHY_PAR); if (par & PAR_10) mii->mii_media_active |= IFM_10_T; else @@ -403,62 +393,6 @@ nsphy_status(sc) if (par & PAR_FDX) mii->mii_media_active |= IFM_FDX; #endif - } else { - if (bmcr & BMCR_S100) - mii->mii_media_active |= IFM_100_TX; - else - mii->mii_media_active |= IFM_10_T; - if (bmcr & BMCR_FDX) - mii->mii_media_active |= IFM_FDX; - } -} - -void -nsphy_auto(sc) - struct nsphy_softc *sc; -{ - int bmsr, i; - - NSPHY_WRITE(sc, MII_ANAR, - BMSR_MEDIA_TO_ANAR(sc->sc_capabilities) | ANAR_CSMA); - NSPHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); - - /* Wait 500ms for it to complete. */ - for (i = 0; i < 500; i++) { - if ((bmsr = NSPHY_READ(sc, MII_BMSR)) & BMSR_ACOMP) - return; - delay(1000); - } -#if 0 - if ((bmsr & BMSR_ACOMP) == 0) - printf("%s: autonegotiation failed to complete\n", - sc->sc_mii.mii_dev.dv_xname); -#endif -} - -void -nsphy_reset(sc) - struct nsphy_softc *sc; -{ - int reg, i; - - /* - * The i82557 wedges if we isolate all of its PHYs! - */ - if (sc->sc_mii.mii_inst == 0) - NSPHY_WRITE(sc, MII_BMCR, BMCR_RESET); - else - NSPHY_WRITE(sc, MII_BMCR, BMCR_RESET|BMCR_ISO); - - /* Wait 100ms for it to complete. */ - for (i = 0; i < 100; i++) { - reg = NSPHY_READ(sc, MII_BMCR); - if ((reg & BMCR_RESET) == 0) - break; - delay(1000); - } - - /* Make sure the PHY is isolated. */ - if (sc->sc_mii.mii_inst != 0) - NSPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); + } else + mii->mii_media_active = mii_media_from_bmcr(bmcr); } diff --git a/sys/dev/mii/qsphy.c b/sys/dev/mii/qsphy.c index d199bd46256..5ac3f7f752e 100644 --- a/sys/dev/mii/qsphy.c +++ b/sys/dev/mii/qsphy.c @@ -1,5 +1,5 @@ -/* $OpenBSD: qsphy.c,v 1.1 1998/09/10 17:17:34 jason Exp $ */ -/* $NetBSD: qsphy.c,v 1.3 1998/08/12 20:56:37 thorpej Exp $ */ +/* $OpenBSD: qsphy.c,v 1.2 1998/11/11 19:34:48 jason Exp $ */ +/* $NetBSD: qsphy.c,v 1.11 1998/11/05 04:08:02 thorpej Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -88,12 +88,6 @@ #include <dev/mii/qsphyreg.h> -struct qsphy_softc { - struct mii_softc sc_mii; /* generic PHY */ - int sc_capabilities; - int sc_active; -}; - #ifdef __NetBSD__ int qsphymatch __P((struct device *, struct cfdata *, void *)); #else @@ -102,7 +96,7 @@ int qsphymatch __P((struct device *, void *, void *)); void qsphyattach __P((struct device *, struct device *, void *)); struct cfattach qsphy_ca = { - sizeof(struct qsphy_softc), qsphymatch, qsphyattach + sizeof(struct mii_softc), qsphymatch, qsphyattach }; #ifdef __OpenBSD__ @@ -111,18 +105,9 @@ struct cfdriver qsphy_cd = { }; #endif -#define QSPHY_READ(sc, reg) \ - (*(sc)->sc_mii.mii_pdata->mii_readreg)((sc)->sc_mii.mii_dev.dv_parent, \ - (sc)->sc_mii.mii_phy, (reg)) - -#define QSPHY_WRITE(sc, reg, val) \ - (*(sc)->sc_mii.mii_pdata->mii_writereg)((sc)->sc_mii.mii_dev.dv_parent, \ - (sc)->sc_mii.mii_phy, (reg), (val)) - int qsphy_service __P((struct mii_softc *, struct mii_data *, int)); -void qsphy_reset __P((struct qsphy_softc *)); -void qsphy_auto __P((struct qsphy_softc *)); -void qsphy_status __P((struct qsphy_softc *)); +void qsphy_reset __P((struct mii_softc *)); +void qsphy_status __P((struct mii_softc *)); int qsphymatch(parent, match, aux) @@ -138,7 +123,7 @@ qsphymatch(parent, match, aux) if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_QUALSEMI && MII_MODEL(ma->mii_id2) == MII_MODEL_QUALSEMI_QS6612) - return (1); + return (10); return (0); } @@ -148,44 +133,46 @@ qsphyattach(parent, self, aux) struct device *parent, *self; void *aux; { - struct qsphy_softc *sc = (struct qsphy_softc *)self; + struct mii_softc *sc = (struct mii_softc *)self; struct mii_attach_args *ma = aux; struct mii_data *mii = ma->mii_data; printf(": %s, rev. %d\n", MII_STR_QUALSEMI_QS6612, MII_REV(ma->mii_id2)); - sc->sc_mii.mii_inst = mii->mii_instance; - sc->sc_mii.mii_phy = ma->mii_phyno; - sc->sc_mii.mii_service = qsphy_service; - sc->sc_mii.mii_pdata = mii; + sc->mii_inst = mii->mii_instance; + sc->mii_phy = ma->mii_phyno; + sc->mii_service = qsphy_service; + sc->mii_pdata = mii; #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->sc_mii.mii_inst), + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), BMCR_ISO); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->sc_mii.mii_inst), + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), BMCR_LOOP|BMCR_S100); qsphy_reset(sc); - sc->sc_capabilities = QSPHY_READ(sc, MII_BMSR) & ma->mii_capmask; - printf("%s: ", sc->sc_mii.mii_dev.dv_xname); - if ((sc->sc_capabilities & BMSR_MEDIAMASK) == 0) + sc->mii_capabilities = + PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + printf("%s: ", sc->mii_dev.dv_xname); + if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) printf("no media present"); else - mii_add_media(mii, sc->sc_capabilities, sc->sc_mii.mii_inst); + mii_add_media(mii, sc->mii_capabilities, + sc->mii_inst); printf("\n"); #undef ADD } int -qsphy_service(self, mii, cmd) - struct mii_softc *self; +qsphy_service(sc, mii, cmd) + struct mii_softc *sc; struct mii_data *mii; int cmd; { - struct qsphy_softc *sc = (struct qsphy_softc *)self; + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int reg; switch (cmd) { @@ -193,8 +180,7 @@ qsphy_service(self, mii, cmd) /* * If we're not polling our PHY instance, just return. */ - if (IFM_INST(mii->mii_media.ifm_media) != - sc->sc_mii.mii_inst) + if (IFM_INST(ife->ifm_media) != sc->mii_inst) return (0); break; @@ -203,10 +189,9 @@ qsphy_service(self, mii, cmd) * If the media indicates a different PHY instance, * isolate ourselves. */ - if (IFM_INST(mii->mii_media.ifm_media) != - sc->sc_mii.mii_inst) { - reg = QSPHY_READ(sc, MII_BMCR); - QSPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); + if (IFM_INST(ife->ifm_media) != sc->mii_inst) { + reg = PHY_READ(sc, MII_BMCR); + PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); return (0); } @@ -216,14 +201,14 @@ qsphy_service(self, mii, cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - switch (IFM_SUBTYPE(mii->mii_media.ifm_media)) { + switch (IFM_SUBTYPE(ife->ifm_media)) { case IFM_AUTO: /* * If we're already in auto mode, just return. */ - if (QSPHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) + if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) return (0); - qsphy_auto(sc); + (void) mii_phy_auto(sc); break; case IFM_100_T4: /* @@ -234,10 +219,9 @@ qsphy_service(self, mii, cmd) /* * BMCR data is stored in the ifmedia entry. */ - QSPHY_WRITE(sc, MII_ANAR, - mii_anar(mii->mii_media.ifm_media)); - QSPHY_WRITE(sc, MII_BMCR, - mii->mii_media.ifm_cur->ifm_data); + PHY_WRITE(sc, MII_ANAR, + mii_anar(ife->ifm_media)); + PHY_WRITE(sc, MII_BMCR, ife->ifm_data); } break; @@ -245,14 +229,13 @@ qsphy_service(self, mii, cmd) /* * If we're not currently selected, just return. */ - if (IFM_INST(mii->mii_media.ifm_media) != - sc->sc_mii.mii_inst) + if (IFM_INST(ife->ifm_media) != sc->mii_inst) return (0); /* * Only used for autonegotiation. */ - if (IFM_SUBTYPE(mii->mii_media.ifm_media) != IFM_AUTO) + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) return (0); /* @@ -272,28 +255,29 @@ qsphy_service(self, mii, cmd) qsphy_status(sc); /* Callback if something changed. */ - if (sc->sc_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - (*mii->mii_statchg)(sc->sc_mii.mii_dev.dv_parent); - sc->sc_active = mii->mii_media_active; + if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { + (*mii->mii_statchg)(sc->mii_dev.dv_parent); + sc->mii_active = mii->mii_media_active; } return (0); } void qsphy_status(sc) - struct qsphy_softc *sc; + struct mii_softc *sc; { - struct mii_data *mii = sc->sc_mii.mii_pdata; + struct mii_data *mii = sc->mii_pdata; int bmsr, bmcr, pctl; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; - bmsr = QSPHY_READ(sc, MII_BMSR) | QSPHY_READ(sc, MII_BMSR); + bmsr = PHY_READ(sc, MII_BMSR) | + PHY_READ(sc, MII_BMSR); if (bmsr & BMSR_LINK) mii->mii_media_status |= IFM_ACTIVE; - bmcr = QSPHY_READ(sc, MII_BMCR); + bmcr = PHY_READ(sc, MII_BMCR); if (bmcr & BMCR_ISO) { mii->mii_media_active |= IFM_NONE; mii->mii_media_status = 0; @@ -303,78 +287,44 @@ qsphy_status(sc) if (bmcr & BMCR_LOOP) mii->mii_media_active |= IFM_LOOP; - if ((bmcr & BMCR_AUTOEN) && (bmsr & BMSR_ACOMP) == 0) { - /* Erg, still trying, I guess... */ - mii->mii_media_active |= IFM_NONE; - return; - } - - pctl = QSPHY_READ(sc, MII_QSPHY_PCTL) | QSPHY_READ(sc, MII_QSPHY_PCTL); - switch (pctl & PCTL_OPMASK) { - case PCTL_10_T: - mii->mii_media_active |= IFM_10_T; - 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; - 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; - break; - default: - /* Erg... this shouldn't happen. */ - mii->mii_media_active |= IFM_NONE; - break; - } -} - -void -qsphy_auto(sc) - struct qsphy_softc *sc; -{ - int bmsr, i; - - QSPHY_WRITE(sc, MII_ANAR, - BMSR_MEDIA_TO_ANAR(sc->sc_capabilities) | ANAR_CSMA); - QSPHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); - - /* Wait 500ms for it to complete. */ - for (i = 0; i < 500; i++) { - if ((bmsr = QSPHY_READ(sc, MII_BMSR)) & BMSR_ACOMP) + if (bmcr & BMCR_AUTOEN) { + if ((bmsr & BMSR_ACOMP) == 0) { + /* Erg, still trying, I guess... */ + mii->mii_media_active |= IFM_NONE; return; - delay(1000); - } -#if 0 - if ((bmsr & BMSR_ACOMP) == 0) - printf("%s: autonegotiation failed to complete\n", - sc->sc_mii.mii_dev.dv_xname); -#endif + } + pctl = PHY_READ(sc, MII_QSPHY_PCTL) | + PHY_READ(sc, MII_QSPHY_PCTL); + switch (pctl & PCTL_OPMASK) { + case PCTL_10_T: + mii->mii_media_active |= IFM_10_T; + 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; + 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; + break; + default: + /* Erg... this shouldn't happen. */ + mii->mii_media_active |= IFM_NONE; + break; + } + } else + mii->mii_media_active = mii_media_from_bmcr(bmcr); } void qsphy_reset(sc) - struct qsphy_softc *sc; + struct mii_softc *sc; { - int reg, i; - - QSPHY_WRITE(sc, MII_BMCR, BMCR_RESET|BMCR_ISO); - - /* Wait 100ms for it to complete. */ - for (i = 0; i < 100; i++) { - reg = QSPHY_READ(sc, MII_BMCR); - if ((reg & BMCR_RESET) == 0) - break; - delay(1000); - } - - /* Make sure the PHY is isolated. */ - if (sc->sc_mii.mii_inst != 0) - QSPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); - QSPHY_WRITE(sc, MII_QSPHY_IMASK, 0); + mii_phy_reset(sc); + PHY_WRITE(sc, MII_QSPHY_IMASK, 0); } diff --git a/sys/dev/mii/sqphy.c b/sys/dev/mii/sqphy.c new file mode 100644 index 00000000000..eecc2ec46ec --- /dev/null +++ b/sys/dev/mii/sqphy.c @@ -0,0 +1,319 @@ +/* $OpenBSD: sqphy.c,v 1.1 1998/11/11 19:34:49 jason Exp $ */ +/* $NetBSD: sqphy.c,v 1.8 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. + * + * 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 the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Manuel Bouyer. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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 Seeq 80220/80221 and 80223 10/100 ethernet PHYs + * datasheet from www.seeq.com + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_media.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> +#include <dev/mii/miidevs.h> + +#include <dev/mii/sqphyreg.h> + +#ifdef __NetBSD__ +int sqphymatch __P((struct device *, struct cfdata *, void *)); +#else +int sqphymatch __P((struct device *, void *, void *)); +#endif +void sqphyattach __P((struct device *, struct device *, void *)); + +struct cfattach sqphy_ca = { + sizeof(struct mii_softc), sqphymatch, sqphyattach +}; + +#ifdef __OpenBSD__ +struct cfdriver sqphy_cd = { + NULL, "sqphy", DV_DULL +}; +#endif + +int sqphy_service __P((struct mii_softc *, struct mii_data *, int)); +void sqphy_status __P((struct mii_softc *)); + +int +sqphymatch(parent, match, aux) + struct device *parent; +#ifdef __NetBSD__ + struct cfdata *match; +#else + void *match; +#endif + void *aux; +{ + struct mii_attach_args *ma = aux; + + if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_SEEQ && + MII_MODEL(ma->mii_id2) == MII_MODEL_SEEQ_80220) + return (10); + + return (0); +} + +void +sqphyattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct mii_softc *sc = (struct mii_softc *)self; + struct mii_attach_args *ma = aux; + struct mii_data *mii = ma->mii_data; + + printf(": %s, rev. %d\n", MII_STR_SEEQ_80220, + MII_REV(ma->mii_id2)); + + sc->mii_inst = mii->mii_instance; + sc->mii_phy = ma->mii_phyno; + sc->mii_service = sqphy_service; + sc->mii_pdata = mii; + +#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) + + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), + BMCR_ISO); + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), + BMCR_LOOP|BMCR_S100); + + mii_phy_reset(sc); + + sc->mii_capabilities = + PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + printf("%s: ", sc->mii_dev.dv_xname); + if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) + printf("no media present"); + else + mii_add_media(mii, sc->mii_capabilities, + sc->mii_inst); + printf("\n"); +#undef ADD +} + +int +sqphy_service(sc, mii, cmd) + struct mii_softc *sc; + struct mii_data *mii; + int cmd; +{ + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; + int reg; + + switch (cmd) { + case MII_POLLSTAT: + /* + * If we're not polling our PHY instance, just return. + */ + if (IFM_INST(ife->ifm_media) != sc->mii_inst) + return (0); + break; + + case MII_MEDIACHG: + /* + * If the media indicates a different PHY instance, + * isolate ourselves. + */ + if (IFM_INST(ife->ifm_media) != sc->mii_inst) { + reg = PHY_READ(sc, MII_BMCR); + PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); + return (0); + } + + /* + * If the interface is not up, don't do anything. + */ + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) + break; + + switch (IFM_SUBTYPE(ife->ifm_media)) { + case IFM_AUTO: + /* + * If we're already in auto mode, just return. + */ + if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) + return (0); + (void) mii_phy_auto(sc); + break; + case IFM_100_T4: + /* + * XXX Not supported as a manual setting right now. + */ + return (EINVAL); + default: + /* + * BMCR data is stored in the ifmedia entry. + */ + PHY_WRITE(sc, MII_ANAR, + mii_anar(ife->ifm_media)); + PHY_WRITE(sc, MII_BMCR, ife->ifm_data); + } + break; + + case MII_TICK: + /* + * If we're not currently selected, just return. + */ + if (IFM_INST(ife->ifm_media) != sc->mii_inst) + return (0); + + /* + * Only used for autonegotiation. + */ + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + return (0); + + /* + * Is the interface even up? + */ + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) + return (0); + + /* + * 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) + return (0); + + /* + * Only retry autonegotiation every 5 seconds. + */ + if (++sc->mii_ticks != 5) + return (0); + + sc->mii_ticks = 0; + mii_phy_reset(sc); + (void) mii_phy_auto(sc); + break; + } + + /* Update the media status. */ + sqphy_status(sc); + + /* Callback if something changed. */ + if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { + (*mii->mii_statchg)(sc->mii_dev.dv_parent); + sc->mii_active = mii->mii_media_active; + } + return (0); +} + +void +sqphy_status(sc) + struct mii_softc *sc; +{ + struct mii_data *mii = sc->mii_pdata; + int bmsr, bmcr, status; + + 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; + } + status = PHY_READ(sc, MII_SQPHY_STATUS); + if (status & STATUS_SPD_DET) + mii->mii_media_active |= IFM_100_TX; + else + mii->mii_media_active |= IFM_10_T; + if (status & STATUS_DPLX_DET) + mii->mii_media_active |= IFM_FDX; + } else + mii->mii_media_active = mii_media_from_bmcr(bmcr); +} diff --git a/sys/dev/mii/sqphyreg.h b/sys/dev/mii/sqphyreg.h new file mode 100644 index 00000000000..169c1de4c7e --- /dev/null +++ b/sys/dev/mii/sqphyreg.h @@ -0,0 +1,128 @@ +/* $OpenBSD: sqphyreg.h,v 1.1 1998/11/11 19:34:49 jason Exp $ */ +/* $NetBSD: sqphyreg.h,v 1.1 1998/11/03 23:51:29 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. + * + * 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 the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 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. + */ + +#ifndef _DEV_MII_SQPHYREG_H_ +#define _DEV_MII_SQPHYREG_H_ + +/* + * Seeq 80220 registers. + */ + +#define MII_SQPHY_CONFIG1 0x10 /* Configuration 1 Register */ +#define CONFIG1_LNK_DIS 0x8000 /* Link Detect Disable */ +#define CONFIG1_XMT_DIS 0x4000 /* TP Transmitter Disable */ +#define CONFIG1_XMT_PDN 0x2000 /* TP Transmitter Powerdown */ +#define CONFIG1_TXEN_CRS 0x1000 /* TX_EN to CRS Loopback Disable */ +#define CONFIG1_BYP_ENC 0x0800 /* Bypass Encoder */ +#define CONFIG1_BYP_SCR 0x0400 /* Bypass Scrambler */ +#define CONFIG1_UNSCR_DIS 0x0200 /* Unscr. Idle Reception Disable */ +#define CONFIG1_EQLZR 0x0100 /* Rx Equalizer Disable */ +#define CONFIG1_CABLE 0x0080 /* Cable: 1 = STP, 0 = UTP */ +#define CONFIG1_RLVL0 0x0040 /* Receive Level Adjust */ +#define CONFIG1_TLVL3 0x0020 /* Transmit output level adjust */ +#define CONFIG1_TLVL2 0x0010 +#define CONFIG1_TLVL1 0x0008 +#define CONFIG1_TLVL0 0x0004 +#define CONFIG1_TRF1 0x0002 /* Transmitter Rise/Fall Adjust */ +#define CONFIG1_TRF0 0x0001 + +#define MII_SQPHY_CONFIG2 0x11 /* Configuration 2 Register */ +#define CONFIG2_PLED3_1 0x8000 /* PLED3 configuration */ +#define CONFIG2_PLED3_0 0x4000 + /* 1 1 LINK100 (default) */ + /* 1 0 Blink */ + /* 0 1 On */ + /* 0 0 Off */ +#define CONFIG2_PLED2_1 0x2000 /* PLED2 configuration */ +#define CONFIG2_PLED2_0 0x1000 + /* 1 1 Activity (default) */ + /* 1 0 Blink */ + /* 0 1 On */ + /* 0 0 Off */ +#define CONFIG2_PLED1_1 0x0800 /* PLED1 configuration */ +#define CONFIG2_PLED1_0 0x0400 + /* 1 1 Full duplex (default) */ + /* 1 0 Blink */ + /* 0 1 On */ + /* 0 0 Off */ +#define CONFIG2_PLED0_1 0x0200 /* PLED0 configuration */ +#define CONFIG2_PLED0_0 0x0100 + /* 1 1 LINK10 (default) */ + /* 1 0 Blink */ + /* 0 1 On */ + /* 0 0 Off */ +#define CONFIG2_LED_DEF1 0x0080 /* LED Normal Function Select */ +#define CONFIG2_LED_DEF0 0x0040 +#define CONFIG2_APOL_DIS 0x0020 /* Auto Polarity Correct Disable */ +#define CONFIG2_JAB_DIS 0x0010 /* Jabber Disable */ +#define CONFIG2_MREG 0x0008 /* Multiple Register Access Enable */ +#define CONFIG2_INT_MDIO 0x0004 /* MDIO Interrupt when idle */ +#define CONFIG2_RJ_CFG 0x0002 /* R/J Configuration Select */ + +#define MII_SQPHY_STATUS 0x12 /* Status Output Register */ +#define STATUS_INT 0x8000 /* Interrupt Detect */ +#define STATUS_LNK_FAIL 0x4000 /* Link Fail */ +#define STATUS_LOSS_SYNC 0x2000 /* Descrabler lost synchronization */ +#define STATUS_CWRD 0x1000 /* Codeword Error */ +#define STATUS_SSD 0x0800 /* Start of Stream Error */ +#define STATUS_ESD 0x0400 /* End of Stream Error */ +#define STATUS_RPOL 0x0200 /* Reverse Polarity Detected */ +#define STATUS_JAB 0x0100 /* Jabber Detected */ +#define STATUS_SPD_DET 0x0080 /* 100Mbps */ +#define STATUS_DPLX_DET 0x0040 /* Full Duplex */ + +#define MII_SQPHY_MASK 0x13 /* Mask Register */ +#define MASK_INT 0x8000 /* mask INT */ +#define MASK_LNK_FAIL 0x4000 /* mask LNK_FAIL */ +#define MASK_LOSS_SYNC 0x2000 /* mask LOSS_SYNC */ +#define MASK_CWRD 0x1000 /* mask CWRD */ +#define MASK_SSD 0x0800 /* mask SSD */ +#define MASK_ESD 0x0400 /* mask ESD */ +#define MASK_RPOL 0x0200 /* mask RPOL */ +#define MASK_JAB 0x0100 /* mask JAB */ +#define MASK_SPD_DET 0x0080 /* mask SPD_DET */ +#define MASK_DPLX_DET 0x0040 /* mask DPLX_DET */ +#define MASK_ANEG_STS1 0x0020 /* mask ANEG_STS1 */ +#define MASK_ANEG_STS0 0x0010 /* mask ANEG_STS0 */ + +#define MII_SQPHY_RESERVED 0x14 /* Reserved Register */ + /* All bits must be 0 */ + +#endif /* _DEV_MII_SQPHYREG_H_ */ diff --git a/sys/dev/mii/tlphy.c b/sys/dev/mii/tlphy.c index 6ef3c6b5d80..18dcfab285e 100644 --- a/sys/dev/mii/tlphy.c +++ b/sys/dev/mii/tlphy.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tlphy.c,v 1.1 1998/09/10 17:17:34 jason Exp $ */ -/* $NetBSD: tlphy.c,v 1.10 1998/08/17 16:41:45 bouyer Exp $ */ +/* $OpenBSD: tlphy.c,v 1.2 1998/11/11 19:34:50 jason Exp $ */ +/* $NetBSD: tlphy.c,v 1.16 1998/11/05 00:19:32 thorpej Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -104,10 +104,7 @@ struct tlphy_softc { struct mii_softc sc_mii; /* generic PHY */ - int sc_capabilities; - int sc_ticks; int sc_tlphycap; - int sc_active; }; #ifdef __NetBSD__ @@ -127,16 +124,7 @@ struct cfattach tlphy_ca = { sizeof(struct tlphy_softc), tlphymatch, tlphyattach }; -#define TLPHY_READ(sc, reg) \ - (*(sc)->sc_mii.mii_pdata->mii_readreg)((sc)->sc_mii.mii_dev.dv_parent, \ - (sc)->sc_mii.mii_phy, (reg)) - -#define TLPHY_WRITE(sc, reg, val) \ - (*(sc)->sc_mii.mii_pdata->mii_writereg)((sc)->sc_mii.mii_dev.dv_parent, \ - (sc)->sc_mii.mii_phy, (reg), (val)) - int tlphy_service __P((struct mii_softc *, struct mii_data *, int)); -void tlphy_reset __P((struct tlphy_softc *)); void tlphy_auto __P((struct tlphy_softc *)); void tlphy_status __P((struct tlphy_softc *)); @@ -154,7 +142,7 @@ tlphymatch(parent, match, aux) if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_TI && MII_MODEL(ma->mii_id2) == MII_MODEL_TI_TLAN10T) - return (1); + return (10); return (0); } @@ -178,7 +166,7 @@ tlphyattach(parent, self, aux) sc->sc_mii.mii_service = tlphy_service; sc->sc_mii.mii_pdata = mii; - tlphy_reset(sc); + mii_phy_reset(&sc->sc_mii); /* * Note that if we're on a device that also supports 100baseTX, @@ -189,10 +177,10 @@ tlphyattach(parent, self, aux) */ sc->sc_tlphycap = tlsc->tl_product->tp_tlphymedia; if ((sc->sc_tlphycap & TLPHY_MEDIA_NO_10_T) == 0) - sc->sc_capabilities = - TLPHY_READ(sc, MII_BMSR) & ma->mii_capmask; + sc->sc_mii.mii_capabilities = + PHY_READ(&sc->sc_mii, MII_BMSR) & ma->mii_capmask; else - sc->sc_capabilities = 0; + sc->sc_mii.mii_capabilities = 0; #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) @@ -217,9 +205,10 @@ tlphyattach(parent, self, aux) PRINT("10base5/AUI"); } } - if (sc->sc_capabilities & BMSR_MEDIAMASK) { + if (sc->sc_mii.mii_capabilities & BMSR_MEDIAMASK) { printf(sep); - mii_add_media(mii, sc->sc_capabilities, sc->sc_mii.mii_inst); + mii_add_media(mii, sc->sc_mii.mii_capabilities, + sc->sc_mii.mii_inst); } else if ((sc->sc_tlphycap & (TLPHY_MEDIA_10_2 | TLPHY_MEDIA_10_5)) == 0) printf("no media present"); @@ -235,6 +224,7 @@ tlphy_service(self, mii, cmd) int cmd; { struct tlphy_softc *sc = (struct tlphy_softc *)self; + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int reg; switch (cmd) { @@ -242,8 +232,7 @@ tlphy_service(self, mii, cmd) /* * If we're not polling our PHY instance, just return. */ - if (IFM_INST(mii->mii_media.ifm_media) != - sc->sc_mii.mii_inst) + if (IFM_INST(ife->ifm_media) != sc->sc_mii.mii_inst) return (0); break; @@ -252,10 +241,9 @@ tlphy_service(self, mii, cmd) * If the media indicates a different PHY instance, * isolate ourselves. */ - if (IFM_INST(mii->mii_media.ifm_media) != - sc->sc_mii.mii_inst) { - reg = TLPHY_READ(sc, MII_BMCR); - TLPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); + if (IFM_INST(ife->ifm_media) != sc->sc_mii.mii_inst) { + reg = PHY_READ(&sc->sc_mii, MII_BMCR); + PHY_WRITE(&sc->sc_mii, MII_BMCR, reg | BMCR_ISO); return (0); } @@ -265,7 +253,7 @@ tlphy_service(self, mii, cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - switch (IFM_SUBTYPE(mii->mii_media.ifm_media)) { + switch (IFM_SUBTYPE(ife->ifm_media)) { case IFM_AUTO: /* * The ThunderLAN PHY doesn't self-configure after @@ -276,17 +264,16 @@ tlphy_service(self, mii, cmd) break; case IFM_10_2: case IFM_10_5: - TLPHY_WRITE(sc, MII_BMCR, 0); - TLPHY_WRITE(sc, MII_TLPHY_CTRL, CTRL_AUISEL); + PHY_WRITE(&sc->sc_mii, MII_BMCR, 0); + PHY_WRITE(&sc->sc_mii, MII_TLPHY_CTRL, CTRL_AUISEL); delay(100000); break; default: - TLPHY_WRITE(sc, MII_TLPHY_CTRL, 0); + PHY_WRITE(&sc->sc_mii, MII_TLPHY_CTRL, 0); delay(100000); - TLPHY_WRITE(sc, MII_ANAR, - mii_anar(mii->mii_media.ifm_media)); - TLPHY_WRITE(sc, MII_BMCR, - mii->mii_media.ifm_cur->ifm_data); + PHY_WRITE(&sc->sc_mii, MII_ANAR, + mii_anar(ife->ifm_media)); + PHY_WRITE(&sc->sc_mii, MII_BMCR, ife->ifm_data); } break; @@ -294,14 +281,13 @@ tlphy_service(self, mii, cmd) /* * If we're not currently selected, just return. */ - if (IFM_INST(mii->mii_media.ifm_media) != - sc->sc_mii.mii_inst) + if (IFM_INST(ife->ifm_media) != sc->sc_mii.mii_inst) return (0); /* * Only used for autonegotiation. */ - if (IFM_SUBTYPE(mii->mii_media.ifm_media) != IFM_AUTO) + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) return (0); /* @@ -317,18 +303,19 @@ tlphy_service(self, mii, cmd) * * XXX WHAT ABOUT CHECKING LINK ON THE BNC/AUI?! */ - reg = TLPHY_READ(sc, MII_BMSR) | TLPHY_READ(sc, MII_BMSR); + reg = PHY_READ(&sc->sc_mii, MII_BMSR) | + PHY_READ(&sc->sc_mii, MII_BMSR); if (reg & BMSR_LINK) return (0); /* * Only retry autonegotiation every 5 seconds. */ - if (++sc->sc_ticks != 5) + if (++sc->sc_mii.mii_ticks != 5) return (0); - sc->sc_ticks = 0; - tlphy_reset(sc); + sc->sc_mii.mii_ticks = 0; + mii_phy_reset(&sc->sc_mii); tlphy_auto(sc); break; } @@ -337,9 +324,10 @@ tlphy_service(self, mii, cmd) tlphy_status(sc); /* Callback if something changed. */ - if (sc->sc_active != mii->mii_media_active || cmd == MII_MEDIACHG) { + if (sc->sc_mii.mii_active != mii->mii_media_active || + cmd == MII_MEDIACHG) { (*mii->mii_statchg)(sc->sc_mii.mii_dev.dv_parent); - sc->sc_active = mii->mii_media_active; + sc->sc_mii.mii_active = mii->mii_media_active; } return (0); } @@ -355,14 +343,14 @@ tlphy_status(sc) mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; - bmcr = TLPHY_READ(sc, MII_BMCR); + 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 = TLPHY_READ(sc, MII_TLPHY_CTRL); + tlctrl = PHY_READ(&sc->sc_mii, MII_TLPHY_CTRL); if (tlctrl & CTRL_AUISEL) { if (sc->sc_tlphycap & TLPHY_MEDIA_10_2) mii->mii_media_active |= IFM_10_2; @@ -376,7 +364,8 @@ tlphy_status(sc) return; } - bmsr = TLPHY_READ(sc, MII_BMSR) | TLPHY_READ(sc, MII_BMSR); + 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; @@ -398,25 +387,10 @@ void tlphy_auto(sc) struct tlphy_softc *sc; { - int aner, anlpar, bmsr, i; - - TLPHY_WRITE(sc, MII_ANAR, - BMSR_MEDIA_TO_ANAR(sc->sc_capabilities) | ANAR_CSMA); - TLPHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); + int aner, anlpar; - /* Wait 500ms for it to complete. */ - for (i = 0; i < 500; i++) { - if ((bmsr = TLPHY_READ(sc, MII_BMSR)) & BMSR_ACOMP) - return; - delay(1000); - } - if ((bmsr & BMSR_ACOMP) == 0) { -#if 0 - printf("%s: autonegotiation failed to complete\n", - sc->sc_mii.mii_dev.dv_xname); -#endif + if (mii_phy_auto(&sc->sc_mii) == 0) goto dflt; - } /* * Grr, braindead ThunderLAN PHY doesn't self-configure @@ -424,12 +398,12 @@ tlphy_auto(sc) * based on the link partner status. */ - aner = TLPHY_READ(sc, MII_ANER); + aner = PHY_READ(&sc->sc_mii, MII_ANER); if (aner & ANER_LPAN) { - anlpar = TLPHY_READ(sc, MII_ANLPAR) & - TLPHY_READ(sc, MII_ANAR); + anlpar = PHY_READ(&sc->sc_mii, MII_ANLPAR) & + PHY_READ(&sc->sc_mii, MII_ANAR); if (anlpar & ANAR_10_FD) { - TLPHY_WRITE(sc, MII_BMCR, BMCR_FDX); + PHY_WRITE(&sc->sc_mii, MII_BMCR, BMCR_FDX); return; } } @@ -439,26 +413,5 @@ tlphy_auto(sc) * Just assume we're not in full-duplex mode. * XXX Check link and try AUI/BNC? */ - TLPHY_WRITE(sc, MII_BMCR, 0); -} - -void -tlphy_reset(sc) - struct tlphy_softc *sc; -{ - int reg, i; - - TLPHY_WRITE(sc, MII_BMCR, BMCR_RESET|BMCR_ISO); - - /* Wait 100ms for it to complete. */ - for (i = 0; i < 100; i++) { - reg = TLPHY_READ(sc, MII_BMCR); - if ((reg & BMCR_RESET) == 0) - break; - delay(1000); - } - - /* Make sure the PHY is isolated. */ - if (sc->sc_mii.mii_inst != 0) - TLPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); + PHY_WRITE(&sc->sc_mii, MII_BMCR, 0); } diff --git a/sys/dev/mii/ukphy.c b/sys/dev/mii/ukphy.c new file mode 100644 index 00000000000..a797a5e25b8 --- /dev/null +++ b/sys/dev/mii/ukphy.c @@ -0,0 +1,274 @@ +/* $OpenBSD: ukphy.c,v 1.1 1998/11/11 19:34:50 jason Exp $ */ +/* $NetBSD: ukphy.c,v 1.1 1998/11/05 00:36:48 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Manuel Bouyer. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 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 unknown PHYs + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_media.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> + +#ifdef __NetBSD__ +int ukphymatch __P((struct device *, struct cfdata *, void *)); +#else +int ukphymatch __P((struct device *, void *, void *)); +#endif +void ukphyattach __P((struct device *, struct device *, void *)); + +struct cfattach ukphy_ca = { + sizeof(struct mii_softc), ukphymatch, ukphyattach +}; + +#ifdef __OpenBSD__ +struct cfdriver ukphy_cd = { + NULL, "ukphy", DV_DULL +}; +#endif + +int ukphy_service __P((struct mii_softc *, struct mii_data *, int)); + +int +ukphymatch(parent, match, aux) + struct device *parent; +#ifdef __NetBSD__ + struct cfdata *match; +#else + void *match; +#endif + void *aux; +{ + + /* + * We know something is here, so always match at a low priority. + */ + return (1); +} + +void +ukphyattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct mii_softc *sc = (struct mii_softc *)self; + struct mii_attach_args *ma = aux; + struct mii_data *mii = ma->mii_data; + + printf(": Generic IEEE 802.3u media interface\n"); + printf("%s: OUI 0x%06x, model 0x%04x, rev. %d\n", + sc->mii_dev.dv_xname, MII_OUI(ma->mii_id1, ma->mii_id2), + MII_MODEL(ma->mii_id2), MII_REV(ma->mii_id2)); + + sc->mii_inst = mii->mii_instance; + sc->mii_phy = ma->mii_phyno; + sc->mii_service = ukphy_service; + sc->mii_pdata = mii; + +#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) + + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), + BMCR_ISO); +#if 0 + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), + BMCR_LOOP|BMCR_S100); +#endif + + mii_phy_reset(sc); + + sc->mii_capabilities = + PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + printf("%s: ", sc->mii_dev.dv_xname); + if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) + printf("no media present"); + else + mii_add_media(mii, sc->mii_capabilities, + sc->mii_inst); + printf("\n"); +#undef ADD +} + +int +ukphy_service(sc, mii, cmd) + struct mii_softc *sc; + struct mii_data *mii; + int cmd; +{ + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; + int reg; + + switch (cmd) { + case MII_POLLSTAT: + /* + * If we're not polling our PHY instance, just return. + */ + if (IFM_INST(ife->ifm_media) != sc->mii_inst) + return (0); + break; + + case MII_MEDIACHG: + /* + * If the media indicates a different PHY instance, + * isolate ourselves. + */ + if (IFM_INST(ife->ifm_media) != sc->mii_inst) { + reg = PHY_READ(sc, MII_BMCR); + PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); + return (0); + } + + /* + * If the interface is not up, don't do anything. + */ + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) + break; + + switch (IFM_SUBTYPE(ife->ifm_media)) { + case IFM_AUTO: + /* + * If we're already in auto mode, just return. + */ + if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) + return (0); + (void) mii_phy_auto(sc); + break; + case IFM_100_T4: + /* + * XXX Not supported as a manual setting right now. + */ + return (EINVAL); + default: + /* + * BMCR data is stored in the ifmedia entry. + */ + PHY_WRITE(sc, MII_ANAR, + mii_anar(ife->ifm_media)); + PHY_WRITE(sc, MII_BMCR, ife->ifm_data); + } + break; + + case MII_TICK: + /* + * If we're not currently selected, just return. + */ + if (IFM_INST(ife->ifm_media) != sc->mii_inst) + return (0); + + /* + * Only used for autonegotiation. + */ + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + return (0); + + /* + * Is the interface even up? + */ + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) + return (0); + + /* + * 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) + return (0); + + /* + * Only retry autonegotiation every 5 seconds. + */ + if (++sc->mii_ticks != 5) + return (0); + + sc->mii_ticks = 0; + mii_phy_reset(sc); + (void) mii_phy_auto(sc); + break; + } + + /* Update the media status. */ + ukphy_status(sc); + + /* Callback if something changed. */ + if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { + (*mii->mii_statchg)(sc->mii_dev.dv_parent); + sc->mii_active = mii->mii_media_active; + } + return (0); +} diff --git a/sys/dev/mii/ukphy_subr.c b/sys/dev/mii/ukphy_subr.c new file mode 100644 index 00000000000..d389507e3ad --- /dev/null +++ b/sys/dev/mii/ukphy_subr.c @@ -0,0 +1,113 @@ +/* $OpenBSD: ukphy_subr.c,v 1.1 1998/11/11 19:34:51 jason Exp $ */ +/* $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. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 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. + */ + +/* + * Subroutines shared by the ukphy driver and other PHY drivers. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/device.h> +#include <sys/malloc.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_media.h> + +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> + +/* + * Media status subroutine. If a PHY driver does media detection simply + * by decoding the NWay autonegotiation, use this routine. + */ +void +ukphy_status(phy) + struct mii_softc *phy; +{ + struct mii_data *mii = phy->mii_pdata; + 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; + } + + anlpar = PHY_READ(phy, MII_ANAR) & PHY_READ(phy, MII_ANLPAR); + if (anlpar & ANLPAR_T4) + mii->mii_media_active |= IFM_100_T4; + else if (anlpar & ANLPAR_TX_FD) + mii->mii_media_active |= IFM_100_TX|IFM_FDX; + else if (anlpar & ANLPAR_TX) + mii->mii_media_active |= IFM_100_TX; + else if (anlpar & ANLPAR_10_FD) + mii->mii_media_active |= IFM_10_T|IFM_FDX; + else if (anlpar & ANLPAR_10) + mii->mii_media_active |= IFM_10_T; + else + mii->mii_media_active |= IFM_NONE; + } else + mii->mii_media_active = mii_media_from_bmcr(bmcr); +} |