From 46ad174e411f5a43bfbf65811350a6fcc31d2d77 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Sun, 6 Aug 2006 10:32:23 +0000 Subject: [PATCH] Sync MII support with NetBSD/OpenBSD: - Standard conforming GMII support: 1) replace mii_media_add() with mii_phy_add_media(). 2) ukphy has generic GMII support now, thus retire nvphy. - Factor common code of PHY modules out into mii_physubr.c, noticably mii_phy_{set_media, tick, update}(). In order to support this refactoring: 1) mii_softc.{mii_reset,mii_status} funtion pointers are added, which are used to reset PHY modules and get PHY modules' status. 2) mii_softc.mii_anegticks is added, which is used by PHY modules to tell mii_phy_tick(), how often auto-negociation should happen. Two commonly used values are defined as MII_ANEGTICKS and MII_ANEGTICKS_GIGE. mii_softc.mii_anegticks is set to MII_ANEGTICKS by default. - Add mii_softc.mii_media_status and rename mii_softc.mii_active to mii_softc.mii_media_active. Now changes in either one of them will cause MIIBUS_STATCHG() being involked. - For PHY modules that utilize mii_phy_add_media(), ifmedia_entry.ifm_data no longer stores value of BMCR. It stores an index of mii_media_table[], which stores BMCR, ANAR and GTCR. - Replace slightly different PHY modules detach routines with ukphy_detach(). - Use OUI and MODEL id array + mii_phy_match() in PHY modules probe routines, instead of original large `if, else if' or `switch' code segment. - Support more OUIs and MODELs in individual PHY module. - Make the usage of `mii' and `sc' stack variable more consistent. `mii' refers to miibus softc, while `sc' refers to PHY module softc. - Nuke no longer used functions' definition and declaration. - Regen miidevs.h Following PHY modules were tested: acphy(dc), brgphy(bge), e1000phy(nv,sk), exphy(xl), inphy(fxp), rgephy(re), rlphy(rl), ruephy(rue), ukphy(nv,vr,...) MII generic code is mainly synced with NetBSD. Individual PHY modules are mainly synced with OpenBSD. Tested-by: swildner, corecode --- sys/conf/files | 3 +- sys/dev/netif/mii_layer/Makefile | 4 +- sys/dev/netif/mii_layer/acphy.c | 106 ++--- sys/dev/netif/mii_layer/amphy.c | 134 ++---- sys/dev/netif/mii_layer/brgphy.c | 436 ++++++++++++-------- sys/dev/netif/mii_layer/ciphy.c | 144 +++---- sys/dev/netif/mii_layer/ciphyreg.h | 14 +- sys/dev/netif/mii_layer/dcphy.c | 168 +++----- sys/dev/netif/mii_layer/e1000phy.c | 172 ++++---- sys/dev/netif/mii_layer/exphy.c | 83 +--- sys/dev/netif/mii_layer/inphy.c | 143 ++----- sys/dev/netif/mii_layer/inphyreg.h | 5 +- sys/dev/netif/mii_layer/lxtphy.c | 166 +++----- sys/dev/netif/mii_layer/mii.c | 44 +- sys/dev/netif/mii_layer/mii.h | 99 ++++- sys/dev/netif/mii_layer/mii_physubr.c | 563 +++++++++++++++++++------- sys/dev/netif/mii_layer/miidevs | 57 ++- sys/dev/netif/mii_layer/miidevs.h | 103 ++++- sys/dev/netif/mii_layer/miivar.h | 146 +++++-- sys/dev/netif/mii_layer/mlphy.c | 77 ++-- sys/dev/netif/mii_layer/nsgphy.c | 250 ++---------- sys/dev/netif/mii_layer/nsphy.c | 135 ++---- sys/dev/netif/mii_layer/nsphyreg.h | 4 +- sys/dev/netif/mii_layer/nvphy.c | 114 ------ sys/dev/netif/mii_layer/pnaphy.c | 111 ++--- sys/dev/netif/mii_layer/pnphy.c | 56 +-- sys/dev/netif/mii_layer/qsphy.c | 146 +++---- sys/dev/netif/mii_layer/rgephy.c | 101 +++-- sys/dev/netif/mii_layer/rlphy.c | 135 +++--- sys/dev/netif/mii_layer/ruephy.c | 73 +--- sys/dev/netif/mii_layer/tlphy.c | 92 ++--- sys/dev/netif/mii_layer/ukphy.c | 99 +---- sys/dev/netif/mii_layer/ukphy_subr.c | 45 +- sys/dev/netif/mii_layer/xmphy.c | 118 ++---- sys/net/if_media.h | 20 +- 35 files changed, 1923 insertions(+), 2243 deletions(-) delete mode 100644 sys/dev/netif/mii_layer/nvphy.c diff --git a/sys/conf/files b/sys/conf/files index 03501663f0..2ae61adf7d 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,5 +1,5 @@ # $FreeBSD: src/sys/conf/files,v 1.340.2.137 2003/06/04 17:10:30 sam Exp $ -# $DragonFly: src/sys/conf/files,v 1.132 2006/07/28 02:17:34 dillon Exp $ +# $DragonFly: src/sys/conf/files,v 1.133 2006/08/06 10:32:23 sephe Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -271,7 +271,6 @@ dev/netif/mii_layer/inphy.c optional miibus dev/netif/mii_layer/mlphy.c optional miibus dev/netif/mii_layer/nsphy.c optional miibus dev/netif/mii_layer/nsgphy.c optional miibus -dev/netif/mii_layer/nvphy.c optional miibus dev/netif/mii_layer/pnphy.c optional miibus dev/netif/mii_layer/pnaphy.c optional miibus dev/netif/mii_layer/tlphy.c optional miibus diff --git a/sys/dev/netif/mii_layer/Makefile b/sys/dev/netif/mii_layer/Makefile index 93c447571e..103b8d6983 100644 --- a/sys/dev/netif/mii_layer/Makefile +++ b/sys/dev/netif/mii_layer/Makefile @@ -1,12 +1,12 @@ # $FreeBSD: src/sys/modules/mii/Makefile,v 1.11.2.6 2001/06/18 18:49:12 wpaul Exp $ -# $DragonFly: src/sys/dev/netif/mii_layer/Makefile,v 1.8 2006/05/20 07:15:17 sephe Exp $ +# $DragonFly: src/sys/dev/netif/mii_layer/Makefile,v 1.9 2006/08/06 10:32:23 sephe Exp $ KMOD = miibus SRCS = mii.c mii_physubr.c ukphy.c ukphy_subr.c bus_if.h pci_if.h SRCS += miibus_if.h device_if.h miibus_if.c e1000phy.c exphy.c nsphy.c SRCS += mlphy.c tlphy.c rlphy.c amphy.c dcphy.c pnphy.c nsgphy.c SRCS += pnaphy.c brgphy.c xmphy.c inphy.c lxtphy.c qsphy.c acphy.c -SRCS += ruephy.c nvphy.c rgephy.c ciphy.c +SRCS += ruephy.c rgephy.c ciphy.c .include "./Makefile.miidevs" diff --git a/sys/dev/netif/mii_layer/acphy.c b/sys/dev/netif/mii_layer/acphy.c index 3739b50539..464b249db7 100644 --- a/sys/dev/netif/mii_layer/acphy.c +++ b/sys/dev/netif/mii_layer/acphy.c @@ -1,4 +1,6 @@ -/*- +/* $NetBSD: acphy.c,v 1.16 2006/03/29 07:05:24 thorpej Exp $ */ + +/* * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. * All rights reserved. * @@ -35,7 +37,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/acphy.c,v 1.2.2.2 2002/10/21 21:20:19 semenu Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/acphy.c,v 1.8 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/acphy.c,v 1.9 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -92,17 +94,24 @@ static int acphy_probe (device_t); static int acphy_attach (device_t); -static int acphy_detach (device_t); static device_method_t acphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, acphy_probe), DEVMETHOD(device_attach, acphy_attach), - DEVMETHOD(device_detach, acphy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; +static const struct mii_phydesc acphys[] = { + MII_PHYDESC(xxALTIMA, AC101), + MII_PHYDESC(xxALTIMA, AC101L), + MII_PHYDESC(xxALTIMA, AC_UNKNOWN), + MII_PHYDESC(xxALTIMA, Am79C875), + MII_PHYDESC_NULL +}; + static devclass_t acphy_devclass; static driver_t acphy_driver = { @@ -113,24 +122,22 @@ static driver_t acphy_driver = { DRIVER_MODULE(acphy, miibus, acphy_driver, acphy_devclass, 0, 0); -int acphy_service (struct mii_softc *, struct mii_data *, int); -void acphy_reset (struct mii_softc *); -void acphy_status (struct mii_softc *); +static int acphy_service(struct mii_softc *, struct mii_data *, int); +static void acphy_reset(struct mii_softc *); +static void acphy_status(struct mii_softc *); static int acphy_probe(device_t dev) { - struct mii_attach_args *ma; - - ma = device_get_ivars(dev); - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxALTIMA && - MII_MODEL(ma->mii_id2) == MII_MODEL_xxALTIMA_AC101) { - device_set_desc(dev, MII_STR_xxALTIMA_AC101); - } else - return (ENXIO); + struct mii_attach_args *ma = device_get_ivars(dev); + const struct mii_phydesc *mpd; - return (0); + mpd = mii_phy_match(ma, acphys); + if (mpd != NULL) { + device_set_desc(dev, mpd->mpd_name); + return (0); + } + return (ENXIO); } static int @@ -149,6 +156,7 @@ acphy_attach(device_t dev) sc->mii_inst = mii->mii_instance; sc->mii_service = acphy_service; + sc->mii_reset = acphy_reset; sc->mii_pdata = mii; sc->mii_flags |= MIIF_NOISOLATE; @@ -156,11 +164,12 @@ acphy_attach(device_t dev) mii->mii_instance++; - sc->mii_capabilities = - PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; device_printf(dev, " "); if (sc->mii_capabilities & BMSR_MEDIAMASK) - mii_add_media(sc, sc->mii_capabilities); + mii_phy_add_media(sc); + else + printf("no media present"); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); @@ -168,20 +177,6 @@ acphy_attach(device_t dev) } static int -acphy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); - - return(0); -} - -int acphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { struct ifmedia_entry *ife = mii->mii_media.ifm_cur; @@ -211,30 +206,7 @@ acphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - /* Wake & deisolate up if necessary */ - reg = PHY_READ(sc, MII_BMCR); - if (reg & (BMCR_ISO | BMCR_PDOWN)) - PHY_WRITE(sc, MII_BMCR, reg & ~(BMCR_ISO | BMCR_PDOWN)); - - 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, 1); - break; - - default: - /* - * BMCR data is stored in the ifmedia entry. - */ - PHY_WRITE(sc, MII_ANAR, - mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); - } + mii_phy_set_media(sc); break; case MII_TICK: @@ -260,19 +232,16 @@ acphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) acphy_status(sc); /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } -void +static void acphy_status(struct mii_softc *sc) { struct mii_data *mii = sc->mii_pdata; struct ifmedia_entry *ife = mii->mii_media.ifm_cur; - int bmsr, bmcr, diag; + int bmsr, bmcr; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; @@ -293,11 +262,14 @@ acphy_status(struct mii_softc *sc) mii->mii_media_active |= IFM_LOOP; if (bmcr & BMCR_AUTOEN) { + int diag; + if ((bmsr & BMSR_ACOMP) == 0) { /* Erg, still trying, I guess... */ mii->mii_media_active |= IFM_NONE; return; } + diag = PHY_READ(sc, MII_ACPHY_DIAG); if (diag & AC_DIAG_SPEED) mii->mii_media_active |= IFM_100_TX; @@ -306,14 +278,14 @@ acphy_status(struct mii_softc *sc) if (diag & AC_DIAG_DUPLEX) mii->mii_media_active |= IFM_FDX; - } else + } else { mii->mii_media_active = ife->ifm_media; + } } -void +static void acphy_reset(struct mii_softc *sc) { - mii_phy_reset(sc); PHY_WRITE(sc, MII_ACPHY_INT, 0); } diff --git a/sys/dev/netif/mii_layer/amphy.c b/sys/dev/netif/mii_layer/amphy.c index f7f1696ae5..5809b11ab7 100644 --- a/sys/dev/netif/mii_layer/amphy.c +++ b/sys/dev/netif/mii_layer/amphy.c @@ -1,3 +1,5 @@ +/* $OpenBSD: amphy.c,v 1.13 2005/05/27 08:04:15 brad Exp $ */ + /* * Copyright (c) 1997, 1998, 1999 * Bill Paul . All rights reserved. @@ -30,7 +32,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/amphy.c,v 1.2.2.2 2002/11/08 21:53:49 semenu Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/amphy.c,v 1.9 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/amphy.c,v 1.10 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -58,17 +60,24 @@ static int amphy_probe (device_t); static int amphy_attach (device_t); -static int amphy_detach (device_t); static device_method_t amphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, amphy_probe), DEVMETHOD(device_attach, amphy_attach), - DEVMETHOD(device_detach, amphy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; +static const struct mii_phydesc amphys[] = { + MII_PHYDESC(xxAMD, 79C873), + MII_PHYDESC(xxDAVICOM, DM9101), + MII_PHYDESC(DAVICOM, DM9102), + MII_PHYDESC(DAVICOM, DM9601), + MII_PHYDESC_NULL +}; + static devclass_t amphy_devclass; static driver_t amphy_driver = { @@ -79,28 +88,21 @@ static driver_t amphy_driver = { DRIVER_MODULE(amphy, miibus, amphy_driver, amphy_devclass, 0, 0); -int amphy_service (struct mii_softc *, struct mii_data *, int); -void amphy_status (struct mii_softc *); +static int amphy_service(struct mii_softc *, struct mii_data *, int); +static void amphy_status(struct mii_softc *); static int amphy_probe(device_t dev) { - struct mii_attach_args *ma; - - ma = device_get_ivars(dev); - - if ((MII_OUI(ma->mii_id1, ma->mii_id2) != MII_OUI_xxAMD || - MII_MODEL(ma->mii_id2) != MII_MODEL_xxAMD_79C873) && - (MII_OUI(ma->mii_id1, ma->mii_id2) != MII_OUI_xxDAVICOM || - MII_MODEL(ma->mii_id2) != MII_MODEL_xxDAVICOM_DM9101)) - return(ENXIO); - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxAMD) - device_set_desc(dev, MII_STR_xxAMD_79C873); - else if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxDAVICOM) - device_set_desc(dev, MII_STR_xxDAVICOM_DM9101); + struct mii_attach_args *ma = device_get_ivars(dev); + const struct mii_phydesc *mpd; - return(0); + mpd = mii_phy_match(ma, amphys); + if (mpd != NULL) { + device_set_desc(dev, mpd->mpd_name); + return (0); + } + return (ENXIO); } static int @@ -127,21 +129,20 @@ amphy_attach(device_t dev) #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); + MII_MEDIA_NONE); #if 0 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), - BMCR_LOOP|BMCR_S100); + MII_MEDIA_100_TX); #endif mii_phy_reset(sc); - sc->mii_capabilities = - PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; device_printf(dev, " "); if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) printf("no media present"); else - mii_add_media(sc, sc->mii_capabilities); + mii_phy_add_media(sc); printf("\n"); #undef ADD MIIBUS_MEDIAINIT(sc->mii_dev); @@ -149,21 +150,6 @@ amphy_attach(device_t dev) } static int -amphy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); - mii_phy_auto_stop(sc); - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); - - return(0); -} - -int amphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { struct ifmedia_entry *ife = mii->mii_media.ifm_cur; @@ -195,28 +181,7 @@ amphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - switch (IFM_SUBTYPE(ife->ifm_media)) { - case IFM_AUTO: - /* - * If we're already in auto mode, just return. - */ - if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) - return (0); - (void) mii_phy_auto(sc, 1); - break; - case IFM_100_T4: - /* - * XXX Not supported as a manual setting right now. - */ - return (EINVAL); - default: - /* - * BMCR data is stored in the ifmedia entry. - */ - PHY_WRITE(sc, MII_ANAR, - mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); - } + mii_phy_set_media(sc); break; case MII_TICK: @@ -226,39 +191,8 @@ amphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 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) + if (mii_phy_tick(sc) == EJUSTRETURN) return (0); - - /* - * Only retry autonegotiation every 5 seconds. - */ - if (++sc->mii_ticks != 5) - return (0); - - sc->mii_ticks = 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) - break; - - mii_phy_reset(sc); - if (mii_phy_auto(sc, 0) == EJUSTRETURN) - return(0); break; } @@ -266,14 +200,11 @@ amphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) amphy_status(sc); /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } -void +static void amphy_status(struct mii_softc *sc) { struct mii_data *mii = sc->mii_pdata; @@ -338,6 +269,7 @@ amphy_status(struct mii_softc *sc) mii->mii_media_active |= IFM_10_T|IFM_HDX; else if (par & DSCSR_10HDX) mii->mii_media_active |= IFM_10_T; - } else - mii->mii_media_active = mii_media_from_bmcr(bmcr); + } else { + mii->mii_media_active = mii->mii_media.ifm_cur->ifm_media; + } } diff --git a/sys/dev/netif/mii_layer/brgphy.c b/sys/dev/netif/mii_layer/brgphy.c index 3369021e53..7960d12dde 100644 --- a/sys/dev/netif/mii_layer/brgphy.c +++ b/sys/dev/netif/mii_layer/brgphy.c @@ -1,3 +1,5 @@ +/* $OpenBSD: brgphy.c,v 1.48 2006/05/20 23:03:53 brad Exp $ */ + /* * Copyright (c) 2000 * Bill Paul . All rights reserved. @@ -30,7 +32,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/brgphy.c,v 1.1.2.7 2003/05/11 18:00:55 ps Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/brgphy.c,v 1.12 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/brgphy.c,v 1.13 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -62,13 +64,36 @@ static int brgphy_probe(device_t); static int brgphy_attach(device_t); -static int brgphy_detach(device_t); + +static const struct mii_phydesc brgphys[] = { + MII_PHYDESC(xxBROADCOM, BCM5400), + MII_PHYDESC(xxBROADCOM, BCM5401), + MII_PHYDESC(xxBROADCOM, BCM5411), + MII_PHYDESC(xxBROADCOM, BCM5421), + MII_PHYDESC(xxBROADCOM, BCM54K2), + MII_PHYDESC(xxBROADCOM, BCM5462), + + MII_PHYDESC(xxBROADCOM, BCM5701), + MII_PHYDESC(xxBROADCOM, BCM5703), + MII_PHYDESC(xxBROADCOM, BCM5704), + MII_PHYDESC(xxBROADCOM, BCM5705), + + MII_PHYDESC(xxBROADCOM, BCM5714), + MII_PHYDESC(xxBROADCOM, BCM5750), + MII_PHYDESC(xxBROADCOM, BCM5752), + MII_PHYDESC(xxBROADCOM, BCM5780), + + MII_PHYDESC(xxBROADCOM, BCM5706C), + MII_PHYDESC(xxBROADCOM, BCM5708C), + + MII_PHYDESC_NULL +}; static device_method_t brgphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, brgphy_probe), DEVMETHOD(device_attach, brgphy_attach), - DEVMETHOD(device_detach, brgphy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; @@ -85,63 +110,30 @@ DRIVER_MODULE(brgphy, miibus, brgphy_driver, brgphy_devclass, 0, 0); static int brgphy_service(struct mii_softc *, struct mii_data *, int); static void brgphy_status(struct mii_softc *); -static int brgphy_mii_phy_auto(struct mii_softc *); +static int brgphy_mii_phy_auto(struct mii_softc *, int); static void brgphy_reset(struct mii_softc *); static void brgphy_loop(struct mii_softc *); -static void bcm5401_load_dspcode(struct mii_softc *); -static void bcm5411_load_dspcode(struct mii_softc *); -static void bcm5703_load_dspcode(struct mii_softc *); -static int brgphy_mii_model; + +static void brgphy_load_dspcode(struct mii_softc *); +static void brgphy_bcm5401_dspcode(struct mii_softc *); +static void brgphy_bcm5411_dspcode(struct mii_softc *); +static void brgphy_bcm5421_dspcode(struct mii_softc *); +static void brgphy_bcm54k2_dspcode(struct mii_softc *); +static void brgphy_bcm5703_dspcode(struct mii_softc *); +static void brgphy_bcm5704_dspcode(struct mii_softc *); +static void brgphy_bcm5750_dspcode(struct mii_softc *); static int brgphy_probe(device_t dev) { - struct mii_attach_args *ma; - - ma = device_get_ivars(dev); + struct mii_attach_args *ma = device_get_ivars(dev); + const struct mii_phydesc *mpd; - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM && - MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5400) { - device_set_desc(dev, MII_STR_xxBROADCOM_BCM5400); - return(0); - } - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM && - MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5401) { - device_set_desc(dev, MII_STR_xxBROADCOM_BCM5401); - return(0); - } - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM && - MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5411) { - device_set_desc(dev, MII_STR_xxBROADCOM_BCM5411); - return(0); - } - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM && - MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5701) { - device_set_desc(dev, MII_STR_xxBROADCOM_BCM5701); - return(0); - } - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM && - MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5703) { - device_set_desc(dev, MII_STR_xxBROADCOM_BCM5703); - return(0); - } - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM && - MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5704) { - device_set_desc(dev, MII_STR_xxBROADCOM_BCM5704); - return(0); - } - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM && - MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5705) { - device_set_desc(dev, MII_STR_xxBROADCOM_BCM5705); - return(0); + mpd = mii_phy_match(ma, brgphys); + if (mpd != NULL) { + device_set_desc(dev, mpd->mpd_name); + return (0); } - return(ENXIO); } @@ -151,7 +143,6 @@ brgphy_attach(device_t dev) struct mii_softc *sc; struct mii_attach_args *ma; struct mii_data *mii; - const char *sep = ""; sc = device_get_softc(dev); ma = device_get_ivars(dev); @@ -162,59 +153,41 @@ brgphy_attach(device_t dev) sc->mii_inst = mii->mii_instance; sc->mii_service = brgphy_service; + sc->mii_reset = brgphy_reset; sc->mii_pdata = mii; sc->mii_flags |= MIIF_NOISOLATE; mii->mii_instance++; + brgphy_reset(sc); + #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) -#define PRINT(s) printf("%s%s", sep, s); sep = ", " ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), - BMCR_ISO); + MII_MEDIA_NONE); #if 0 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), - BMCR_LOOP|BMCR_S100); + MII_MEDIA_100_TX); #endif - brgphy_mii_model = MII_MODEL(ma->mii_id2); - brgphy_reset(sc); +#undef ADD - sc->mii_capabilities = - PHY_READ(sc, MII_BMSR) & ma->mii_capmask; - device_printf(dev, " "); - if (sc->mii_capabilities & BMSR_MEDIAMASK) - mii_add_media(sc, (sc->mii_capabilities & ~BMSR_ANEG)); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst), - BRGPHY_BMCR_FDX); - PRINT(", 1000baseTX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst), 0); - PRINT("1000baseTX-FDX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0); - PRINT("auto"); + sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + if (sc->mii_capabilities & BMSR_EXTSTAT) + sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); + device_printf(dev, " "); + if ((sc->mii_capabilities & BMSR_MEDIAMASK) || + (sc->mii_extcapabilities & EXTSR_MEDIAMASK)) + mii_phy_add_media(sc); + else + printf("no media present"); printf("\n"); -#undef ADD -#undef PRINT MIIBUS_MEDIAINIT(sc->mii_dev); return(0); } -static int -brgphy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); - - return(0); -} - static int brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { @@ -258,7 +231,7 @@ brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if (PHY_READ(sc, BRGPHY_MII_BMCR) & BRGPHY_BMCR_AUTOEN) return (0); #endif - (void) brgphy_mii_phy_auto(sc); + brgphy_mii_phy_auto(sc, 1); break; case IFM_1000_T: speed = BRGPHY_S1000; @@ -288,7 +261,7 @@ setit: PHY_WRITE(sc, BRGPHY_MII_BMCR, speed|BRGPHY_BMCR_AUTOEN|BRGPHY_BMCR_STARTNEG); - if (brgphy_mii_model != MII_MODEL_xxBROADCOM_BCM5701) + if (sc->mii_model != MII_MODEL_xxBROADCOM_BCM5701) break; /* @@ -326,16 +299,16 @@ setit: return (0); /* - * Only used for autonegotiation. + * Is the interface even up? */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) return (0); /* - * Is the interface even up? + * Only used for autonegotiation. */ - if ((mii->mii_ifp->if_flags & IFF_UP) == 0) - return (0); + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + break; /* * Check to see if we have link. If we do, we don't @@ -349,12 +322,13 @@ setit: /* * Only retry autonegotiation every 5 seconds. */ - if (++sc->mii_ticks != 5) - return (0); + if (++sc->mii_ticks <= sc->mii_anegticks) + break; sc->mii_ticks = 0; - brgphy_mii_phy_auto(sc); - return (0); + if (brgphy_mii_phy_auto(sc, 0) == EJUSTRETURN) + return (0); + break; } /* Update the media status. */ @@ -364,22 +338,22 @@ setit: * Callback if something changed. Note that we need to poke * the DSP on the Broadcom PHYs if the media changes. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - switch (brgphy_mii_model) { + if (sc->mii_media_active != mii->mii_media_active || + sc->mii_media_status != mii->mii_media_status || + cmd == MII_MEDIACHG) { + switch (sc->mii_model) { + case MII_MODEL_BROADCOM_BCM5400: case MII_MODEL_xxBROADCOM_BCM5401: - bcm5401_load_dspcode(sc); - break; case MII_MODEL_xxBROADCOM_BCM5411: - bcm5411_load_dspcode(sc); + brgphy_load_dspcode(sc); break; } } + mii_phy_update(sc, cmd); return (0); } -void +static void brgphy_status(struct mii_softc *sc) { struct mii_data *mii = sc->mii_pdata; @@ -436,54 +410,120 @@ brgphy_status(struct mii_softc *sc) } mii->mii_media_active = ife->ifm_media; - - return; } static int -brgphy_mii_phy_auto(struct mii_softc *mii) +brgphy_mii_phy_auto(struct mii_softc *sc, int waitfor) { - int ktcr = 0; - - brgphy_loop(mii); - brgphy_reset(mii); - ktcr = BRGPHY_1000CTL_AFD|BRGPHY_1000CTL_AHD; - if (brgphy_mii_model == MII_MODEL_xxBROADCOM_BCM5701) - ktcr |= BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC; - PHY_WRITE(mii, BRGPHY_MII_1000CTL, ktcr); - ktcr = PHY_READ(mii, BRGPHY_MII_1000CTL); - DELAY(1000); - PHY_WRITE(mii, BRGPHY_MII_ANAR, mii_bmsr_media_to_anar(mii)); - DELAY(1000); - PHY_WRITE(mii, BRGPHY_MII_BMCR, - BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG); - PHY_WRITE(mii, BRGPHY_MII_IMR, 0xFF00); + int bmsr, ktcr = 0, i; + + if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) { + brgphy_loop(sc); + brgphy_reset(sc); + ktcr = BRGPHY_1000CTL_AFD|BRGPHY_1000CTL_AHD; + if (sc->mii_model == MII_MODEL_xxBROADCOM_BCM5701) + ktcr |= BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC; + PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr); + ktcr = PHY_READ(sc, BRGPHY_MII_1000CTL); + DELAY(1000); + PHY_WRITE(sc, BRGPHY_MII_ANAR, + BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA); + DELAY(1000); + PHY_WRITE(sc, BRGPHY_MII_BMCR, + BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG); + PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00); + } + + if (waitfor) { + /* Wait 500ms for it to complete. */ + for (i = 0; i < 500; i++) { + if ((bmsr = PHY_READ(sc, BRGPHY_MII_BMSR)) & + BRGPHY_BMSR_ACOMP) + return (0); + DELAY(1000); + } + + /* + * Don't need to worry about clearing MIIF_DOINGAUTO. + * If that's set, a timeout is pending, and it will + * clear the flag. + */ + return (EIO); + } + + /* + * Just let it finish asynchronously. This is for the benefit of + * the tick handler driving autonegotiation. Don't want 500ms + * delays all the time while the system is running! + */ + if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) { + sc->mii_flags |= MIIF_DOINGAUTO; + callout_reset(&sc->mii_auto_ch, hz >> 1, + mii_phy_auto_timeout, sc); + } + return (EJUSTRETURN); } static void brgphy_loop(struct mii_softc *sc) { - u_int32_t bmsr; + uint32_t bmsr; int i; PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_LOOP); for (i = 0; i < 15000; i++) { bmsr = PHY_READ(sc, BRGPHY_MII_BMSR); - if (!(bmsr & BRGPHY_BMSR_LINK)) { -#if 0 - device_printf(sc->mii_dev, "looped %d\n", i); -#endif + if (!(bmsr & BRGPHY_BMSR_LINK)) break; - } DELAY(10); } } +static void +brgphy_reset(struct mii_softc *sc) +{ + u_int32_t val; + struct ifnet *ifp; + struct bge_softc *bge_sc; + + mii_phy_reset(sc); + + ifp = sc->mii_pdata->mii_ifp; + bge_sc = ifp->if_softc; + + brgphy_load_dspcode(sc); + + /* + * Don't enable Ethernet@WireSpeed for the 5700 or 5705 + * other than A0 and A1 chips. Make sure we only do this + * test on "bge" NICs, since other drivers may use this + * same PHY subdriver. + */ + if (strncmp(ifp->if_xname, "bge", 3) == 0 && + (bge_sc->bge_asicrev == BGE_ASICREV_BCM5700 || + (bge_sc->bge_asicrev == BGE_ASICREV_BCM5705 && + (bge_sc->bge_chipid != BGE_CHIPID_BCM5705_A0 && + bge_sc->bge_chipid != BGE_CHIPID_BCM5705_A1)))) + return; + + /* Enable Ethernet@WireSpeed. */ + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007); + val = PHY_READ(sc, BRGPHY_MII_AUXCTL); + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, val | (1 << 15) | (1 << 4)); + + /* Enable Link LED on Dell boxes */ + if (bge_sc->bge_no_3_led) { + PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, + PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL) + & ~BRGPHY_PHY_EXTCTL_3_LED); + } +} + /* Turn off tap power management on 5401. */ static void -bcm5401_load_dspcode(struct mii_softc *sc) +brgphy_bcm5401_dspcode(struct mii_softc *sc) { static const struct { int reg; @@ -509,8 +549,9 @@ bcm5401_load_dspcode(struct mii_softc *sc) DELAY(40); } +/* Setting some undocumented voltage */ static void -bcm5411_load_dspcode(struct mii_softc *sc) +brgphy_bcm5411_dspcode(struct mii_softc *sc) { static const struct { int reg; @@ -528,7 +569,43 @@ bcm5411_load_dspcode(struct mii_softc *sc) } static void -bcm5703_load_dspcode(struct mii_softc *sc) +brgphy_bcm5421_dspcode(struct mii_softc *sc) +{ + uint16_t data; + + /* Set Class A mode */ + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x1007); + data = PHY_READ(sc, BRGPHY_MII_AUXCTL); + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, data | 0x0400); + + /* Set FFE gamma override to -0.125 */ + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x0007); + data = PHY_READ(sc, BRGPHY_MII_AUXCTL); + PHY_WRITE(sc, BRGPHY_MII_AUXCTL, data | 0x0800); + PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x000a); + data = PHY_READ(sc, BRGPHY_MII_DSP_RW_PORT); + PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, data | 0x0200); +} + +static void +brgphy_bcm54k2_dspcode(struct mii_softc *sc) +{ + static const struct { + int reg; + uint16_t val; + } dspcode[] = { + { 4, 0x01e1 }, + { 9, 0x0300 }, + { 0, 0 }, + }; + int i; + + for (i = 0; dspcode[i].reg != 0; i++) + PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); +} + +static void +brgphy_bcm5703_dspcode(struct mii_softc *sc) { static const struct { int reg; @@ -546,12 +623,18 @@ bcm5703_load_dspcode(struct mii_softc *sc) } static void -bcm5704_load_dspcode(struct mii_softc *sc) +brgphy_bcm5704_dspcode(struct mii_softc *sc) { static const struct { int reg; u_int16_t val; } dspcode[] = { + { BRGPHY_MII_AUXCTL, 0x0c00 }, + { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, + { BRGPHY_MII_DSP_RW_PORT, 0x2aaa }, + { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, + { BRGPHY_MII_DSP_RW_PORT, 0x0323 }, + { BRGPHY_MII_AUXCTL, 0x0400 }, { 0x1c, 0x8d68 }, { 0x1c, 0x8d68 }, { 0, 0 }, @@ -563,53 +646,62 @@ bcm5704_load_dspcode(struct mii_softc *sc) } static void -brgphy_reset(struct mii_softc *sc) +brgphy_bcm5750_dspcode(struct mii_softc *sc) { - u_int32_t val; - struct ifnet *ifp; - struct bge_softc *bge_sc; + static const struct { + int reg; + uint16_t val; + } dspcode[] = { + { BRGPHY_MII_AUXCTL, 0x0c00 }, + { BRGPHY_MII_DSP_ADDR_REG, 0x000a }, + { BRGPHY_MII_DSP_RW_PORT, 0x310b }, + { BRGPHY_MII_DSP_ADDR_REG, 0x201f }, + { BRGPHY_MII_DSP_RW_PORT, 0x9506 }, + { BRGPHY_MII_DSP_ADDR_REG, 0x401f }, + { BRGPHY_MII_DSP_RW_PORT, 0x14e2 }, + { BRGPHY_MII_AUXCTL, 0x0400 }, + { 0, 0 }, + }; + int i; - mii_phy_reset(sc); + for (i = 0; dspcode[i].reg != 0; i++) + PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); +} - switch (brgphy_mii_model) { - case MII_MODEL_xxBROADCOM_BCM5401: - bcm5401_load_dspcode(sc); +static void +brgphy_load_dspcode(struct mii_softc *sc) +{ + switch (sc->mii_model) { + case MII_MODEL_BROADCOM_BCM5400: + brgphy_bcm5401_dspcode(sc); + break; + case MII_MODEL_BROADCOM_BCM5401: + if (sc->mii_rev == 1 || sc->mii_rev == 3) + brgphy_bcm5401_dspcode(sc); + break; + case MII_MODEL_BROADCOM_BCM5411: + brgphy_bcm5411_dspcode(sc); + break; + case MII_MODEL_xxBROADCOM_BCM5421: + brgphy_bcm5421_dspcode(sc); break; - case MII_MODEL_xxBROADCOM_BCM5411: - bcm5411_load_dspcode(sc); + case MII_MODEL_xxBROADCOM_BCM54K2: + brgphy_bcm54k2_dspcode(sc); break; case MII_MODEL_xxBROADCOM_BCM5703: - bcm5703_load_dspcode(sc); + brgphy_bcm5703_dspcode(sc); break; case MII_MODEL_xxBROADCOM_BCM5704: - bcm5704_load_dspcode(sc); + brgphy_bcm5704_dspcode(sc); + break; + case MII_MODEL_xxBROADCOM_BCM5705: + case MII_MODEL_xxBROADCOM_BCM5750: + case MII_MODEL_xxBROADCOM_BCM5714: + case MII_MODEL_xxBROADCOM_BCM5780: + case MII_MODEL_xxBROADCOM_BCM5752: + case MII_MODEL_xxBROADCOM_BCM5706C: + case MII_MODEL_xxBROADCOM_BCM5708C: + brgphy_bcm5750_dspcode(sc); break; - } - - ifp = sc->mii_pdata->mii_ifp; - bge_sc = ifp->if_softc; - - /* - * Don't enable Ethernet@WireSpeed for the 5700 or the - * 5705 A1 and A2 chips. Make sure we only do this test - * on "bge" NICs, since other drivers may use this same - * PHY subdriver. - */ - if (strcmp(ifp->if_dname, "bge") == 0 && - (bge_sc->bge_asicrev == BGE_ASICREV_BCM5700 || - bge_sc->bge_chipid == BGE_CHIPID_BCM5705_A1 || - bge_sc->bge_chipid == BGE_CHIPID_BCM5705_A2)) - return; - - /* Enable Ethernet@WireSpeed. */ - PHY_WRITE(sc, BRGPHY_MII_AUXCTL, 0x7007); - val = PHY_READ(sc, BRGPHY_MII_AUXCTL); - PHY_WRITE(sc, BRGPHY_MII_AUXCTL, val | (1 << 15) | (1 << 4)); - - /* Enable Link LED on Dell boxes */ - if (bge_sc->bge_no_3_led) { - PHY_WRITE(sc, BRGPHY_MII_PHY_EXTCTL, - PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL) - & ~BRGPHY_PHY_EXTCTL_3_LED); } } diff --git a/sys/dev/netif/mii_layer/ciphy.c b/sys/dev/netif/mii_layer/ciphy.c index d023b626b1..6624c4a980 100644 --- a/sys/dev/netif/mii_layer/ciphy.c +++ b/sys/dev/netif/mii_layer/ciphy.c @@ -1,3 +1,5 @@ +/* $OpenBSD: ciphy.c,v 1.13 2006/03/10 09:53:16 jsg Exp $ */ + /* * Copyright (c) 2004 * Bill Paul . All rights reserved. @@ -30,7 +32,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/ciphy.c,v 1.3 2005/09/30 19:39:27 imp Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/ciphy.c,v 1.1 2006/05/20 07:15:17 sephe Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/ciphy.c,v 1.2 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -70,6 +72,16 @@ static device_method_t ciphy_methods[] = { { 0, 0 } }; +static const struct mii_phydesc ciphys[] = { + MII_PHYDESC(CICADA, CS8201), + MII_PHYDESC(CICADA, CS8201A), + MII_PHYDESC(CICADA, CS8201B), + MII_PHYDESC(xxCICADA, CS8201), + MII_PHYDESC(xxCICADA, CS8201A), + MII_PHYDESC(xxCICADA, CS8201B), + MII_PHYDESC_NULL +}; + static devclass_t ciphy_devclass; static driver_t ciphy_driver = { @@ -84,34 +96,19 @@ static int ciphy_service(struct mii_softc *, struct mii_data *, int); static void ciphy_status(struct mii_softc *); static void ciphy_reset(struct mii_softc *); static void ciphy_fixup(struct mii_softc *); -static void ciphy_mii_phy_auto(struct mii_softc *); static int ciphy_probe(device_t dev) { - struct mii_attach_args *ma; - - ma = device_get_ivars(dev); + struct mii_attach_args *ma = device_get_ivars(dev); + const struct mii_phydesc *mpd; - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_CICADA && - MII_MODEL(ma->mii_id2) == MII_MODEL_CICADA_CS8201) { - device_set_desc(dev, MII_STR_CICADA_CS8201); - return(0); - } - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_CICADA && - MII_MODEL(ma->mii_id2) == MII_MODEL_CICADA_CS8201A) { - device_set_desc(dev, MII_STR_CICADA_CS8201A); - return(0); - } - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_CICADA && - MII_MODEL(ma->mii_id2) == MII_MODEL_CICADA_CS8201B) { - device_set_desc(dev, MII_STR_CICADA_CS8201B); - return(0); + mpd = mii_phy_match(ma, ciphys); + if (mpd != NULL) { + device_set_desc(dev, mpd->mpd_name); + return (0); } - - return(ENXIO); + return (ENXIO); } static int @@ -120,7 +117,6 @@ ciphy_attach(device_t dev) struct mii_softc *sc; struct mii_attach_args *ma; struct mii_data *mii; - const char *sep = ""; sc = device_get_softc(dev); ma = device_get_ivars(dev); @@ -132,39 +128,27 @@ ciphy_attach(device_t dev) sc->mii_inst = mii->mii_instance; sc->mii_service = ciphy_service; + sc->mii_reset = ciphy_reset; sc->mii_pdata = mii; sc->mii_flags |= MIIF_NOISOLATE; mii->mii_instance++; -#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) -#define PRINT(s) printf("%s%s", sep, s); sep = ", " - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), - BMCR_ISO); - ciphy_reset(sc); sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; -#ifdef notyet if (sc->mii_capabilities & BMSR_EXTSTAT) sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); -#endif device_printf(dev, " "); - mii_add_media(sc, sc->mii_capabilities & ~BMSR_ANEG); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst), - CIPHY_BMCR_FDX); - PRINT(", 1000baseTX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst), 0); - PRINT("1000baseTX-FDX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0); - PRINT("auto"); - + if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 && + (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) + printf("no media present"); + else + mii_phy_add_media(sc); printf("\n"); - ma->mii_flags |= MIIF_IS_1000X; MIIBUS_MEDIAINIT(sc->mii_dev); - return(0); } @@ -211,7 +195,8 @@ ciphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if (PHY_READ(sc, CIPHY_MII_BMCR) & CIPHY_BMCR_AUTOEN) return (0); #endif - ciphy_mii_phy_auto(sc); + if (mii_phy_auto(sc, 0) == EJUSTRETURN) + return (0); break; case IFM_1000_T: speed = CIPHY_S1000; @@ -272,36 +257,9 @@ setit: if (IFM_INST(ife->ifm_media) != sc->mii_inst) return (0); - /* - * Is the interface even up? - */ - if ((mii->mii_ifp->if_flags & IFF_UP) == 0) + if (mii_phy_tick(sc) == EJUSTRETURN) return (0); - - /* - * Only used for autonegotiation. - */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) - break; - - /* - * Check to see if we have link. If we do, we don't - * need to restart the autonegotiation process. Read - * the BMSR twice in case it's latched. - */ - reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); - if (reg & BMSR_LINK) - break; - - /* - * Only retry autonegotiation every 5 seconds. - */ - if (++sc->mii_ticks <= 5/*10*/) - break; - - sc->mii_ticks = 0; - ciphy_mii_phy_auto(sc); - return (0); + break; } /* Update the media status. */ @@ -311,11 +269,11 @@ setit: * Callback if something changed. Note that we need to poke * apply fixups for certain PHY revs. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { + if (sc->mii_media_active != mii->mii_media_active || + sc->mii_media_status != mii->mii_media_status || + cmd == MII_MEDIACHG) ciphy_fixup(sc); - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } @@ -382,16 +340,22 @@ ciphy_reset(struct mii_softc *sc) static void ciphy_fixup(struct mii_softc *sc) { - uint16_t model; - uint16_t status, speed; + uint16_t model, status, speed; + device_t parent; model = MII_MODEL(PHY_READ(sc, CIPHY_MII_PHYIDR2)); status = PHY_READ(sc, CIPHY_MII_AUXCSR); speed = status & CIPHY_AUXCSR_SPEED; - switch (model) { - case MII_MODEL_CICADA_CS8201: + parent = device_get_parent(sc->mii_dev); + if (strncmp(device_get_name(parent), "nfe", 3) == 0) { + /* Need to set for 2.5V RGMII for NVIDIA adapters */ + PHY_SETBIT(sc, CIPHY_MII_ECTL1, CIPHY_INTSEL_RGMII); + PHY_SETBIT(sc, CIPHY_MII_ECTL1, CIPHY_IOVOL_2500MV); + } + switch (model) { + case MII_MODEL_CICADA_CS8201: /* MII_MODEL_xxCICADA_CS8201 */ /* Turn off "aux mode" (whatever that means) */ PHY_SETBIT(sc, CIPHY_MII_AUXCSR, CIPHY_AUXCSR_MDPPS); @@ -408,12 +372,10 @@ ciphy_fixup(struct mii_softc *sc) /* Enable link/activity LED blink. */ PHY_SETBIT(sc, CIPHY_MII_LED, CIPHY_LED_LINKACTBLINK); - break; - case MII_MODEL_CICADA_CS8201A: - case MII_MODEL_CICADA_CS8201B: - + case MII_MODEL_CICADA_CS8201A: /* MII_MODEL_xxCICADA_CS8201A */ + case MII_MODEL_CICADA_CS8201B: /* MII_MODEL_xxCICADA_CS8201B */ /* * Work around speed polling bug in VT3119/VT3216 * when using MII in full duplex mode. @@ -424,19 +386,11 @@ ciphy_fixup(struct mii_softc *sc) } else { PHY_CLRBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO); } - break; + default: - device_printf(sc->mii_dev, "unknown CICADA PHY model %x\n", - model); + device_printf(sc->mii_dev, + "unknown CICADA PHY model %x\n", model); break; } } - -static void -ciphy_mii_phy_auto(struct mii_softc *sc) -{ - PHY_WRITE(sc, CIPHY_MII_ANAR, mii_bmsr_media_to_anar(sc)); - PHY_WRITE(sc, CIPHY_MII_1000CTL, CIPHY_1000CTL_AFD); - PHY_WRITE(sc, CIPHY_MII_BMCR, CIPHY_BMCR_AUTOEN | CIPHY_BMCR_STARTNEG); -} diff --git a/sys/dev/netif/mii_layer/ciphyreg.h b/sys/dev/netif/mii_layer/ciphyreg.h index 311dba98b0..09900ba232 100644 --- a/sys/dev/netif/mii_layer/ciphyreg.h +++ b/sys/dev/netif/mii_layer/ciphyreg.h @@ -1,3 +1,5 @@ +/* $OpenBSD: ciphyreg.h,v 1.2 2006/02/28 08:13:47 jsg Exp $ */ + /* * Copyright (c) 2004 * Bill Paul . All rights reserved. @@ -30,7 +32,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/ciphyreg.h,v 1.2 2005/01/06 01:42:55 imp Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/ciphyreg.h,v 1.1 2006/05/20 07:15:17 sephe Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/ciphyreg.h,v 1.2 2006/08/06 10:32:23 sephe Exp $ */ #ifndef _DEV_MII_CIPHYREG_H_ @@ -252,6 +254,16 @@ /* Extended PHY control register #1 */ #define CIPHY_MII_ECTL1 0x17 #define CIPHY_ECTL1_ACTIPHY 0x0020 /* Enable ActiPHY power saving */ +#define CIPHY_ECTL1_IOVOL 0x0e00 /* MAC interface and I/O voltage select */ +#define CIPHY_ECTL1_INTSEL 0xf000 /* select MAC interface */ + +#define CIPHY_IOVOL_3300MV 0x0000 /* 3.3V for I/O pins */ +#define CIPHY_IOVOL_2500MV 0x0200 /* 2.5V for I/O pins */ + +#define CIPHY_INTSEL_GMII 0x0000 /* GMII/MII */ +#define CIPHY_INTSEL_RGMII 0x1000 +#define CIPHY_INTSEL_TBI 0x2000 +#define CIPHY_INTSEL_RTBI 0x3000 /* Extended PHY control register #2 */ #define CIPHY_MII_ECTL2 0x18 diff --git a/sys/dev/netif/mii_layer/dcphy.c b/sys/dev/netif/mii_layer/dcphy.c index 6a0ecad878..c5950515b6 100644 --- a/sys/dev/netif/mii_layer/dcphy.c +++ b/sys/dev/netif/mii_layer/dcphy.c @@ -30,9 +30,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/dcphy.c,v 1.2.2.2 2000/10/14 00:44:40 wpaul Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/dcphy.c,v 1.8 2005/12/11 01:54:08 swildner Exp $ - * - * $FreeBSD: src/sys/dev/mii/dcphy.c,v 1.2.2.2 2000/10/14 00:44:40 wpaul Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/dcphy.c,v 1.9 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -60,7 +58,6 @@ #include "miivar.h" #include "miidevs.h" -#include #include #include #include @@ -91,13 +88,12 @@ static int dcphy_probe (device_t); static int dcphy_attach (device_t); -static int dcphy_detach (device_t); static device_method_t dcphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, dcphy_probe), DEVMETHOD(device_attach, dcphy_attach), - DEVMETHOD(device_detach, dcphy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; @@ -112,10 +108,10 @@ static driver_t dcphy_driver = { DRIVER_MODULE(dcphy, miibus, dcphy_driver, dcphy_devclass, 0, 0); -int dcphy_service (struct mii_softc *, struct mii_data *, int); -void dcphy_status (struct mii_softc *); -static int dcphy_auto (struct mii_softc *, int); -static void dcphy_reset (struct mii_softc *); +static int dcphy_service(struct mii_softc *, struct mii_data *, int); +static void dcphy_status(struct mii_softc *); +static void dcphy_auto(struct mii_softc *); +static void dcphy_reset(struct mii_softc *); static int dcphy_probe(device_t dev) @@ -154,16 +150,13 @@ dcphy_attach(device_t dev) sc->mii_inst = mii->mii_instance; sc->mii_service = dcphy_service; + sc->mii_reset = dcphy_reset; + sc->mii_anegticks = 50; sc->mii_pdata = mii; sc->mii_flags |= MIIF_NOISOLATE; mii->mii_instance++; -#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); - /*dcphy_reset(sc);*/ dc_sc = mii->mii_ifp->if_softc; CSR_WRITE_4(dc_sc, DC_10BTSTAT, 0); @@ -180,8 +173,12 @@ dcphy_attach(device_t dev) sc->mii_capabilities = BMSR_ANEG|BMSR_10TFDX|BMSR_10THDX; } else { +#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, - sc->mii_inst), BMCR_LOOP|BMCR_S100); + sc->mii_inst), MII_MEDIA_100_TX); + +#undef ADD sc->mii_capabilities = BMSR_ANEG|BMSR_100TXFDX|BMSR_100TXHDX| @@ -190,34 +187,24 @@ dcphy_attach(device_t dev) break; } +#ifdef notyet + if (dc_sc->dc_type == DC_TYPE_21145) + sc->mii_capabilities = BMSR_10THDX; +#endif + sc->mii_capabilities &= ma->mii_capmask; device_printf(dev, " "); if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) printf("no media present"); else - mii_add_media(sc, sc->mii_capabilities); + mii_phy_add_media(sc); printf("\n"); -#undef ADD MIIBUS_MEDIAINIT(sc->mii_dev); return(0); } static int -dcphy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); - - return(0); -} - -int dcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { struct dc_softc *dc_sc; @@ -240,7 +227,7 @@ dcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) case MII_MEDIACHG: /* * If the media indicates a different PHY instance, - * isolate ourselves. + * isolate ourselves. XXX how? */ if (IFM_INST(ife->ifm_media) != sc->mii_inst) { return (0); @@ -261,8 +248,7 @@ dcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) switch (IFM_SUBTYPE(ife->ifm_media)) { case IFM_AUTO: /*dcphy_reset(sc);*/ - sc->mii_flags &= ~MIIF_DOINGAUTO; - (void) dcphy_auto(sc, 0); + dcphy_auto(sc); break; case IFM_100_T4: /* @@ -299,7 +285,6 @@ dcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) break; default: return(EINVAL); - break; } break; @@ -310,34 +295,37 @@ dcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 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); - reg = CSR_READ_4(dc_sc, DC_10BTSTAT) & - (DC_TSTAT_LS10|DC_TSTAT_LS100); + /* + * Only used for autonegotiation. + */ + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + break; + reg = CSR_READ_4(dc_sc, DC_10BTSTAT); if (!(reg & DC_TSTAT_LS10) || !(reg & DC_TSTAT_LS100)) return(0); /* - * Only retry autonegotiation every 5 seconds. + * Only retry autonegotiation every mii_anegticks seconds. + * + * Otherwise, fall through to calling dcphy_status() + * since real Intel 21143 chips don't show valid link + * status until autonegotiation is switched off, and + * that only happens in dcphy_status(). Without this, + * successful autonegotation is never recognised on + * these chips. */ - if (++sc->mii_ticks != 50) - return (0); + if (++sc->mii_ticks <= sc->mii_anegticks) + break; sc->mii_ticks = 0; - /*if (DC_IS_INTEL(dc_sc))*/ - sc->mii_flags &= ~MIIF_DOINGAUTO; - dcphy_auto(sc, 0); + dcphy_auto(sc); break; } @@ -346,14 +334,11 @@ dcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) dcphy_status(sc); /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } -void +static void dcphy_status(struct mii_softc *sc) { struct mii_data *mii = sc->mii_pdata; @@ -368,9 +353,7 @@ dcphy_status(struct mii_softc *sc) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) return; - reg = CSR_READ_4(dc_sc, DC_10BTSTAT) & - (DC_TSTAT_LS10|DC_TSTAT_LS100); - + reg = CSR_READ_4(dc_sc, DC_10BTSTAT); if (!(reg & DC_TSTAT_LS10) || !(reg & DC_TSTAT_LS100)) mii->mii_media_status |= IFM_ACTIVE; @@ -438,64 +421,31 @@ skip: return; } -static int -dcphy_auto(struct mii_softc *mii, int waitfor) +static void +dcphy_auto(struct mii_softc *sc) { - int i; - struct dc_softc *sc; - - sc = mii->mii_pdata->mii_ifp->if_softc; - - if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) { - DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL); - DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_FULLDUPLEX); - DC_CLRBIT(sc, DC_SIARESET, DC_SIA_RESET); - if (mii->mii_capabilities & BMSR_100TXHDX) - CSR_WRITE_4(sc, DC_10BTCTRL, 0x3FFFF); - else - CSR_WRITE_4(sc, DC_10BTCTRL, 0xFFFF); - DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET); - DC_SETBIT(sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL); - DC_SETBIT(sc, DC_10BTSTAT, DC_ASTAT_TXDISABLE); - } - - if (waitfor) { - /* Wait 500ms for it to complete. */ - for (i = 0; i < 500; i++) { - if ((CSR_READ_4(sc, DC_10BTSTAT) & DC_TSTAT_ANEGSTAT) - == DC_ASTAT_AUTONEGCMP) - return(0); - DELAY(1000); - } - /* - * Don't need to worry about clearing MIIF_DOINGAUTO. - * If that's set, a timeout is pending, and it will - * clear the flag. - */ - return(EIO); - } + struct dc_softc *dc_sc = sc->mii_pdata->mii_ifp->if_softc; - /* - * Just let it finish asynchronously. This is for the benefit of - * the tick handler driving autonegotiation. Don't want 500ms - * delays all the time while the system is running! - */ - if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) - mii->mii_flags |= MIIF_DOINGAUTO; + DC_CLRBIT(dc_sc, DC_NETCFG, DC_NETCFG_PORTSEL); + DC_SETBIT(dc_sc, DC_NETCFG, DC_NETCFG_FULLDUPLEX); + DC_CLRBIT(dc_sc, DC_SIARESET, DC_SIA_RESET); + if (sc->mii_capabilities & BMSR_100TXHDX) + CSR_WRITE_4(dc_sc, DC_10BTCTRL, 0x3FFFF); + else + CSR_WRITE_4(dc_sc, DC_10BTCTRL, 0xFFFF); + DC_SETBIT(dc_sc, DC_SIARESET, DC_SIA_RESET); + DC_SETBIT(dc_sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL); + DC_SETBIT(dc_sc, DC_10BTSTAT, DC_ASTAT_TXDISABLE); - return(EJUSTRETURN); + sc->mii_flags |= MIIF_DOINGAUTO; } static void -dcphy_reset(struct mii_softc *mii) +dcphy_reset(struct mii_softc *sc) { - struct dc_softc *sc; + struct dc_softc *dc_sc = sc->mii_pdata->mii_ifp->if_softc; - sc = mii->mii_pdata->mii_ifp->if_softc; - - DC_CLRBIT(sc, DC_SIARESET, DC_SIA_RESET); + DC_CLRBIT(dc_sc, DC_SIARESET, DC_SIA_RESET); DELAY(1000); - DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET); - - return; + DC_SETBIT(dc_sc, DC_SIARESET, DC_SIA_RESET); } diff --git a/sys/dev/netif/mii_layer/e1000phy.c b/sys/dev/netif/mii_layer/e1000phy.c index 0fb5a7c9bf..8b380b9d05 100644 --- a/sys/dev/netif/mii_layer/e1000phy.c +++ b/sys/dev/netif/mii_layer/e1000phy.c @@ -1,5 +1,6 @@ /* $FreeBSD: src/sys/dev/mii/e1000phy.c,v 1.1.2.2 2002/11/08 21:53:49 semenu Exp $ */ -/* $DragonFly: src/sys/dev/netif/mii_layer/e1000phy.c,v 1.7 2005/10/24 16:55:40 dillon Exp $ */ +/* $DragonFly: src/sys/dev/netif/mii_layer/e1000phy.c,v 1.8 2006/08/06 10:32:23 sephe Exp $ */ +/* $OpenBSD: eephy.c,v 1.26 2006/06/08 00:27:12 brad Exp $ */ /* * Principal Author: Parag Patel * Copyright (c) 2001 @@ -48,8 +49,6 @@ #include #include -#include - #include #include @@ -61,50 +60,59 @@ #include "miibus_if.h" -static int e1000phy_probe(device_t); -static int e1000phy_attach(device_t); -static int e1000phy_detach(device_t); +static int e1000phy_probe(device_t); +static int e1000phy_attach(device_t); +static int e1000phy_service(struct mii_softc *, struct mii_data *, int); +static void e1000phy_status(struct mii_softc *); +static int e1000phy_mii_phy_auto(struct mii_softc *, int); +static void e1000phy_reset(struct mii_softc *); static device_method_t e1000phy_methods[] = { /* device interface */ DEVMETHOD(device_probe, e1000phy_probe), DEVMETHOD(device_attach, e1000phy_attach), - DEVMETHOD(device_detach, e1000phy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; +static const struct mii_phydesc e1000phys[] = { + MII_PHYDESC(xxMARVELL, E1000_2), + MII_PHYDESC(xxMARVELL, E1000_3), + MII_PHYDESC(xxMARVELL, E1000_5), + MII_PHYDESC(xxMARVELL, E1111), + MII_PHYDESC(MARVELL, E1000), + MII_PHYDESC(MARVELL, E1011), + MII_PHYDESC(MARVELL, E1000_3), + MII_PHYDESC(MARVELL, E1000_4), + MII_PHYDESC(MARVELL, E1000_5), + MII_PHYDESC(MARVELL, E1000_6), + MII_PHYDESC(MARVELL, E1111), + MII_PHYDESC(MARVELL, E1116), + MII_PHYDESC_NULL +}; + static devclass_t e1000phy_devclass; + static driver_t e1000phy_driver = { - "e1000phy", e1000phy_methods, sizeof (struct mii_softc) + "e1000phy", + e1000phy_methods, + sizeof(struct mii_softc) }; DRIVER_MODULE(e1000phy, miibus, e1000phy_driver, e1000phy_devclass, 0, 0); -int e1000phy_service(struct mii_softc *, struct mii_data *, int); -void e1000phy_status(struct mii_softc *); - -static int e1000phy_mii_phy_auto(struct mii_softc *, int); -extern void mii_phy_auto_timeout(void *); -static void e1000phy_reset(struct mii_softc *); - -static int e1000phy_debug = 0; - static int e1000phy_probe(device_t dev) { - struct mii_attach_args *ma; - u_int32_t id; + struct mii_attach_args *ma = device_get_ivars(dev); + const struct mii_phydesc *mpd; - ma = device_get_ivars(dev); - id = ((ma->mii_id1 << 16) | ma->mii_id2) & E1000_ID_MASK; - if (id != E1000_ID_88E1000 - && id != E1000_ID_88E1000S - && id != E1000_ID_88E1011) { - return ENXIO; + mpd = mii_phy_match(ma, e1000phys); + if (mpd != NULL) { + device_set_desc(dev, mpd->mpd_name); + return 0; } - - device_set_desc(dev, MII_STR_MARVELL_E1000); - return 0; + return (ENXIO); } static int @@ -114,9 +122,6 @@ e1000phy_attach(device_t dev) struct mii_attach_args *ma; struct mii_data *mii; const char *sep = ""; - u_int32_t id; - - getenv_int("e1000phy_debug", &e1000phy_debug); sc = device_get_softc(dev); ma = device_get_ivars(dev); @@ -127,14 +132,19 @@ e1000phy_attach(device_t dev) sc->mii_inst = mii->mii_instance; sc->mii_service = e1000phy_service; + sc->mii_reset = e1000phy_reset; + sc->mii_anegticks = MII_ANEGTICKS_GIGE; sc->mii_pdata = mii; + sc->mii_flags |= MIIF_NOISOLATE; - id = ((ma->mii_id1 << 16) | ma->mii_id2) & E1000_ID_MASK; - if (id == E1000_ID_88E1011 - && (PHY_READ(sc, E1000_ESSR) & E1000_ESSR_FIBER_LINK)) + if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_MARVELL && + MII_MODEL(ma->mii_id2) == MII_MODEL_MARVELL_E1011 && + (PHY_READ(sc, E1000_ESSR) & E1000_ESSR_FIBER_LINK)) sc->mii_flags |= MIIF_HAVEFIBER; + mii->mii_instance++; + e1000phy_reset(sc); #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) @@ -173,6 +183,7 @@ e1000phy_attach(device_t dev) E1000_CR_SPEED_1000); PRINT("1000baseSX-FDX"); } + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0); PRINT("auto"); @@ -184,28 +195,10 @@ e1000phy_attach(device_t dev) return(0); } -static int -e1000phy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); - - if (sc->mii_flags & MIIF_DOINGAUTO) - callout_stop(&sc->mii_auto_ch); - - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); - - return 0; -} - static void e1000phy_reset(struct mii_softc *sc) { - u_int32_t reg; + uint32_t reg; int i; /* initialize custom E1000 registers to magic values */ @@ -241,7 +234,7 @@ e1000phy_reset(struct mii_softc *sc) PHY_WRITE(sc, 30, 0x00); } -int +static int e1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { struct ifmedia_entry *ife = mii->mii_media.ifm_cur; @@ -283,7 +276,7 @@ e1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) return (0); } e1000phy_reset(sc); - (void)e1000phy_mii_phy_auto(sc, 1); + e1000phy_mii_phy_auto(sc, 1); break; case IFM_1000_SX: @@ -301,7 +294,7 @@ e1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) e1000phy_reset(sc); /* TODO - any other way to force 1000BT? */ - (void)e1000phy_mii_phy_auto(sc, 1); + e1000phy_mii_phy_auto(sc, 1); break; case IFM_100_TX: @@ -345,13 +338,6 @@ e1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) return (0); } - /* - * Only used for autonegotiation. - */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { - return (0); - } - /* * Is the interface even up? */ @@ -360,12 +346,11 @@ e1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) } /* - * Only retry autonegotiation every 5 seconds. + * Only used for autonegotiation. */ - if (++(sc->mii_ticks) != 5) { - return (0); + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) { + break; } - sc->mii_ticks = 0; /* * Check to see if we have link. If we do, we don't @@ -373,14 +358,21 @@ e1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) * the BMSR twice in case it's latched. */ reg = PHY_READ(sc, E1000_SR) | PHY_READ(sc, E1000_SR); - if (reg & E1000_SR_LINK_STATUS) break; + /* + * Only retry autonegotiation every mii_anegticks seconds. + */ + if (++(sc->mii_ticks) != sc->mii_anegticks) { + return (0); + } + sc->mii_ticks = 0; + e1000phy_reset(sc); if (e1000phy_mii_phy_auto(sc, 0) == EJUSTRETURN) { - return(0); + return (0); } break; @@ -390,15 +382,11 @@ e1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) e1000phy_status(sc); /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } - + mii_phy_update(sc, cmd); return (0); } -void +static void e1000phy_status(struct mii_softc *sc) { struct mii_data *mii = sc->mii_pdata; @@ -461,26 +449,28 @@ e1000phy_status(struct mii_softc *sc) } static int -e1000phy_mii_phy_auto(struct mii_softc *mii, int waitfor) +e1000phy_mii_phy_auto(struct mii_softc *sc, int waitfor) { int bmsr, i; - if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) { - if ((mii->mii_flags & MIIF_HAVEFIBER) == 0) { - PHY_WRITE(mii, E1000_AR, E1000_AR_10T | E1000_AR_10T_FD | + if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) { + if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { + PHY_WRITE(sc, E1000_AR, E1000_AR_10T | E1000_AR_10T_FD | E1000_AR_100TX | E1000_AR_100TX_FD | E1000_AR_PAUSE | E1000_AR_ASM_DIR); - PHY_WRITE(mii, E1000_1GCR, E1000_1GCR_1000T_FD); - PHY_WRITE(mii, E1000_CR, - E1000_CR_AUTO_NEG_ENABLE | E1000_CR_RESTART_AUTO_NEG); + PHY_WRITE(sc, E1000_1GCR, E1000_1GCR_1000T_FD); + } else { + PHY_WRITE(sc, E1000_AR, E1000_FA_1000X_FD | + E1000_FA_SYM_PAUSE | E1000_FA_ASYM_PAUSE); } + PHY_WRITE(sc, E1000_CR, + E1000_CR_AUTO_NEG_ENABLE | E1000_CR_RESTART_AUTO_NEG); } if (waitfor) { /* Wait 5 seconds for it to complete. */ for (i = 0; i < 5000; i++) { - bmsr = - PHY_READ(mii, E1000_SR) | PHY_READ(mii, E1000_SR); + bmsr = PHY_READ(sc, E1000_SR) | PHY_READ(sc, E1000_SR); if (bmsr & E1000_SR_AUTO_NEG_COMPLETE) { return (0); @@ -493,6 +483,7 @@ e1000phy_mii_phy_auto(struct mii_softc *mii, int waitfor) * If that's set, a timeout is pending, and it will * clear the flag. [do it anyway] */ + return (EIO); } /* @@ -500,11 +491,14 @@ e1000phy_mii_phy_auto(struct mii_softc *mii, int waitfor) * the tick handler driving autonegotiation. Don't want 500ms * delays all the time while the system is running! */ - if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) { - mii->mii_flags |= MIIF_DOINGAUTO; - mii->mii_ticks = 0; - callout_reset(&mii->mii_auto_ch, 5 * hz, - mii_phy_auto_timeout, mii); + if (sc->mii_flags & MIIF_AUTOTSLEEP) { + sc->mii_flags |= MIIF_DOINGAUTO; + tsleep(&sc->mii_flags, 0, "miiaut", hz >> 1); + mii_phy_auto_timeout(sc); + } else if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) { + sc->mii_flags |= MIIF_DOINGAUTO; + callout_reset(&sc->mii_auto_ch, 5 * hz, + mii_phy_auto_timeout, sc); } return (EJUSTRETURN); } diff --git a/sys/dev/netif/mii_layer/exphy.c b/sys/dev/netif/mii_layer/exphy.c index 7756079493..cf365ee0a5 100644 --- a/sys/dev/netif/mii_layer/exphy.c +++ b/sys/dev/netif/mii_layer/exphy.c @@ -37,7 +37,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/exphy.c,v 1.4.2.2 2002/11/08 21:53:49 semenu Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/exphy.c,v 1.8 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/exphy.c,v 1.9 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -91,13 +91,12 @@ static int exphy_probe (device_t); static int exphy_attach (device_t); -static int exphy_detach (device_t); static device_method_t exphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, exphy_probe), DEVMETHOD(device_attach, exphy_attach), - DEVMETHOD(device_detach, exphy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; @@ -130,11 +129,11 @@ exphy_probe(device_t dev) if ((MII_OUI(ma->mii_id1, ma->mii_id2) != 0 || MII_MODEL(ma->mii_id2) != 0) && (MII_OUI(ma->mii_id1, ma->mii_id2) != MII_OUI_BROADCOM || - MII_MODEL(ma->mii_id2) != MII_MODEL_BROADCOM_3c905Cphy)) + MII_MODEL(ma->mii_id2) != MII_MODEL_BROADCOM_3C905C)) return (ENXIO); /* - * Make sure the parent is an `ex'. + * Make sure the parent is an `xl'. */ if (strcmp(device_get_name(parent), "xl") != 0) return (ENXIO); @@ -142,7 +141,7 @@ exphy_probe(device_t dev) if (MII_OUI(ma->mii_id1, ma->mii_id2) == 0) device_set_desc(dev, "3Com internal media interface"); else - device_set_desc(dev, MII_STR_BROADCOM_3c905Cphy); + device_set_desc(dev, MII_STR_BROADCOM_3C905C); return (0); } @@ -173,48 +172,23 @@ exphy_attach(device_t dev) sc->mii_inst = mii->mii_instance; sc->mii_service = exphy_service; + sc->mii_reset = exphy_reset; sc->mii_pdata = mii; mii->mii_instance++; sc->mii_flags |= MIIF_NOISOLATE; -#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) - -#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->mii_inst), - BMCR_LOOP|BMCR_S100); - exphy_reset(sc); - sc->mii_capabilities = - PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; device_printf(dev, " "); if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) printf("no media present"); else - mii_add_media(sc, sc->mii_capabilities); + mii_phy_add_media(sc); printf("\n"); -#undef ADD - MIIBUS_MEDIAINIT(sc->mii_dev); - return(0); -} - -static int -exphy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); - mii_phy_auto_stop(sc); - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); + MIIBUS_MEDIAINIT(sc->mii_dev); return(0); } @@ -226,8 +200,8 @@ exphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) /* * We can't isolate the 3Com PHY, so it has to be the only one! */ - if (IFM_INST(ife->ifm_media) != sc->mii_inst) - panic("exphy_service: can't isolate 3Com PHY"); + KASSERT(IFM_INST(ife->ifm_media) == sc->mii_inst, + ("exphy_service: can't isolate 3Com PHY")); switch (cmd) { case MII_POLLSTAT: @@ -240,42 +214,28 @@ exphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - switch (IFM_SUBTYPE(ife->ifm_media)) { - case IFM_AUTO: - /* - * If we're already in auto mode, just return. - */ - if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) - return (0); - (void) mii_phy_auto(sc, 1); - break; - case IFM_100_T4: + if (IFM_SUBTYPE(ife->ifm_media) == IFM_100_T4) { /* * XXX Not supported as a manual setting right now. */ return (EINVAL); - default: - /* - * BMCR data is stored in the ifmedia entry. - */ - PHY_WRITE(sc, MII_ANAR, - mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); } + + mii_phy_set_media(sc); break; case MII_TICK: /* - * Only used for autonegotiation. + * Is the interface even up? */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) return (0); /* - * Is the interface even up? + * Only used for autonegotiation. */ - if ((mii->mii_ifp->if_flags & IFF_UP) == 0) - return (0); + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + break; /* * The 3Com PHY's autonegotiation doesn't need to be @@ -288,10 +248,7 @@ exphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) ukphy_status(sc); /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } diff --git a/sys/dev/netif/mii_layer/inphy.c b/sys/dev/netif/mii_layer/inphy.c index 2a77b0de1c..f8fb228256 100644 --- a/sys/dev/netif/mii_layer/inphy.c +++ b/sys/dev/netif/mii_layer/inphy.c @@ -26,8 +26,8 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/mii/inphy.c,v 1.4.2.2 2002/11/08 21:53:49 semenu Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/inphy.c,v 1.6 2005/10/24 16:55:40 dillon Exp $ + * $FreeBSD: src/sys/dev/mii/inphy.c,v 1.14 2004/05/30 17:57:40 phk Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/inphy.c,v 1.7 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -53,17 +53,27 @@ static int inphy_probe(device_t dev); static int inphy_attach(device_t dev); -static int inphy_detach(device_t dev); +static int inphy_service(struct mii_softc *, struct mii_data *, int); +static void inphy_status(struct mii_softc *); static device_method_t inphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, inphy_probe), DEVMETHOD(device_attach, inphy_attach), - DEVMETHOD(device_detach, inphy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; +static const struct mii_phydesc inphys[] = { + MII_PHYDESC(xxINTEL, I82553AB), /* Intel 82553 A/B steppings */ + MII_PHYDESC(INTEL, I82555), + MII_PHYDESC(INTEL, I82553C), + MII_PHYDESC(INTEL, I82562EM), + MII_PHYDESC(INTEL, I82562ET), + MII_PHYDESC_NULL +}; + static devclass_t inphy_devclass; static driver_t inphy_driver = { @@ -74,43 +84,17 @@ static driver_t inphy_driver = { DRIVER_MODULE(inphy, miibus, inphy_driver, inphy_devclass, 0, 0); -int inphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd); -void inphy_status(struct mii_softc *sc); - - static int inphy_probe(device_t dev) { - struct mii_attach_args *ma; - device_t parent; - - ma = device_get_ivars(dev); - parent = device_get_parent(device_get_parent(dev)); + struct mii_attach_args *ma = device_get_ivars(dev); + const struct mii_phydesc *mpd; - /* Intel 82553 A/B steppings */ - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxINTEL && - MII_MODEL(ma->mii_id2) == MII_MODEL_xxINTEL_I82553AB) { - device_set_desc(dev, MII_STR_xxINTEL_I82553AB); + mpd = mii_phy_match(ma, inphys); + if (mpd != NULL) { + device_set_desc(dev, mpd->mpd_name); return (0); } - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_INTEL) { - switch (MII_MODEL(ma->mii_id2)) { - case MII_MODEL_INTEL_I82555: - device_set_desc(dev, MII_STR_INTEL_I82555); - return (0); - case MII_MODEL_INTEL_I82553C: - device_set_desc(dev, MII_STR_INTEL_I82553C); - return (0); - case MII_MODEL_INTEL_I82562EM: - device_set_desc(dev, MII_STR_INTEL_I82562EM); - return (0); - case MII_MODEL_INTEL_I82562ET: - device_set_desc(dev, MII_STR_INTEL_I82562ET); - return (0); - } - } - return (ENXIO); } @@ -139,39 +123,24 @@ inphy_attach(device_t dev) ifmedia_add(&mii->mii_media, IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), - BMCR_LOOP|BMCR_S100, NULL); + MII_MEDIA_100_TX, NULL); mii_phy_reset(sc); sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + device_printf(dev, " "); if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) printf("no media present"); else - mii_add_media(sc, sc->mii_capabilities); + mii_phy_add_media(sc); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); - return (0); } static int -inphy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_softc(dev)); - mii_phy_auto_stop(sc); - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); - - return (0); -} - -int inphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { struct ifmedia_entry *ife = mii->mii_media.ifm_cur; @@ -196,62 +165,14 @@ inphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - switch (IFM_SUBTYPE(ife->ifm_media)) { - case IFM_AUTO: - /* - * If we're already in auto mode, just return. - */ - if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) - return (0); - (void) mii_phy_auto(sc, 0); - break; - case IFM_100_T4: - /* - * XXX Not supported as a manual setting right now. - */ - return (EINVAL); - default: - /* - * BMCR data is stored in the ifmedia entry. - */ - PHY_WRITE(sc, MII_ANAR, mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); - } + mii_phy_set_media(sc); break; case MII_TICK: if (IFM_INST(ife->ifm_media) != sc->mii_inst) return (0); - /* - * Is the interface even up? - */ - if ((mii->mii_ifp->if_flags & IFF_UP) == 0) - return (0); - - /* - * Only used for autonegotiation. - */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) - return (0); - - /* - * check for link. - * Read the status register twice; BMSR_LINK is latch-low. - */ - reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); - if (reg & BMSR_LINK) - return (0); - - /* - * Only retry autonegotiation every 5 seconds. - */ - if (++sc->mii_ticks != 5) - return (0); - - sc->mii_ticks = 0; - mii_phy_reset(sc); - if (mii_phy_auto(sc, 0) == EJUSTRETURN) + if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } @@ -260,14 +181,11 @@ inphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) inphy_status(sc); /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } -void +static void inphy_status(struct mii_softc *sc) { struct mii_data *mii = sc->mii_pdata; @@ -297,12 +215,15 @@ inphy_status(struct mii_softc *sc) } scr = PHY_READ(sc, MII_INPHY_SCR); - if (scr & SCR_S100) + if ((bmsr & BMSR_100T4) && (scr & SCR_T4)) + mii->mii_media_active |= IFM_100_T4; + else if (scr & SCR_S100) mii->mii_media_active |= IFM_100_TX; else mii->mii_media_active |= IFM_10_T; if (scr & SCR_FDX) mii->mii_media_active |= IFM_FDX; - } else - mii->mii_media_active |= mii_media_from_bmcr(bmcr); + } else { + mii->mii_media_active = mii->mii_media.ifm_cur->ifm_media; + } } diff --git a/sys/dev/netif/mii_layer/inphyreg.h b/sys/dev/netif/mii_layer/inphyreg.h index 68a430141b..75bb740990 100644 --- a/sys/dev/netif/mii_layer/inphyreg.h +++ b/sys/dev/netif/mii_layer/inphyreg.h @@ -26,11 +26,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/mii/inphyreg.h,v 1.1.2.1 2001/05/13 00:16:08 jlemon Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/inphyreg.h,v 1.2 2003/06/17 04:28:28 dillon Exp $ + * $FreeBSD: src/sys/dev/mii/inphyreg.h,v 1.1.2.1 2001/05/13 00:16:08 jlemon Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/inphyreg.h,v 1.3 2006/08/06 10:32:23 sephe Exp $ */ #define MII_INPHY_SCR 0x10 /* status and control register */ #define SCR_FLOWCTL 0x8000 +#define SCR_T4 0x0004 #define SCR_S100 0x0002 /* autonegotiated speed */ #define SCR_FDX 0x0001 /* autonegotiated duplex */ diff --git a/sys/dev/netif/mii_layer/lxtphy.c b/sys/dev/netif/mii_layer/lxtphy.c index 31bbaca2c0..e52b141503 100644 --- a/sys/dev/netif/mii_layer/lxtphy.c +++ b/sys/dev/netif/mii_layer/lxtphy.c @@ -1,4 +1,4 @@ -/* OpenBSD: lxtphy.c,v 1.5 2000/08/26 20:04:17 nate Exp */ +/* $OpenBSD: lxtphy.c,v 1.14 2005/02/19 06:00:04 brad Exp $ */ /* NetBSD: lxtphy.c,v 1.19 2000/02/02 23:34:57 thorpej Exp */ /*- @@ -38,7 +38,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/lxtphy.c,v 1.1.2.1 2001/06/08 19:58:33 semenu Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/lxtphy.c,v 1.8 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/lxtphy.c,v 1.9 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -71,7 +71,7 @@ */ /* - * driver for Level One's LXT-970 ethernet 10/100 PHY + * driver for Level One's LXT-970/LXT-971 ethernet 10/100 PHY * datasheet from www.level1.com */ @@ -94,19 +94,30 @@ #include "miibus_if.h" -static int lxtphy_probe (device_t); -static int lxtphy_attach (device_t); -static int lxtphy_detach (device_t); +static int lxtphy_probe(device_t); +static int lxtphy_attach(device_t); + +static int lxtphy_service(struct mii_softc *, struct mii_data *, int); +static void lxtphy_status(struct mii_softc *); +static void lxtphy_reset(struct mii_softc *); +static void lxtphy_set_tp(struct mii_softc *); +static void lxtphy_set_fx(struct mii_softc *); static device_method_t lxtphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, lxtphy_probe), DEVMETHOD(device_attach, lxtphy_attach), - DEVMETHOD(device_detach, lxtphy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; +static const struct mii_phydesc lxtphys[] = { + MII_PHYDESC_ARG(xxLEVEL1, LXT970, lxtphy_status), + MII_PHYDESC_ARG(xxLEVEL1a, LXT971, ukphy_status), + MII_PHYDESC_NULL +}; + static devclass_t lxtphy_devclass; static driver_t lxtphy_driver = { @@ -117,25 +128,21 @@ static driver_t lxtphy_driver = { DRIVER_MODULE(lxtphy, miibus, lxtphy_driver, lxtphy_devclass, 0, 0); -static int lxtphy_service (struct mii_softc *, struct mii_data *, int); -static void lxtphy_status (struct mii_softc *); -static void lxtphy_set_tp (struct mii_softc *); -static void lxtphy_set_fx (struct mii_softc *); - static int lxtphy_probe(device_t dev) { - struct mii_attach_args *ma; - - ma = device_get_ivars(dev); + struct mii_attach_args *ma = device_get_ivars(dev); + const struct mii_phydesc *mpd; - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxLEVEL1 && - MII_MODEL(ma->mii_id2) == MII_MODEL_xxLEVEL1_LXT970) { - device_set_desc(dev, MII_STR_xxLEVEL1_LXT970); - } else - return (ENXIO); + mpd = mii_phy_match(ma, lxtphys); + if (mpd != NULL) { + struct mii_softc *sc = device_get_softc(dev); - return (0); + sc->mii_status = mpd->mpd_priv; + device_set_desc(dev, mpd->mpd_name); + return (0); + } + return (ENXIO); } static int @@ -154,51 +161,32 @@ lxtphy_attach(device_t dev) sc->mii_inst = mii->mii_instance; sc->mii_service = lxtphy_service; + sc->mii_reset = lxtphy_reset; sc->mii_pdata = mii; sc->mii_flags |= MIIF_NOISOLATE; - mii_phy_reset(sc); + lxtphy_reset(sc); mii->mii_instance++; - sc->mii_capabilities = - PHY_READ(sc, MII_BMSR) & ma->mii_capmask; - device_printf(dev, " "); - #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_FX, 0, sc->mii_inst), - BMCR_S100); - printf("100baseFX, "); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_FX, IFM_FDX, sc->mii_inst), - BMCR_S100|BMCR_FDX); - printf("100baseFX-FDX, "); + MII_MEDIA_NONE); #undef ADD + sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + + device_printf(dev, " "); if (sc->mii_capabilities & BMSR_MEDIAMASK) - mii_add_media(sc, sc->mii_capabilities); + mii_phy_add_media(sc); + else + printf("no media present"); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); return(0); } - -static int -lxtphy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); - - return(0); -} - static int lxtphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { @@ -231,35 +219,12 @@ lxtphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - switch (IFM_SUBTYPE(ife->ifm_media)) { - case IFM_AUTO: - /* - * If we're already in auto mode, just return. - */ - if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) - return (0); - - lxtphy_set_tp(sc); - - (void) mii_phy_auto(sc, 1); - break; - case IFM_100_T4: - /* - * XXX Not supported as a manual setting right now. - */ - return (EINVAL); - - case IFM_100_FX: + if (IFM_SUBTYPE(ife->ifm_media) == IFM_100_FX) lxtphy_set_fx(sc); + else + lxtphy_set_tp(sc); - default: - /* - * BMCR data is stored in the ifmedia entry. - */ - PHY_WRITE(sc, MII_ANAR, - mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); - } + mii_phy_set_media(sc); break; case MII_TICK: @@ -269,49 +234,16 @@ lxtphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 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); - if (mii_phy_auto(sc, 0) == EJUSTRETURN) + if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } /* Update the media status. */ - lxtphy_status(sc); + sc->mii_status(sc); /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } @@ -380,3 +312,13 @@ lxtphy_set_fx(struct mii_softc *sc) cfg |= CONFIG_100BASEFX; PHY_WRITE(sc, MII_LXTPHY_CONFIG, cfg); } + +static void +lxtphy_reset(struct mii_softc *sc) +{ + mii_phy_reset(sc); +#if 0 + PHY_WRITE(sc, MII_LXTPHY_IER, + PHY_READ(sc, MII_LXTPHY_IER) & ~IER_INTEN); +#endif +} diff --git a/sys/dev/netif/mii_layer/mii.c b/sys/dev/netif/mii_layer/mii.c index 262b2c1afe..60d1f3c35a 100644 --- a/sys/dev/netif/mii_layer/mii.c +++ b/sys/dev/netif/mii_layer/mii.c @@ -1,7 +1,7 @@ -/* $NetBSD: mii.c,v 1.12 1999/08/03 19:41:49 drochner Exp $ */ +/* $NetBSD: mii.c,v 1.40 2005/12/11 12:22:42 christos Exp $ */ /*- - * Copyright (c) 1998 The NetBSD Foundation, Inc. + * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -37,7 +37,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/mii.c,v 1.6.2.2 2002/08/19 16:56:33 ambrisko Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/mii.c,v 1.8 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/mii.c,v 1.9 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -95,6 +95,21 @@ driver_t miibus_driver = { sizeof(struct mii_data) }; +/* + * Check to see if there is a PHY at this address. Note, + * many braindead PHYs report 0/0 in their ID registers, + * so we test for media in the BMSR. + */ +static __inline int +miibus_no_phy(device_t dev, int phyno) +{ + int bmsr; + + bmsr = MIIBUS_READREG(dev, phyno, MII_BMSR); + return (bmsr == 0 || bmsr == 0xffff || + (bmsr & (BMSR_MEDIAMASK | BMSR_EXTSTAT)) == 0); +} + /* * Helper function used by network interface drivers, attaches PHYs * to the network interface driver parent. @@ -106,7 +121,7 @@ miibus_probe(device_t dev) struct mii_attach_args ma, *args; struct mii_data *mii; device_t child = NULL, parent; - int bmsr, capmask = 0xFFFFFFFF; + int capmask = 0xFFFFFFFF; mii = device_get_softc(dev); parent = device_get_parent(dev); @@ -114,17 +129,8 @@ miibus_probe(device_t dev) bzero(&ma, sizeof(ma)); for (ma.mii_phyno = 0; ma.mii_phyno < MII_NPHY; ma.mii_phyno++) { - /* - * Check to see if there is a PHY at this address. Note, - * many braindead PHYs report 0/0 in their ID registers, - * so we test for media in the BMSR. - */ - bmsr = MIIBUS_READREG(parent, ma.mii_phyno, MII_BMSR); - if (bmsr == 0 || bmsr == 0xffff || - (bmsr & BMSR_MEDIAMASK) == 0) { - /* Assume no PHY at this address. */ + if (miibus_no_phy(parent, ma.mii_phyno)) continue; - } /* * Extract the IDs. Braindead PHYs will be handled by @@ -242,7 +248,7 @@ mii_phy_probe(device_t dev, device_t *child, ifm_change_cb_t ifmedia_upd, ifm_stat_cb_t ifmedia_sts) { void **v; - int bmsr, i; + int i; v = malloc(sizeof(vm_offset_t) * 2, M_DEVBUF, M_INTWAIT); v[0] = ifmedia_upd; @@ -251,12 +257,7 @@ mii_phy_probe(device_t dev, device_t *child, ifm_change_cb_t ifmedia_upd, device_set_ivars(*child, v); for (i = 0; i < MII_NPHY; i++) { - bmsr = MIIBUS_READREG(dev, i, MII_BMSR); - if (bmsr == 0 || bmsr == 0xffff || - (bmsr & BMSR_MEDIAMASK) == 0) { - /* Assume no PHY at this address. */ - continue; - } else + if (!miibus_no_phy(dev, i)) break; } @@ -324,4 +325,3 @@ mii_pollstat(struct mii_data *mii) static moduledata_t miibus_mod = { "miibus" }; DECLARE_MODULE(miibus, miibus_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); - diff --git a/sys/dev/netif/mii_layer/mii.h b/sys/dev/netif/mii_layer/mii.h index d9fdffe996..53a7fbe290 100644 --- a/sys/dev/netif/mii_layer/mii.h +++ b/sys/dev/netif/mii_layer/mii.h @@ -1,4 +1,4 @@ -/* $NetBSD: mii.h,v 1.1 1998/08/10 23:55:17 thorpej Exp $ */ +/* $NetBSD: mii.h,v 1.13 2005/12/11 12:22:42 christos Exp $ */ /* * Copyright (c) 1997 Manuel Bouyer. All rights reserved. @@ -32,7 +32,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/mii.h,v 1.2 1999/08/28 00:42:14 peter Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/mii.h,v 1.3 2005/10/12 00:57:41 dillon Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/mii.h,v 1.4 2006/08/06 10:32:23 sephe Exp $ */ #ifndef _DEV_MII_MII_H_ @@ -53,17 +53,6 @@ #define MII_COMMAND_WRITE 0x01 #define MII_COMMAND_ACK 0x02 -/* - * MII registers are bits - * - * note 1: Most adapters seem to have adopted these bits for GigE support, - * but they have not been verified against any standard. - * Theoretically the speed select will extend to 10GigE as well. - * - * The netgear GigE switch reports both the bits I have labeled - * ANLPAR_1000 and ANLPAR_1000_FD, but it is unclear what they mean - * other then probably being related to GigE. - */ #define MII_BMCR 0x00 /* Basic mode control register (rw) */ #define BMCR_RESET 0x8000 /* reset */ #define BMCR_LOOP 0x4000 /* loopback */ @@ -75,23 +64,40 @@ #define BMCR_FDX 0x0100 /* Set duplex mode */ #define BMCR_CTEST 0x0080 /* collision test */ #define BMCR_S1000 0x0040 /* speed select (high bit) (note 1) */ +#define BMCR_S10 0x0000 /* 10 Mb/s */ +#define BMCR_SPEED(x) ((x) & (BMCR_S1000 | BMCR_S100)) +/* + * Note that the EXTSTAT bit indicates that there is extended status + * info available in register 15, but 802.3 section 22.2.4.3 also + * states that that all 1000 Mb/s capable PHYs will set this bit to 1. + */ #define MII_BMSR 0x01 /* Basic mode status register (ro) */ #define BMSR_100T4 0x8000 /* 100 base T4 capable */ #define BMSR_100TXFDX 0x4000 /* 100 base Tx full duplex capable */ #define BMSR_100TXHDX 0x2000 /* 100 base Tx half duplex capable */ #define BMSR_10TFDX 0x1000 /* 10 base T full duplex capable */ #define BMSR_10THDX 0x0800 /* 10 base T half duplex capable */ -#define BMSR_1000 0x0100 /* 1000baseT extended status present */ +#define BMSR_100T2FDX 0x0400 /* 100 base T2 full duplex capable */ +#define BMSR_100T2HDX 0x0200 /* 100 base T2 half duplex capable */ +#define BMSR_EXTSTAT 0x0100 /* Extended status in register 15 */ +#define BMSR_MFPS 0x0040 /* MII Frame Preamble Suppression */ #define BMSR_ACOMP 0x0020 /* Autonegotiation complete */ #define BMSR_RFAULT 0x0010 /* Link partner fault */ #define BMSR_ANEG 0x0008 /* Autonegotiation capable */ #define BMSR_LINK 0x0004 /* Link status */ #define BMSR_JABBER 0x0002 /* Jabber detected */ -#define BMSR_EXT 0x0001 /* Extended capability */ +#define BMSR_EXTCAP 0x0001 /* Extended capability */ + +#define BMSR_MEDIAMASK (BMSR_100T4 | BMSR_100TXFDX | BMSR_100TXHDX | \ + BMSR_10TFDX | BMSR_10THDX| BMSR_100T2FDX | \ + BMSR_100T2HDX) -#define BMSR_MEDIAMASK (BMSR_100T4|BMSR_100TXFDX|BMSR_100TXHDX|BMSR_10TFDX| \ - BMSR_10THDX|BMSR_1000|BMSR_ANEG) +/* + * Convert BMSR media capabilities to ANAR bits for autonegotiation. + * Note the shift chopps off the BMSR_ANEG bit. + */ +#define BMSR_MEDIA_TO_ANAR(x) (((x) & BMSR_MEDIAMASK) >> 6) #define MII_PHYIDR1 0x02 /* ID register 1 (ro) */ @@ -105,11 +111,11 @@ #define MII_REV(id2) ((id2) & IDR2_REV) #define MII_ANAR 0x04 /* Autonegotiation advertisement (rw) */ + /* section 28.2.4.1 and 37.2.6.1 */ #define ANAR_NP 0x8000 /* Next page (ro) */ #define ANAR_ACK 0x4000 /* link partner abilities acknowledged (ro) */ #define ANAR_RF 0x2000 /* remote fault (ro) */ -#define ANAR_1000_FD 0x0800 /* local device supports GigE/FD (note 1) */ -#define ANAR_1000 0x0400 /* local device supports GigE (note 1) */ +#define ANAR_FC 0x0400 /* local device supports PAUSE */ #define ANAR_T4 0x0200 /* local device supports 100bT4 */ #define ANAR_TX_FD 0x0100 /* local device supports 100bTx FD */ #define ANAR_TX 0x0080 /* local device supports 100bTx */ @@ -117,12 +123,19 @@ #define ANAR_10 0x0020 /* local device supports 10bT */ #define ANAR_CSMA 0x0001 /* protocol selector CSMA/CD */ +#define ANAR_X_FD 0x0020 /* local device supports 1000BASE-X FD */ +#define ANAR_X_HD 0x0040 /* local device supports 1000BASE-X HD */ +#define ANAR_X_PAUSE_NONE (0 << 10) +#define ANAR_X_PAUSE_SYM (1 << 10) +#define ANAR_X_PAUSE_ASYM (2 << 10) +#define ANAR_X_PAUSE_TOWARDS (3 << 10) + #define MII_ANLPAR 0x05 /* Autonegotiation lnk partner abilities (rw) */ + /* section 28.2.4.1 and 37.2.6.1 */ #define ANLPAR_NP 0x8000 /* Next page (ro) */ #define ANLPAR_ACK 0x4000 /* link partner accepted ACK (ro) */ #define ANLPAR_RF 0x2000 /* remote fault (ro) */ -#define ANLPAR_1000_FD 0x0800 /* link partner supports GigE/FD (note 1) */ -#define ANLPAR_1000 0x0400 /* link partner supports GigE (note 1) */ +#define ANLPAR_FC 0x0400 /* link partner supports PAUSE */ #define ANLPAR_T4 0x0200 /* link partner supports 100bT4 */ #define ANLPAR_TX_FD 0x0100 /* link partner supports 100bTx FD */ #define ANLPAR_TX 0x0080 /* link partner supports 100bTx */ @@ -130,11 +143,55 @@ #define ANLPAR_10 0x0020 /* link partner supports 10bT */ #define ANLPAR_CSMA 0x0001 /* protocol selector CSMA/CD */ +#define ANLPAR_X_FD 0x0020 /* local device supports 1000BASE-X FD */ +#define ANLPAR_X_HD 0x0040 /* local device supports 1000BASE-X HD */ +#define ANLPAR_X_PAUSE_MASK (3 << 10) +#define ANLPAR_X_PAUSE_NONE (0 << 10) +#define ANLPAR_X_PAUSE_SYM (1 << 10) +#define ANLPAR_X_PAUSE_ASYM (2 << 10) +#define ANLPAR_X_PAUSE_TOWARDS (3 << 10) + #define MII_ANER 0x06 /* Autonegotiation expansion (ro) */ + /* section 28.2.4.1 and 37.2.6.1 */ #define ANER_MLF 0x0010 /* multiple link detection fault */ #define ANER_LPNP 0x0008 /* link parter next page-able */ #define ANER_NP 0x0004 /* next page-able */ #define ANER_PAGE_RX 0x0002 /* Page received */ #define ANER_LPAN 0x0001 /* link parter autoneg-able */ +#define MII_ANNP 0x07 /* Autonegotiation next page */ + /* section 28.2.4.1 and 37.2.6.1 */ + +#define MII_ANLPRNP 0x08 /* Autonegotiation link partner rx next page */ + /* section 32.5.1 and 37.2.6.1 */ + + /* This is also the 1000baseT control register */ +#define MII_100T2CR 0x09 /* 100base-T2 control register */ +#define GTCR_TEST_MASK 0xe000 /* see 802.3ab ss. 40.6.1.1.2 */ +#define GTCR_MAN_MS 0x1000 /* enable manual master/slave control */ +#define GTCR_ADV_MS 0x0800 /* 1 = adv. master, 0 = adv. slave */ +#define GTCR_PORT_TYPE 0x0400 /* 1 = DCE, 0 = DTE (NIC) */ +#define GTCR_ADV_1000TFDX 0x0200 /* adv. 1000baseT FDX */ +#define GTCR_ADV_1000THDX 0x0100 /* adv. 1000baseT HDX */ + + /* This is also the 1000baseT status register */ +#define MII_100T2SR 0x0a /* 100base-T2 status register */ +#define GTSR_MAN_MS_FLT 0x8000 /* master/slave config fault */ +#define GTSR_MS_RES 0x4000 /* result: 1 = master, 0 = slave */ +#define GTSR_LRS 0x2000 /* local rx status, 1 = ok */ +#define GTSR_RRS 0x1000 /* remove rx status, 1 = ok */ +#define GTSR_LP_1000TFDX 0x0800 /* link partner 1000baseT FDX capable */ +#define GTSR_LP_1000THDX 0x0400 /* link partner 1000baseT HDX capable */ +#define GTSR_LP_ASM_DIR 0x0200 /* link partner asym. pause dir. capable */ +#define GTSR_IDLE_ERR 0x00ff /* IDLE error count */ + +#define MII_EXTSR 0x0f /* Extended status register */ +#define EXTSR_1000XFDX 0x8000 /* 1000X full-duplex capable */ +#define EXTSR_1000XHDX 0x4000 /* 1000X half-duplex capable */ +#define EXTSR_1000TFDX 0x2000 /* 1000T full-duplex capable */ +#define EXTSR_1000THDX 0x1000 /* 1000T half-duplex capable */ + +#define EXTSR_MEDIAMASK (EXTSR_1000XFDX | EXTSR_1000XHDX | \ + EXTSR_1000TFDX | EXTSR_1000THDX) + #endif /* _DEV_MII_MII_H_ */ diff --git a/sys/dev/netif/mii_layer/mii_physubr.c b/sys/dev/netif/mii_layer/mii_physubr.c index df06cec455..cb0c082244 100644 --- a/sys/dev/netif/mii_layer/mii_physubr.c +++ b/sys/dev/netif/mii_layer/mii_physubr.c @@ -1,7 +1,7 @@ -/* $NetBSD: mii_physubr.c,v 1.5 1999/08/03 19:41:49 drochner Exp $ */ +/* $NetBSD: mii_physubr.c,v 1.49 2006/03/29 07:05:24 thorpej Exp $ */ /*- - * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. + * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -37,7 +37,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/mii_physubr.c,v 1.2.2.1 2000/12/12 19:29:14 wpaul Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/mii_physubr.c,v 1.11 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/mii_physubr.c,v 1.12 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -53,8 +53,6 @@ #include #include -#include - #include #include @@ -63,7 +61,47 @@ #include "miibus_if.h" -void mii_phy_auto_timeout (void *); +const struct mii_media mii_media_table[MII_NMEDIA] = { + [MII_MEDIA_NONE] = { .mm_bmcr = BMCR_ISO, + .mm_anar = ANAR_CSMA, + .mm_gtcr = 0 }, + + [MII_MEDIA_10_T] = { .mm_bmcr = BMCR_S10, + .mm_anar = ANAR_CSMA | ANAR_10, + .mm_gtcr = 0 }, + + [MII_MEDIA_10_T_FDX] = { .mm_bmcr = BMCR_S10 | BMCR_FDX, + .mm_anar = ANAR_CSMA | ANAR_10_FD, + .mm_gtcr = 0 }, + + [MII_MEDIA_100_T4] = { .mm_bmcr = BMCR_S100, + .mm_anar = ANAR_CSMA | ANAR_T4, + .mm_gtcr = 0 }, + + [MII_MEDIA_100_TX] = { .mm_bmcr = BMCR_S100, + .mm_anar = ANAR_CSMA | ANAR_TX, + .mm_gtcr = 0 }, + + [MII_MEDIA_100_TX_FDX] = { .mm_bmcr = BMCR_S100 | BMCR_FDX, + .mm_anar = ANAR_CSMA | ANAR_TX_FD, + .mm_gtcr = 0 }, + + [MII_MEDIA_1000_X] = { .mm_bmcr = BMCR_S1000, + .mm_anar = ANAR_CSMA, + .mm_gtcr = 0 }, + + [MII_MEDIA_1000_X_FDX] = { .mm_bmcr = BMCR_S1000 | BMCR_FDX, + .mm_anar = ANAR_CSMA, + .mm_gtcr = 0 }, + + [MII_MEDIA_1000_T] = { .mm_bmcr = BMCR_S1000, + .mm_anar = ANAR_CSMA, + .mm_gtcr = GTCR_ADV_1000THDX }, + + [MII_MEDIA_1000_T_FDX] = { .mm_bmcr = BMCR_S1000, + .mm_anar = ANAR_CSMA, + .mm_gtcr = GTCR_ADV_1000TFDX } +}; void mii_softc_init(struct mii_softc *mii, struct mii_attach_args *ma) @@ -71,29 +109,73 @@ mii_softc_init(struct mii_softc *mii, struct mii_attach_args *ma) callout_init(&mii->mii_auto_ch); mii->mii_phy = ma->mii_phyno; mii->mii_flags |= ma->mii_flags; + mii->mii_model = MII_MODEL(ma->mii_id2); + mii->mii_rev = MII_REV(ma->mii_id2); + + if (mii->mii_reset == NULL) + mii->mii_reset = mii_phy_reset; + if (mii->mii_anegticks == 0) + mii->mii_anegticks = MII_ANEGTICKS; } int -mii_phy_auto(struct mii_softc *mii, int waitfor) +mii_phy_auto(struct mii_softc *sc, int waitfor) { - int bmsr, i; + int i; - if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) { - PHY_WRITE(mii, MII_ANAR, mii_bmsr_media_to_anar(mii)); - PHY_WRITE(mii, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); + if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) { + /* + * Check for 1000BASE-X. Autonegotiation is a bit + * different on such devices. + */ + if (sc->mii_flags & MIIF_IS_1000X) { + uint16_t anar = 0; + + if (sc->mii_extcapabilities & EXTSR_1000XFDX) + anar |= ANAR_X_FD; + if (sc->mii_extcapabilities & EXTSR_1000XHDX) + anar |= ANAR_X_HD; + + if (sc->mii_flags & MIIF_DOPAUSE) { + /* XXX Asymmetric vs. symmetric? */ + anar |= ANLPAR_X_PAUSE_TOWARDS; + } + + PHY_WRITE(sc, MII_ANAR, anar); + } else { + uint16_t anar; + + anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | + ANAR_CSMA; + if (sc->mii_flags & MIIF_DOPAUSE) { + anar |= ANAR_FC; + /* XXX Only 1000BASE-T has PAUSE_ASYM? */ + if ((sc->mii_flags & MIIF_HAVE_GTCR) && + (sc->mii_extcapabilities & + (EXTSR_1000THDX|EXTSR_1000TFDX))) + anar |= ANAR_X_PAUSE_ASYM; + } + PHY_WRITE(sc, MII_ANAR, anar); + if (sc->mii_flags & MIIF_HAVE_GTCR) { + uint16_t gtcr = 0; + + if (sc->mii_extcapabilities & EXTSR_1000TFDX) + gtcr |= GTCR_ADV_1000TFDX; + if (sc->mii_extcapabilities & EXTSR_1000THDX) + gtcr |= GTCR_ADV_1000THDX; + + PHY_WRITE(sc, MII_100T2CR, gtcr); + } + } + PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); } if (waitfor) { /* Wait 500ms for it to complete. */ for (i = 0; i < 500; i++) { - if ((bmsr = PHY_READ(mii, MII_BMSR)) & BMSR_ACOMP) + if (PHY_READ(sc, MII_BMSR) & BMSR_ACOMP) return (0); DELAY(1000); -#if 0 - if ((bmsr & BMSR_ACOMP) == 0) - printf("%s: autonegotiation failed to complete\n", - mii->mii_dev.dv_xname); -#endif } /* @@ -109,10 +191,14 @@ mii_phy_auto(struct mii_softc *mii, int waitfor) * the tick handler driving autonegotiation. Don't want 500ms * delays all the time while the system is running! */ - if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) { - mii->mii_flags |= MIIF_DOINGAUTO; - callout_reset(&mii->mii_auto_ch, hz >> 1, - mii_phy_auto_timeout, mii); + if (sc->mii_flags & MIIF_AUTOTSLEEP) { + sc->mii_flags |= MIIF_DOINGAUTO; + tsleep(&sc->mii_flags, 0, "miiaut", hz >> 1); + mii_phy_auto_timeout(sc); + } else if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) { + sc->mii_flags |= MIIF_DOINGAUTO; + callout_reset(&sc->mii_auto_ch, hz >> 1, + mii_phy_auto_timeout, sc); } return (EJUSTRETURN); } @@ -126,105 +212,53 @@ mii_phy_auto_stop(struct mii_softc *sc) } } +/* XXX should use serializer */ void mii_phy_auto_timeout(void *arg) { - struct mii_softc *mii = arg; - int bmsr; + struct mii_softc *sc = arg; crit_enter(); - mii->mii_flags &= ~MIIF_DOINGAUTO; - bmsr = PHY_READ(mii, MII_BMSR); -#if 0 - if ((bmsr & BMSR_ACOMP) == 0) - printf("%s: autonegotiation failed to complete\n", - sc->sc_dev.dv_xname); -#endif + sc->mii_flags &= ~MIIF_DOINGAUTO; /* Update the media status. */ - (void) (*mii->mii_service)(mii, mii->mii_pdata, MII_POLLSTAT); + sc->mii_service(sc, sc->mii_pdata, MII_POLLSTAT); crit_exit(); } void -mii_phy_reset(struct mii_softc *mii) +mii_phy_reset(struct mii_softc *sc) { int reg, i; - if (mii->mii_flags & MIIF_NOISOLATE) + if (sc->mii_flags & MIIF_NOISOLATE) reg = BMCR_RESET; else reg = BMCR_RESET | BMCR_ISO; - PHY_WRITE(mii, MII_BMCR, reg); + PHY_WRITE(sc, MII_BMCR, reg); + + /* + * It is best to allow a little time for the reset to settle + * in before we start polling the BMCR again. Notably, the + * DP83840A manual states that there should be a 500us delay + * between asserting software reset and attempting MII serial + * operations. Also, a DP83815 can get into a bad state on + * cable removal and reinsertion if we do not delay here. + */ + DELAY(500); /* Wait 100ms for it to complete. */ for (i = 0; i < 100; i++) { - reg = PHY_READ(mii, MII_BMCR); + reg = PHY_READ(sc, MII_BMCR); if ((reg & BMCR_RESET) == 0) break; DELAY(1000); } - if (mii->mii_inst != 0 && ((mii->mii_flags & MIIF_NOISOLATE) == 0)) - PHY_WRITE(mii, MII_BMCR, reg | BMCR_ISO); -} - -/* - * Given an ifmedia word, return the corresponding ANAR value. - */ -int -mii_anar(int media) -{ - int rv; - - rv = ANAR_CSMA; - switch (media & (IFM_TMASK|IFM_NMASK|IFM_FDX)) { - case IFM_ETHER|IFM_1000_T: - rv |= ANAR_1000; - break; - case IFM_ETHER|IFM_1000_T|IFM_FDX: - rv |= ANAR_1000_FD; - break; - case IFM_ETHER|IFM_10_T: - rv |= ANAR_10; - break; - case IFM_ETHER|IFM_10_T|IFM_FDX: - rv |= ANAR_10_FD; - break; - case IFM_ETHER|IFM_100_TX: - rv |= ANAR_TX; - break; - case IFM_ETHER|IFM_100_TX|IFM_FDX: - rv |= ANAR_TX_FD; - break; - case IFM_ETHER|IFM_100_T4: - rv |= ANAR_T4; - break; - default: - rv = 0; - break; - } - return (rv); -} - -/* - * Given a BMCR value, return the corresponding ifmedia word. - */ -int -mii_media_from_bmcr(int bmcr) -{ - int rv = IFM_ETHER; - - if (bmcr & BMCR_S100) - rv |= IFM_100_TX; - else - rv |= IFM_10_T; - if (bmcr & BMCR_FDX) - rv |= IFM_FDX; - - return (rv); + if (sc->mii_inst != 0 && ((sc->mii_flags & MIIF_NOISOLATE) == 0)) + PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); } /* @@ -233,80 +267,331 @@ mii_media_from_bmcr(int bmcr) * of media names. Does not print a newline. */ void -mii_add_media(struct mii_softc *sc, int bmsr) +mii_phy_add_media(struct mii_softc *sc) { struct mii_data *mii = sc->mii_pdata; - int instance = sc->mii_inst; const char *sep = ""; + int fdx = 0; #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) #define PRINT(s) printf("%s%s", sep, s); sep = ", " - if (bmsr & BMSR_10THDX) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, instance), 0); + if ((sc->mii_flags & MIIF_NOISOLATE) == 0) + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), + MII_MEDIA_NONE); + + /* + * There are different interpretations for the bits in + * HomePNA PHYs. And there is really only one media type + * that is supported. + */ + if (sc->mii_flags & MIIF_IS_HPNA) { + if (sc->mii_capabilities & BMSR_10THDX) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0, + sc->mii_inst), + MII_MEDIA_10_T); + PRINT("HomePNA1"); + } + return; + } + + if (sc->mii_capabilities & BMSR_10THDX) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst), + MII_MEDIA_10_T); PRINT("10baseT"); } - if (bmsr & BMSR_10TFDX) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, instance), - BMCR_FDX); + if (sc->mii_capabilities & BMSR_10TFDX) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst), + MII_MEDIA_10_T_FDX); PRINT("10baseT-FDX"); + fdx = 1; } - if (bmsr & BMSR_100TXHDX) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, instance), - BMCR_S100); + if (sc->mii_capabilities & BMSR_100TXHDX) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst), + MII_MEDIA_100_TX); PRINT("100baseTX"); } - if (bmsr & BMSR_100TXFDX) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, instance), - BMCR_S100|BMCR_FDX); + if (sc->mii_capabilities & BMSR_100TXFDX) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst), + MII_MEDIA_100_TX_FDX); PRINT("100baseTX-FDX"); + fdx = 1; } - if (bmsr & BMSR_100T4) { - /* - * XXX How do you enable 100baseT4? I assume we set - * XXX BMCR_S100 and then assume the PHYs will take - * XXX watever action is necessary to switch themselves - * XXX into T4 mode. - */ - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, instance), - BMCR_S100); + if (sc->mii_capabilities & BMSR_100T4) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst), + MII_MEDIA_100_T4); PRINT("100baseT4"); } - if (sc->mii_flags & MIIF_IS_1000X) { - if (bmsr & BMSR_1000) { + + if (sc->mii_extcapabilities & EXTSR_MEDIAMASK) { + /* + * XXX Right now only handle 1000SX and 1000TX. Need + * XXX to handle 1000LX and 1000CX some how. + * + * Note since it can take 5 seconds to auto-negotiate + * a gigabit link, we make anegticks 10 seconds for + * all the gigabit media types. + */ + if (sc->mii_extcapabilities & EXTSR_1000XHDX) { + sc->mii_anegticks = MII_ANEGTICKS_GIGE; + sc->mii_flags |= MIIF_IS_1000X; + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, 0, + sc->mii_inst), MII_MEDIA_1000_X); + PRINT("1000baseSX"); + } + if (sc->mii_extcapabilities & EXTSR_1000XFDX) { + sc->mii_anegticks = MII_ANEGTICKS_GIGE; + sc->mii_flags |= MIIF_IS_1000X; + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, + sc->mii_inst), MII_MEDIA_1000_X_FDX); + PRINT("1000baseSX-FDX"); + fdx = 1; + } + + /* + * 1000baseT media needs to be able to manipulate + * master/slave mode. We set IFM_ETH_MASTER in + * the "don't care mask" and filter it out when + * the media is set. + * + * All 1000baseT PHYs have a 1000baseT control register. + */ + if (sc->mii_extcapabilities & EXTSR_1000THDX) { + sc->mii_anegticks = MII_ANEGTICKS_GIGE; + sc->mii_flags |= MIIF_HAVE_GTCR; + mii->mii_media.ifm_mask |= IFM_ETH_MASTER; + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, + sc->mii_inst), MII_MEDIA_1000_T); + PRINT("1000baseT"); + } + if (sc->mii_extcapabilities & EXTSR_1000TFDX) { + sc->mii_anegticks = MII_ANEGTICKS_GIGE; + sc->mii_flags |= MIIF_HAVE_GTCR; + mii->mii_media.ifm_mask |= IFM_ETH_MASTER; ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, - instance), BMCR_S1000); + sc->mii_inst), MII_MEDIA_1000_T_FDX); PRINT("1000baseT-FDX"); + fdx = 1; } } - if (bmsr & BMSR_ANEG) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, instance), - BMCR_AUTOEN); + + if (sc->mii_capabilities & BMSR_ANEG) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), + MII_NMEDIA); /* intentionally invalid index */ PRINT("auto"); } #undef ADD #undef PRINT + if (fdx != 0 && (sc->mii_flags & MIIF_DOPAUSE)) + mii->mii_media.ifm_mask |= IFM_ETH_FMASK; } +void +mii_phy_set_media(struct mii_softc *sc) +{ + struct mii_data *mii = sc->mii_pdata; + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; + int bmcr, anar, gtcr; + + if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { + /* + * Force renegotiation if MIIF_DOPAUSE. + * + * XXX This is only necessary because many NICs don't + * XXX advertise PAUSE capabilities at boot time. Maybe + * XXX we should force this only once? + */ + if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0 || + (sc->mii_flags & (MIIF_FORCEANEG | MIIF_DOPAUSE))) + mii_phy_auto(sc, 1); + return; + } + + /* + * Table index is stored in the media entry. + */ + + KASSERT(ife->ifm_data >= 0 && ife->ifm_data < MII_NMEDIA, + ("bogus ife->ifm_data (%d)\n", ife->ifm_data)); + + anar = mii_media_table[ife->ifm_data].mm_anar; + bmcr = mii_media_table[ife->ifm_data].mm_bmcr; + gtcr = mii_media_table[ife->ifm_data].mm_gtcr; + + if (mii->mii_media.ifm_media & IFM_ETH_MASTER) { + switch (IFM_SUBTYPE(ife->ifm_media)) { + case IFM_1000_T: + gtcr |= GTCR_MAN_MS|GTCR_ADV_MS; + break; + + default: + panic("mii_phy_setmedia: MASTER on wrong media"); + } + } + + if (mii->mii_media.ifm_media & IFM_FLOW) { + if (sc->mii_flags & MIIF_IS_1000X) { + anar |= ANAR_X_PAUSE_SYM | ANAR_X_PAUSE_ASYM; + } else { + anar |= ANAR_FC; + /* XXX Only 1000BASE-T has PAUSE_ASYM? */ + if ((sc->mii_flags & MIIF_HAVE_GTCR) && + (sc->mii_extcapabilities & + (EXTSR_1000THDX | EXTSR_1000TFDX))) + anar |= ANAR_X_PAUSE_ASYM; + } + } + + if (ife->ifm_media & IFM_LOOP) + bmcr |= BMCR_LOOP; + + PHY_WRITE(sc, MII_ANAR, anar); + PHY_WRITE(sc, MII_BMCR, bmcr); + if (sc->mii_flags & MIIF_HAVE_GTCR) + PHY_WRITE(sc, MII_100T2CR, gtcr); +} + +int +mii_phy_tick(struct mii_softc *sc) +{ + struct mii_data *mii = sc->mii_pdata; + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; + int reg; + + /* Just bail now if the interface is down. */ + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) + return (EJUSTRETURN); + + /* + * If we're not doing autonegotiation, we don't need to do + * any extra work here. However, we need to check the link + * status so we can generate an announcement if the status + * changes. + */ + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + return (0); + + /* Read the status register twice; BMSR_LINK is latch-low. */ + reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); + if (reg & BMSR_LINK) { + /* + * See above. + */ + return (0); + } + + /* + * Only retry autonegotiation every N seconds. + */ + KKASSERT(sc->mii_anegticks > 0); + if (++sc->mii_ticks != sc->mii_anegticks) + return (EJUSTRETURN); + + sc->mii_ticks = 0; + sc->mii_reset(sc); /* Reset PHY */ + + if (mii_phy_auto(sc, 0) == EJUSTRETURN) + return (EJUSTRETURN); + + /* + * Might need to generate a status message if autonegotiation + * failed. + */ + return (0); +} + +#ifdef notyet +static void +mii_phy_statusmsg(struct mii_softc *sc) +{ + struct mii_data *mii = sc->mii_pdata; + struct ifnet *ifp = mii->mii_ifp; + int s; + + crit_enter(); + if (mii->mii_media_status & IFM_AVALID) { + if (mii->mii_media_status & IFM_ACTIVE) + if_link_state_change(ifp, LINK_STATE_UP); + else + if_link_state_change(ifp, LINK_STATE_DOWN); + } else + if_link_state_change(ifp, LINK_STATE_UNKNOWN); + crit_exit(); + + ifp->if_baudrate = ifmedia_baudrate(mii->mii_media_active); +} +#endif + +void +mii_phy_update(struct mii_softc *sc, int cmd) +{ + struct mii_data *mii = sc->mii_pdata; + + if (sc->mii_media_active != mii->mii_media_active || + sc->mii_media_status != mii->mii_media_status || + cmd == MII_MEDIACHG) { +#ifdef notyet + mii_phy_statusmsg(sc); +#endif + MIIBUS_STATCHG(sc->mii_dev); + sc->mii_media_active = mii->mii_media_active; + sc->mii_media_status = mii->mii_media_status; + } +} + +/* + * Return the flow control status flag from MII_ANAR & MII_ANLPAR. + */ int -mii_bmsr_media_to_anar(struct mii_softc *mii) +mii_phy_flowstatus(struct mii_softc *sc) +{ + int anar, anlpar; + + if ((sc->mii_flags & MIIF_DOPAUSE) == 0) + return (0); + + anar = PHY_READ(sc, MII_ANAR); + anlpar = PHY_READ(sc, MII_ANLPAR); + + if ((anar & ANAR_X_PAUSE_SYM) & (anlpar & ANLPAR_X_PAUSE_SYM)) + return (IFM_FLOW | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE); + + if ((anar & ANAR_X_PAUSE_SYM) == 0) { + if ((anar & ANAR_X_PAUSE_ASYM) && + ((anlpar & ANLPAR_X_PAUSE_TOWARDS) == + ANLPAR_X_PAUSE_TOWARDS)) + return (IFM_FLOW | IFM_ETH_TXPAUSE); + else + return (0); + } + + if ((anar & ANAR_X_PAUSE_ASYM) == 0) { + if (anlpar & ANLPAR_X_PAUSE_SYM) + return (IFM_FLOW | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE); + else + return (0); + } + + switch (anlpar & ANLPAR_X_PAUSE_TOWARDS) { + case ANLPAR_X_PAUSE_NONE: + return (0); + + case ANLPAR_X_PAUSE_ASYM: + return (IFM_FLOW | IFM_ETH_RXPAUSE); + + default: + return (IFM_FLOW | IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE); + } + /* NOTREACHED */ +} + +const struct mii_phydesc * +mii_phy_match(const struct mii_attach_args *ma, const struct mii_phydesc *mpd) { - int bmsr = mii->mii_capabilities; - int res = ANAR_CSMA; - - if (bmsr & BMSR_100T4) - res |= ANAR_T4; - if (bmsr & BMSR_100TXFDX) - res |= ANAR_TX_FD; - if (bmsr & BMSR_100TXHDX) - res |= ANAR_TX; - if (bmsr & BMSR_10TFDX) - res |= ANAR_10_FD; - if (bmsr & BMSR_10THDX) - res |= ANAR_10; - if (mii->mii_flags & MIIF_IS_1000X) { - if (bmsr & BMSR_1000) - res |= ANAR_1000_FD; + for (; mpd->mpd_name != NULL; mpd++) { + if (MII_OUI(ma->mii_id1, ma->mii_id2) == mpd->mpd_oui && + MII_MODEL(ma->mii_id2) == mpd->mpd_model) + return (mpd); } - return (res); + return (NULL); } diff --git a/sys/dev/netif/mii_layer/miidevs b/sys/dev/netif/mii_layer/miidevs index c54a3cdb5d..ca50717448 100644 --- a/sys/dev/netif/mii_layer/miidevs +++ b/sys/dev/netif/mii_layer/miidevs @@ -1,4 +1,4 @@ -$DragonFly: src/sys/dev/netif/mii_layer/miidevs,v 1.7 2006/05/20 04:27:16 sephe Exp $ +$DragonFly: src/sys/dev/netif/mii_layer/miidevs,v 1.8 2006/08/06 10:32:23 sephe Exp $ /* $FreeBSD: src/sys/dev/mii/miidevs,v 1.4.2.13 2003/07/22 02:12:55 ps Exp $ */ /*$NetBSD: miidevs,v 1.6 1999/05/14 11:37:30 drochner Exp $*/ @@ -53,7 +53,7 @@ $DragonFly: src/sys/dev/netif/mii_layer/miidevs,v 1.7 2006/05/20 04:27:16 sephe oui ALTIMA 0x0010a9 Altima Communications oui AMD 0x00001a Advanced Micro Devices oui BROADCOM 0x001018 Broadcom Corporation -oui CICADA 0x0003F1 Cicada Semiconductor +oui CICADA 0x0003f1 Cicada Semiconductor oui DAVICOM 0x00606e Davicom Semiconductor oui ICS 0x00a0be Integrated Circuit Systems oui INTEL 0x00aa00 Intel @@ -62,12 +62,14 @@ oui LEVEL1 0x00207b Level 1 oui NATSEMI 0x080017 National Semiconductor oui QUALSEMI 0x006051 Quality Semiconductor oui REALTEK 0x000020 RealTek Semicondctor +oui REALTEK2 0x00e04c RealTek Semicondctor oui SEEQ 0x00a07d Seeq oui SIS 0x00e006 Silicon Integrated Systems oui TDK 0x00c039 TDK oui TI 0x080028 Texas Instruments oui XAQTI 0x00e0ae XaQti Corp. oui MARVELL 0x005043 Marvell Semiconductor +oui ICPLUS 0x0090c3 IC Plus Corp. /* in the 79c873, AMD uses another OUI (which matches Davicom!) */ oui xxAMD 0x00606e Advanced Micro Devices @@ -88,6 +90,7 @@ oui xxXAQTI 0x350700 XaQti Corp. /* Level 1 is completely different - from right to left. (Two bits get lost in the third OUI byte.) */ oui xxLEVEL1 0x1e0400 Level 1 +oui xxLEVEL1a 0x0004de Level 1 /* Don't know what's going on here. */ oui xxDAVICOM 0x006040 Davicom Semiconductor @@ -95,12 +98,19 @@ oui xxDAVICOM 0x006040 Davicom Semiconductor /* This is the OUI of the gigE PHY in the RealTek 8169S/8110S chips */ oui xxREALTEK 0x000732 +oui xxMARVELL 0x000ac2 Marvell Semiconductor +oui xxCICADA 0x00c08f Cicada Semiconductor + /* * List of known models. Grouped by oui. */ /* Altima Communications PHYs */ +model xxALTIMA AC_UNKNOWN 0x0001 AC_UNKNOWN 10/100 media interface +model xxALTIMA AC101L 0x0012 AC101L 10/100 media interface model xxALTIMA AC101 0x0021 AC101 10/100 media interface +/* AMD Am79C875 have ALTIMA OUI */ +model xxALTIMA Am79C875 0x0014 Am79C875 10/100 media interface /* Advanced Micro Devices PHYs */ model xxAMD 79C873 0x0000 Am79C873 10/100 media interface @@ -108,22 +118,46 @@ model AMD 79c973phy 0x0036 Am79c973 internal PHY model AMD 79c978 0x0039 Am79c978 HomePNA PHY /* Broadcom Corp. PHYs. */ -model BROADCOM 3c905Cphy 0x0017 3c905C 10/100 internal PHY +model BROADCOM BCM5400 0x0004 BCM5400 1000baseT PHY +model BROADCOM BCM5401 0x0005 BCM5401 1000baseT PHY +model BROADCOM BCM5411 0x0007 BCM5411 1000baseT PHY +model BROADCOM 3C905B 0x0012 Broadcom 3C905B internal PHY +model BROADCOM 3C905C 0x0017 Broadcom 3C905C internal PHY +model BROADCOM BCM5221 0x001e BCM5221 100baseTX PHY +model BROADCOM BCM5201 0x0021 BCM5201 10/100 PHY +model BROADCOM BCM5214 0x0028 BCM5214 Quad 10/100 PHY +model BROADCOM BCM5222 0x0032 BCM5222 Dual 10/100 PHY +model BROADCOM BCM5220 0x0033 BCM5220 10/100 PHY +model BROADCOM BCM4401 0x0036 BCM4401 10/100baseTX PHY model xxBROADCOM BCM5400 0x0004 Broadcom 1000baseTX PHY model xxBROADCOM BCM5401 0x0005 BCM5401 10/100/1000baseTX PHY model xxBROADCOM BCM5411 0x0007 BCM5411 10/100/1000baseTX PHY +model xxBROADCOM BCM5462 0x000d BCM5462 10/100/1000baseT PHY +model xxBROADCOM BCM5421 0x000e BCM5421 10/100/1000baseT PHY +model xxBROADCOM BCM5752 0x0010 BCM5752 10/100/1000baseT PHY model xxBROADCOM BCM5701 0x0011 BCM5701 10/100/1000baseTX PHY +model xxBROADCOM BCM5706C 0x0015 BCM5706C 10/100/1000baseT PHY model xxBROADCOM BCM5703 0x0016 BCM5703 10/100/1000baseTX PHY model xxBROADCOM BCM5704 0x0019 BCM5704 10/100/1000baseTX PHY model xxBROADCOM BCM5705 0x001a BCM5705 10/100/1000baseTX PHY +model xxBROADCOM BCM5750 0x0018 BCM5750 10/100/1000baseT PHY +model xxBROADCOM BCM54K2 0x002e BCM54K2 10/100/1000baseT PHY +model xxBROADCOM BCM5714 0x0034 BCM5714 10/100/1000baseT PHY +model xxBROADCOM BCM5780 0x0035 BCM5780 10/100/1000baseT PHY +model xxBROADCOM BCM5708C 0x0036 BCM5708C 10/100/1000baseT PHY /* Cicada Semiconductor PHYs (now owned by Vitesse?) */ model CICADA CS8201 0x0001 Cicada CS8201 10/100/1000TX PHY model CICADA CS8201A 0x0020 Cicada CS8201 10/100/1000TX PHY model CICADA CS8201B 0x0021 Cicada CS8201 10/100/1000TX PHY +model xxCICADA CS8201 0x0001 Cicada CS8201 10/100/1000TX PHY +model xxCICADA CS8201A 0x0020 Cicada CS8201 10/100/1000TX PHY +model xxCICADA CS8201B 0x0021 Cicada CS8201 10/100/1000TX PHY /* Davicom Semiconductor PHYs */ model xxDAVICOM DM9101 0x0000 DM9101 10/100 media interface +model DAVICOM DM9102 0x0004 DM9102 10/100 media interface +model DAVICOM DM9601 0x000c DM9601 10/100 media interface /* Integrated Circuit Systems PHYs */ model xxICS 1890 0x0002 ICS1890 10/100 media interface @@ -140,6 +174,7 @@ model JATO BASEX 0x0000 Jato 1000baseX media interface /* Level 1 PHYs */ model xxLEVEL1 LXT970 0x0000 LXT970 10/100 media interface +model xxLEVEL1a LXT971 0x000e LXT971 10/100 media interface /* National Semiconductor PHYs */ model NATSEMI DP83840 0x0000 DP83840 10/100 media interface @@ -153,6 +188,7 @@ model QUALSEMI QS6612 0x0000 QS6612 10/100 media interface /* RealTek Semiconductor PHYs */ model REALTEK RTL8201L 0x0020 RTL8201L 10/100 media interface model xxREALTEK RTL8169S 0x0011 RTL8169S/8110S media interface +model REALTEK2 RTL8169S 0x0011 RTL8169S/8110S media interface /* Seeq PHYs */ model xxSEEQ 80220 0x0003 Seeq 80220 10/100 media interface @@ -169,8 +205,21 @@ model xxTI TLAN10T 0x0001 ThunderLAN 10baseT media interface model xxTI 100VGPMI 0x0002 ThunderLAN 100VG-AnyLan media interface /* XaQti Corp. PHYs. */ -model XAQTI XMACII 0x0000 XaQti Corp. XMAC II gigabit interface +model xxXAQTI XMACII 0x0000 XaQti Corp. XMAC II gigabit interface /* Marvell Semiconductor PHYs */ model MARVELL E1000 0x0000 Marvell Semiconductor 88E1000* gigabit PHY model MARVELL E1011 0x0002 Marvell Semiconductor 88E1011 Gigabit PHY +model MARVELL E1000_3 0x0003 Marvell 88E1000 Gigabit PHY +model MARVELL E1000_4 0x0004 Marvell 88E1000S Gigabit PHY +model MARVELL E1000_5 0x0005 Marvell 88E1000 Gigabit PHY +model MARVELL E1000_6 0x0006 Marvell 88E1000 Gigabit PHY +model MARVELL E1111 0x000c Marvell 88E1111 Gigabit PHY +model MARVELL E1116 0x0021 Marvell 88E1116 Gigabit PHY +model xxMARVELL E1000_2 0x0002 Marvell 88E1000 Gigabit PHY +model xxMARVELL E1000_3 0x0003 Marvell 88E1000 Gigabit PHY +model xxMARVELL E1000_5 0x0005 Marvell 88E1000 Gigabit PHY +model xxMARVELL E1111 0x000c Marvell 88E1111 Gigabit PHY + +/* IC Plus Corp. PHYs */ +model ICPLUS IP101 0x0005 IP101 10/100 PHY diff --git a/sys/dev/netif/mii_layer/miidevs.h b/sys/dev/netif/mii_layer/miidevs.h index 8e578f6704..315ecb47b3 100644 --- a/sys/dev/netif/mii_layer/miidevs.h +++ b/sys/dev/netif/mii_layer/miidevs.h @@ -1,10 +1,10 @@ -/* $DragonFly: src/sys/dev/netif/mii_layer/miidevs.h,v 1.7 2006/05/20 04:35:30 sephe Exp $ */ +/* $DragonFly: src/sys/dev/netif/mii_layer/miidevs.h,v 1.8 2006/08/06 10:32:23 sephe Exp $ */ /* * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT. * * generated from: - * DragonFly: src/sys/dev/netif/mii_layer/miidevs,v 1.6 2005/12/26 13:36:18 sephe Exp + * DragonFly: src/sys/dev/netif/mii_layer/miidevs,v 1.7 2006/05/20 04:27:16 sephe Exp */ /* $FreeBSD: src/sys/dev/mii/miidevs,v 1.4.2.13 2003/07/22 02:12:55 ps Exp $ */ /*$NetBSD: miidevs,v 1.6 1999/05/14 11:37:30 drochner Exp $*/ @@ -60,7 +60,7 @@ #define MII_OUI_ALTIMA 0x0010a9 /* Altima Communications */ #define MII_OUI_AMD 0x00001a /* Advanced Micro Devices */ #define MII_OUI_BROADCOM 0x001018 /* Broadcom Corporation */ -#define MII_OUI_CICADA 0x0003F1 /* Cicada Semiconductor */ +#define MII_OUI_CICADA 0x0003f1 /* Cicada Semiconductor */ #define MII_OUI_DAVICOM 0x00606e /* Davicom Semiconductor */ #define MII_OUI_ICS 0x00a0be /* Integrated Circuit Systems */ #define MII_OUI_INTEL 0x00aa00 /* Intel */ @@ -69,12 +69,14 @@ #define MII_OUI_NATSEMI 0x080017 /* National Semiconductor */ #define MII_OUI_QUALSEMI 0x006051 /* Quality Semiconductor */ #define MII_OUI_REALTEK 0x000020 /* RealTek Semicondctor */ +#define MII_OUI_REALTEK2 0x00e04c /* RealTek Semicondctor */ #define MII_OUI_SEEQ 0x00a07d /* Seeq */ #define MII_OUI_SIS 0x00e006 /* Silicon Integrated Systems */ #define MII_OUI_TDK 0x00c039 /* TDK */ #define MII_OUI_TI 0x080028 /* Texas Instruments */ #define MII_OUI_XAQTI 0x00e0ae /* XaQti Corp. */ #define MII_OUI_MARVELL 0x005043 /* Marvell Semiconductor */ +#define MII_OUI_ICPLUS 0x0090c3 /* IC Plus Corp. */ /* in the 79c873, AMD uses another OUI (which matches Davicom!) */ #define MII_OUI_xxAMD 0x00606e /* Advanced Micro Devices */ @@ -95,6 +97,7 @@ /* Level 1 is completely different - from right to left. (Two bits get lost in the third OUI byte.) */ #define MII_OUI_xxLEVEL1 0x1e0400 /* Level 1 */ +#define MII_OUI_xxLEVEL1a 0x0004de /* Level 1 */ /* Don't know what's going on here. */ #define MII_OUI_xxDAVICOM 0x006040 /* Davicom Semiconductor */ @@ -102,13 +105,23 @@ /* This is the OUI of the gigE PHY in the RealTek 8169S/8110S chips */ #define MII_OUI_xxREALTEK 0x000732 /* */ +#define MII_OUI_xxMARVELL 0x000ac2 /* Marvell Semiconductor */ +#define MII_OUI_xxCICADA 0x00c08f /* Cicada Semiconductor */ + /* * List of known models. Grouped by oui. */ /* Altima Communications PHYs */ +#define MII_MODEL_xxALTIMA_AC_UNKNOWN 0x0001 +#define MII_STR_xxALTIMA_AC_UNKNOWN "AC_UNKNOWN 10/100 media interface" +#define MII_MODEL_xxALTIMA_AC101L 0x0012 +#define MII_STR_xxALTIMA_AC101L "AC101L 10/100 media interface" #define MII_MODEL_xxALTIMA_AC101 0x0021 #define MII_STR_xxALTIMA_AC101 "AC101 10/100 media interface" +/* AMD Am79C875 have ALTIMA OUI */ +#define MII_MODEL_xxALTIMA_Am79C875 0x0014 +#define MII_STR_xxALTIMA_Am79C875 "Am79C875 10/100 media interface" /* Advanced Micro Devices PHYs */ #define MII_MODEL_xxAMD_79C873 0x0000 @@ -119,22 +132,60 @@ #define MII_STR_AMD_79c978 "Am79c978 HomePNA PHY" /* Broadcom Corp. PHYs. */ -#define MII_MODEL_BROADCOM_3c905Cphy 0x0017 -#define MII_STR_BROADCOM_3c905Cphy "3c905C 10/100 internal PHY" +#define MII_MODEL_BROADCOM_BCM5400 0x0004 +#define MII_STR_BROADCOM_BCM5400 "BCM5400 1000baseT PHY" +#define MII_MODEL_BROADCOM_BCM5401 0x0005 +#define MII_STR_BROADCOM_BCM5401 "BCM5401 1000baseT PHY" +#define MII_MODEL_BROADCOM_BCM5411 0x0007 +#define MII_STR_BROADCOM_BCM5411 "BCM5411 1000baseT PHY" +#define MII_MODEL_BROADCOM_3C905B 0x0012 +#define MII_STR_BROADCOM_3C905B "Broadcom 3C905B internal PHY" +#define MII_MODEL_BROADCOM_3C905C 0x0017 +#define MII_STR_BROADCOM_3C905C "Broadcom 3C905C internal PHY" +#define MII_MODEL_BROADCOM_BCM5221 0x001e +#define MII_STR_BROADCOM_BCM5221 "BCM5221 100baseTX PHY" +#define MII_MODEL_BROADCOM_BCM5201 0x0021 +#define MII_STR_BROADCOM_BCM5201 "BCM5201 10/100 PHY" +#define MII_MODEL_BROADCOM_BCM5214 0x0028 +#define MII_STR_BROADCOM_BCM5214 "BCM5214 Quad 10/100 PHY" +#define MII_MODEL_BROADCOM_BCM5222 0x0032 +#define MII_STR_BROADCOM_BCM5222 "BCM5222 Dual 10/100 PHY" +#define MII_MODEL_BROADCOM_BCM5220 0x0033 +#define MII_STR_BROADCOM_BCM5220 "BCM5220 10/100 PHY" +#define MII_MODEL_BROADCOM_BCM4401 0x0036 +#define MII_STR_BROADCOM_BCM4401 "BCM4401 10/100baseTX PHY" #define MII_MODEL_xxBROADCOM_BCM5400 0x0004 #define MII_STR_xxBROADCOM_BCM5400 "Broadcom 1000baseTX PHY" #define MII_MODEL_xxBROADCOM_BCM5401 0x0005 #define MII_STR_xxBROADCOM_BCM5401 "BCM5401 10/100/1000baseTX PHY" #define MII_MODEL_xxBROADCOM_BCM5411 0x0007 #define MII_STR_xxBROADCOM_BCM5411 "BCM5411 10/100/1000baseTX PHY" +#define MII_MODEL_xxBROADCOM_BCM5462 0x000d +#define MII_STR_xxBROADCOM_BCM5462 "BCM5462 10/100/1000baseT PHY" +#define MII_MODEL_xxBROADCOM_BCM5421 0x000e +#define MII_STR_xxBROADCOM_BCM5421 "BCM5421 10/100/1000baseT PHY" +#define MII_MODEL_xxBROADCOM_BCM5752 0x0010 +#define MII_STR_xxBROADCOM_BCM5752 "BCM5752 10/100/1000baseT PHY" #define MII_MODEL_xxBROADCOM_BCM5701 0x0011 #define MII_STR_xxBROADCOM_BCM5701 "BCM5701 10/100/1000baseTX PHY" +#define MII_MODEL_xxBROADCOM_BCM5706C 0x0015 +#define MII_STR_xxBROADCOM_BCM5706C "BCM5706C 10/100/1000baseT PHY" #define MII_MODEL_xxBROADCOM_BCM5703 0x0016 #define MII_STR_xxBROADCOM_BCM5703 "BCM5703 10/100/1000baseTX PHY" #define MII_MODEL_xxBROADCOM_BCM5704 0x0019 #define MII_STR_xxBROADCOM_BCM5704 "BCM5704 10/100/1000baseTX PHY" #define MII_MODEL_xxBROADCOM_BCM5705 0x001a #define MII_STR_xxBROADCOM_BCM5705 "BCM5705 10/100/1000baseTX PHY" +#define MII_MODEL_xxBROADCOM_BCM5750 0x0018 +#define MII_STR_xxBROADCOM_BCM5750 "BCM5750 10/100/1000baseT PHY" +#define MII_MODEL_xxBROADCOM_BCM54K2 0x002e +#define MII_STR_xxBROADCOM_BCM54K2 "BCM54K2 10/100/1000baseT PHY" +#define MII_MODEL_xxBROADCOM_BCM5714 0x0034 +#define MII_STR_xxBROADCOM_BCM5714 "BCM5714 10/100/1000baseT PHY" +#define MII_MODEL_xxBROADCOM_BCM5780 0x0035 +#define MII_STR_xxBROADCOM_BCM5780 "BCM5780 10/100/1000baseT PHY" +#define MII_MODEL_xxBROADCOM_BCM5708C 0x0036 +#define MII_STR_xxBROADCOM_BCM5708C "BCM5708C 10/100/1000baseT PHY" /* Cicada Semiconductor PHYs (now owned by Vitesse?) */ #define MII_MODEL_CICADA_CS8201 0x0001 @@ -143,10 +194,20 @@ #define MII_STR_CICADA_CS8201A "Cicada CS8201 10/100/1000TX PHY" #define MII_MODEL_CICADA_CS8201B 0x0021 #define MII_STR_CICADA_CS8201B "Cicada CS8201 10/100/1000TX PHY" +#define MII_MODEL_xxCICADA_CS8201 0x0001 +#define MII_STR_xxCICADA_CS8201 "Cicada CS8201 10/100/1000TX PHY" +#define MII_MODEL_xxCICADA_CS8201A 0x0020 +#define MII_STR_xxCICADA_CS8201A "Cicada CS8201 10/100/1000TX PHY" +#define MII_MODEL_xxCICADA_CS8201B 0x0021 +#define MII_STR_xxCICADA_CS8201B "Cicada CS8201 10/100/1000TX PHY" /* Davicom Semiconductor PHYs */ #define MII_MODEL_xxDAVICOM_DM9101 0x0000 #define MII_STR_xxDAVICOM_DM9101 "DM9101 10/100 media interface" +#define MII_MODEL_DAVICOM_DM9102 0x0004 +#define MII_STR_DAVICOM_DM9102 "DM9102 10/100 media interface" +#define MII_MODEL_DAVICOM_DM9601 0x000c +#define MII_STR_DAVICOM_DM9601 "DM9601 10/100 media interface" /* Integrated Circuit Systems PHYs */ #define MII_MODEL_xxICS_1890 0x0002 @@ -171,6 +232,8 @@ /* Level 1 PHYs */ #define MII_MODEL_xxLEVEL1_LXT970 0x0000 #define MII_STR_xxLEVEL1_LXT970 "LXT970 10/100 media interface" +#define MII_MODEL_xxLEVEL1a_LXT971 0x000e +#define MII_STR_xxLEVEL1a_LXT971 "LXT971 10/100 media interface" /* National Semiconductor PHYs */ #define MII_MODEL_NATSEMI_DP83840 0x0000 @@ -191,6 +254,8 @@ #define MII_STR_REALTEK_RTL8201L "RTL8201L 10/100 media interface" #define MII_MODEL_xxREALTEK_RTL8169S 0x0011 #define MII_STR_xxREALTEK_RTL8169S "RTL8169S/8110S media interface" +#define MII_MODEL_REALTEK2_RTL8169S 0x0011 +#define MII_STR_REALTEK2_RTL8169S "RTL8169S/8110S media interface" /* Seeq PHYs */ #define MII_MODEL_xxSEEQ_80220 0x0003 @@ -213,11 +278,35 @@ #define MII_STR_xxTI_100VGPMI "ThunderLAN 100VG-AnyLan media interface" /* XaQti Corp. PHYs. */ -#define MII_MODEL_XAQTI_XMACII 0x0000 -#define MII_STR_XAQTI_XMACII "XaQti Corp. XMAC II gigabit interface" +#define MII_MODEL_xxXAQTI_XMACII 0x0000 +#define MII_STR_xxXAQTI_XMACII "XaQti Corp. XMAC II gigabit interface" /* Marvell Semiconductor PHYs */ #define MII_MODEL_MARVELL_E1000 0x0000 #define MII_STR_MARVELL_E1000 "Marvell Semiconductor 88E1000* gigabit PHY" #define MII_MODEL_MARVELL_E1011 0x0002 #define MII_STR_MARVELL_E1011 "Marvell Semiconductor 88E1011 Gigabit PHY" +#define MII_MODEL_MARVELL_E1000_3 0x0003 +#define MII_STR_MARVELL_E1000_3 "Marvell 88E1000 Gigabit PHY" +#define MII_MODEL_MARVELL_E1000_4 0x0004 +#define MII_STR_MARVELL_E1000_4 "Marvell 88E1000S Gigabit PHY" +#define MII_MODEL_MARVELL_E1000_5 0x0005 +#define MII_STR_MARVELL_E1000_5 "Marvell 88E1000 Gigabit PHY" +#define MII_MODEL_MARVELL_E1000_6 0x0006 +#define MII_STR_MARVELL_E1000_6 "Marvell 88E1000 Gigabit PHY" +#define MII_MODEL_MARVELL_E1111 0x000c +#define MII_STR_MARVELL_E1111 "Marvell 88E1111 Gigabit PHY" +#define MII_MODEL_MARVELL_E1116 0x0021 +#define MII_STR_MARVELL_E1116 "Marvell 88E1116 Gigabit PHY" +#define MII_MODEL_xxMARVELL_E1000_2 0x0002 +#define MII_STR_xxMARVELL_E1000_2 "Marvell 88E1000 Gigabit PHY" +#define MII_MODEL_xxMARVELL_E1000_3 0x0003 +#define MII_STR_xxMARVELL_E1000_3 "Marvell 88E1000 Gigabit PHY" +#define MII_MODEL_xxMARVELL_E1000_5 0x0005 +#define MII_STR_xxMARVELL_E1000_5 "Marvell 88E1000 Gigabit PHY" +#define MII_MODEL_xxMARVELL_E1111 0x000c +#define MII_STR_xxMARVELL_E1111 "Marvell 88E1111 Gigabit PHY" + +/* IC Plus Corp. PHYs */ +#define MII_MODEL_ICPLUS_IP101 0x0005 +#define MII_STR_ICPLUS_IP101 "IP101 10/100 PHY" diff --git a/sys/dev/netif/mii_layer/miivar.h b/sys/dev/netif/mii_layer/miivar.h index 167b438cd0..a26dd9377e 100644 --- a/sys/dev/netif/mii_layer/miivar.h +++ b/sys/dev/netif/mii_layer/miivar.h @@ -1,7 +1,7 @@ -/* $NetBSD: miivar.h,v 1.8 1999/04/23 04:24:32 thorpej Exp $ */ +/* $NetBSD: miivar.h,v 1.46 2006/03/25 23:17:36 thorpej Exp $ */ /*- - * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. + * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -37,7 +37,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/miivar.h,v 1.3.2.1 2000/12/12 19:29:14 wpaul Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/miivar.h,v 1.11 2005/10/31 13:08:35 sephe Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/miivar.h,v 1.12 2006/08/06 10:32:23 sephe Exp $ */ #ifndef _DEV_MII_MIIVAR_H_ @@ -79,12 +79,6 @@ struct mii_data { }; typedef struct mii_data mii_data_t; -/* - * This call is used by the MII layer to call into the PHY driver - * to perform a `service request'. - */ -typedef int (*mii_downcall_t) (struct mii_softc *, struct mii_data *, int); - /* * Requests that can be made to the downcall. */ @@ -102,17 +96,39 @@ struct mii_softc { LIST_ENTRY(mii_softc) mii_list; /* entry on parent's PHY list */ + int mii_model; /* MII_MODEL(ma->mii_id2) */ + int mii_rev; /* MII_REV(ma->mii_id2) */ int mii_phy; /* our MII address */ int mii_inst; /* instance for ifmedia */ - mii_downcall_t mii_service; /* our downcall */ + /* + * This function pointer is used by the MII layer to call into + * the PHY driver to perform a `service request'. + */ + int (*mii_service)(struct mii_softc *, struct mii_data *, int); + + /* + * This function pointer is used by the MII layer to reset PHY + */ + void (*mii_reset)(struct mii_softc *); + + /* + * This function pointer is used by the MII layer to get the + * status of PHY + */ + void (*mii_status)(struct mii_softc *); + struct mii_data *mii_pdata; /* pointer to parent's mii_data */ struct callout mii_auto_ch; /* callout handle for phy autoneg */ int mii_flags; /* misc. flags; see below */ int mii_capabilities; /* capabilities from BMSR */ + int mii_extcapabilities; /* extended capabilities from EXTSR */ int mii_ticks; /* MII_TICK counter */ - int mii_active; /* last active media */ + int mii_anegticks; /* ticks before retrying aneg */ + + int mii_media_active; /* last active media */ + int mii_media_status; /* last active status */ }; typedef struct mii_softc mii_softc_t; @@ -144,6 +160,38 @@ struct mii_attach_args { }; typedef struct mii_attach_args mii_attach_args_t; +/* + * Used to match a PHY + */ +struct mii_phydesc { + uint32_t mpd_oui; /* PHY's oui */ + uint32_t mpd_model; /* PHY's model */ + const char *mpd_name; /* PHY's name */ + void *mpd_priv; /* PHY's private data */ +}; + +#define MII_PHYDESC_NULL \ +{ \ + .mpd_oui = 0, \ + .mpd_model = 0, \ + .mpd_name = NULL, \ + .mpd_priv = NULL \ +} +#define MII_PHYDESC(oui, model) \ +{ \ + .mpd_oui = MII_OUI_##oui, \ + .mpd_model = MII_MODEL_##oui##_##model, \ + .mpd_name = MII_STR_##oui##_##model, \ + .mpd_priv = NULL \ +} +#define MII_PHYDESC_ARG(oui, model, arg) \ +{ \ + .mpd_oui = MII_OUI_##oui, \ + .mpd_model = MII_MODEL_##oui##_##model, \ + .mpd_name = MII_STR_##oui##_##model, \ + .mpd_priv = arg \ +} + #ifdef _KERNEL #define PHY_READ(p, r) \ @@ -152,32 +200,62 @@ typedef struct mii_attach_args mii_attach_args_t; #define PHY_WRITE(p, r, v) \ MIIBUS_WRITEREG((p)->mii_dev, (p)->mii_phy, (r), (v)) +/* + * An array of these structures map MII media types to BMCR/ANAR settings. + */ +struct mii_media { + int mm_bmcr; /* BMCR settings for this media */ + int mm_anar; /* ANAR settings for this media */ + int mm_gtcr; /* 100base-T2 or 1000base-T CR */ +}; + +#define MII_MEDIA_NONE 0 +#define MII_MEDIA_10_T 1 +#define MII_MEDIA_10_T_FDX 2 +#define MII_MEDIA_100_T4 3 +#define MII_MEDIA_100_TX 4 +#define MII_MEDIA_100_TX_FDX 5 +#define MII_MEDIA_1000_X 6 +#define MII_MEDIA_1000_X_FDX 7 +#define MII_MEDIA_1000_T 8 +#define MII_MEDIA_1000_T_FDX 9 +#define MII_NMEDIA 10 + +extern const struct mii_media mii_media_table[MII_NMEDIA]; + +#define MII_ANEGTICKS 5 +#define MII_ANEGTICKS_GIGE 10 + extern devclass_t miibus_devclass; extern driver_t miibus_driver; -int miibus_probe (device_t); -int miibus_attach (device_t); -int miibus_detach (device_t); - -int mii_anar (int); -int mii_mediachg (struct mii_data *); -void mii_tick (struct mii_data *); -void mii_pollstat (struct mii_data *); -int mii_phy_probe (device_t, device_t *, - ifm_change_cb_t, ifm_stat_cb_t); -void mii_add_media (struct mii_softc *, int); -int mii_bmsr_media_to_anar(struct mii_softc *); -void mii_softc_init (struct mii_softc *, struct mii_attach_args *); - -int mii_media_from_bmcr (int); - -int mii_phy_auto (struct mii_softc *, int); -void mii_phy_auto_stop (struct mii_softc *); -void mii_phy_reset (struct mii_softc *); - -void ukphy_status (struct mii_softc *); -int ukphy_attach (device_t); -int ukphy_detach (device_t); +int miibus_probe(device_t); +int miibus_attach(device_t); +int miibus_detach(device_t); + +int mii_mediachg(struct mii_data *); +void mii_tick(struct mii_data *); +void mii_pollstat(struct mii_data *); +int mii_phy_probe(device_t, device_t *, ifm_change_cb_t, ifm_stat_cb_t); + +void mii_phy_add_media(struct mii_softc *); +void mii_phy_set_media(struct mii_softc *); +int mii_phy_tick(struct mii_softc *); +void mii_phy_update(struct mii_softc *, int); +int mii_phy_flowstatus(struct mii_softc *); +const struct mii_phydesc *mii_phy_match(const struct mii_attach_args *, + const struct mii_phydesc *); + +void mii_softc_init(struct mii_softc *, struct mii_attach_args *); + +int mii_phy_auto(struct mii_softc *, int); +void mii_phy_auto_stop(struct mii_softc *); +void mii_phy_auto_timeout(void *arg); +void mii_phy_reset(struct mii_softc *); + +void ukphy_status(struct mii_softc *); +int ukphy_attach(device_t); +int ukphy_detach(device_t); #endif /* _KERNEL */ diff --git a/sys/dev/netif/mii_layer/mlphy.c b/sys/dev/netif/mii_layer/mlphy.c index c5984591f8..06fa9d7b01 100644 --- a/sys/dev/netif/mii_layer/mlphy.c +++ b/sys/dev/netif/mii_layer/mlphy.c @@ -30,7 +30,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/mlphy.c,v 1.2.2.3 2001/02/09 09:50:15 asmodai Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/mlphy.c,v 1.8 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/mlphy.c,v 1.9 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -149,6 +149,7 @@ mlphy_attach(device_t dev) sc->mii_inst = mii->mii_instance; sc->mii_service = mlphy_service; + sc->mii_reset = mlphy_reset; sc->mii_pdata = mii; mii->mii_instance++; @@ -157,23 +158,22 @@ mlphy_attach(device_t dev) #if 0 /* See above. */ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), - BMCR_ISO); + MII_MEDIA_NONE); #endif ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), - BMCR_LOOP|BMCR_S100); + MII_MEDIA_100_TX); sc->mii_flags &= ~MIIF_NOISOLATE; mii_phy_reset(sc); sc->mii_flags |= MIIF_NOISOLATE; - sc->mii_capabilities = - PHY_READ(sc, MII_BMSR) & ma->mii_capmask; - ma->mii_capmask = ~sc->mii_capabilities; + sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + device_printf(dev, " "); if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) printf("no media present"); else - mii_add_media(sc, sc->mii_capabilities); + mii_phy_add_media(sc); printf("\n"); #undef ADD MIIBUS_MEDIAINIT(sc->mii_dev); @@ -183,11 +183,9 @@ mlphy_attach(device_t dev) static int mlphy_detach(device_t dev) { - struct mlphy_softc *sc; - struct mii_data *mii; + struct mlphy_softc *sc; sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); mii_phy_auto_stop(&sc->ml_mii); sc->ml_mii.mii_dev = NULL; LIST_REMOVE(&sc->ml_mii, mii_list); @@ -205,6 +203,7 @@ mlphy_service(struct mii_softc *xsc, struct mii_data *mii, int cmd) struct mii_softc *sc = (struct mii_softc *)&msc->ml_mii; device_t *devlist; int devs, i; + const struct mii_media *mm; /* * See if there's another PHY on this bus with us. @@ -219,6 +218,9 @@ mlphy_service(struct mii_softc *xsc, struct mii_data *mii, int cmd) } free(devlist, M_TEMP); + KKASSERT(ife->ifm_data >= 0 && ife->ifm_data < MII_NMEDIA); + mm = &mii_media_table[ife->ifm_data]; + switch (cmd) { case MII_POLLSTAT: /* @@ -257,10 +259,10 @@ mlphy_service(struct mii_softc *xsc, struct mii_data *mii, int cmd) mii_phy_reset(other); PHY_WRITE(other, MII_BMCR, BMCR_ISO); } - (void) mii_phy_auto(sc, 1); + mii_phy_auto(sc, 1); msc->ml_linked = 0; return(0); - break; + case IFM_10_T: /* * For 10baseT modes, reset and program the @@ -268,33 +270,31 @@ mlphy_service(struct mii_softc *xsc, struct mii_data *mii, int cmd) * to match. This will put us in pass-through * mode and let the companion PHY do all the * work. - * - * BMCR data is stored in the ifmedia entry. */ if (other != NULL) { mii_phy_reset(other); - PHY_WRITE(other, MII_BMCR, ife->ifm_data); + PHY_WRITE(other, MII_BMCR, mm->mm_bmcr); } - PHY_WRITE(sc, MII_ANAR, mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); + PHY_WRITE(sc, MII_ANAR, mm->mm_anar); + PHY_WRITE(sc, MII_BMCR, mm->mm_bmcr); msc->ml_state = 0; break; + case IFM_100_TX: /* * For 100baseTX modes, reset and isolate the * companion PHY (if any), then program ourselves * accordingly. - * - * BMCR data is stored in the ifmedia entry. */ if (other != NULL) { mii_phy_reset(other); PHY_WRITE(other, MII_BMCR, BMCR_ISO); } - PHY_WRITE(sc, MII_ANAR, mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); + PHY_WRITE(sc, MII_ANAR, mm->mm_anar); + PHY_WRITE(sc, MII_BMCR, mm->mm_bmcr); msc->ml_state = 0; break; + case IFM_100_T4: /* * XXX Not supported as a manual setting right now. @@ -302,7 +302,6 @@ mlphy_service(struct mii_softc *xsc, struct mii_data *mii, int cmd) return (EINVAL); default: break; - } break; @@ -314,21 +313,21 @@ mlphy_service(struct mii_softc *xsc, struct mii_data *mii, int cmd) return (0); /* - * Only used for autonegotiation. + * Is the interface even up? */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) return (0); /* - * Is the interface even up? + * Only used for autonegotiation. */ - if ((mii->mii_ifp->if_flags & IFF_UP) == 0) - return (0); + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + break; /* * Only retry autonegotiation every 5 seconds. */ - if (++sc->mii_ticks != 5) + if (++sc->mii_ticks <= sc->mii_anegticks) return (0); sc->mii_ticks = 0; @@ -373,23 +372,21 @@ mlphy_service(struct mii_softc *xsc, struct mii_data *mii, int cmd) } /* Update the media status. */ - if (msc->ml_state == ML_STATE_AUTO_OTHER) { - int other_inst; + int other_inst; + other_inst = other->mii_inst; other->mii_inst = sc->mii_inst; - (void) (*other->mii_service)(other, mii, MII_POLLSTAT); + other->mii_service(other, mii, MII_POLLSTAT); other->mii_inst = other_inst; - sc->mii_active = other->mii_active; - } else + sc->mii_media_active = other->mii_media_active; + sc->mii_media_status = other->mii_media_status; + } else { ukphy_status(sc); - - /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; } + /* Callback if something changed. */ + mii_phy_update(sc, cmd); return (0); } @@ -406,8 +403,6 @@ mlphy_reset(struct mii_softc *sc) reg = PHY_READ(sc, MII_BMCR); reg &= ~BMCR_AUTOEN; PHY_WRITE(sc, MII_BMCR, reg); - - return; } /* @@ -451,6 +446,4 @@ mlphy_status(struct mii_softc *sc) mii_phy_reset(other); mii_phy_auto(other, 1); } - - return; } diff --git a/sys/dev/netif/mii_layer/nsgphy.c b/sys/dev/netif/mii_layer/nsgphy.c index 4b29e3dc57..ab472e3aa3 100644 --- a/sys/dev/netif/mii_layer/nsgphy.c +++ b/sys/dev/netif/mii_layer/nsgphy.c @@ -31,7 +31,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/nsgphy.c,v 1.1.2.3 2002/11/08 21:53:49 semenu Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/nsgphy.c,v 1.12 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/nsgphy.c,v 1.13 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -69,17 +69,21 @@ static int nsgphy_probe (device_t); static int nsgphy_attach (device_t); -static int nsgphy_detach (device_t); static device_method_t nsgphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, nsgphy_probe), DEVMETHOD(device_attach, nsgphy_attach), - DEVMETHOD(device_detach, nsgphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; +static const struct mii_phydesc nsgphys[] = { + MII_PHYDESC(NATSEMI, DP83891), + MII_PHYDESC(NATSEMI, DP83861), + MII_PHYDESC_NULL +}; + static devclass_t nsgphy_devclass; static driver_t nsgphy_driver = { @@ -90,30 +94,20 @@ static driver_t nsgphy_driver = { DRIVER_MODULE(nsgphy, miibus, nsgphy_driver, nsgphy_devclass, 0, 0); -int nsgphy_service (struct mii_softc *, struct mii_data *, int); -void nsgphy_status (struct mii_softc *); - -static int nsgphy_mii_phy_auto (struct mii_softc *, int); -extern void mii_phy_auto_timeout (void *); +static int nsgphy_service(struct mii_softc *, struct mii_data *, int); +static void nsgphy_status(struct mii_softc *); static int nsgphy_probe(device_t dev) { - struct mii_attach_args *ma; + struct mii_attach_args *ma = device_get_ivars(dev); + const struct mii_phydesc *mpd; - ma = device_get_ivars(dev); - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_NATSEMI) { - if (MII_MODEL(ma->mii_id2) == MII_MODEL_NATSEMI_DP83891) { - device_set_desc(dev, MII_STR_NATSEMI_DP83891); - return(0); - } - if (MII_MODEL(ma->mii_id2) == MII_MODEL_NATSEMI_DP83861) { - device_set_desc(dev, MII_STR_NATSEMI_DP83861); - return(0); - } + mpd = mii_phy_match(ma, nsgphys); + if (mpd != NULL) { + device_set_desc(dev, mpd->mpd_name); + return (0); } - return(ENXIO); } @@ -123,7 +117,6 @@ nsgphy_attach(device_t dev) struct mii_softc *sc; struct mii_attach_args *ma; struct mii_data *mii; - const char *sep = ""; sc = device_get_softc(dev); ma = device_get_ivars(dev); @@ -134,69 +127,47 @@ nsgphy_attach(device_t dev) sc->mii_inst = mii->mii_instance; sc->mii_service = nsgphy_service; + /* + * Only retry autonegotiation every 17 seconds. + * Actually, for gigE PHYs, we should wait longer, since + * 5 seconds is the mimimum time the documentation + * says to wait for a 1000mbps link to be established. + */ + sc->mii_anegticks = 17; sc->mii_pdata = mii; sc->mii_flags |= MIIF_NOISOLATE; mii->mii_instance++; #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) -#define PRINT(s) printf("%s%s", sep, s); sep = ", " ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), - BMCR_ISO); + MII_MEDIA_NONE); #if 0 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), - BMCR_LOOP|BMCR_S100); + MII_MEDIA_100_TX); #endif mii_phy_reset(sc); + sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + if (sc->mii_capabilities & BMSR_EXTSTAT) + sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); + device_printf(dev, " "); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst), - NSGPHY_S1000|NSGPHY_BMCR_FDX); - PRINT("1000baseTX-FDX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst), - NSGPHY_S1000); - PRINT("1000baseTX"); - sc->mii_capabilities = - (PHY_READ(sc, MII_BMSR) | - (BMSR_10TFDX|BMSR_10THDX)) & ma->mii_capmask; - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst), - NSGPHY_S100|NSGPHY_BMCR_FDX); - PRINT("100baseTX-FDX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst), NSGPHY_S100); - PRINT("100baseTX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst), - NSGPHY_S10|NSGPHY_BMCR_FDX); - PRINT("10baseT-FDX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst), NSGPHY_S10); - PRINT("10baseT"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0); - PRINT("auto"); + if ((sc->mii_capabilities & BMSR_MEDIAMASK) || + (sc->mii_extcapabilities & EXTSR_MEDIAMASK)) + mii_phy_add_media(sc); + else + printf("no media present"); + printf("\n"); #undef ADD -#undef PRINT MIIBUS_MEDIAINIT(sc->mii_dev); return(0); } -static int -nsgphy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); - if (sc->mii_flags & MIIF_DOINGAUTO) - callout_stop(&sc->mii_auto_ch); - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); - - return(0); -} - int nsgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { @@ -230,60 +201,7 @@ nsgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) break; - switch (IFM_SUBTYPE(ife->ifm_media)) { - case IFM_AUTO: -#ifdef foo - /* - * If we're already in auto mode, just return. - */ - if (PHY_READ(sc, NSGPHY_MII_BMCR) & NSGPHY_BMCR_AUTOEN) - return (0); -#endif - (void) nsgphy_mii_phy_auto(sc, 0); - break; - case IFM_1000_T: - if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) { - PHY_WRITE(sc, NSGPHY_MII_BMCR, - NSGPHY_BMCR_FDX|NSGPHY_BMCR_SPD1); - } else { - PHY_WRITE(sc, NSGPHY_MII_BMCR, - NSGPHY_BMCR_SPD1); - } - PHY_WRITE(sc, NSGPHY_MII_ANAR, NSGPHY_SEL_TYPE); - - /* - * When setting the link manually, one side must - * be the master and the other the slave. However - * ifmedia doesn't give us a good way to specify - * this, so we fake it by using one of the LINK - * flags. If LINK0 is set, we program the PHY to - * be a master, otherwise it's a slave. - */ - if ((mii->mii_ifp->if_flags & IFF_LINK0)) { - PHY_WRITE(sc, NSGPHY_MII_1000CTL, - NSGPHY_1000CTL_MSE|NSGPHY_1000CTL_MSC); - } else { - PHY_WRITE(sc, NSGPHY_MII_1000CTL, - NSGPHY_1000CTL_MSE); - } - break; - case IFM_100_T4: - /* - * XXX Not supported as a manual setting right now. - */ - return (EINVAL); - case IFM_NONE: - PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN); - break; - default: - /* - * BMCR data is stored in the ifmedia entry. - */ - PHY_WRITE(sc, MII_ANAR, - mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); - break; - } + mii_phy_set_media(sc); break; case MII_TICK: @@ -293,39 +211,8 @@ nsgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 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) + if (mii_phy_tick(sc) == EJUSTRETURN) return (0); - - /* - * Only retry autonegotiation every 17 seconds. - * Actually, for gigE PHYs, we should wait longer, since - * 5 seconds is the mimimum time the documentation - * says to wait for a 1000mbps link to be established. - */ - if (++sc->mii_ticks != 17) - return (0); - - sc->mii_ticks = 0; - - /* - * Check to see if we have link. - */ - reg = PHY_READ(sc, NSGPHY_MII_PHYSUP); - if (reg & NSGPHY_PHYSUP_LNKSTS) - break; - - mii_phy_reset(sc); - if (nsgphy_mii_phy_auto(sc, 0) == EJUSTRETURN) - return(0); break; } @@ -333,14 +220,11 @@ nsgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) nsgphy_status(sc); /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } -void +static void nsgphy_status(struct mii_softc *sc) { struct mii_data *mii = sc->mii_pdata; @@ -404,62 +288,4 @@ nsgphy_status(struct mii_softc *sc) mii->mii_media_active |= IFM_FDX; else mii->mii_media_active |= IFM_HDX; - - return; -} - - -static int -nsgphy_mii_phy_auto(struct mii_softc *mii, int waitfor) -{ - int bmsr, ktcr = 0, i; - - if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) { - mii_phy_reset(mii); - PHY_WRITE(mii, NSGPHY_MII_BMCR, 0); - DELAY(1000); - ktcr = PHY_READ(mii, NSGPHY_MII_1000CTL); - PHY_WRITE(mii, NSGPHY_MII_1000CTL, ktcr | - (NSGPHY_1000CTL_AFD|NSGPHY_1000CTL_AHD)); - ktcr = PHY_READ(mii, NSGPHY_MII_1000CTL); - DELAY(1000); - PHY_WRITE(mii, NSGPHY_MII_ANAR, mii_bmsr_media_to_anar(mii)); - DELAY(1000); - PHY_WRITE(mii, NSGPHY_MII_BMCR, - NSGPHY_BMCR_AUTOEN | NSGPHY_BMCR_STARTNEG); - } - - if (waitfor) { - /* Wait 500ms for it to complete. */ - for (i = 0; i < 500; i++) { - if ((bmsr = PHY_READ(mii, NSGPHY_MII_BMSR)) & - NSGPHY_BMSR_ACOMP) - return (0); - DELAY(1000); -#if 0 - if ((bmsr & BMSR_ACOMP) == 0) - printf("%s: autonegotiation failed to complete\n", - mii->mii_dev.dv_xname); -#endif - } - - /* - * Don't need to worry about clearing MIIF_DOINGAUTO. - * If that's set, a timeout is pending, and it will - * clear the flag. - */ - return (EIO); - } - - /* - * Just let it finish asynchronously. This is for the benefit of - * the tick handler driving autonegotiation. Don't want 500ms - * delays all the time while the system is running! - */ - if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) { - mii->mii_flags |= MIIF_DOINGAUTO; - callout_reset(&mii->mii_auto_ch, hz >> 1, - mii_phy_auto_timeout, mii); - } - return (EJUSTRETURN); } diff --git a/sys/dev/netif/mii_layer/nsphy.c b/sys/dev/netif/mii_layer/nsphy.c index 0fd207ca6a..19bea3a893 100644 --- a/sys/dev/netif/mii_layer/nsphy.c +++ b/sys/dev/netif/mii_layer/nsphy.c @@ -37,7 +37,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/nsphy.c,v 1.2.2.5 2001/06/08 19:58:33 semenu Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/nsphy.c,v 1.8 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/nsphy.c,v 1.9 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -95,17 +95,21 @@ static int nsphy_probe (device_t); static int nsphy_attach (device_t); -static int nsphy_detach (device_t); static device_method_t nsphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, nsphy_probe), DEVMETHOD(device_attach, nsphy_attach), - DEVMETHOD(device_detach, nsphy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; +static const struct mii_phydesc nsphys[] = { + MII_PHYDESC(NATSEMI, DP83840), + MII_PHYDESC_NULL +}; + static devclass_t nsphy_devclass; static driver_t nsphy_driver = { @@ -116,23 +120,22 @@ static driver_t nsphy_driver = { DRIVER_MODULE(nsphy, miibus, nsphy_driver, nsphy_devclass, 0, 0); -int nsphy_service (struct mii_softc *, struct mii_data *, int); -void nsphy_status (struct mii_softc *); +static int nsphy_service(struct mii_softc *, struct mii_data *, int); +static void nsphy_status(struct mii_softc *); +static void nsphy_reset(struct mii_softc *); static int nsphy_probe(device_t dev) { - struct mii_attach_args *ma; - - ma = device_get_ivars(dev); - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_NATSEMI && - MII_MODEL(ma->mii_id2) == MII_MODEL_NATSEMI_DP83840) { - device_set_desc(dev, MII_STR_NATSEMI_DP83840); - } else - return (ENXIO); + struct mii_attach_args *ma = device_get_ivars(dev); + const struct mii_phydesc *mpd; - return (0); + mpd = mii_phy_match(ma, nsphys); + if (mpd != NULL) { + device_set_desc(dev, mpd->mpd_name); + return (0); + } + return (ENXIO); } static int @@ -151,6 +154,7 @@ nsphy_attach(device_t dev) sc->mii_inst = mii->mii_instance; sc->mii_service = nsphy_service; + sc->mii_reset = nsphy_reset; sc->mii_pdata = mii; #ifdef foo @@ -172,17 +176,16 @@ nsphy_attach(device_t dev) BMCR_ISO); #endif ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), - BMCR_LOOP|BMCR_S100); + MII_MEDIA_100_TX); - mii_phy_reset(sc); + nsphy_reset(sc); - sc->mii_capabilities = - PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; device_printf(dev, " "); if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) printf("no media present"); else - mii_add_media(sc, sc->mii_capabilities); + mii_phy_add_media(sc); printf("\n"); #undef ADD @@ -191,21 +194,6 @@ nsphy_attach(device_t dev) } static int -nsphy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); - mii_phy_auto_stop(sc); - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); - - return(0); -} - -int nsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { struct ifmedia_entry *ife = mii->mii_media.ifm_cur; @@ -268,34 +256,13 @@ nsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) * (nsphy with a DP83840 chip) * 0x0100 may be needed for some other card */ - reg |= 0x0100 | 0x0400; + reg |= PCR_CONGCTRL | PCR_TXREADYSEL; if (strcmp(device_get_name(device_get_parent(sc->mii_dev)), "fxp") == 0) PHY_WRITE(sc, MII_NSPHY_PCR, reg); - 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, 1); - break; - case IFM_100_T4: - /* - * XXX Not supported as a manual setting right now. - */ - return (EINVAL); - default: - /* - * BMCR data is stored in the ifmedia entry. - */ - PHY_WRITE(sc, MII_ANAR, - mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); - } + mii_phy_set_media(sc); break; case MII_TICK: @@ -305,37 +272,7 @@ nsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 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); - if (mii_phy_auto(sc, 0) == EJUSTRETURN) + if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } @@ -344,14 +281,11 @@ nsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) nsphy_status(sc); /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } -void +static void nsphy_status(struct mii_softc *sc) { struct mii_data *mii = sc->mii_pdata; @@ -424,5 +358,16 @@ nsphy_status(struct mii_softc *sc) mii->mii_media_active |= IFM_FDX; #endif } else - mii->mii_media_active |= mii_media_from_bmcr(bmcr); + mii->mii_media_active |= mii->mii_media.ifm_cur->ifm_media; +} + +static void +nsphy_reset(struct mii_softc *sc) +{ + int anar; + + mii_phy_reset(sc); + anar = PHY_READ(sc, MII_ANAR); + anar |= BMSR_MEDIA_TO_ANAR(PHY_READ(sc, MII_BMSR)); + PHY_WRITE(sc, MII_ANAR, anar); } diff --git a/sys/dev/netif/mii_layer/nsphyreg.h b/sys/dev/netif/mii_layer/nsphyreg.h index 30b830b8ca..d1802ecc07 100644 --- a/sys/dev/netif/mii_layer/nsphyreg.h +++ b/sys/dev/netif/mii_layer/nsphyreg.h @@ -37,7 +37,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/nsphyreg.h,v 1.2 1999/08/28 00:42:16 peter Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/nsphyreg.h,v 1.2 2003/06/17 04:28:28 dillon Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/nsphyreg.h,v 1.3 2006/08/06 10:32:23 sephe Exp $ */ #ifndef _DEV_MII_NSPHYREG_H_ @@ -61,6 +61,8 @@ #define PCR_DESCRTODIS 0x2000 /* descrambler t/o disable */ #define PCR_REPEATER 0x1000 /* repeater mode */ #define PCR_ENCSEL 0x0800 /* encoder mode select */ +#define PCR_TXREADYSEL 0x0400 /* use internal txrdy signal */ +#define PCR_CONGCTRL 0x0100 /* congestion control */ #define PCR_CLK25MDIS 0x0080 /* CLK25M disable */ #define PCR_FLINK100 0x0040 /* force good link in 100mbps */ #define PCR_CIMDIS 0x0020 /* carrier integrity monitor disable */ diff --git a/sys/dev/netif/mii_layer/nvphy.c b/sys/dev/netif/mii_layer/nvphy.c deleted file mode 100644 index 2a31c4a9c6..0000000000 --- a/sys/dev/netif/mii_layer/nvphy.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2005 The DragonFly Project. All rights reserved. - * - * This code is derived from software contributed to The DragonFly Project - * by Matthew Dillon - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name of The DragonFly Project nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific, prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $DragonFly: src/sys/dev/netif/mii_layer/Attic/nvphy.c,v 1.1 2005/10/24 16:45:19 dillon Exp $ - */ - -/* - * Driver for NVidia PHYs - * - * Basically just use the generic MII driver (ukphy) but flag it as being - * GiGE capable. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "mii.h" -#include "miivar.h" -#include "miidevs.h" - -#include "miibus_if.h" - -#define ML_STATE_AUTO_SELF 1 -#define ML_STATE_AUTO_OTHER 2 - -static int nvphy_probe (device_t); - -/* - * Use a custom probe + the generic mii device functions. - */ -static device_method_t nvphy_methods[] = { - /* device interface */ - DEVMETHOD(device_probe, nvphy_probe), - DEVMETHOD(device_attach, ukphy_attach), - DEVMETHOD(device_detach, ukphy_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - { 0, 0 } -}; - -static devclass_t nvphy_devclass; - -static driver_t nvphy_driver = { - "nvphy", - nvphy_methods, - sizeof(struct mii_softc) -}; - -DRIVER_MODULE(nvphy, miibus, nvphy_driver, nvphy_devclass, 0, 0); - -static -int -nvphy_probe(device_t dev) -{ - struct mii_attach_args *ma; - device_t parent; - - ma = device_get_ivars(dev); - parent = device_get_parent(device_get_parent(dev)); - - /* - * Marvell chipset, nvidia driver - */ - if (MII_OUI(ma->mii_id1, ma->mii_id2) != MII_OUI_MARVELL) - return (ENXIO); - if (strcmp(device_get_name(parent), "nv") != 0) - return (ENXIO); - - /* - * MII device name + flag for generic GigE support. - */ - device_set_desc(dev, "NVidia media interface"); - ma->mii_flags |= MIIF_IS_1000X; - - return (0); -} - diff --git a/sys/dev/netif/mii_layer/pnaphy.c b/sys/dev/netif/mii_layer/pnaphy.c index f4b58e8894..26d8b5ed6b 100644 --- a/sys/dev/netif/mii_layer/pnaphy.c +++ b/sys/dev/netif/mii_layer/pnaphy.c @@ -31,7 +31,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/pnaphy.c,v 1.1.2.3 2002/11/08 21:53:49 semenu Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/pnaphy.c,v 1.9 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/pnaphy.c,v 1.10 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -64,17 +64,21 @@ static int pnaphy_probe (device_t); static int pnaphy_attach (device_t); -static int pnaphy_detach (device_t); static device_method_t pnaphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, pnaphy_probe), DEVMETHOD(device_attach, pnaphy_attach), - DEVMETHOD(device_detach, pnaphy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; +static const struct mii_phydesc pnaphys[] = { + MII_PHYDESC(AMD, 79c978), + MII_PHYDESC_NULL +}; + static devclass_t pnaphy_devclass; static driver_t pnaphy_driver = { @@ -85,22 +89,19 @@ static driver_t pnaphy_driver = { DRIVER_MODULE(pnaphy, miibus, pnaphy_driver, pnaphy_devclass, 0, 0); -int pnaphy_service (struct mii_softc *, struct mii_data *, int); +static int pnaphy_service(struct mii_softc *, struct mii_data *, int); static int pnaphy_probe(device_t dev) { + struct mii_attach_args *ma = device_get_ivars(dev); + const struct mii_phydesc *mpd; - struct mii_attach_args *ma; - - ma = device_get_ivars(dev); - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_AMD && - MII_MODEL(ma->mii_id2) == MII_MODEL_AMD_79c978) { - device_set_desc(dev, MII_STR_AMD_79c978); - return(0); + mpd = mii_phy_match(ma, pnaphys); + if (mpd != NULL) { + device_set_desc(dev, mpd->mpd_name); + return (0); } - return(ENXIO); } @@ -110,7 +111,6 @@ pnaphy_attach(device_t dev) struct mii_softc *sc; struct mii_attach_args *ma; struct mii_data *mii; - const char *sep = ""; sc = device_get_softc(dev); ma = device_get_ivars(dev); @@ -125,51 +125,30 @@ pnaphy_attach(device_t dev) mii->mii_instance++; - sc->mii_flags |= MIIF_NOISOLATE; - -#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) -#define PRINT(s) printf("%s%s", sep, s); sep = ", " + sc->mii_flags |= MIIF_NOISOLATE | + MIIF_IS_HPNA; /* force HomePNA */ mii_phy_reset(sc); - sc->mii_capabilities = - PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + device_printf(dev, " "); if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) printf("no media present"); - else { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0, sc->mii_inst), 0); - PRINT("HomePNA"); - } - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), - BMCR_ISO); - + else + mii_phy_add_media(sc); printf("\n"); +#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), + MII_MEDIA_NONE); #undef ADD -#undef PRINT MIIBUS_MEDIAINIT(sc->mii_dev); - return(0); } static int -pnaphy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); - mii_phy_auto_stop(sc); - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); - - return(0); -} - -int pnaphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { struct ifmedia_entry *ife = mii->mii_media.ifm_cur; @@ -208,12 +187,7 @@ pnaphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) case IFM_100_T4: return (EINVAL); default: - /* - * BMCR data is stored in the ifmedia entry. - */ - PHY_WRITE(sc, MII_ANAR, - mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); + mii_phy_set_media(sc); } break; @@ -224,37 +198,7 @@ pnaphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 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); - if (mii_phy_auto(sc, 0) == EJUSTRETURN) + if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } @@ -265,9 +209,6 @@ pnaphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) mii->mii_media_active = IFM_ETHER | IFM_HPNA_1; /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } diff --git a/sys/dev/netif/mii_layer/pnphy.c b/sys/dev/netif/mii_layer/pnphy.c index 40ba5e9aa8..a021775a24 100644 --- a/sys/dev/netif/mii_layer/pnphy.c +++ b/sys/dev/netif/mii_layer/pnphy.c @@ -30,7 +30,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/pnphy.c,v 1.1.2.1 2002/11/08 21:53:49 semenu Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/pnphy.c,v 1.9 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/pnphy.c,v 1.10 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -77,13 +77,12 @@ static int pnphy_probe (device_t); static int pnphy_attach (device_t); -static int pnphy_detach (device_t); static device_method_t pnphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, pnphy_probe), DEVMETHOD(device_attach, pnphy_attach), - DEVMETHOD(device_detach, pnphy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; @@ -98,8 +97,8 @@ static driver_t pnphy_driver = { DRIVER_MODULE(pnphy, miibus, pnphy_driver, pnphy_devclass, 0, 0); -int pnphy_service (struct mii_softc *, struct mii_data *, int); -void pnphy_status (struct mii_softc *); +static int pnphy_service(struct mii_softc *, struct mii_data *, int); +static void pnphy_status(struct mii_softc *); static int pnphy_probe(device_t dev) @@ -151,13 +150,14 @@ pnphy_attach(device_t dev) if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) printf("no media present"); else - mii_add_media(sc, sc->mii_capabilities); + mii_phy_add_media(sc); printf("\n"); + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), - BMCR_ISO); + MII_MEDIA_NONE); ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), - BMCR_LOOP|BMCR_S100); + MII_MEDIA_100_TX); #undef ADD @@ -166,27 +166,10 @@ pnphy_attach(device_t dev) } static int -pnphy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); - - return(0); -} - -int pnphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { - struct dc_softc *dc_sc; struct ifmedia_entry *ife = mii->mii_media.ifm_cur; - dc_sc = mii->mii_ifp->if_softc; - switch (cmd) { case MII_POLLSTAT: /* @@ -249,16 +232,16 @@ pnphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) return (0); /* - * Only used for autonegotiation. + * Is the interface even up? */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) return (0); /* - * Is the interface even up? + * Only used for autonegotiation. */ - if ((mii->mii_ifp->if_flags & IFF_UP) == 0) - return (0); + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + break; return(0); } @@ -267,21 +250,16 @@ pnphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) pnphy_status(sc); /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } -void +static void pnphy_status(struct mii_softc *sc) { struct mii_data *mii = sc->mii_pdata; + struct dc_softc *dc_sc = mii->mii_ifp->if_softc; int reg; - struct dc_softc *dc_sc; - - dc_sc = mii->mii_ifp->if_softc; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; @@ -297,6 +275,4 @@ pnphy_status(struct mii_softc *sc) mii->mii_media_active |= IFM_100_TX; if (CSR_READ_4(dc_sc, DC_NETCFG) & DC_NETCFG_FULLDUPLEX) mii->mii_media_active |= IFM_FDX; - - return; } diff --git a/sys/dev/netif/mii_layer/qsphy.c b/sys/dev/netif/mii_layer/qsphy.c index e7a312154d..c81077440a 100644 --- a/sys/dev/netif/mii_layer/qsphy.c +++ b/sys/dev/netif/mii_layer/qsphy.c @@ -1,4 +1,4 @@ -/* OpenBSD: qsphy.c,v 1.6 2000/08/26 20:04:18 nate Exp */ +/* $OpenBSD: qsphy.c,v 1.13 2005/02/19 06:00:04 brad Exp $ */ /* NetBSD: qsphy.c,v 1.19 2000/02/02 23:34:57 thorpej Exp */ /*- @@ -38,7 +38,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/qsphy.c,v 1.1.2.2 2002/10/21 21:21:42 semenu Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/qsphy.c,v 1.8 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/qsphy.c,v 1.9 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -96,17 +96,21 @@ static int qsphy_probe (device_t); static int qsphy_attach (device_t); -static int qsphy_detach (device_t); static device_method_t qsphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, qsphy_probe), DEVMETHOD(device_attach, qsphy_attach), - DEVMETHOD(device_detach, qsphy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; +static const struct mii_phydesc qsphys[] = { + MII_PHYDESC(QUALSEMI, QS6612), + MII_PHYDESC_NULL +}; + static devclass_t qsphy_devclass; static driver_t qsphy_driver = { @@ -117,24 +121,22 @@ static driver_t qsphy_driver = { DRIVER_MODULE(qsphy, miibus, qsphy_driver, qsphy_devclass, 0, 0); -int qsphy_service (struct mii_softc *, struct mii_data *, int); -void qsphy_reset (struct mii_softc *); -void qsphy_status (struct mii_softc *); +static int qsphy_service(struct mii_softc *, struct mii_data *, int); +static void qsphy_reset(struct mii_softc *); +static void qsphy_status(struct mii_softc *); static int qsphy_probe(device_t dev) { - struct mii_attach_args *ma; - - ma = device_get_ivars(dev); - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_QUALSEMI && - MII_MODEL(ma->mii_id2) == MII_MODEL_QUALSEMI_QS6612) { - device_set_desc(dev, MII_STR_QUALSEMI_QS6612); - } else - return (ENXIO); + struct mii_attach_args *ma = device_get_ivars(dev); + const struct mii_phydesc *mpd; - return (0); + mpd = mii_phy_match(ma, qsphys); + if (mpd != NULL) { + device_set_desc(dev, mpd->mpd_name); + return (0); + } + return (ENXIO); } static int @@ -153,6 +155,7 @@ qsphy_attach(device_t dev) sc->mii_inst = mii->mii_instance; sc->mii_service = qsphy_service; + sc->mii_reset = qsphy_reset; sc->mii_pdata = mii; sc->mii_flags |= MIIF_NOISOLATE; @@ -160,11 +163,12 @@ qsphy_attach(device_t dev) mii->mii_instance++; - sc->mii_capabilities = - PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; device_printf(dev, " "); if (sc->mii_capabilities & BMSR_MEDIAMASK) - mii_add_media(sc, sc->mii_capabilities); + mii_phy_add_media(sc); + else + printf("no media present"); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); @@ -172,20 +176,6 @@ qsphy_attach(device_t dev) } static int -qsphy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); - - return(0); -} - -int qsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { struct ifmedia_entry *ife = mii->mii_media.ifm_cur; @@ -215,25 +205,7 @@ qsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - switch (IFM_SUBTYPE(ife->ifm_media)) { - case IFM_AUTO: - /* - * If we're already in auto mode, just return. - */ - if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) - return (0); - - (void) mii_phy_auto(sc, 1); - break; - - default: - /* - * BMCR data is stored in the ifmedia entry. - */ - PHY_WRITE(sc, MII_ANAR, - mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); - } + mii_phy_set_media(sc); break; case MII_TICK: @@ -259,14 +231,11 @@ qsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) qsphy_status(sc); /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } -void +static void qsphy_status(struct mii_softc *sc) { struct mii_data *mii = sc->mii_pdata; @@ -290,37 +259,46 @@ qsphy_status(struct mii_softc *sc) if (bmcr & BMCR_LOOP) mii->mii_media_active |= IFM_LOOP; - pctl = PHY_READ(sc, MII_QSPHY_PCTL); - switch (pctl & PCTL_OPMASK) { - case PCTL_10_T: - mii->mii_media_active |= IFM_10_T; - 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; - case PCTL_AN: - mii->mii_media_active |= IFM_NONE; - break; - default: - /* Erg... this shouldn't happen. */ - mii->mii_media_active |= IFM_NONE; - break; + if (bmcr & BMCR_AUTOEN) { + if ((bmsr & BMSR_ACOMP) == 0) { + /* Erg, still trying, I guess... */ + mii->mii_media_active |= IFM_NONE; + return; + } + + 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; + case PCTL_AN: + mii->mii_media_active |= IFM_NONE; + break; + default: + /* Erg... this shouldn't happen. */ + mii->mii_media_active |= IFM_NONE; + break; + } + } else { + mii->mii_media_active = mii->mii_media.ifm_cur->ifm_media; } } -void +static void qsphy_reset(struct mii_softc *sc) { - mii_phy_reset(sc); PHY_WRITE(sc, MII_QSPHY_IMASK, 0); } diff --git a/sys/dev/netif/mii_layer/rgephy.c b/sys/dev/netif/mii_layer/rgephy.c index a378078c92..1d5e25d21a 100644 --- a/sys/dev/netif/mii_layer/rgephy.c +++ b/sys/dev/netif/mii_layer/rgephy.c @@ -1,4 +1,6 @@ -/*- +/* $OpenBSD: rgephy.c,v 1.12 2006/06/27 05:36:58 brad Exp $ */ + +/* * Copyright (c) 2003 * Bill Paul . All rights reserved. * @@ -30,7 +32,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/rgephy.c,v 1.7 2005/09/30 19:39:27 imp Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/rgephy.c,v 1.1 2005/12/26 13:36:18 sephe Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/rgephy.c,v 1.2 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -74,6 +76,12 @@ static device_method_t rgephy_methods[] = { { 0, 0 } }; +static const struct mii_phydesc rgephys[] = { + MII_PHYDESC(REALTEK2, RTL8169S), + MII_PHYDESC(xxREALTEK, RTL8169S), + MII_PHYDESC_NULL +}; + static devclass_t rgephy_devclass; static driver_t rgephy_driver = { @@ -90,21 +98,18 @@ static int rgephy_mii_phy_auto(struct mii_softc *); static void rgephy_reset(struct mii_softc *); static void rgephy_loop(struct mii_softc *); static void rgephy_load_dspcode(struct mii_softc *); -static int rgephy_mii_model; static int rgephy_probe(device_t dev) { - struct mii_attach_args *ma; - - ma = device_get_ivars(dev); + struct mii_attach_args *ma = device_get_ivars(dev); + const struct mii_phydesc *mpd; - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxREALTEK && - MII_MODEL(ma->mii_id2) == MII_MODEL_xxREALTEK_RTL8169S) { - device_set_desc(dev, MII_STR_xxREALTEK_RTL8169S); - return(0); + mpd = mii_phy_match(ma, rgephys); + if (mpd != NULL) { + device_set_desc(dev, mpd->mpd_name); + return (0); } - return(ENXIO); } @@ -114,7 +119,6 @@ rgephy_attach(device_t dev) struct mii_softc *sc; struct mii_attach_args *ma; struct mii_data *mii; - const char *sep = ""; sc = device_get_softc(dev); ma = device_get_ivars(dev); @@ -126,43 +130,25 @@ rgephy_attach(device_t dev) sc->mii_inst = mii->mii_instance; sc->mii_service = rgephy_service; + sc->mii_reset = rgephy_reset; sc->mii_pdata = mii; sc->mii_flags |= MIIF_NOISOLATE; mii->mii_instance++; -#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) -#define PRINT(s) printf("%s%s", sep, s); sep = ", " - - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), - BMCR_ISO); -#if 0 - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), - BMCR_LOOP|BMCR_S100); -#endif - - rgephy_mii_model = MII_MODEL(ma->mii_id2); rgephy_reset(sc); sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; - sc->mii_capabilities &= ~BMSR_ANEG; + if (sc->mii_capabilities & BMSR_EXTSTAT) + sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); device_printf(dev, " "); - mii_add_media(sc, sc->mii_capabilities); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst), - RGEPHY_BMCR_FDX); - PRINT(", 1000baseTX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst), 0); - PRINT("1000baseTX-FDX"); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0); - PRINT("auto"); - + if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 && + (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) + printf("no media present"); + else + mii_phy_add_media(sc); printf("\n"); -#undef ADD -#undef PRINT - - /* Make mii_bmsr_media_to_anar() work correctly */ - sc->mii_flags |= MIIF_IS_1000X; MIIBUS_MEDIAINIT(sc->mii_dev); return(0); @@ -285,7 +271,7 @@ setit: * Only used for autonegotiation. */ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) - return (0); + break; /* * Check to see if we have link. If we do, we don't @@ -298,14 +284,20 @@ setit: break; /* - * Only retry autonegotiation every 5 seconds. + * Only retry autonegotiation every mii_anegticks seconds. */ - if (++sc->mii_ticks <= 5/*10*/) + if (++sc->mii_ticks <= sc->mii_anegticks) break; sc->mii_ticks = 0; - rgephy_mii_phy_auto(sc); - return (0); + + /* + * Although rgephy_mii_phy_auto() always returns EJUSTRETURN, + * we should not rely on that. + */ + if (rgephy_mii_phy_auto(sc) == EJUSTRETURN) + return (0); + break; } /* Update the media status. */ @@ -315,11 +307,11 @@ setit: * Callback if something changed. Note that we need to poke * the DSP on the RealTek PHYs if the media changes. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { + if (sc->mii_media_active != mii->mii_media_active || + sc->mii_media_status != mii->mii_media_status || + cmd == MII_MEDIACHG) rgephy_load_dspcode(sc); - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } @@ -369,16 +361,17 @@ rgephy_status(struct mii_softc *sc) } static int -rgephy_mii_phy_auto(struct mii_softc *mii) +rgephy_mii_phy_auto(struct mii_softc *sc) { - rgephy_loop(mii); - rgephy_reset(mii); + rgephy_loop(sc); + rgephy_reset(sc); - PHY_WRITE(mii, RGEPHY_MII_ANAR, mii_bmsr_media_to_anar(mii)); + PHY_WRITE(sc, RGEPHY_MII_ANAR, + BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA); DELAY(1000); - PHY_WRITE(mii, RGEPHY_MII_1000CTL, RGEPHY_1000CTL_AFD); + PHY_WRITE(sc, RGEPHY_MII_1000CTL, RGEPHY_1000CTL_AFD); DELAY(1000); - PHY_WRITE(mii, RGEPHY_MII_BMCR, + PHY_WRITE(sc, RGEPHY_MII_BMCR, RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG); DELAY(100); @@ -388,7 +381,7 @@ rgephy_mii_phy_auto(struct mii_softc *mii) static void rgephy_loop(struct mii_softc *sc) { - u_int32_t bmsr; + uint32_t bmsr; int i; PHY_WRITE(sc, RGEPHY_MII_BMCR, RGEPHY_BMCR_PDOWN); diff --git a/sys/dev/netif/mii_layer/rlphy.c b/sys/dev/netif/mii_layer/rlphy.c index f4443c1f82..4c0c64b3ca 100644 --- a/sys/dev/netif/mii_layer/rlphy.c +++ b/sys/dev/netif/mii_layer/rlphy.c @@ -1,3 +1,5 @@ +/* $OpenBSD: rlphy.c,v 1.23 2006/05/16 02:24:45 brad Exp $ */ + /* * Copyright (c) 1997, 1998, 1999 * Bill Paul . All rights reserved. @@ -30,7 +32,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/rlphy.c,v 1.2.2.4 2002/11/08 21:53:49 semenu Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/rlphy.c,v 1.9 2005/10/31 09:20:05 sephe Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/rlphy.c,v 1.10 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -56,19 +58,26 @@ #include "miibus_if.h" -static int rlphy_probe (device_t); -static int rlphy_attach (device_t); -static int rlphy_detach (device_t); +static int rlphy_probe(device_t); +static int rlphy_attach(device_t); +static int rlphy_service(struct mii_softc *, struct mii_data *, int); +static void rlphy_status(struct mii_softc *); static device_method_t rlphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, rlphy_probe), DEVMETHOD(device_attach, rlphy_attach), - DEVMETHOD(device_detach, rlphy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; +static const struct mii_phydesc rlphys[] = { + MII_PHYDESC(REALTEK, RTL8201L), + MII_PHYDESC(ICPLUS, IP101), + MII_PHYDESC_NULL +}; + static devclass_t rlphy_devclass; static driver_t rlphy_driver = { @@ -79,23 +88,21 @@ static driver_t rlphy_driver = { DRIVER_MODULE(rlphy, miibus, rlphy_driver, rlphy_devclass, 0, 0); -static int rlphy_service(struct mii_softc *, struct mii_data *, int); -static void rlphy_status(struct mii_softc *); - static int rlphy_probe(device_t dev) { - struct mii_attach_args *ma; - device_t parent; - - ma = device_get_ivars(dev); - parent = device_get_parent(device_get_parent(dev)); + struct mii_attach_args *ma = device_get_ivars(dev); + const struct mii_phydesc *mpd; + device_t parent; - /* Test for RealTek 8201L PHY */ - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_REALTEK && - MII_MODEL(ma->mii_id2) == MII_MODEL_REALTEK_RTL8201L) { - device_set_desc(dev, MII_STR_REALTEK_RTL8201L); - return(0); + /* + * A "real" phy should get preference, but on the 8139 there + * is no phyid register. + */ + mpd = mii_phy_match(ma, rlphys); + if (mpd != NULL) { + device_set_desc(dev, mpd->mpd_name); + return (0); } /* @@ -106,6 +113,8 @@ rlphy_probe(device_t dev) MII_MODEL(ma->mii_id2) != 0) return (ENXIO); + parent = device_get_parent(device_get_parent(dev)); + /* * Make sure the parent is an `rl'. */ @@ -156,7 +165,7 @@ rlphy_attach(device_t dev) #endif ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), - BMCR_LOOP|BMCR_S100); + MII_MEDIA_100_TX); mii_phy_reset(sc); @@ -174,28 +183,13 @@ rlphy_attach(device_t dev) if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) printf("no media present"); else - mii_add_media(sc, sc->mii_capabilities); + mii_phy_add_media(sc); printf("\n"); #undef ADD MIIBUS_MEDIAINIT(sc->mii_dev); return(0); } -static int -rlphy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_softc(dev)); - mii_phy_auto_stop(sc); - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); - - return(0); -} - static int rlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { @@ -204,8 +198,8 @@ rlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) /* * We can't isolate the RealTek PHY, so it has to be the only one! */ - if (IFM_INST(ife->ifm_media) != sc->mii_inst) - panic("rlphy_service: can't isolate RealTek PHY"); + KASSERT(IFM_INST(ife->ifm_media) == sc->mii_inst, + ("rlphy_service: can't isolate RealTek PHY")); switch (cmd) { case MII_POLLSTAT: @@ -218,37 +212,17 @@ rlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - switch (IFM_SUBTYPE(ife->ifm_media)) { - case IFM_AUTO: - /* - * If we're already in auto mode, just return. - */ - if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) - return (0); - (void) mii_phy_auto(sc, 0); - break; - case IFM_100_T4: + if (IFM_SUBTYPE(ife->ifm_media) == IFM_100_T4) { /* * XXX Not supported as a manual setting right now. */ return (EINVAL); - default: - /* - * BMCR data is stored in the ifmedia entry. - */ - PHY_WRITE(sc, MII_ANAR, - mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); } + + mii_phy_set_media(sc); break; case MII_TICK: - /* - * Only used for autonegotiation. - */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) - return (0); - /* * Is the interface even up? */ @@ -256,12 +230,10 @@ rlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) return (0); /* - * Only retry autonegotiation every 5 seconds. + * Only used for autonegotiation. */ - if (++sc->mii_ticks != 5) - return (0); - - sc->mii_ticks = 0; + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + break; /* * The RealTek PHY's autonegotiation doesn't need to be @@ -274,28 +246,24 @@ rlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) rlphy_status(sc); /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } static void -rlphy_status(struct mii_softc *phy) +rlphy_status(struct mii_softc *sc) { - struct mii_data *mii = phy->mii_pdata; + struct mii_data *mii = sc->mii_pdata; int bmsr, bmcr, anlpar; - device_t parent; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; - bmsr = PHY_READ(phy, MII_BMSR) | PHY_READ(phy, MII_BMSR); + bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (bmsr & BMSR_LINK) mii->mii_media_status |= IFM_ACTIVE; - bmcr = PHY_READ(phy, MII_BMCR); + bmcr = PHY_READ(sc, MII_BMCR); if (bmcr & BMCR_ISO) { mii->mii_media_active |= IFM_NONE; mii->mii_media_status = 0; @@ -306,6 +274,8 @@ rlphy_status(struct mii_softc *phy) mii->mii_media_active |= IFM_LOOP; if (bmcr & BMCR_AUTOEN) { + device_t parent; + /* * NWay autonegotiation takes the highest-order common * bit of the ANAR and ANLPAR (i.e. best media advertised @@ -317,8 +287,8 @@ rlphy_status(struct mii_softc *phy) return; } - if ((anlpar = PHY_READ(phy, MII_ANAR) & - PHY_READ(phy, MII_ANLPAR))) { + if ((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) @@ -342,7 +312,6 @@ rlphy_status(struct mii_softc *phy) * change the media settings if we're wrong. */ - /* * The RealTek PHY supports non-NWAY link speed * detection, however it does not report the link @@ -361,20 +330,20 @@ rlphy_status(struct mii_softc *phy) * can test the 'SPEED10' bit of the MAC's media status * register. */ - parent = device_get_parent(phy->mii_dev); + parent = device_get_parent(sc->mii_dev); if (strcmp(device_get_name(parent), "rl") != 0) { - if (PHY_READ(phy, 0x0019) & 0x01) + if (PHY_READ(sc, 0x0019) & 0x01) mii->mii_media_active |= IFM_100_TX; else mii->mii_media_active |= IFM_10_T; } else { - if (PHY_READ(phy, RL_MEDIASTAT) & + if (PHY_READ(sc, RL_MEDIASTAT) & RL_MEDIASTAT_SPEED10) mii->mii_media_active |= IFM_10_T; else mii->mii_media_active |= IFM_100_TX; } - - } else - mii->mii_media_active = mii_media_from_bmcr(bmcr); + } else { + mii->mii_media_active = mii->mii_media.ifm_cur->ifm_media; + } } diff --git a/sys/dev/netif/mii_layer/ruephy.c b/sys/dev/netif/mii_layer/ruephy.c index 97ae1aed7d..fa993870c1 100644 --- a/sys/dev/netif/mii_layer/ruephy.c +++ b/sys/dev/netif/mii_layer/ruephy.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/ruephy.c,v 1.1.4.1 2003/07/30 13:57:35 akiyama Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/ruephy.c,v 1.4 2005/11/05 10:01:54 sephe Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/ruephy.c,v 1.5 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -49,13 +49,12 @@ static int ruephy_probe(device_t); static int ruephy_attach(device_t); -static int ruephy_detach(device_t); static device_method_t ruephy_methods[] = { /* device interface */ DEVMETHOD(device_probe, ruephy_probe), DEVMETHOD(device_attach, ruephy_attach), - DEVMETHOD(device_detach, ruephy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; @@ -128,6 +127,7 @@ ruephy_attach(device_t dev) sc->mii_inst = mii->mii_instance; sc->mii_service = ruephy_service; + sc->mii_reset = ruephy_reset; sc->mii_pdata = mii; mii->mii_instance++; @@ -135,34 +135,19 @@ ruephy_attach(device_t dev) ruephy_reset(sc); - sc->mii_capabilities = - PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + device_printf(dev, " "); if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) printf("no media present"); else - mii_add_media(sc, sc->mii_capabilities); + mii_phy_add_media(sc); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); return (0); } -static int -ruephy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_softc(dev)); - mii_phy_auto_stop(sc); - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); - - return (0); -} - static int ruephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { @@ -173,8 +158,8 @@ ruephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) * We can't isolate the RealTek RTL8150 PHY, * so it has to be the only one! */ - if (IFM_INST(ife->ifm_media) != sc->mii_inst) - panic("ruephy_service: can't isolate RealTek RTL8150 PHY"); + KASSERT(IFM_INST(ife->ifm_media) == sc->mii_inst, + ("ruephy_service: can't isolate RealTek RTL8150 PHY")); switch (cmd) { case MII_POLLSTAT: @@ -187,28 +172,14 @@ ruephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - switch (IFM_SUBTYPE(ife->ifm_media)) { - case IFM_AUTO: - /* - * If we're already in auto mode, just return. - */ - if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) - return (0); - (void) mii_phy_auto(sc, 1); - break; - case IFM_100_T4: + if (IFM_SUBTYPE(ife->ifm_media) == IFM_100_T4) { /* * XXX Not supported as a manual setting right now. */ return (EINVAL); - default: - /* - * BMCR data is stored in the ifmedia entry. - */ - PHY_WRITE(sc, MII_ANAR, - mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); } + + mii_phy_set_media(sc); break; case MII_TICK: @@ -242,6 +213,7 @@ ruephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) sc->mii_ticks = 0; ruephy_reset(sc); + if (mii_phy_auto(sc, 0) == EJUSTRETURN) return (0); break; @@ -251,11 +223,7 @@ ruephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) ruephy_status(sc); /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } - + mii_phy_update(sc, cmd); return (0); } @@ -273,26 +241,26 @@ ruephy_reset(struct mii_softc *sc) } static void -ruephy_status(struct mii_softc *phy) +ruephy_status(struct mii_softc *sc) { - struct mii_data *mii = phy->mii_pdata; + struct mii_data *mii = sc->mii_pdata; int bmsr, bmcr, msr; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; - msr = PHY_READ(phy, RUEPHY_MII_MSR) | PHY_READ(phy, RUEPHY_MII_MSR); + msr = PHY_READ(sc, RUEPHY_MII_MSR) | PHY_READ(sc, RUEPHY_MII_MSR); if (msr & RUEPHY_MSR_LINK) mii->mii_media_status |= IFM_ACTIVE; - bmcr = PHY_READ(phy, MII_BMCR); + bmcr = PHY_READ(sc, MII_BMCR); if (bmcr & BMCR_ISO) { mii->mii_media_active |= IFM_NONE; mii->mii_media_status = 0; return; } - bmsr = PHY_READ(phy, MII_BMSR) | PHY_READ(phy, MII_BMSR); + bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); if (bmcr & BMCR_AUTOEN) { if ((bmsr & BMSR_ACOMP) == 0) { @@ -308,6 +276,7 @@ ruephy_status(struct mii_softc *phy) if (msr & RUEPHY_MSR_DUPLEX) mii->mii_media_active |= IFM_FDX; - } else - mii->mii_media_active = mii_media_from_bmcr(bmcr); + } else { + mii->mii_media_active = mii->mii_media.ifm_cur->ifm_media; + } } diff --git a/sys/dev/netif/mii_layer/tlphy.c b/sys/dev/netif/mii_layer/tlphy.c index 1173f22b89..4e08a0a428 100644 --- a/sys/dev/netif/mii_layer/tlphy.c +++ b/sys/dev/netif/mii_layer/tlphy.c @@ -37,7 +37,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/tlphy.c,v 1.2.2.2 2001/07/29 22:48:37 kris Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/tlphy.c,v 1.8 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/tlphy.c,v 1.9 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -103,17 +103,21 @@ struct tlphy_softc { static int tlphy_probe (device_t); static int tlphy_attach (device_t); -static int tlphy_detach (device_t); static device_method_t tlphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, tlphy_probe), DEVMETHOD(device_attach, tlphy_attach), - DEVMETHOD(device_detach, tlphy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; +static const struct mii_phydesc tlphys[] = { + MII_PHYDESC(xxTI, TLAN10T), + MII_PHYDESC_NULL +}; + static devclass_t tlphy_devclass; static driver_t tlphy_driver = { @@ -124,25 +128,23 @@ static driver_t tlphy_driver = { DRIVER_MODULE(tlphy, miibus, tlphy_driver, tlphy_devclass, 0, 0); -int tlphy_service (struct mii_softc *, struct mii_data *, int); -int tlphy_auto (struct tlphy_softc *, int); -void tlphy_acomp (struct tlphy_softc *); -void tlphy_status (struct tlphy_softc *); +static int tlphy_service(struct mii_softc *, struct mii_data *, int); +static int tlphy_auto(struct tlphy_softc *, int); +static void tlphy_acomp(struct tlphy_softc *); +static void tlphy_status(struct tlphy_softc *); static int tlphy_probe(device_t dev) { - struct mii_attach_args *ma; - - ma = device_get_ivars(dev); + struct mii_attach_args *ma = device_get_ivars(dev); + const struct mii_phydesc *mpd; - if (MII_OUI(ma->mii_id1, ma->mii_id2) != MII_OUI_xxTI || - MII_MODEL(ma->mii_id2) != MII_MODEL_xxTI_TLAN10T) - return (ENXIO); - - device_set_desc(dev, MII_STR_xxTI_TLAN10T); - - return (0); + mpd = mii_phy_match(ma, tlphys); + if (mpd != NULL) { + device_set_desc(dev, mpd->mpd_name); + return (0); + } + return (ENXIO); } static int @@ -163,6 +165,7 @@ tlphy_attach(device_t dev) sc->sc_mii.mii_inst = mii->mii_instance; sc->sc_mii.mii_service = tlphy_service; + sc->sc_mii.mii_reset = mii_phy_reset; sc->sc_mii.mii_pdata = mii; if (mii->mii_instance) { @@ -199,11 +202,8 @@ tlphy_attach(device_t dev) #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), - BMCR_ISO); - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_LOOP, - sc->sc_mii.mii_inst), BMCR_LOOP); + sc->sc_mii.mii_inst), MII_MEDIA_10_T); #define PRINT(s) printf("%s%s", sep, s); sep = ", " @@ -215,7 +215,10 @@ tlphy_attach(device_t dev) if (sc->sc_mii.mii_capabilities & BMSR_MEDIAMASK) { printf("%s", sep); - mii_add_media(&sc->sc_mii, sc->sc_mii.mii_capabilities); + mii_phy_add_media(&sc->sc_mii); + } else { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->sc_mii.mii_inst), + MII_MEDIA_NONE); } printf("\n"); @@ -226,20 +229,6 @@ tlphy_attach(device_t dev) } static int -tlphy_detach(device_t dev) -{ - struct tlphy_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); - sc->sc_mii.mii_dev = NULL; - LIST_REMOVE(&sc->sc_mii, mii_list); - - return(0); -} - -int tlphy_service(struct mii_softc *self, struct mii_data *mii, int cmd) { struct tlphy_softc *sc = (struct tlphy_softc *)self; @@ -282,7 +271,7 @@ tlphy_service(struct mii_softc *self, struct mii_data *mii, int cmd) * an autonegotiation cycle, so there's no such * thing as "already in auto mode". */ - (void) tlphy_auto(sc, 1); + tlphy_auto(sc, 1); break; case IFM_10_2: case IFM_10_5: @@ -293,9 +282,8 @@ tlphy_service(struct mii_softc *self, struct mii_data *mii, int cmd) default: PHY_WRITE(&sc->sc_mii, MII_TLPHY_CTRL, 0); DELAY(100000); - PHY_WRITE(&sc->sc_mii, MII_ANAR, - mii_anar(ife->ifm_media)); - PHY_WRITE(&sc->sc_mii, MII_BMCR, ife->ifm_data); + mii_phy_set_media(&sc->sc_mii); + break; } break; @@ -307,16 +295,16 @@ tlphy_service(struct mii_softc *self, struct mii_data *mii, int cmd) return (0); /* - * Only used for autonegotiation. + * Is the interface even up? */ - if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) return (0); /* - * Is the interface even up? + * Only used for autonegotiation. */ - if ((mii->mii_ifp->if_flags & IFF_UP) == 0) - return (0); + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + break; /* * Check to see if we have link. If we do, we don't @@ -331,9 +319,9 @@ tlphy_service(struct mii_softc *self, struct mii_data *mii, int cmd) return (0); /* - * Only retry autonegotiation every 5 seconds. + * Only retry autonegotiation every mii_anegticks seconds. */ - if (++sc->sc_mii.mii_ticks != 5) + if (++sc->sc_mii.mii_ticks <= sc->sc_mii.mii_anegticks) return (0); sc->sc_mii.mii_ticks = 0; @@ -347,15 +335,11 @@ tlphy_service(struct mii_softc *self, struct mii_data *mii, int cmd) tlphy_status(sc); /* Callback if something changed. */ - if (sc->sc_mii.mii_active != mii->mii_media_active || - cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->sc_mii.mii_dev); - sc->sc_mii.mii_active = mii->mii_media_active; - } + mii_phy_update(&sc->sc_mii, cmd); return (0); } -void +static void tlphy_status(struct tlphy_softc *sc) { struct mii_data *mii = sc->sc_mii.mii_pdata; @@ -397,7 +381,7 @@ tlphy_status(struct tlphy_softc *sc) mii->mii_media_active |= IFM_10_T; } -int +static int tlphy_auto(struct tlphy_softc *sc, int waitfor) { int error; diff --git a/sys/dev/netif/mii_layer/ukphy.c b/sys/dev/netif/mii_layer/ukphy.c index 578da3d5f9..389ed664c6 100644 --- a/sys/dev/netif/mii_layer/ukphy.c +++ b/sys/dev/netif/mii_layer/ukphy.c @@ -1,7 +1,7 @@ -/* $NetBSD: ukphy.c,v 1.2 1999/04/23 04:24:32 thorpej Exp $ */ +/* $NetBSD: ukphy.c,v 1.27 2006/03/29 07:05:24 thorpej Exp $ */ /*- - * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. + * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -37,7 +37,7 @@ * POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/ukphy.c,v 1.2.2.2 2002/11/08 21:53:49 semenu Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/ukphy.c,v 1.9 2005/10/31 13:08:35 sephe Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/ukphy.c,v 1.10 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -133,15 +133,17 @@ ukphy_attach(device_t dev) sc = device_get_softc(dev); ma = device_get_ivars(dev); + mii_softc_init(sc, ma); sc->mii_dev = device_get_parent(dev); mii = device_get_softc(sc->mii_dev); LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); - if (bootverbose) + if (bootverbose) { device_printf(dev, "OUI 0x%06x, model 0x%04x, rev. %d\n", 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_service = ukphy_service; @@ -149,31 +151,26 @@ ukphy_attach(device_t dev) mii->mii_instance++; - 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->mii_inst), - BMCR_ISO); -#if 0 - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), - BMCR_LOOP|BMCR_S100); -#endif + /* + * Don't do loopback on unknown PHYs. It might confuse some of them. + */ + sc->mii_flags |= MIIF_NOLOOP; mii_phy_reset(sc); - sc->mii_capabilities = - PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + if (sc->mii_capabilities & BMSR_EXTSTAT) + sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); + device_printf(dev, " "); - if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) + if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 && + (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) printf("no media present"); else - mii_add_media(sc, sc->mii_capabilities); + mii_phy_add_media(sc); printf("\n"); -#undef ADD MIIBUS_MEDIAINIT(sc->mii_dev); - return(0); } @@ -181,10 +178,8 @@ int ukphy_detach(device_t dev) { struct mii_softc *sc; - struct mii_data *mii; sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); mii_phy_auto_stop(sc); sc->mii_dev = NULL; LIST_REMOVE(sc, mii_list); @@ -224,28 +219,7 @@ ukphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if ((mii->mii_ifp->if_flags & IFF_UP) == 0) break; - switch (IFM_SUBTYPE(ife->ifm_media)) { - case IFM_AUTO: - /* - * If we're already in auto mode, just return. - */ - if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) - return (0); - (void) mii_phy_auto(sc, 1); - break; - case IFM_100_T4: - /* - * XXX Not supported as a manual setting right now. - */ - return (EINVAL); - default: - /* - * BMCR data is stored in the ifmedia entry. - */ - PHY_WRITE(sc, MII_ANAR, - mii_anar(ife->ifm_media)); - PHY_WRITE(sc, MII_BMCR, ife->ifm_data); - } + mii_phy_set_media(sc); break; case MII_TICK: @@ -255,37 +229,7 @@ ukphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 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); - if (mii_phy_auto(sc, 0) == EJUSTRETURN) + if (mii_phy_tick(sc) == EJUSTRETURN) return (0); break; } @@ -294,9 +238,6 @@ ukphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) ukphy_status(sc); /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } diff --git a/sys/dev/netif/mii_layer/ukphy_subr.c b/sys/dev/netif/mii_layer/ukphy_subr.c index e8c950bfa1..37e24a9941 100644 --- a/sys/dev/netif/mii_layer/ukphy_subr.c +++ b/sys/dev/netif/mii_layer/ukphy_subr.c @@ -1,4 +1,4 @@ -/* $NetBSD: ukphy_subr.c,v 1.2 1998/11/05 04:08:02 thorpej Exp $ */ +/* $NetBSD: ukphy_subr.c,v 1.9 2005/12/11 12:22:42 christos Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -36,8 +36,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/mii/ukphy_subr.c,v 1.2.2.1 2002/11/08 21:53:49 semenu Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/ukphy_subr.c,v 1.6 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/ukphy_subr.c,v 1.7 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -67,7 +66,7 @@ void ukphy_status(struct mii_softc *phy) { struct mii_data *mii = phy->mii_pdata; - int bmsr, bmcr, anlpar; + int bmsr, bmcr, anlpar, gtcr, gtsr; mii->mii_media_status = IFM_AVALID; mii->mii_media_active = IFM_ETHER; @@ -99,26 +98,40 @@ ukphy_status(struct mii_softc *phy) } anlpar = PHY_READ(phy, MII_ANAR) & PHY_READ(phy, MII_ANLPAR); - if ((phy->mii_flags & MIIF_IS_1000X) && - (anlpar & ANLPAR_1000_FD)) { + if ((phy->mii_flags & MIIF_HAVE_GTCR) != 0 && + (phy->mii_extcapabilities & + (EXTSR_1000THDX | EXTSR_1000TFDX)) != 0) { + gtcr = PHY_READ(phy, MII_100T2CR); + gtsr = PHY_READ(phy, MII_100T2SR); + } else { + gtcr = gtsr = 0; + } + + if ((gtcr & GTCR_ADV_1000TFDX) && (gtsr & GTSR_LP_1000TFDX)) mii->mii_media_active |= IFM_1000_T|IFM_FDX; - } else if ((phy->mii_flags & MIIF_IS_1000X) && - (anlpar & ANLPAR_1000)) { + else if ((gtcr & GTCR_ADV_1000THDX) && + (gtsr & GTSR_LP_1000THDX)) mii->mii_media_active |= IFM_1000_T; - } else if (anlpar & ANLPAR_T4) { + else if (anlpar & ANLPAR_T4) mii->mii_media_active |= IFM_100_T4; - } else if (anlpar & ANLPAR_TX_FD) { + else if (anlpar & ANLPAR_TX_FD) mii->mii_media_active |= IFM_100_TX|IFM_FDX; - } else if (anlpar & ANLPAR_TX) { + else if (anlpar & ANLPAR_TX) mii->mii_media_active |= IFM_100_TX; - } else if (anlpar & ANLPAR_10_FD) { + else if (anlpar & ANLPAR_10_FD) mii->mii_media_active |= IFM_10_T|IFM_FDX; - } else if (anlpar & ANLPAR_10) { + else if (anlpar & ANLPAR_10) mii->mii_media_active |= IFM_10_T; - } else { + else mii->mii_media_active |= IFM_NONE; - } + + if ((mii->mii_media_active & IFM_1000_T) && + (gtsr & GTSR_MS_RES)) + mii->mii_media_active |= IFM_ETH_MASTER; + + if (mii->mii_media_active & IFM_FDX) + mii->mii_media_active |= mii_phy_flowstatus(phy); } else { - mii->mii_media_active = mii_media_from_bmcr(bmcr); + mii->mii_media_active = mii->mii_media.ifm_cur->ifm_media; } } diff --git a/sys/dev/netif/mii_layer/xmphy.c b/sys/dev/netif/mii_layer/xmphy.c index 8e902b8dd8..3667e1b2b5 100644 --- a/sys/dev/netif/mii_layer/xmphy.c +++ b/sys/dev/netif/mii_layer/xmphy.c @@ -30,7 +30,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/dev/mii/xmphy.c,v 1.1.2.5 2002/11/08 21:53:49 semenu Exp $ - * $DragonFly: src/sys/dev/netif/mii_layer/xmphy.c,v 1.8 2005/12/11 01:54:08 swildner Exp $ + * $DragonFly: src/sys/dev/netif/mii_layer/xmphy.c,v 1.9 2006/08/06 10:32:23 sephe Exp $ */ /* @@ -60,17 +60,22 @@ static int xmphy_probe (device_t); static int xmphy_attach (device_t); -static int xmphy_detach (device_t); static device_method_t xmphy_methods[] = { /* device interface */ DEVMETHOD(device_probe, xmphy_probe), DEVMETHOD(device_attach, xmphy_attach), - DEVMETHOD(device_detach, xmphy_detach), + DEVMETHOD(device_detach, ukphy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), { 0, 0 } }; +static const struct mii_phydesc xmphys[] = { + MII_PHYDESC(xxXAQTI, XMACII), + MII_PHYDESC(JATO, BASEX), + MII_PHYDESC_NULL +}; + static devclass_t xmphy_devclass; static driver_t xmphy_driver = { @@ -81,32 +86,23 @@ static driver_t xmphy_driver = { DRIVER_MODULE(xmphy, miibus, xmphy_driver, xmphy_devclass, 0, 0); -int xmphy_service (struct mii_softc *, struct mii_data *, int); -void xmphy_status (struct mii_softc *); +static int xmphy_service(struct mii_softc *, struct mii_data *, int); +static void xmphy_status(struct mii_softc *); -static int xmphy_mii_phy_auto (struct mii_softc *, int); -extern void mii_phy_auto_timeout (void *); +static int xmphy_mii_phy_auto(struct mii_softc *, int); static int xmphy_probe(device_t dev) { - struct mii_attach_args *ma; + struct mii_attach_args *ma = device_get_ivars(dev); + const struct mii_phydesc *mpd; - ma = device_get_ivars(dev); - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxXAQTI && - MII_MODEL(ma->mii_id2) == MII_MODEL_XAQTI_XMACII) { - device_set_desc(dev, MII_STR_XAQTI_XMACII); - return(0); + mpd = mii_phy_match(ma, xmphys); + if (mpd != NULL) { + device_set_desc(dev, mpd->mpd_name); + return (0); } - - if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_JATO && - MII_MODEL(ma->mii_id2) == MII_MODEL_JATO_BASEX) { - device_set_desc(dev, MII_STR_JATO_BASEX); - return(0); - } - - return(ENXIO); + return (ENXIO); } static int @@ -126,6 +122,7 @@ xmphy_attach(device_t dev) sc->mii_inst = mii->mii_instance; sc->mii_service = xmphy_service; + sc->mii_reset = mii_phy_reset; sc->mii_pdata = mii; sc->mii_flags |= MIIF_NOISOLATE; @@ -160,22 +157,6 @@ xmphy_attach(device_t dev) return(0); } -static int -xmphy_detach(device_t dev) -{ - struct mii_softc *sc; - struct mii_data *mii; - - sc = device_get_softc(dev); - mii = device_get_softc(device_get_parent(dev)); - if (sc->mii_flags & MIIF_DOINGAUTO) - callout_stop(&sc->mii_auto_ch); - sc->mii_dev = NULL; - LIST_REMOVE(sc, mii_list); - - return(0); -} - int xmphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { @@ -217,7 +198,7 @@ xmphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if (PHY_READ(sc, XMPHY_MII_BMCR) & XMPHY_BMCR_AUTOEN) return (0); #endif - (void) xmphy_mii_phy_auto(sc, 1); + xmphy_mii_phy_auto(sc, 1); break; case IFM_1000_SX: mii_phy_reset(sc); @@ -244,12 +225,6 @@ xmphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) 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? */ @@ -257,12 +232,10 @@ xmphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) return (0); /* - * Only retry autonegotiation every 5 seconds. + * Only used for autonegotiation. */ - if (++sc->mii_ticks != 5) - return (0); - - sc->mii_ticks = 0; + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + break; /* * Check to see if we have link. If we do, we don't @@ -274,6 +247,14 @@ xmphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) if (reg & XMPHY_BMSR_LINK) break; + /* + * Only retry autonegotiation every mii_anegticks seconds. + */ + if (++sc->mii_ticks <= sc->mii_anegticks) + return (0); + + sc->mii_ticks = 0; + mii_phy_reset(sc); if (xmphy_mii_phy_auto(sc, 0) == EJUSTRETURN) return(0); @@ -284,10 +265,7 @@ xmphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) xmphy_status(sc); /* Callback if something changed. */ - if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { - MIIBUS_STATCHG(sc->mii_dev); - sc->mii_active = mii->mii_media_active; - } + mii_phy_update(sc, cmd); return (0); } @@ -313,7 +291,6 @@ xmphy_status(struct mii_softc *sc) if (bmcr & XMPHY_BMCR_LOOP) mii->mii_media_active |= IFM_LOOP; - if (bmcr & XMPHY_BMCR_AUTOEN) { if ((bmsr & XMPHY_BMSR_ACOMP) == 0) { if (bmsr & XMPHY_BMSR_LINK) { @@ -340,36 +317,29 @@ xmphy_status(struct mii_softc *sc) mii->mii_media_active |= IFM_FDX; else mii->mii_media_active |= IFM_HDX; - - return; } static int -xmphy_mii_phy_auto(struct mii_softc *mii, int waitfor) +xmphy_mii_phy_auto(struct mii_softc *sc, int waitfor) { int bmsr, anar = 0, i; - if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) { - anar = PHY_READ(mii, XMPHY_MII_ANAR); - anar |= XMPHY_ANAR_FDX|XMPHY_ANAR_HDX; - PHY_WRITE(mii, XMPHY_MII_ANAR, anar); + if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) { + anar = PHY_READ(sc, XMPHY_MII_ANAR); + anar |= XMPHY_ANAR_FDX | XMPHY_ANAR_HDX; + PHY_WRITE(sc, XMPHY_MII_ANAR, anar); DELAY(1000); - PHY_WRITE(mii, XMPHY_MII_BMCR, + PHY_WRITE(sc, XMPHY_MII_BMCR, XMPHY_BMCR_AUTOEN | XMPHY_BMCR_STARTNEG); } if (waitfor) { /* Wait 500ms for it to complete. */ for (i = 0; i < 500; i++) { - if ((bmsr = PHY_READ(mii, XMPHY_MII_BMSR)) & - XMPHY_BMSR_ACOMP) + bmsr = PHY_READ(sc, XMPHY_MII_BMSR); + if (bmsr & XMPHY_BMSR_ACOMP) return (0); DELAY(1000); -#if 0 - if ((bmsr & BMSR_ACOMP) == 0) - printf("%s: autonegotiation failed to complete\n", - mii->mii_dev.dv_xname); -#endif } /* @@ -385,10 +355,10 @@ xmphy_mii_phy_auto(struct mii_softc *mii, int waitfor) * the tick handler driving autonegotiation. Don't want 500ms * delays all the time while the system is running! */ - if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) { - mii->mii_flags |= MIIF_DOINGAUTO; - callout_reset(&mii->mii_auto_ch, hz >> 1, - mii_phy_auto_timeout, mii); + if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) { + sc->mii_flags |= MIIF_DOINGAUTO; + callout_reset(&sc->mii_auto_ch, hz >> 1, + mii_phy_auto_timeout, sc); } return (EJUSTRETURN); } diff --git a/sys/net/if_media.h b/sys/net/if_media.h index e1a98ac41e..c8a40dd10e 100644 --- a/sys/net/if_media.h +++ b/sys/net/if_media.h @@ -1,6 +1,6 @@ -/* $NetBSD: if_media.h,v 1.3 1997/03/26 01:19:27 thorpej Exp $ */ +/* $NetBSD: if_media.h,v 1.45 2006/05/18 09:05:51 liamjfoy Exp $ */ /* $FreeBSD: src/sys/net/if_media.h,v 1.9.2.4 2002/07/30 06:22:40 imp Exp $ */ -/* $DragonFly: src/sys/net/if_media.h,v 1.10 2006/05/20 02:42:08 dillon Exp $ */ +/* $DragonFly: src/sys/net/if_media.h,v 1.11 2006/08/06 10:32:23 sephe Exp $ */ /* * Copyright (c) 1997 @@ -121,10 +121,11 @@ int ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr, * if_media Options word: * Bits Use * ---- ------- - * 0-4 Media variant + * 0-4 Media variant MAX SUBTYPE == 31!! * 5-7 Media type * 8-15 Type specific options - * 16-19 RFU + * 16-18 Mode (for multi-mode devices) + * 19 RFU * 20-27 Shared (global) options * 28-31 Instance */ @@ -149,7 +150,10 @@ int ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr, #define IFM_1000_CX 16 /* 1000BaseCX 150ohm STP */ #define IFM_1000_T 17 /* 1000BaseTX 4 pair cat 5 */ #define IFM_HPNA_1 18 /* HomePNA media for ethernet frames */ -/* note 31 is the max! */ + +#define IFM_ETH_MASTER 0x00000100 /* master mode (1000baseT) */ +#define IFM_ETH_RXPAUSE 0x00000200 /* receive PAUSE frames */ +#define IFM_ETH_TXPAUSE 0x00000400 /* transmit PAUSE frames */ /* * Token ring @@ -244,6 +248,7 @@ int ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr, */ #define IFM_FDX 0x00100000 /* Force full duplex */ #define IFM_HDX 0x00200000 /* Force half duplex */ +#define IFM_FLOW 0x00400000 /* enable hardware flow control */ #define IFM_FLAG0 0x01000000 /* Driver defined flag */ #define IFM_FLAG1 0x02000000 /* Driver defined flag */ #define IFM_FLAG2 0x04000000 /* Driver defined flag */ @@ -260,6 +265,11 @@ int ifmedia_ioctl(struct ifnet *ifp, struct ifreq *ifr, #define IFM_MMASK 0x00070000 /* Mode */ #define IFM_MSHIFT 16 /* Mode shift */ #define IFM_GMASK 0x0ff00000 /* Global options */ + /* Ethernet flow control mask */ +#define IFM_ETH_FMASK (IFM_FLOW | IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE) + +#define IFM_NMIN IFM_ETHER /* lowest Network type */ +#define IFM_NMAX IFM_NMASK /* highest Network type */ /* * Status bits -- 2.41.0