diff options
author | Jason Wright <jason@cvs.openbsd.org> | 1998-09-08 04:48:39 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 1998-09-08 04:48:39 +0000 |
commit | ed71f170aed8f176999a712295c75512826b91f2 (patch) | |
tree | 6d6094d0cdb00b3640ab8e80ae091baabf76f224 /sys/arch/sparc/dev | |
parent | 46cc0af104a96e4a80cb7d01864e4c03a65be726 (diff) |
o hme get ifmedia support
o nuked manual negotiatie that wasn't finished anyway in favor of if_media
Diffstat (limited to 'sys/arch/sparc/dev')
-rw-r--r-- | sys/arch/sparc/dev/hme.c | 176 | ||||
-rw-r--r-- | sys/arch/sparc/dev/hmevar.h | 5 |
2 files changed, 160 insertions, 21 deletions
diff --git a/sys/arch/sparc/dev/hme.c b/sys/arch/sparc/dev/hme.c index 317aa69b0f1..939c000913b 100644 --- a/sys/arch/sparc/dev/hme.c +++ b/sys/arch/sparc/dev/hme.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hme.c,v 1.5 1998/09/01 17:36:59 jason Exp $ */ +/* $OpenBSD: hme.c,v 1.6 1998/09/08 04:48:38 jason Exp $ */ /* * Copyright (c) 1998 Jason L. Wright (jason@thought.net) @@ -52,6 +52,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> @@ -105,7 +106,6 @@ static int hme_mint __P((struct hme_softc *, u_int32_t)); static int hme_eint __P((struct hme_softc *, u_int32_t)); static void hme_auto_negotiate __P((struct hme_softc *)); -static void hme_manual_negotiate __P((struct hme_softc *)); static void hme_negotiate_watchdog __P((void *)); static void hme_print_link_mode __P((struct hme_softc *)); static void hme_set_initial_advertisement __P((struct hme_softc *)); @@ -117,7 +117,10 @@ static struct mbuf * hme_get __P((struct hme_softc *, int, int)); static void hme_read __P((struct hme_softc *, int, int)); static int hme_put __P((struct hme_softc *, int, struct mbuf *)); -static void hme_mcreset __P((struct hme_softc *)); +static int hme_ifmedia_upd __P((struct ifnet *)); +static void hme_ifmedia_sts __P((struct ifnet *, struct ifmediareq *)); + +static void hme_mcreset __P((struct hme_softc *)); struct cfattach hme_ca = { sizeof (struct hme_softc), hmematch, hmeattach @@ -438,6 +441,10 @@ hmeioctl(ifp, cmd, data) error = 0; } break; + case SIOCGIFMEDIA: + case SIOCSIFMEDIA: + error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd); + break; default: error = EINVAL; } @@ -596,7 +603,7 @@ hmeinit(sc) cr->tx_cfg |= CR_TXCFG_ENABLE; /* enable tx */ cr->rx_cfg |= CR_RXCFG_ENABLE; /* enable rx */ - hme_auto_negotiate(sc); + hme_ifmedia_upd(&sc->sc_arpcom.ac_if); } static void @@ -628,27 +635,54 @@ hme_set_initial_advertisement(sc) sc->sc_sw.bmsr = hme_tcvr_read(sc, DP83840_BMSR); sc->sc_sw.anar = hme_tcvr_read(sc, DP83840_ANAR); + ifmedia_init(&sc->sc_ifmedia, 0, hme_ifmedia_upd, hme_ifmedia_sts); + /* If 10BaseT Half duplex supported, advertise it, and so on... */ - if (sc->sc_sw.bmsr & BMSR_10BASET_HALF) + if (sc->sc_sw.bmsr & BMSR_10BASET_HALF) { + ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_T, 0, NULL); + ifmedia_add(&sc->sc_ifmedia, + IFM_ETHER | IFM_10_T | IFM_HDX, 0, NULL); + sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_10_T | IFM_HDX; sc->sc_sw.anar |= ANAR_10; + } else sc->sc_sw.anar &= ~(ANAR_10); - if (sc->sc_sw.bmsr & BMSR_10BASET_FULL) + if (sc->sc_sw.bmsr & 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; sc->sc_sw.anar |= ANAR_10_FD; + } else sc->sc_sw.anar &= ~(ANAR_10_FD); - if (sc->sc_sw.bmsr & BMSR_100BASETX_HALF) + if (sc->sc_sw.bmsr & BMSR_100BASETX_HALF) { + ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_100_TX, 0, NULL); + ifmedia_add(&sc->sc_ifmedia, + IFM_ETHER | IFM_100_TX | IFM_HDX, 0, NULL); + sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_100_TX | IFM_HDX; sc->sc_sw.anar |= ANAR_TX; + } else sc->sc_sw.anar &= ~(ANAR_TX); - if (sc->sc_sw.bmsr & BMSR_100BASETX_FULL) + if (sc->sc_sw.bmsr & 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; sc->sc_sw.anar |= ANAR_TX_FD; + } else sc->sc_sw.anar &= ~(ANAR_TX_FD); + if (sc->sc_sw.bmsr & 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); + /* Inform card about what it should advertise */ hme_tcvr_write(sc, DP83840_ANAR, sc->sc_sw.anar); } @@ -987,9 +1021,9 @@ hme_auto_negotiate(sc) sc->sc_sw.phyidr2 = hme_tcvr_read(sc, DP83840_PHYIDR2); sc->sc_sw.anar = hme_tcvr_read(sc, DP83840_ANAR); - /* can this board autonegotiate? No, do it manually */ + /* can this board autonegotiate? No, die. */ if (! (sc->sc_sw.bmsr & BMSR_ANC)) - hme_manual_negotiate(sc); + return; /* advertise -everything- supported */ if (sc->sc_sw.bmsr & BMSR_10BASET_HALF) @@ -1034,7 +1068,6 @@ hme_auto_negotiate(sc) if (!tries) { printf("%s: failed to start auto-negotiation\n", sc->sc_dev.dv_xname); - hme_manual_negotiate(sc); return; } sc->sc_an_state = HME_TIMER_AUTONEG; @@ -1042,14 +1075,6 @@ hme_auto_negotiate(sc) timeout(hme_negotiate_watchdog, sc, (12 * hz)/10); } -static void -hme_manual_negotiate(sc) - struct hme_softc *sc; -{ - printf("%s: Starting manual negotiation... not yet!\n", - sc->sc_dev.dv_xname); -} - /* * If auto-negotiating, check to see if it has completed successfully. If so, * wait for a link up. If it completed unsucessfully, try the manual process. @@ -1530,3 +1555,116 @@ hme_mcreset(sc) cr->htable0 = hash[0]; } } + +/* + * Get current media settings. + */ +static void +hme_ifmedia_sts(ifp, ifmr) + struct ifnet *ifp; + struct ifmediareq *ifmr; +{ + struct hme_softc *sc = ifp->if_softc; + + sc->sc_sw.bmcr = hme_tcvr_read(sc, DP83840_BMCR); + sc->sc_sw.bmsr = hme_tcvr_read(sc, DP83840_BMSR); + + switch (sc->sc_sw.bmcr & (BMCR_SPEED | BMCR_DUPLEX)) { + case (BMCR_SPEED | BMCR_DUPLEX): + ifmr->ifm_active = IFM_ETHER | IFM_100_TX | IFM_FDX; + break; + case BMCR_SPEED: + ifmr->ifm_active = IFM_ETHER | IFM_100_TX | IFM_HDX; + break; + case BMCR_DUPLEX: + ifmr->ifm_active = IFM_ETHER | IFM_10_T | IFM_FDX; + break; + case 0: + ifmr->ifm_active = IFM_ETHER | IFM_10_T | IFM_HDX; + break; + } + + if (sc->sc_sw.bmsr & BMSR_LINKSTATUS) + ifmr->ifm_status |= IFM_AVALID | IFM_ACTIVE; + else { + ifmr->ifm_status |= IFM_AVALID; + ifmr->ifm_status &= ~IFM_ACTIVE; + } +} + +static int +hme_ifmedia_upd(ifp) + struct ifnet *ifp; +{ + struct hme_softc *sc = ifp->if_softc; + struct ifmedia *ifm = &sc->sc_ifmedia; + int tries, result; + + if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) + return (EINVAL); + + if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO && + sc->sc_sw.bmsr & BMSR_ANC) { + hme_auto_negotiate(sc); + return (0); + } + if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) + return (EINVAL); + + hme_tcvr_write(sc, DP83840_BMCR, + (BMCR_LOOPBACK | BMCR_PDOWN | BMCR_ISOLATE)); + if (result == TCVR_FAILURE) { + printf("%s: tcvr_reset failed\n", sc->sc_dev.dv_xname); + return (EIO); + } + hme_tcvr_write(sc, DP83840_BMCR, BMCR_RESET); + + tries = 32; + while (--tries) { + result = hme_tcvr_read(sc, DP83840_BMCR); + if (result == TCVR_FAILURE) + return (EIO); + sc->sc_sw.bmcr = result; + if (!(result & BMCR_RESET)) + break; + DELAY(200); + } + if (!tries) { + printf("%s: bmcr reset failed\n", sc->sc_dev.dv_xname); + return -1; + } + + sc->sc_sw.bmcr = hme_tcvr_read(sc, DP83840_BMCR); + + if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_T4) { + sc->sc_sw.bmcr |= BMCR_SPEED; + sc->sc_sw.bmcr &= ~BMCR_DUPLEX; + } + + if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_TX) + sc->sc_sw.bmcr |= BMCR_SPEED; + + if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T) + sc->sc_sw.bmcr &= ~BMCR_SPEED; + + if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) + sc->sc_sw.bmcr |= BMCR_DUPLEX; + else + sc->sc_sw.bmcr &= ~BMCR_DUPLEX; + + sc->sc_sw.bmcr &= ~(BMCR_ISOLATE); + hme_tcvr_write(sc, DP83840_BMCR, sc->sc_sw.bmcr); + tries = 32; + while (--tries) { + sc->sc_sw.bmcr = hme_tcvr_read(sc, DP83840_BMCR); + if ((sc->sc_sw.bmcr & BMCR_ISOLATE) == 0) + break; + DELAY(20); + } + if (!tries) { + printf("%s: bmcr unisolate failed\n", sc->sc_dev.dv_xname); + return (EIO); + } + + return (0); +} diff --git a/sys/arch/sparc/dev/hmevar.h b/sys/arch/sparc/dev/hmevar.h index ac597485bbf..ac434468678 100644 --- a/sys/arch/sparc/dev/hmevar.h +++ b/sys/arch/sparc/dev/hmevar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hmevar.h,v 1.3 1998/09/01 17:36:59 jason Exp $ */ +/* $OpenBSD: hmevar.h,v 1.4 1998/09/08 04:48:38 jason Exp $ */ /* * Copyright (c) 1998 Jason L. Wright (jason@thought.net) @@ -36,7 +36,8 @@ struct hme_softc { struct sbusdev sc_sd; /* sbus device */ struct intrhand sc_ih; /* interrupt vectoring */ int sc_node; /* which sbus node */ - struct arpcom sc_arpcom; + struct ifmedia sc_ifmedia; /* interface media */ + struct arpcom sc_arpcom; /* ethernet common */ /* * Register sets |