From fc84b1a733b5c4774a2dcd8035e4f71948716a55 Mon Sep 17 00:00:00 2001 From: wpaul Date: Sun, 19 Sep 1999 22:03:31 +0000 Subject: Convert the VIA Rhine driver to miibus. --- sys/pci/if_vr.c | 608 +++++++++++--------------------------------------------- 1 file changed, 111 insertions(+), 497 deletions(-) (limited to 'sys/pci/if_vr.c') diff --git a/sys/pci/if_vr.c b/sys/pci/if_vr.c index 1e47ec1..7ed0d86 100644 --- a/sys/pci/if_vr.c +++ b/sys/pci/if_vr.c @@ -94,15 +94,19 @@ #include #include +#include +#include + #include #include #define VR_USEIOSPACE -/* #define VR_BACKGROUND_AUTONEG */ - #include +/* "controller miibus0" required. See GENERIC if you get errors here. */ +#include "miibus_if.h" + #ifndef lint static const char rcsid[] = "$FreeBSD$"; @@ -123,22 +127,6 @@ static struct vr_type vr_devs[] = { { 0, 0, NULL } }; -/* - * Various supported PHY vendors/types and their names. Note that - * this driver will work with pretty much any MII-compliant PHY, - * so failure to positively identify the chip is not a fatal error. - */ - -static struct vr_type vr_phys[] = { - { TI_PHY_VENDORID, TI_PHY_10BT, "" }, - { TI_PHY_VENDORID, TI_PHY_100VGPMI, "" }, - { NS_PHY_VENDORID, NS_PHY_83840A, ""}, - { LEVEL1_PHY_VENDORID, LEVEL1_PHY_LXT970, "" }, - { INTEL_PHY_VENDORID, INTEL_PHY_82555, "" }, - { SEEQ_PHY_VENDORID, SEEQ_PHY_80220, "" }, - { 0, 0, "" } -}; - static int vr_probe __P((device_t)); static int vr_attach __P((device_t)); static int vr_detach __P((device_t)); @@ -153,6 +141,7 @@ static void vr_rxeof __P((struct vr_softc *)); static void vr_rxeoc __P((struct vr_softc *)); static void vr_txeof __P((struct vr_softc *)); static void vr_txeoc __P((struct vr_softc *)); +static void vr_tick __P((void *)); static void vr_intr __P((void *)); static void vr_start __P((struct ifnet *)); static int vr_ioctl __P((struct ifnet *, u_long, caddr_t)); @@ -167,14 +156,11 @@ static void vr_mii_sync __P((struct vr_softc *)); static void vr_mii_send __P((struct vr_softc *, u_int32_t, int)); static int vr_mii_readreg __P((struct vr_softc *, struct vr_mii_frame *)); static int vr_mii_writereg __P((struct vr_softc *, struct vr_mii_frame *)); -static u_int16_t vr_phy_readreg __P((struct vr_softc *, int)); -static void vr_phy_writereg __P((struct vr_softc *, u_int16_t, u_int16_t)); - -static void vr_autoneg_xmit __P((struct vr_softc *)); -static void vr_autoneg_mii __P((struct vr_softc *, int, int)); -static void vr_setmode_mii __P((struct vr_softc *, int)); -static void vr_getmode_mii __P((struct vr_softc *)); -static void vr_setcfg __P((struct vr_softc *, u_int16_t)); +static int vr_miibus_readreg __P((device_t, int, int)); +static int vr_miibus_writereg __P((device_t, int, int, int)); +static void vr_miibus_statchg __P((device_t)); + +static void vr_setcfg __P((struct vr_softc *, int)); static u_int8_t vr_calchash __P((u_int8_t *)); static void vr_setmulti __P((struct vr_softc *)); static void vr_reset __P((struct vr_softc *)); @@ -195,6 +181,16 @@ static device_method_t vr_methods[] = { DEVMETHOD(device_attach, vr_attach), DEVMETHOD(device_detach, vr_detach), DEVMETHOD(device_shutdown, vr_shutdown), + + /* bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + + /* MII interface */ + DEVMETHOD(miibus_readreg, vr_miibus_readreg), + DEVMETHOD(miibus_writereg, vr_miibus_writereg), + DEVMETHOD(miibus_statchg, vr_miibus_statchg), + { 0, 0 } }; @@ -207,6 +203,7 @@ static driver_t vr_driver = { static devclass_t vr_devclass; DRIVER_MODULE(vr, pci, vr_driver, vr_devclass, 0, 0); +DRIVER_MODULE(miibus, vr, miibus_driver, miibus_devclass, 0, 0); #define VR_SETBIT(sc, reg, x) \ CSR_WRITE_1(sc, reg, \ @@ -432,36 +429,52 @@ static int vr_mii_writereg(sc, frame) return(0); } -static u_int16_t vr_phy_readreg(sc, reg) - struct vr_softc *sc; - int reg; +static int vr_miibus_readreg(dev, phy, reg) + device_t dev; + int phy, reg; { + struct vr_softc *sc; struct vr_mii_frame frame; + sc = device_get_softc(dev); bzero((char *)&frame, sizeof(frame)); - frame.mii_phyaddr = sc->vr_phy_addr; + frame.mii_phyaddr = phy; frame.mii_regaddr = reg; vr_mii_readreg(sc, &frame); return(frame.mii_data); } -static void vr_phy_writereg(sc, reg, data) - struct vr_softc *sc; - u_int16_t reg; - u_int16_t data; +static int vr_miibus_writereg(dev, phy, reg, data) + device_t dev; + u_int16_t phy, reg, data; { + struct vr_softc *sc; struct vr_mii_frame frame; + sc = device_get_softc(dev); bzero((char *)&frame, sizeof(frame)); - frame.mii_phyaddr = sc->vr_phy_addr; + frame.mii_phyaddr = phy; frame.mii_regaddr = reg; frame.mii_data = data; vr_mii_writereg(sc, &frame); + return(0); +} + +static void vr_miibus_statchg(dev) + device_t dev; +{ + struct vr_softc *sc; + struct mii_data *mii; + + sc = device_get_softc(dev); + mii = device_get_softc(sc->vr_miibus); + vr_setcfg(sc, mii->mii_media_active); + return; } @@ -548,319 +561,13 @@ static void vr_setmulti(sc) } /* - * Initiate an autonegotiation session. - */ -static void vr_autoneg_xmit(sc) - struct vr_softc *sc; -{ - u_int16_t phy_sts; - - vr_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET); - DELAY(500); - while(vr_phy_readreg(sc, PHY_BMCR) - & PHY_BMCR_RESET); - - phy_sts = vr_phy_readreg(sc, PHY_BMCR); - phy_sts |= PHY_BMCR_AUTONEGENBL|PHY_BMCR_AUTONEGRSTR; - vr_phy_writereg(sc, PHY_BMCR, phy_sts); - - return; -} - -/* - * Invoke autonegotiation on a PHY. - */ -static void vr_autoneg_mii(sc, flag, verbose) - struct vr_softc *sc; - int flag; - int verbose; -{ - u_int16_t phy_sts = 0, media, advert, ability; - struct ifnet *ifp; - struct ifmedia *ifm; - - ifm = &sc->ifmedia; - ifp = &sc->arpcom.ac_if; - - ifm->ifm_media = IFM_ETHER | IFM_AUTO; - - /* - * The 100baseT4 PHY on the 3c905-T4 has the 'autoneg supported' - * bit cleared in the status register, but has the 'autoneg enabled' - * bit set in the control register. This is a contradiction, and - * I'm not sure how to handle it. If you want to force an attempt - * to autoneg for 100baseT4 PHYs, #define FORCE_AUTONEG_TFOUR - * and see what happens. - */ -#ifndef FORCE_AUTONEG_TFOUR - /* - * First, see if autoneg is supported. If not, there's - * no point in continuing. - */ - phy_sts = vr_phy_readreg(sc, PHY_BMSR); - if (!(phy_sts & PHY_BMSR_CANAUTONEG)) { - if (verbose) - printf("vr%d: autonegotiation not supported\n", - sc->vr_unit); - ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX; - return; - } -#endif - - switch (flag) { - case VR_FLAG_FORCEDELAY: - /* - * XXX Never use this option anywhere but in the probe - * routine: making the kernel stop dead in its tracks - * for three whole seconds after we've gone multi-user - * is really bad manners. - */ - vr_autoneg_xmit(sc); - DELAY(5000000); - break; - case VR_FLAG_SCHEDDELAY: - /* - * Wait for the transmitter to go idle before starting - * an autoneg session, otherwise vr_start() may clobber - * our timeout, and we don't want to allow transmission - * during an autoneg session since that can screw it up. - */ - if (sc->vr_cdata.vr_tx_head != NULL) { - sc->vr_want_auto = 1; - return; - } - vr_autoneg_xmit(sc); - ifp->if_timer = 5; - sc->vr_autoneg = 1; - sc->vr_want_auto = 0; - return; - break; - case VR_FLAG_DELAYTIMEO: - ifp->if_timer = 0; - sc->vr_autoneg = 0; - break; - default: - printf("vr%d: invalid autoneg flag: %d\n", sc->vr_unit, flag); - return; - } - - if (vr_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_AUTONEGCOMP) { - if (verbose) - printf("vr%d: autoneg complete, ", sc->vr_unit); - phy_sts = vr_phy_readreg(sc, PHY_BMSR); - } else { - if (verbose) - printf("vr%d: autoneg not complete, ", sc->vr_unit); - } - - media = vr_phy_readreg(sc, PHY_BMCR); - - /* Link is good. Report modes and set duplex mode. */ - if (vr_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT) { - if (verbose) - printf("link status good "); - advert = vr_phy_readreg(sc, PHY_ANAR); - ability = vr_phy_readreg(sc, PHY_LPAR); - - if (advert & PHY_ANAR_100BT4 && ability & PHY_ANAR_100BT4) { - ifm->ifm_media = IFM_ETHER|IFM_100_T4; - media |= PHY_BMCR_SPEEDSEL; - media &= ~PHY_BMCR_DUPLEX; - printf("(100baseT4)\n"); - } else if (advert & PHY_ANAR_100BTXFULL && - ability & PHY_ANAR_100BTXFULL) { - ifm->ifm_media = IFM_ETHER|IFM_100_TX|IFM_FDX; - media |= PHY_BMCR_SPEEDSEL; - media |= PHY_BMCR_DUPLEX; - printf("(full-duplex, 100Mbps)\n"); - } else if (advert & PHY_ANAR_100BTXHALF && - ability & PHY_ANAR_100BTXHALF) { - ifm->ifm_media = IFM_ETHER|IFM_100_TX|IFM_HDX; - media |= PHY_BMCR_SPEEDSEL; - media &= ~PHY_BMCR_DUPLEX; - printf("(half-duplex, 100Mbps)\n"); - } else if (advert & PHY_ANAR_10BTFULL && - ability & PHY_ANAR_10BTFULL) { - ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_FDX; - media &= ~PHY_BMCR_SPEEDSEL; - media |= PHY_BMCR_DUPLEX; - printf("(full-duplex, 10Mbps)\n"); - } else { - ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX; - media &= ~PHY_BMCR_SPEEDSEL; - media &= ~PHY_BMCR_DUPLEX; - printf("(half-duplex, 10Mbps)\n"); - } - - media &= ~PHY_BMCR_AUTONEGENBL; - - /* Set ASIC's duplex mode to match the PHY. */ - vr_setcfg(sc, media); - vr_phy_writereg(sc, PHY_BMCR, media); - } else { - if (verbose) - printf("no carrier\n"); - } - - vr_init(sc); - - if (sc->vr_tx_pend) { - sc->vr_autoneg = 0; - sc->vr_tx_pend = 0; - vr_start(ifp); - } - - return; -} - -static void vr_getmode_mii(sc) - struct vr_softc *sc; -{ - u_int16_t bmsr; - struct ifnet *ifp; - - ifp = &sc->arpcom.ac_if; - - bmsr = vr_phy_readreg(sc, PHY_BMSR); - if (bootverbose) - printf("vr%d: PHY status word: %x\n", sc->vr_unit, bmsr); - - /* fallback */ - sc->ifmedia.ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX; - - if (bmsr & PHY_BMSR_10BTHALF) { - if (bootverbose) - printf("vr%d: 10Mbps half-duplex mode supported\n", - sc->vr_unit); - ifmedia_add(&sc->ifmedia, - IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL); - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL); - } - - if (bmsr & PHY_BMSR_10BTFULL) { - if (bootverbose) - printf("vr%d: 10Mbps full-duplex mode supported\n", - sc->vr_unit); - ifmedia_add(&sc->ifmedia, - IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); - sc->ifmedia.ifm_media = IFM_ETHER|IFM_10_T|IFM_FDX; - } - - if (bmsr & PHY_BMSR_100BTXHALF) { - if (bootverbose) - printf("vr%d: 100Mbps half-duplex mode supported\n", - sc->vr_unit); - ifp->if_baudrate = 100000000; - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL); - ifmedia_add(&sc->ifmedia, - IFM_ETHER|IFM_100_TX|IFM_HDX, 0, NULL); - sc->ifmedia.ifm_media = IFM_ETHER|IFM_100_TX|IFM_HDX; - } - - if (bmsr & PHY_BMSR_100BTXFULL) { - if (bootverbose) - printf("vr%d: 100Mbps full-duplex mode supported\n", - sc->vr_unit); - ifp->if_baudrate = 100000000; - ifmedia_add(&sc->ifmedia, - IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); - sc->ifmedia.ifm_media = IFM_ETHER|IFM_100_TX|IFM_FDX; - } - - /* Some also support 100BaseT4. */ - if (bmsr & PHY_BMSR_100BT4) { - if (bootverbose) - printf("vr%d: 100baseT4 mode supported\n", sc->vr_unit); - ifp->if_baudrate = 100000000; - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_T4, 0, NULL); - sc->ifmedia.ifm_media = IFM_ETHER|IFM_100_T4; -#ifdef FORCE_AUTONEG_TFOUR - if (bootverbose) - printf("vr%d: forcing on autoneg support for BT4\n", - sc->vr_unit); - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0 NULL): - sc->ifmedia.ifm_media = IFM_ETHER|IFM_AUTO; -#endif - } - - if (bmsr & PHY_BMSR_CANAUTONEG) { - if (bootverbose) - printf("vr%d: autoneg supported\n", sc->vr_unit); - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); - sc->ifmedia.ifm_media = IFM_ETHER|IFM_AUTO; - } - - return; -} - -/* - * Set speed and duplex mode. - */ -static void vr_setmode_mii(sc, media) - struct vr_softc *sc; - int media; -{ - u_int16_t bmcr; - struct ifnet *ifp; - - ifp = &sc->arpcom.ac_if; - - /* - * If an autoneg session is in progress, stop it. - */ - if (sc->vr_autoneg) { - printf("vr%d: canceling autoneg session\n", sc->vr_unit); - ifp->if_timer = sc->vr_autoneg = sc->vr_want_auto = 0; - bmcr = vr_phy_readreg(sc, PHY_BMCR); - bmcr &= ~PHY_BMCR_AUTONEGENBL; - vr_phy_writereg(sc, PHY_BMCR, bmcr); - } - - printf("vr%d: selecting MII, ", sc->vr_unit); - - bmcr = vr_phy_readreg(sc, PHY_BMCR); - - bmcr &= ~(PHY_BMCR_AUTONEGENBL|PHY_BMCR_SPEEDSEL| - PHY_BMCR_DUPLEX|PHY_BMCR_LOOPBK); - - if (IFM_SUBTYPE(media) == IFM_100_T4) { - printf("100Mbps/T4, half-duplex\n"); - bmcr |= PHY_BMCR_SPEEDSEL; - bmcr &= ~PHY_BMCR_DUPLEX; - } - - if (IFM_SUBTYPE(media) == IFM_100_TX) { - printf("100Mbps, "); - bmcr |= PHY_BMCR_SPEEDSEL; - } - - if (IFM_SUBTYPE(media) == IFM_10_T) { - printf("10Mbps, "); - bmcr &= ~PHY_BMCR_SPEEDSEL; - } - - if ((media & IFM_GMASK) == IFM_FDX) { - printf("full duplex\n"); - bmcr |= PHY_BMCR_DUPLEX; - } else { - printf("half duplex\n"); - bmcr &= ~PHY_BMCR_DUPLEX; - } - - vr_setcfg(sc, bmcr); - vr_phy_writereg(sc, PHY_BMCR, bmcr); - - return; -} - -/* * In order to fiddle with the * 'full-duplex' and '100Mbps' bits in the netconfig register, we * first have to put the transmit and/or receive logic in the idle state. */ -static void vr_setcfg(sc, bmcr) +static void vr_setcfg(sc, media) struct vr_softc *sc; - u_int16_t bmcr; + int media; { int restart = 0; @@ -869,7 +576,7 @@ static void vr_setcfg(sc, bmcr) VR_CLRBIT16(sc, VR_COMMAND, (VR_CMD_TX_ON|VR_CMD_RX_ON)); } - if (bmcr & PHY_BMCR_DUPLEX) + if ((media & IFM_GMASK) == IFM_FDX) VR_SETBIT16(sc, VR_COMMAND, VR_CMD_FULLDUPLEX); else VR_CLRBIT16(sc, VR_COMMAND, VR_CMD_FULLDUPLEX); @@ -931,16 +638,11 @@ static int vr_probe(dev) static int vr_attach(dev) device_t dev; { - int s, i; + int i, s; u_char eaddr[ETHER_ADDR_LEN]; u_int32_t command; struct vr_softc *sc; struct ifnet *ifp; - int media = IFM_ETHER|IFM_100_TX|IFM_FDX; - unsigned int round; - caddr_t roundptr; - struct vr_type *p; - u_int16_t phy_vid, phy_did, phy_sts; int unit, error = 0, rid; s = splimp(); @@ -1057,9 +759,10 @@ static int vr_attach(dev) sc->vr_unit = unit; bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); - sc->vr_ldata_ptr = malloc(sizeof(struct vr_list_data) + 8, - M_DEVBUF, M_NOWAIT); - if (sc->vr_ldata_ptr == NULL) { + sc->vr_ldata = contigmalloc(sizeof(struct vr_list_data), M_DEVBUF, + M_NOWAIT, 0x100000, 0xffffffff, PAGE_SIZE, 0); + + if (sc->vr_ldata == NULL) { printf("vr%d: no memory for list buffers!\n", unit); bus_teardown_intr(dev, sc->vr_irq, sc->vr_intrhand); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->vr_irq); @@ -1068,17 +771,6 @@ static int vr_attach(dev) goto fail; } - sc->vr_ldata = (struct vr_list_data *)sc->vr_ldata_ptr; - round = (unsigned int)sc->vr_ldata_ptr & 0xF; - roundptr = sc->vr_ldata_ptr; - for (i = 0; i < 8; i++) { - if (round % 8) { - round++; - roundptr++; - } else - break; - } - sc->vr_ldata = (struct vr_list_data *)roundptr; bzero(sc->vr_ldata, sizeof(struct vr_list_data)); ifp = &sc->arpcom.ac_if; @@ -1095,70 +787,22 @@ static int vr_attach(dev) ifp->if_baudrate = 10000000; ifp->if_snd.ifq_maxlen = VR_TX_LIST_CNT - 1; - if (bootverbose) - printf("vr%d: probing for a PHY\n", sc->vr_unit); - for (i = VR_PHYADDR_MIN; i < VR_PHYADDR_MAX + 1; i++) { - if (bootverbose) - printf("vr%d: checking address: %d\n", - sc->vr_unit, i); - sc->vr_phy_addr = i; - vr_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET); - DELAY(500); - while(vr_phy_readreg(sc, PHY_BMCR) - & PHY_BMCR_RESET); - if ((phy_sts = vr_phy_readreg(sc, PHY_BMSR))) - break; - } - if (phy_sts) { - phy_vid = vr_phy_readreg(sc, PHY_VENID); - phy_did = vr_phy_readreg(sc, PHY_DEVID); - if (bootverbose) - printf("vr%d: found PHY at address %d, ", - sc->vr_unit, sc->vr_phy_addr); - if (bootverbose) - printf("vendor id: %x device id: %x\n", - phy_vid, phy_did); - p = vr_phys; - while(p->vr_vid) { - if (phy_vid == p->vr_vid && - (phy_did | 0x000F) == p->vr_did) { - sc->vr_pinfo = p; - break; - } - p++; - } - if (sc->vr_pinfo == NULL) - sc->vr_pinfo = &vr_phys[PHY_UNKNOWN]; - if (bootverbose) - printf("vr%d: PHY type: %s\n", - sc->vr_unit, sc->vr_pinfo->vr_name); - } else { + /* + * Do MII setup. + */ + if (mii_phy_probe(dev, &sc->vr_miibus, + vr_ifmedia_upd, vr_ifmedia_sts)) { printf("vr%d: MII without any phy!\n", sc->vr_unit); bus_teardown_intr(dev, sc->vr_irq, sc->vr_intrhand); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->vr_irq); bus_release_resource(dev, VR_RES, VR_RID, sc->vr_res); - free(sc->vr_ldata_ptr, M_DEVBUF); + contigfree(sc->vr_ldata, + sizeof(struct vr_list_data), M_DEVBUF); error = ENXIO; goto fail; } - /* - * Do ifmedia setup. - */ - ifmedia_init(&sc->ifmedia, 0, vr_ifmedia_upd, vr_ifmedia_sts); - - vr_getmode_mii(sc); - if (cold) { - vr_autoneg_mii(sc, VR_FLAG_FORCEDELAY, 1); - vr_stop(sc); - } else { - vr_init(sc); - vr_autoneg_mii(sc, VR_FLAG_SCHEDDELAY, 1); - } - - media = sc->ifmedia.ifm_media; - - ifmedia_set(&sc->ifmedia, media); + callout_handle_init(&sc->vr_stat_ch); /* * Call MI attach routines. @@ -1190,12 +834,14 @@ static int vr_detach(dev) vr_stop(sc); if_detach(ifp); + bus_generic_detach(dev); + device_delete_child(dev, sc->vr_miibus); + bus_teardown_intr(dev, sc->vr_irq, sc->vr_intrhand); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->vr_irq); bus_release_resource(dev, VR_RES, VR_RID, sc->vr_res); - free(sc->vr_ldata_ptr, M_DEVBUF); - ifmedia_removeall(&sc->ifmedia); + contigfree(sc->vr_ldata, sizeof(struct vr_list_data), M_DEVBUF); splx(s); @@ -1466,7 +1112,6 @@ static void vr_txeof(sc) { struct vr_chain *cur_tx; struct ifnet *ifp; - register struct mbuf *n; ifp = &sc->arpcom.ac_if; @@ -1501,8 +1146,10 @@ static void vr_txeof(sc) ifp->if_collisions +=(txstat & VR_TXSTAT_COLLCNT) >> 3; ifp->if_opackets++; - MFREE(cur_tx->vr_mbuf, n); - cur_tx->vr_mbuf = NULL; + if (cur_tx->vr_mbuf != NULL) { + m_freem(cur_tx->vr_mbuf); + cur_tx->vr_mbuf = NULL; + } if (sc->vr_cdata.vr_tx_head == sc->vr_cdata.vr_tx_tail) { sc->vr_cdata.vr_tx_head = NULL; @@ -1531,13 +1178,31 @@ static void vr_txeoc(sc) if (sc->vr_cdata.vr_tx_head == NULL) { ifp->if_flags &= ~IFF_OACTIVE; sc->vr_cdata.vr_tx_tail = NULL; - if (sc->vr_want_auto) - vr_autoneg_mii(sc, VR_FLAG_SCHEDDELAY, 1); } return; } +static void vr_tick(xsc) + void *xsc; +{ + struct vr_softc *sc; + struct mii_data *mii; + int s; + + s = splimp(); + + sc = xsc; + mii = device_get_softc(sc->vr_miibus); + mii_tick(mii); + + sc->vr_stat_ch = timeout(vr_tick, sc, hz); + + splx(s); + + return; +} + static void vr_intr(arg) void *arg; { @@ -1691,10 +1356,8 @@ static void vr_start(ifp) sc = ifp->if_softc; - if (sc->vr_autoneg) { - sc->vr_tx_pend = 1; + if (ifp->if_flags & IFF_OACTIVE) return; - } /* * Check for an available queue slot. If there are none, @@ -1731,7 +1394,7 @@ static void vr_start(ifp) bpf_mtap(ifp, cur_tx->vr_mbuf); #endif VR_TXOWN(cur_tx) = VR_TXSTAT_OWN; - VR_SETBIT16(sc, VR_COMMAND, VR_CMD_TX_ON|VR_CMD_TX_GO); + VR_SETBIT16(sc, VR_COMMAND, /*VR_CMD_TX_ON|*/VR_CMD_TX_GO); } /* @@ -1758,16 +1421,12 @@ static void vr_init(xsc) { struct vr_softc *sc = xsc; struct ifnet *ifp = &sc->arpcom.ac_if; - u_int16_t phy_bmcr = 0; + struct mii_data *mii; int s; - if (sc->vr_autoneg) - return; - s = splimp(); - if (sc->vr_pinfo != NULL) - phy_bmcr = vr_phy_readreg(sc, PHY_BMCR); + mii = device_get_softc(sc->vr_miibus); /* * Cancel pending I/O and free all RX/TX buffers. @@ -1822,8 +1481,6 @@ static void vr_init(xsc) VR_CMD_TX_ON|VR_CMD_RX_ON| VR_CMD_RX_GO); - vr_setcfg(sc, vr_phy_readreg(sc, PHY_BMCR)); - CSR_WRITE_4(sc, VR_TXADDR, vtophys(&sc->vr_ldata->vr_tx_list[0])); /* @@ -1832,15 +1489,15 @@ static void vr_init(xsc) CSR_WRITE_2(sc, VR_ISR, 0xFFFF); CSR_WRITE_2(sc, VR_IMR, VR_INTRS); - /* Restore state of BMCR */ - if (sc->vr_pinfo != NULL) - vr_phy_writereg(sc, PHY_BMCR, phy_bmcr); + mii_mediachg(mii); ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; (void)splx(s); + sc->vr_stat_ch = timeout(vr_tick, sc, hz); + return; } @@ -1851,18 +1508,11 @@ static int vr_ifmedia_upd(ifp) struct ifnet *ifp; { struct vr_softc *sc; - struct ifmedia *ifm; sc = ifp->if_softc; - ifm = &sc->ifmedia; - - if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) - return(EINVAL); - if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) - vr_autoneg_mii(sc, VR_FLAG_SCHEDDELAY, 1); - else - vr_setmode_mii(sc, ifm->ifm_media); + if (ifp->if_flags & IFF_UP) + vr_init(sc); return(0); } @@ -1875,42 +1525,13 @@ static void vr_ifmedia_sts(ifp, ifmr) struct ifmediareq *ifmr; { struct vr_softc *sc; - u_int16_t advert = 0, ability = 0; + struct mii_data *mii; sc = ifp->if_softc; - - ifmr->ifm_active = IFM_ETHER; - - if (!(vr_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_AUTONEGENBL)) { - if (vr_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_SPEEDSEL) - ifmr->ifm_active = IFM_ETHER|IFM_100_TX; - else - ifmr->ifm_active = IFM_ETHER|IFM_10_T; - if (vr_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_DUPLEX) - ifmr->ifm_active |= IFM_FDX; - else - ifmr->ifm_active |= IFM_HDX; - return; - } - - ability = vr_phy_readreg(sc, PHY_LPAR); - advert = vr_phy_readreg(sc, PHY_ANAR); - if (advert & PHY_ANAR_100BT4 && - ability & PHY_ANAR_100BT4) { - ifmr->ifm_active = IFM_ETHER|IFM_100_T4; - } else if (advert & PHY_ANAR_100BTXFULL && - ability & PHY_ANAR_100BTXFULL) { - ifmr->ifm_active = IFM_ETHER|IFM_100_TX|IFM_FDX; - } else if (advert & PHY_ANAR_100BTXHALF && - ability & PHY_ANAR_100BTXHALF) { - ifmr->ifm_active = IFM_ETHER|IFM_100_TX|IFM_HDX; - } else if (advert & PHY_ANAR_10BTFULL && - ability & PHY_ANAR_10BTFULL) { - ifmr->ifm_active = IFM_ETHER|IFM_10_T|IFM_FDX; - } else if (advert & PHY_ANAR_10BTHALF && - ability & PHY_ANAR_10BTHALF) { - ifmr->ifm_active = IFM_ETHER|IFM_10_T|IFM_HDX; - } + mii = device_get_softc(sc->vr_miibus); + mii_pollstat(mii); + ifmr->ifm_active = mii->mii_media_active; + ifmr->ifm_status = mii->mii_media_status; return; } @@ -1922,6 +1543,7 @@ static int vr_ioctl(ifp, command, data) { struct vr_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *) data; + struct mii_data *mii; int s, error = 0; s = splimp(); @@ -1948,7 +1570,8 @@ static int vr_ioctl(ifp, command, data) break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); + mii = device_get_softc(sc->vr_miibus); + error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; default: error = EINVAL; @@ -1967,20 +1590,9 @@ static void vr_watchdog(ifp) sc = ifp->if_softc; - if (sc->vr_autoneg) { - vr_autoneg_mii(sc, VR_FLAG_DELAYTIMEO, 1); - if (!(ifp->if_flags & IFF_UP)) - vr_stop(sc); - return; - } - ifp->if_oerrors++; printf("vr%d: watchdog timeout\n", sc->vr_unit); - if (!(vr_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT)) - printf("vr%d: no carrier - transceiver cable problem?\n", - sc->vr_unit); - vr_stop(sc); vr_reset(sc); vr_init(sc); @@ -2004,6 +1616,8 @@ static void vr_stop(sc) ifp = &sc->arpcom.ac_if; ifp->if_timer = 0; + untimeout(vr_tick, sc, sc->vr_stat_ch); + VR_SETBIT16(sc, VR_COMMAND, VR_CMD_STOP); VR_CLRBIT16(sc, VR_COMMAND, (VR_CMD_RX_ON|VR_CMD_TX_ON)); CSR_WRITE_2(sc, VR_IMR, 0x0000); -- cgit v1.1