diff options
author | Jason Wright <jason@cvs.openbsd.org> | 1998-09-04 05:59:21 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 1998-09-04 05:59:21 +0000 |
commit | 77672799ad484151ea7bb1fe52d54d041ebd9d53 (patch) | |
tree | ce32d411dd47b40bb979ec73c31d74b3f8e3487c /sys/arch | |
parent | 7936ef1dfd81def049205aab515e2aee900ecb91 (diff) |
ifmedia-fy qec+be
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sparc/dev/be.c | 216 | ||||
-rw-r--r-- | sys/arch/sparc/dev/bereg.h | 10 | ||||
-rw-r--r-- | sys/arch/sparc/dev/bevar.h | 3 |
3 files changed, 168 insertions, 61 deletions
diff --git a/sys/arch/sparc/dev/be.c b/sys/arch/sparc/dev/be.c index 187bcd9f36b..280ee79e8a0 100644 --- a/sys/arch/sparc/dev/be.c +++ b/sys/arch/sparc/dev/be.c @@ -1,4 +1,4 @@ -/* $OpenBSD: be.c,v 1.8 1998/09/01 20:04:14 jason Exp $ */ +/* $OpenBSD: be.c,v 1.9 1998/09/04 05:59:19 jason Exp $ */ /* * Copyright (c) 1998 Theo de Raadt and Jason L. Wright. @@ -42,6 +42,7 @@ #include <net/if_dl.h> #include <net/if_types.h> #include <net/netisr.h> +#include <net/if_media.h> #ifdef INET #include <netinet/in.h> @@ -90,14 +91,13 @@ struct mbuf * be_get __P((struct besoftc *, int, int)); void be_tcvr_idle __P((struct besoftc *sc)); void be_tcvr_init __P((struct besoftc *sc)); -void be_tcvr_setspeed __P((struct besoftc *sc)); void be_tcvr_write __P((struct besoftc *sc, u_int8_t reg, u_int16_t val)); void be_tcvr_write_bit __P((struct besoftc *sc, int bit)); int be_tcvr_read_bit1 __P((struct besoftc *sc)); int be_tcvr_read_bit2 __P((struct besoftc *sc)); int be_tcvr_read __P((struct besoftc *sc, u_int8_t reg)); - -void be_negotiate_watchdog __P((void *)); +void be_ifmedia_sts __P((struct ifnet *, struct ifmediareq *)); +int be_ifmedia_upd __P((struct ifnet *)); struct cfdriver be_cd = { NULL, "be", DV_IFNET @@ -131,7 +131,7 @@ beattach(parent, self, aux) struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct confargs *ca = aux; extern void myetheraddr __P((u_char *)); - int pri; + int pri, bmsr; if (ca->ca_ra.ra_nintr != 1) { printf(": expected 1 interrupt, got %d\n", ca->ca_ra.ra_nintr); @@ -164,6 +164,53 @@ beattach(parent, self, aux) myetheraddr(sc->sc_arpcom.ac_enaddr); + be_tcvr_init(sc); + + ifmedia_init(&sc->sc_ifmedia, 0, be_ifmedia_upd, be_ifmedia_sts); + bmsr = be_tcvr_read(sc, PHY_BMSR); + if (bmsr == BE_TCVR_READ_INVALID) + return; + + if (bmsr & PHY_BMSR_10BASET_HALF) { + ifmedia_add(&sc->sc_ifmedia, + IFM_ETHER | IFM_10_T | IFM_HDX, 0, NULL); + ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_T, 0, NULL); + sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_10_T | IFM_HDX; + } + + if (bmsr & PHY_BMSR_10BASET_FULL) { + ifmedia_add(&sc->sc_ifmedia, + IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL); + sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_10_T | IFM_FDX; + } + + if (bmsr & PHY_BMSR_100BASETX_HALF) { + ifmedia_add(&sc->sc_ifmedia, + IFM_ETHER | IFM_100_TX | IFM_HDX, 0, NULL); + ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_100_TX, 0, NULL); + sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_100_TX | IFM_HDX; + } + + if (bmsr & PHY_BMSR_100BASETX_FULL) { + ifmedia_add(&sc->sc_ifmedia, + IFM_ETHER | IFM_100_TX | IFM_FDX, 0, NULL); + sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_100_TX | IFM_FDX; + } + + if (bmsr & PHY_BMSR_100BASET4) { + ifmedia_add(&sc->sc_ifmedia, + IFM_ETHER | IFM_100_T4, 0, NULL); + sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_100_T4; + } + + if (bmsr & PHY_BMSR_ANC) { + ifmedia_add(&sc->sc_ifmedia, + IFM_ETHER | IFM_AUTO, 0, NULL); + sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_AUTO; + } + + ifmedia_set(&sc->sc_ifmedia, sc->sc_ifmedia.ifm_media); + bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); ifp->if_softc = sc; ifp->if_start = bestart; @@ -621,6 +668,10 @@ beioctl(ifp, cmd, data) error = 0; } break; + case SIOCGIFMEDIA: + case SIOCSIFMEDIA: + error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd); + break; default: if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) { splx(s); @@ -641,7 +692,6 @@ beinit(sc) int s = splimp(); int i; - untimeout(be_negotiate_watchdog, sc); sc->sc_nticks = 0; qec_reset(sc->sc_qec); @@ -691,7 +741,8 @@ beinit(sc) sc->sc_last_rd = 0; be_tcvr_init(sc); - be_tcvr_setspeed(sc); + + be_ifmedia_upd(ifp); bestop(sc); @@ -757,38 +808,6 @@ beinit(sc) splx(s); } -void -be_tcvr_setspeed(sc) - struct besoftc *sc; -{ - int x, tries, i; - - be_tcvr_write(sc, PHY_BMCR, - PHY_BMCR_LOOPBACK | PHY_BMCR_PDOWN | PHY_BMCR_ISOLATE); - be_tcvr_write(sc, PHY_BMCR, PHY_BMCR_RESET); - - for (tries = 0; tries < 16; i++) { - x = be_tcvr_read(sc, PHY_BMCR); - if ((x & PHY_BMCR_RESET) == 0) - break; - DELAY(20); - } - - x = be_tcvr_read(sc, PHY_BMCR); - be_tcvr_write(sc, PHY_BMCR, x & (~PHY_BMCR_ISOLATE)); - - for (tries = 0; tries < 32; i++) { - x = be_tcvr_read(sc, PHY_BMCR); - if ((x & PHY_BMCR_ISOLATE) == 0) - break; - DELAY(20); - } - - x = be_tcvr_read(sc, PHY_BMSR); - if ((x & PHY_BMSR_LINKSTATUS) == 0) - timeout(be_negotiate_watchdog, sc, (12 * hz)/10); -} - /* * Set the tcvr to an idle state */ @@ -1162,29 +1181,116 @@ be_get(sc, idx, totlen) return (top); } +/* + * Get current media settings. + */ void -be_negotiate_watchdog(v) - void *v; +be_ifmedia_sts(ifp, ifmr) + struct ifnet *ifp; + struct ifmediareq *ifmr; { - struct besoftc *sc = (struct besoftc *)v; - int x; + struct besoftc *sc = ifp->if_softc; + int bmcr, bmsr; - if (sc->sc_nticks == BE_NEGOTIATE_MAXTICKS) { - sc->sc_nticks = 0; - be_tcvr_setspeed(sc); + bmcr = be_tcvr_read(sc, PHY_BMCR); + + if ((bmcr & (PHY_BMCR_SPEED | PHY_BMCR_DUPLEX)) == + (PHY_BMCR_SPEED | PHY_BMCR_DUPLEX)) { + ifmr->ifm_active = IFM_ETHER | IFM_100_TX | IFM_FDX; return; } - sc->sc_nticks++; - x = be_tcvr_read(sc, PHY_BMSR); - if ((x & PHY_BMSR_LINKSTATUS) == 0) { - timeout(be_negotiate_watchdog, sc, (12 * hz)/10); + if (bmcr & PHY_BMCR_SPEED) { + ifmr->ifm_active = IFM_ETHER | IFM_100_TX | IFM_HDX; return; } - x = be_tcvr_read(sc, PHY_BMCR); - printf("%s: %d Mb/s %s duplex, link up.\n", - sc->sc_dev.dv_xname, - (x & PHY_BMCR_SPEED) ? 100 : 10, - (x & PHY_BMCR_DUPLEX) ? "full" : "half"); + if (bmcr & PHY_BMCR_DUPLEX) { + ifmr->ifm_active = IFM_ETHER | IFM_10_T | IFM_FDX; + return; + } + + ifmr->ifm_active = IFM_ETHER | IFM_10_T | IFM_HDX; + + bmsr = be_tcvr_read(sc, PHY_BMSR); + if (bmsr & PHY_BMSR_LINKSTATUS) + ifmr->ifm_active |= IFM_AVALID | IFM_ACTIVE; + else { + ifmr->ifm_active |= IFM_AVALID; + ifmr->ifm_active &= ~IFM_ACTIVE; + } +} + +/* + * Set media options. + */ +int +be_ifmedia_upd(ifp) + struct ifnet *ifp; +{ + struct besoftc *sc = ifp->if_softc; + struct ifmedia *ifm = &sc->sc_ifmedia; + int bmcr, tries; + + if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) + return (EINVAL); + + be_tcvr_write(sc, PHY_BMCR, + PHY_BMCR_LOOPBACK | PHY_BMCR_PDOWN | PHY_BMCR_ISOLATE); + be_tcvr_write(sc, PHY_BMCR, PHY_BMCR_RESET); + + for (tries = 16; tries >= 0; tries--) { + bmcr = be_tcvr_read(sc, PHY_BMCR); + if ((bmcr & PHY_BMCR_RESET) == 0) + break; + DELAY(20); + } + if (tries == 0) { + printf("%s: bmcr reset failed\n", sc->sc_dev.dv_xname); + return (EIO); + } + + bmcr = be_tcvr_read(sc, PHY_BMCR); + + if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_T4) { + bmcr |= PHY_BMCR_SPEED; + bmcr &= ~PHY_BMCR_DUPLEX; + printf("%s: selecting 100baseT4", sc->sc_dev.dv_xname); + } + + if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_TX) { + bmcr |= PHY_BMCR_SPEED; + printf("%s: selecting 100baseTX", sc->sc_dev.dv_xname); + } + + if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T) { + bmcr &= ~PHY_BMCR_SPEED; + printf("%s: selecting 10baseT", sc->sc_dev.dv_xname); + } + + if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) { + bmcr |= PHY_BMCR_DUPLEX; + sc->sc_br->tx_cfg |= BE_BR_TXCFG_FULLDPLX; + printf(" full-duplex\n"); + } + else { + bmcr &= ~PHY_BMCR_DUPLEX; + sc->sc_br->tx_cfg &= ~BE_BR_TXCFG_FULLDPLX; + printf(" half-duplex\n"); + } + + be_tcvr_write(sc, PHY_BMCR, bmcr & (~PHY_BMCR_ISOLATE)); + + for (tries = 32; tries >= 0; tries--) { + bmcr = be_tcvr_read(sc, PHY_BMCR); + if ((bmcr & PHY_BMCR_ISOLATE) == 0) + break; + DELAY(20); + } + if (tries == 0) { + printf("%s: bmcr unisolate failed\n", sc->sc_dev.dv_xname); + return (EIO); + } + + return (0); } diff --git a/sys/arch/sparc/dev/bereg.h b/sys/arch/sparc/dev/bereg.h index ec02b15e059..7d67c6c7c44 100644 --- a/sys/arch/sparc/dev/bereg.h +++ b/sys/arch/sparc/dev/bereg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bereg.h,v 1.5 1998/09/01 20:04:16 jason Exp $ */ +/* $OpenBSD: bereg.h,v 1.6 1998/09/04 05:59:19 jason Exp $ */ /* * Copyright (c) 1998 Theo de Raadt and Jason L. Wright. @@ -294,10 +294,10 @@ struct be_bufs { * Basic Mode Status Register (BMSR) */ #define PHY_BMSR_100BASET4 0x8000 /* 100BaseT4 capable? */ -#define PHY_BMSR_100BASETX_FULL 0x4000 /* 100BaseTX full duplex? */ -#define PHY_BMSR_100BASETX_HALF 0x2000 /* 100BaseTX half duplex? */ -#define PHY_BMSR_10BASET_FULL 0x1000 /* 10BaseT full duplex? */ -#define PHY_BMSR_10BASET_HALF 0x0800 /* 10BaseT half duplex? */ +#define PHY_BMSR_100BASETX_FULL 0x4000 /* 100BaseTX full duplex cap? */ +#define PHY_BMSR_100BASETX_HALF 0x2000 /* 100BaseTX half duplex cap? */ +#define PHY_BMSR_10BASET_FULL 0x1000 /* 10BaseT full duplex cap? */ +#define PHY_BMSR_10BASET_HALF 0x0800 /* 10BaseT half duplex cap? */ #define PHY_BMSR_ANCOMPLETE 0x0020 /* auto-negotiation complete? */ #define PHY_BMSR_REMOTEFAULT 0x0010 /* Fault condition seen? */ #define PHY_BMSR_ANC 0x0008 /* Can auto-negotiate? */ diff --git a/sys/arch/sparc/dev/bevar.h b/sys/arch/sparc/dev/bevar.h index 2f1b6793ae0..b9855053fe3 100644 --- a/sys/arch/sparc/dev/bevar.h +++ b/sys/arch/sparc/dev/bevar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bevar.h,v 1.6 1998/08/28 19:06:52 jason Exp $ */ +/* $OpenBSD: bevar.h,v 1.7 1998/09/04 05:59:20 jason Exp $ */ /* * Copyright (c) 1998 Theo de Raadt and Jason L. Wright. @@ -32,6 +32,7 @@ struct besoftc { struct sbusdev sc_sd; /* sbus device */ struct intrhand sc_ih; /* interrupt vectoring */ struct arpcom sc_arpcom; /* ethernet common */ + struct ifmedia sc_ifmedia; /* interface media */ struct qec_softc *sc_qec; /* QEC parent */ struct qecregs *sc_qr; /* QEC registers */ |