diff options
Diffstat (limited to 'sys/pci/if_sf.c')
-rw-r--r-- | sys/pci/if_sf.c | 528 |
1 files changed, 79 insertions, 449 deletions
diff --git a/sys/pci/if_sf.c b/sys/pci/if_sf.c index a07b04f..7225d8e 100644 --- a/sys/pci/if_sf.c +++ b/sys/pci/if_sf.c @@ -108,13 +108,16 @@ #include <sys/bus.h> #include <sys/rman.h> +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> + +#include "miibus_if.h" + #include <pci/pcireg.h> #include <pci/pcivar.h> #define SF_USEIOSPACE -/* #define SF_BACKGROUND_AUTONEG */ - #include <pci/if_sfreg.h> #ifndef lint @@ -128,10 +131,6 @@ static struct sf_type sf_devs[] = { { 0, 0, NULL } }; -static struct sf_type sf_phys[] = { - { 0, 0, "<MII-compliant physical interface>" } -}; - static int sf_probe __P((device_t)); static int sf_attach __P((device_t)); static int sf_detach __P((device_t)); @@ -166,12 +165,9 @@ static int sf_setvlan __P((struct sf_softc *, int, u_int32_t)); static u_int8_t sf_read_eeprom __P((struct sf_softc *, int)); static u_int32_t sf_calchash __P((caddr_t)); -static int sf_phy_readreg __P((struct sf_softc *, int)); -static void sf_phy_writereg __P((struct sf_softc *, int, int)); -static void sf_autoneg_xmit __P((struct sf_softc *)); -static void sf_autoneg_mii __P((struct sf_softc *, int, int)); -static void sf_getmode_mii __P((struct sf_softc *)); -static void sf_setmode_mii __P((struct sf_softc *, int)); +static int sf_miibus_readreg __P((device_t, int, int)); +static int sf_miibus_writereg __P((device_t, int, int, int)); +static void sf_miibus_statchg __P((device_t)); static u_int32_t csr_read_4 __P((struct sf_softc *, int)); static void csr_write_4 __P((struct sf_softc *, int, u_int32_t)); @@ -190,6 +186,16 @@ static device_method_t sf_methods[] = { DEVMETHOD(device_attach, sf_attach), DEVMETHOD(device_detach, sf_detach), DEVMETHOD(device_shutdown, sf_shutdown), + + /* bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + + /* MII interface */ + DEVMETHOD(miibus_readreg, sf_miibus_readreg), + DEVMETHOD(miibus_writereg, sf_miibus_writereg), + DEVMETHOD(miibus_statchg, sf_miibus_statchg), + { 0, 0 } }; @@ -202,6 +208,7 @@ static driver_t sf_driver = { static devclass_t sf_devclass; DRIVER_MODULE(sf, pci, sf_driver, sf_devclass, 0, 0); +DRIVER_MODULE(miibus, sf, miibus_driver, miibus_devclass, 0, 0); #define SF_SETBIT(sc, reg, x) \ csr_write_4(sc, reg, csr_read_4(sc, reg) | x) @@ -353,15 +360,18 @@ static int sf_setvlan(sc, idx, vlan) } #endif -static int sf_phy_readreg(sc, reg) - struct sf_softc *sc; - int reg; +static int sf_miibus_readreg(dev, phy, reg) + device_t dev; + int phy, reg; { + struct sf_softc *sc; int i; u_int32_t val = 0; + sc = device_get_softc(dev); + for (i = 0; i < SF_TIMEOUT; i++) { - val = csr_read_4(sc, SF_PHY_REG(sc->sf_phy_addr, reg)); + val = csr_read_4(sc, SF_PHY_REG(phy, reg)); if (val & SF_MII_DATAVALID) break; } @@ -375,21 +385,42 @@ static int sf_phy_readreg(sc, reg) return(val & 0x0000FFFF); } -static void sf_phy_writereg(sc, reg, val) - struct sf_softc *sc; - int reg, val; +static int sf_miibus_writereg(dev, phy, reg, val) + device_t dev; + int phy, reg, val; { + struct sf_softc *sc; int i; int busy; - csr_write_4(sc, SF_PHY_REG(sc->sf_phy_addr, reg), val); + sc = device_get_softc(dev); + + csr_write_4(sc, SF_PHY_REG(phy, reg), val); for (i = 0; i < SF_TIMEOUT; i++) { - busy = csr_read_4(sc, SF_PHY_REG(sc->sf_phy_addr, reg)); + busy = csr_read_4(sc, SF_PHY_REG(phy, reg)); if (!(busy & SF_MII_BUSY)) break; } + return(0); +} + +static void sf_miibus_statchg(dev) + device_t dev; +{ + struct sf_softc *sc; + struct mii_data *mii; + + sc = device_get_softc(dev); + mii = device_get_softc(sc->sf_miibus); + + if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) { + SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX); + } else { + SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX); + } + return; } @@ -448,329 +479,17 @@ static void sf_setmulti(sc) } /* - * Initiate an autonegotiation session. - */ -static void sf_autoneg_xmit(sc) - struct sf_softc *sc; -{ - u_int16_t phy_sts; - - sf_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET); - DELAY(500); - while(sf_phy_readreg(sc, PHY_BMCR) - & PHY_BMCR_RESET); - - phy_sts = sf_phy_readreg(sc, PHY_BMCR); - phy_sts |= PHY_BMCR_AUTONEGENBL|PHY_BMCR_AUTONEGRSTR; - sf_phy_writereg(sc, PHY_BMCR, phy_sts); - - return; -} - -/* - * Invoke autonegotiation on a PHY. - */ -static void sf_autoneg_mii(sc, flag, verbose) - struct sf_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; - -#ifndef FORCE_AUTONEG_TFOUR - /* - * First, see if autoneg is supported. If not, there's - * no point in continuing. - */ - phy_sts = sf_phy_readreg(sc, PHY_BMSR); - if (!(phy_sts & PHY_BMSR_CANAUTONEG)) { - if (verbose) - printf("sf%d: autonegotiation not supported\n", - sc->sf_unit); - ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX; - return; - } -#endif - - switch (flag) { - case SF_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. - */ - sf_autoneg_xmit(sc); - DELAY(5000000); - break; - case SF_FLAG_SCHEDDELAY: - /* - * Wait for the transmitter to go idle before starting - * an autoneg session, otherwise sf_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->sf_tx_cnt) { - sc->sf_want_auto = 1; - return; - } - sf_autoneg_xmit(sc); - ifp->if_timer = 5; - sc->sf_autoneg = 1; - sc->sf_want_auto = 0; - return; - break; - case SF_FLAG_DELAYTIMEO: - ifp->if_timer = 0; - sc->sf_autoneg = 0; - break; - default: - printf("sf%d: invalid autoneg flag: %d\n", sc->sf_unit, flag); - return; - } - - if (sf_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_AUTONEGCOMP) { - if (verbose) - printf("sf%d: autoneg complete, ", sc->sf_unit); - phy_sts = sf_phy_readreg(sc, PHY_BMSR); - } else { - if (verbose) - printf("sf%d: autoneg not complete, ", sc->sf_unit); - } - - media = sf_phy_readreg(sc, PHY_BMCR); - - /* Link is good. Report modes and set duplex mode. */ - if (sf_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT) { - if (verbose) - printf("link status good "); - advert = sf_phy_readreg(sc, PHY_ANAR); - ability = sf_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 if (advert & PHY_ANAR_10BTHALF && - ability & PHY_ANAR_10BTHALF) { - 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. */ - sf_phy_writereg(sc, PHY_BMCR, media); - if ((media & IFM_GMASK) == IFM_FDX) { - SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX); - } else { - SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX); - } - } else { - if (verbose) - printf("no carrier\n"); - } - - sf_init(sc); - - if (sc->sf_tx_pend) { - sc->sf_autoneg = 0; - sc->sf_tx_pend = 0; - sf_start(ifp); - } - - return; -} - -static void sf_getmode_mii(sc) - struct sf_softc *sc; -{ - u_int16_t bmsr; - struct ifnet *ifp; - - ifp = &sc->arpcom.ac_if; - - bmsr = sf_phy_readreg(sc, PHY_BMSR); - if (bootverbose) - printf("sf%d: PHY status word: %x\n", sc->sf_unit, bmsr); - - /* fallback */ - sc->ifmedia.ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX; - - if (bmsr & PHY_BMSR_10BTHALF) { - if (bootverbose) - printf("sf%d: 10Mbps half-duplex mode supported\n", - sc->sf_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("sf%d: 10Mbps full-duplex mode supported\n", - sc->sf_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("sf%d: 100Mbps half-duplex mode supported\n", - sc->sf_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("sf%d: 100Mbps full-duplex mode supported\n", - sc->sf_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("sf%d: 100baseT4 mode supported\n", sc->sf_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("sf%d: forcing on autoneg support for BT4\n", - sc->sf_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("sf%d: autoneg supported\n", sc->sf_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 sf_setmode_mii(sc, media) - struct sf_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->sf_autoneg) { - printf("sf%d: canceling autoneg session\n", sc->sf_unit); - ifp->if_timer = sc->sf_autoneg = sc->sf_want_auto = 0; - bmcr = sf_phy_readreg(sc, PHY_BMCR); - bmcr &= ~PHY_BMCR_AUTONEGENBL; - sf_phy_writereg(sc, PHY_BMCR, bmcr); - } - - printf("sf%d: selecting MII, ", sc->sf_unit); - - bmcr = sf_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; - SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX); - } else { - printf("half duplex\n"); - bmcr &= ~PHY_BMCR_DUPLEX; - SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX); - } - - sf_phy_writereg(sc, PHY_BMCR, bmcr); - - return; -} - -/* * Set media options. */ static int sf_ifmedia_upd(ifp) struct ifnet *ifp; { struct sf_softc *sc; - struct ifmedia *ifm; + struct mii_data *mii; 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) - sf_autoneg_mii(sc, SF_FLAG_SCHEDDELAY, 1); - else { - sf_setmode_mii(sc, ifm->ifm_media); - } + mii = device_get_softc(sc->sf_miibus); + mii_mediachg(mii); return(0); } @@ -783,42 +502,14 @@ static void sf_ifmedia_sts(ifp, ifmr) struct ifmediareq *ifmr; { struct sf_softc *sc; - u_int16_t advert = 0, ability = 0; + struct mii_data *mii; sc = ifp->if_softc; + mii = device_get_softc(sc->sf_miibus); - ifmr->ifm_active = IFM_ETHER; - - if (!(sf_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_AUTONEGENBL)) { - if (sf_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 (sf_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_DUPLEX) - ifmr->ifm_active |= IFM_FDX; - else - ifmr->ifm_active |= IFM_HDX; - return; - } - - ability = sf_phy_readreg(sc, PHY_LPAR); - advert = sf_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_pollstat(mii); + ifmr->ifm_active = mii->mii_media_active; + ifmr->ifm_status = mii->mii_media_status; return; } @@ -830,6 +521,7 @@ static int sf_ioctl(ifp, command, data) { struct sf_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *) data; + struct mii_data *mii; int s, error = 0; s = splimp(); @@ -856,7 +548,8 @@ static int sf_ioctl(ifp, command, data) break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); + mii = device_get_softc(sc->sf_miibus); + error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; default: error = EINVAL; @@ -961,9 +654,6 @@ static int sf_attach(dev) u_int32_t command; struct sf_softc *sc; struct ifnet *ifp; - int media = IFM_ETHER|IFM_100_TX|IFM_FDX; - struct sf_type *p; - u_int16_t phy_vid, phy_did, phy_sts; int unit, rid, error = 0; s = splimp(); @@ -1079,7 +769,7 @@ static int sf_attach(dev) /* Allocate the descriptor queues. */ sc->sf_ldata = contigmalloc(sizeof(struct sf_list_data), M_DEVBUF, - M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0); + M_NOWAIT, 0x100000, 0xffffffff, PAGE_SIZE, 0); if (sc->sf_ldata == NULL) { printf("sf%d: no memory for list buffers!\n", unit); @@ -1092,44 +782,9 @@ static int sf_attach(dev) bzero(sc->sf_ldata, sizeof(struct sf_list_data)); - if (bootverbose) - printf("sf%d: probing for a PHY\n", sc->sf_unit); - for (i = SF_PHYADDR_MIN; i < SF_PHYADDR_MAX + 1; i++) { - if (bootverbose) - printf("sf%d: checking address: %d\n", - sc->sf_unit, i); - sc->sf_phy_addr = i; - sf_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET); - DELAY(500); - while(sf_phy_readreg(sc, PHY_BMCR) - & PHY_BMCR_RESET); - if ((phy_sts = sf_phy_readreg(sc, PHY_BMSR))) - break; - } - if (phy_sts) { - phy_vid = sf_phy_readreg(sc, PHY_VENID); - phy_did = sf_phy_readreg(sc, PHY_DEVID); - if (bootverbose) - printf("sf%d: found PHY at address %d, ", - sc->sf_unit, sc->sf_phy_addr); - if (bootverbose) - printf("vendor id: %x device id: %x\n", - phy_vid, phy_did); - p = sf_phys; - while(p->sf_vid) { - if (phy_vid == p->sf_vid && - (phy_did | 0x000F) == p->sf_did) { - sc->sf_pinfo = p; - break; - } - p++; - } - if (sc->sf_pinfo == NULL) - sc->sf_pinfo = &sf_phys[PHY_UNKNOWN]; - if (bootverbose) - printf("sf%d: PHY type: %s\n", - sc->sf_unit, sc->sf_pinfo->sf_name); - } else { + /* Do MII setup. */ + if (mii_phy_probe(dev, &sc->sf_miibus, + sf_ifmedia_upd, sf_ifmedia_sts)) { printf("sf%d: MII without any phy!\n", sc->sf_unit); free(sc->sf_ldata, M_DEVBUF); bus_teardown_intr(dev, sc->sf_irq, sc->sf_intrhand); @@ -1154,23 +809,6 @@ static int sf_attach(dev) ifp->if_snd.ifq_maxlen = SF_TX_DLIST_CNT - 1; /* - * Do ifmedia setup. - */ - ifmedia_init(&sc->ifmedia, 0, sf_ifmedia_upd, sf_ifmedia_sts); - - sf_getmode_mii(sc); - if (cold) { - sf_autoneg_mii(sc, SF_FLAG_FORCEDELAY, 1); - sf_stop(sc); - } else { - sf_init(sc); - sf_autoneg_mii(sc, SF_FLAG_SCHEDDELAY, 1); - } - - media = sc->ifmedia.ifm_media; - ifmedia_set(&sc->ifmedia, media); - - /* * Call MI attach routines. */ if_attach(ifp); @@ -1200,12 +838,14 @@ static int sf_detach(dev) if_detach(ifp); sf_stop(sc); + bus_generic_detach(dev); + device_delete_child(dev, sc->sf_miibus); + bus_teardown_intr(dev, sc->sf_irq, sc->sf_intrhand); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sf_irq); bus_release_resource(dev, SF_RES, SF_RID, sc->sf_res); free(sc->sf_ldata, M_DEVBUF); - ifmedia_removeall(&sc->ifmedia); splx(s); @@ -1490,12 +1130,14 @@ static void sf_init(xsc) { struct sf_softc *sc; struct ifnet *ifp; + struct mii_data *mii; int i, s; s = splimp(); sc = xsc; ifp = &sc->arpcom.ac_if; + mii = device_get_softc(sc->sf_miibus); sf_stop(sc); sf_reset(sc); @@ -1573,7 +1215,7 @@ static void sf_init(xsc) SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_AUTOPAD); /* Make sure the duplex mode is set correctly. */ - if ((sc->ifmedia.ifm_media & IFM_GMASK) == IFM_FDX) { + if ((mii->mii_media.ifm_media & IFM_GMASK) == IFM_FDX) { SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX); } else { SF_CLRBIT(sc, SF_MACCFG_1, SF_MACCFG1_FULLDUPLEX); @@ -1587,6 +1229,8 @@ static void sf_init(xsc) SF_SETBIT(sc, SF_GEN_ETH_CTL, SF_ETHCTL_RX_ENB|SF_ETHCTL_RXDMA_ENB); SF_SETBIT(sc, SF_GEN_ETH_CTL, SF_ETHCTL_TX_ENB|SF_ETHCTL_TXDMA_ENB); + mii_mediachg(mii); + ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; @@ -1673,11 +1317,6 @@ static void sf_start(ifp) if (ifp->if_flags & IFF_OACTIVE) return; - if (sc->sf_autoneg) { - sc->sf_tx_pend = 1; - return; - } - txprod = csr_read_4(sc, SF_TXDQ_PRODIDX); i = SF_IDX_HI(txprod) >> 4; @@ -1768,6 +1407,7 @@ static void sf_stats_update(xsc) { struct sf_softc *sc; struct ifnet *ifp; + struct mii_data *mii; struct sf_stats stats; u_int32_t *ptr; int i, s; @@ -1776,6 +1416,7 @@ static void sf_stats_update(xsc) sc = xsc; ifp = &sc->arpcom.ac_if; + mii = device_get_softc(sc->sf_miibus); ptr = (u_int32_t *)&stats; for (i = 0; i < sizeof(stats)/sizeof(u_int32_t); i++) @@ -1789,6 +1430,8 @@ static void sf_stats_update(xsc) ifp->if_collisions += stats.sf_tx_single_colls + stats.sf_tx_multi_colls + stats.sf_tx_excess_colls; + mii_tick(mii); + sc->sf_stat_ch = timeout(sf_stats_update, sc, hz); splx(s); @@ -1803,22 +1446,9 @@ static void sf_watchdog(ifp) sc = ifp->if_softc; - if (sc->sf_autoneg) { - sf_autoneg_mii(sc, SF_FLAG_DELAYTIMEO, 1); - if (!(ifp->if_flags & IFF_UP)) - sf_stop(sc); - return; - } - ifp->if_oerrors++; printf("sf%d: watchdog timeout\n", sc->sf_unit); - if (sc->sf_pinfo != NULL) { - if (!(sf_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT)) - printf("sf%d: no carrier - transceiver " - "cable problem?\n", sc->sf_unit); - } - sf_stop(sc); sf_reset(sc); sf_init(sc); |