diff options
author | wpaul <wpaul@FreeBSD.org> | 1999-08-30 23:08:32 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 1999-08-30 23:08:32 +0000 |
commit | 67e37159de11fce7443692e5c1fe7f16b01ec091 (patch) | |
tree | ec7143d79d90671e26c26b6ba9731b99593460f5 /sys | |
parent | 56842578ac635aaac2ea2af6459b06fba2c3a3f1 (diff) | |
download | FreeBSD-src-67e37159de11fce7443692e5c1fe7f16b01ec091.zip FreeBSD-src-67e37159de11fce7443692e5c1fe7f16b01ec091.tar.gz |
Convert the Adaptec and Winbond drivers to miibus.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/sf/if_sf.c | 528 | ||||
-rw-r--r-- | sys/dev/sf/if_sfreg.h | 142 | ||||
-rw-r--r-- | sys/modules/sf/Makefile | 6 | ||||
-rw-r--r-- | sys/modules/wb/Makefile | 9 | ||||
-rw-r--r-- | sys/pci/if_sf.c | 528 | ||||
-rw-r--r-- | sys/pci/if_sfreg.h | 142 | ||||
-rw-r--r-- | sys/pci/if_wb.c | 752 | ||||
-rw-r--r-- | sys/pci/if_wbreg.h | 158 |
8 files changed, 411 insertions, 1854 deletions
diff --git a/sys/dev/sf/if_sf.c b/sys/dev/sf/if_sf.c index a07b04f..7225d8e 100644 --- a/sys/dev/sf/if_sf.c +++ b/sys/dev/sf/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); diff --git a/sys/dev/sf/if_sfreg.h b/sys/dev/sf/if_sfreg.h index e5149ae..b9a8b9d 100644 --- a/sys/dev/sf/if_sfreg.h +++ b/sys/dev/sf/if_sfreg.h @@ -1010,20 +1010,14 @@ struct sf_list_data { struct sf_softc { struct arpcom arpcom; /* interface info */ - struct ifmedia ifmedia; /* media info */ bus_space_handle_t sf_bhandle; /* bus space handle */ bus_space_tag_t sf_btag; /* bus space tag */ void *sf_intrhand; /* interrupt handler cookie */ struct resource *sf_irq; /* irq resource descriptor */ struct resource *sf_res; /* mem/ioport resource */ struct sf_type *sf_info; /* Starfire adapter info */ - struct sf_type *sf_pinfo; /* phy info */ + device_t sf_miibus; u_int8_t sf_unit; /* interface number */ - u_int8_t sf_type; - u_int8_t sf_phy_addr; /* PHY address */ - u_int8_t sf_tx_pend; /* TX pending */ - u_int8_t sf_want_auto; - u_int8_t sf_autoneg; struct sf_list_data *sf_ldata; int sf_tx_cnt; struct callout_handle sf_stat_ch; @@ -1031,140 +1025,6 @@ struct sf_softc { #define SF_TIMEOUT 1000 -#define SF_FLAG_FORCEDELAY 1 -#define SF_FLAG_SCHEDDELAY 2 -#define SF_FLAG_DELAYTIMEO 3 - -/* - * Texas Instruments PHY identifiers - */ -#define TI_PHY_VENDORID 0x4000 -#define TI_PHY_10BT 0x501F -#define TI_PHY_100VGPMI 0x502F - -/* - * These ID values are for the NS DP83840A 10/100 PHY - */ -#define NS_PHY_VENDORID 0x2000 -#define NS_PHY_83840A 0x5C0F - -/* - * Level 1 10/100 PHY - */ -#define LEVEL1_PHY_VENDORID 0x7810 -#define LEVEL1_PHY_LXT970 0x000F - -/* - * Intel 82555 10/100 PHY - */ -#define INTEL_PHY_VENDORID 0x0A28 -#define INTEL_PHY_82555 0x015F - -/* - * SEEQ 80220 10/100 PHY - */ -#define SEEQ_PHY_VENDORID 0x0016 -#define SEEQ_PHY_80220 0xF83F - -#define PHY_UNKNOWN 6 - -#define SF_PHYADDR_MIN 0x00 -#define SF_PHYADDR_MAX 0x1F - -#define PHY_BMCR 0x00 -#define PHY_BMSR 0x01 -#define PHY_VENID 0x02 -#define PHY_DEVID 0x03 -#define PHY_ANAR 0x04 -#define PHY_LPAR 0x05 -#define PHY_ANEXP 0x06 - -#define PHY_ANAR_NEXTPAGE 0x8000 -#define PHY_ANAR_RSVD0 0x4000 -#define PHY_ANAR_TLRFLT 0x2000 -#define PHY_ANAR_RSVD1 0x1000 -#define PHY_ANAR_RSVD2 0x0800 -#define PHY_ANAR_RSVD3 0x0400 -#define PHY_ANAR_100BT4 0x0200 -#define PHY_ANAR_100BTXFULL 0x0100 -#define PHY_ANAR_100BTXHALF 0x0080 -#define PHY_ANAR_10BTFULL 0x0040 -#define PHY_ANAR_10BTHALF 0x0020 -#define PHY_ANAR_PROTO4 0x0010 -#define PHY_ANAR_PROTO3 0x0008 -#define PHY_ANAR_PROTO2 0x0004 -#define PHY_ANAR_PROTO1 0x0002 -#define PHY_ANAR_PROTO0 0x0001 - -/* - * These are the register definitions for the PHY (physical layer - * interface chip). - */ -/* - * PHY BMCR Basic Mode Control Register - */ -#define PHY_BMCR_RESET 0x8000 -#define PHY_BMCR_LOOPBK 0x4000 -#define PHY_BMCR_SPEEDSEL 0x2000 -#define PHY_BMCR_AUTONEGENBL 0x1000 -#define PHY_BMCR_RSVD0 0x0800 /* write as zero */ -#define PHY_BMCR_ISOLATE 0x0400 -#define PHY_BMCR_AUTONEGRSTR 0x0200 -#define PHY_BMCR_DUPLEX 0x0100 -#define PHY_BMCR_COLLTEST 0x0080 -#define PHY_BMCR_RSVD1 0x0040 /* write as zero, don't care */ -#define PHY_BMCR_RSVD2 0x0020 /* write as zero, don't care */ -#define PHY_BMCR_RSVD3 0x0010 /* write as zero, don't care */ -#define PHY_BMCR_RSVD4 0x0008 /* write as zero, don't care */ -#define PHY_BMCR_RSVD5 0x0004 /* write as zero, don't care */ -#define PHY_BMCR_RSVD6 0x0002 /* write as zero, don't care */ -#define PHY_BMCR_RSVD7 0x0001 /* write as zero, don't care */ -/* - * RESET: 1 == software reset, 0 == normal operation - * Resets status and control registers to default values. - * Relatches all hardware config values. - * - * LOOPBK: 1 == loopback operation enabled, 0 == normal operation - * - * SPEEDSEL: 1 == 100Mb/s, 0 == 10Mb/s - * Link speed is selected byt his bit or if auto-negotiation if bit - * 12 (AUTONEGENBL) is set (in which case the value of this register - * is ignored). - * - * AUTONEGENBL: 1 == Autonegotiation enabled, 0 == Autonegotiation disabled - * Bits 8 and 13 are ignored when autoneg is set, otherwise bits 8 and 13 - * determine speed and mode. Should be cleared and then set if PHY configured - * for no autoneg on startup. - * - * ISOLATE: 1 == isolate PHY from MII, 0 == normal operation - * - * AUTONEGRSTR: 1 == restart autonegotiation, 0 = normal operation - * - * DUPLEX: 1 == full duplex mode, 0 == half duplex mode - * - * COLLTEST: 1 == collision test enabled, 0 == normal operation - */ - -/* - * PHY, BMSR Basic Mode Status Register - */ -#define PHY_BMSR_100BT4 0x8000 -#define PHY_BMSR_100BTXFULL 0x4000 -#define PHY_BMSR_100BTXHALF 0x2000 -#define PHY_BMSR_10BTFULL 0x1000 -#define PHY_BMSR_10BTHALF 0x0800 -#define PHY_BMSR_RSVD1 0x0400 /* write as zero, don't care */ -#define PHY_BMSR_RSVD2 0x0200 /* write as zero, don't care */ -#define PHY_BMSR_RSVD3 0x0100 /* write as zero, don't care */ -#define PHY_BMSR_RSVD4 0x0080 /* write as zero, don't care */ -#define PHY_BMSR_MFPRESUP 0x0040 -#define PHY_BMSR_AUTONEGCOMP 0x0020 -#define PHY_BMSR_REMFAULT 0x0010 -#define PHY_BMSR_CANAUTONEG 0x0008 -#define PHY_BMSR_LINKSTAT 0x0004 -#define PHY_BMSR_JABBER 0x0002 -#define PHY_BMSR_EXTENDED 0x0001 - #ifdef __alpha__ #undef vtophys #define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va) diff --git a/sys/modules/sf/Makefile b/sys/modules/sf/Makefile index 0e75096..a58a2c8 100644 --- a/sys/modules/sf/Makefile +++ b/sys/modules/sf/Makefile @@ -4,7 +4,10 @@ S = ${.CURDIR}/../.. .PATH: $S/pci KMOD = sf SRCS = if_sf.c sf.h bpf.h opt_bdg.h device_if.h bus_if.h pci_if.h +SRCS += miibus_if.h CLEANFILES += sf.h bpf.h opt_bdg.h device_if.h bus_if.h pci_if.h +CLEANFILES += miibus_if.h + CFLAGS += ${DEBUG_FLAGS} sf.h: @@ -25,4 +28,7 @@ bus_if.h: $S/kern/makedevops.pl $S/kern/bus_if.m pci_if.h: $S/kern/makedevops.pl $S/pci/pci_if.m perl $S/kern/makedevops.pl -h $S/pci/pci_if.m +miibus_if.h: $S/kern/makedevops.pl $S/dev/mii/miibus_if.m + perl $S/kern/makedevops.pl -h $S/dev/mii/miibus_if.m + .include <bsd.kmod.mk> diff --git a/sys/modules/wb/Makefile b/sys/modules/wb/Makefile index 0b8f4de..b81758e 100644 --- a/sys/modules/wb/Makefile +++ b/sys/modules/wb/Makefile @@ -3,8 +3,10 @@ S = ${.CURDIR}/../.. .PATH: $S/pci KMOD = wb -SRCS = if_wb.c wb.h bpf.h opt_bdg.h device_if.h bus_if.h pci_if.h -CLEANFILES += wb.h bpf.h opt_bdg.h device_if.h bus_if.h pci_if.h +SRCS = if_wb.c wb.h bpf.h opt_bdg.h device_if.h +SRCS += bus_if.h miibus_if.h pci_if.h +CLEANFILES += wb.h bpf.h opt_bdg.h device_if.h +CLEANFILES += bus_if.h miibus_if.h pci_if.h CFLAGS += ${DEBUG_FLAGS} wb.h: @@ -25,4 +27,7 @@ bus_if.h: $S/kern/makedevops.pl $S/kern/bus_if.m pci_if.h: $S/kern/makedevops.pl $S/pci/pci_if.m perl $S/kern/makedevops.pl -h $S/pci/pci_if.m +miibus_if.h: $S/kern/makedevops.pl $S/dev/mii/miibus_if.m + perl $S/kern/makedevops.pl -h $S/dev/mii/miibus_if.m + .include <bsd.kmod.mk> 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); diff --git a/sys/pci/if_sfreg.h b/sys/pci/if_sfreg.h index e5149ae..b9a8b9d 100644 --- a/sys/pci/if_sfreg.h +++ b/sys/pci/if_sfreg.h @@ -1010,20 +1010,14 @@ struct sf_list_data { struct sf_softc { struct arpcom arpcom; /* interface info */ - struct ifmedia ifmedia; /* media info */ bus_space_handle_t sf_bhandle; /* bus space handle */ bus_space_tag_t sf_btag; /* bus space tag */ void *sf_intrhand; /* interrupt handler cookie */ struct resource *sf_irq; /* irq resource descriptor */ struct resource *sf_res; /* mem/ioport resource */ struct sf_type *sf_info; /* Starfire adapter info */ - struct sf_type *sf_pinfo; /* phy info */ + device_t sf_miibus; u_int8_t sf_unit; /* interface number */ - u_int8_t sf_type; - u_int8_t sf_phy_addr; /* PHY address */ - u_int8_t sf_tx_pend; /* TX pending */ - u_int8_t sf_want_auto; - u_int8_t sf_autoneg; struct sf_list_data *sf_ldata; int sf_tx_cnt; struct callout_handle sf_stat_ch; @@ -1031,140 +1025,6 @@ struct sf_softc { #define SF_TIMEOUT 1000 -#define SF_FLAG_FORCEDELAY 1 -#define SF_FLAG_SCHEDDELAY 2 -#define SF_FLAG_DELAYTIMEO 3 - -/* - * Texas Instruments PHY identifiers - */ -#define TI_PHY_VENDORID 0x4000 -#define TI_PHY_10BT 0x501F -#define TI_PHY_100VGPMI 0x502F - -/* - * These ID values are for the NS DP83840A 10/100 PHY - */ -#define NS_PHY_VENDORID 0x2000 -#define NS_PHY_83840A 0x5C0F - -/* - * Level 1 10/100 PHY - */ -#define LEVEL1_PHY_VENDORID 0x7810 -#define LEVEL1_PHY_LXT970 0x000F - -/* - * Intel 82555 10/100 PHY - */ -#define INTEL_PHY_VENDORID 0x0A28 -#define INTEL_PHY_82555 0x015F - -/* - * SEEQ 80220 10/100 PHY - */ -#define SEEQ_PHY_VENDORID 0x0016 -#define SEEQ_PHY_80220 0xF83F - -#define PHY_UNKNOWN 6 - -#define SF_PHYADDR_MIN 0x00 -#define SF_PHYADDR_MAX 0x1F - -#define PHY_BMCR 0x00 -#define PHY_BMSR 0x01 -#define PHY_VENID 0x02 -#define PHY_DEVID 0x03 -#define PHY_ANAR 0x04 -#define PHY_LPAR 0x05 -#define PHY_ANEXP 0x06 - -#define PHY_ANAR_NEXTPAGE 0x8000 -#define PHY_ANAR_RSVD0 0x4000 -#define PHY_ANAR_TLRFLT 0x2000 -#define PHY_ANAR_RSVD1 0x1000 -#define PHY_ANAR_RSVD2 0x0800 -#define PHY_ANAR_RSVD3 0x0400 -#define PHY_ANAR_100BT4 0x0200 -#define PHY_ANAR_100BTXFULL 0x0100 -#define PHY_ANAR_100BTXHALF 0x0080 -#define PHY_ANAR_10BTFULL 0x0040 -#define PHY_ANAR_10BTHALF 0x0020 -#define PHY_ANAR_PROTO4 0x0010 -#define PHY_ANAR_PROTO3 0x0008 -#define PHY_ANAR_PROTO2 0x0004 -#define PHY_ANAR_PROTO1 0x0002 -#define PHY_ANAR_PROTO0 0x0001 - -/* - * These are the register definitions for the PHY (physical layer - * interface chip). - */ -/* - * PHY BMCR Basic Mode Control Register - */ -#define PHY_BMCR_RESET 0x8000 -#define PHY_BMCR_LOOPBK 0x4000 -#define PHY_BMCR_SPEEDSEL 0x2000 -#define PHY_BMCR_AUTONEGENBL 0x1000 -#define PHY_BMCR_RSVD0 0x0800 /* write as zero */ -#define PHY_BMCR_ISOLATE 0x0400 -#define PHY_BMCR_AUTONEGRSTR 0x0200 -#define PHY_BMCR_DUPLEX 0x0100 -#define PHY_BMCR_COLLTEST 0x0080 -#define PHY_BMCR_RSVD1 0x0040 /* write as zero, don't care */ -#define PHY_BMCR_RSVD2 0x0020 /* write as zero, don't care */ -#define PHY_BMCR_RSVD3 0x0010 /* write as zero, don't care */ -#define PHY_BMCR_RSVD4 0x0008 /* write as zero, don't care */ -#define PHY_BMCR_RSVD5 0x0004 /* write as zero, don't care */ -#define PHY_BMCR_RSVD6 0x0002 /* write as zero, don't care */ -#define PHY_BMCR_RSVD7 0x0001 /* write as zero, don't care */ -/* - * RESET: 1 == software reset, 0 == normal operation - * Resets status and control registers to default values. - * Relatches all hardware config values. - * - * LOOPBK: 1 == loopback operation enabled, 0 == normal operation - * - * SPEEDSEL: 1 == 100Mb/s, 0 == 10Mb/s - * Link speed is selected byt his bit or if auto-negotiation if bit - * 12 (AUTONEGENBL) is set (in which case the value of this register - * is ignored). - * - * AUTONEGENBL: 1 == Autonegotiation enabled, 0 == Autonegotiation disabled - * Bits 8 and 13 are ignored when autoneg is set, otherwise bits 8 and 13 - * determine speed and mode. Should be cleared and then set if PHY configured - * for no autoneg on startup. - * - * ISOLATE: 1 == isolate PHY from MII, 0 == normal operation - * - * AUTONEGRSTR: 1 == restart autonegotiation, 0 = normal operation - * - * DUPLEX: 1 == full duplex mode, 0 == half duplex mode - * - * COLLTEST: 1 == collision test enabled, 0 == normal operation - */ - -/* - * PHY, BMSR Basic Mode Status Register - */ -#define PHY_BMSR_100BT4 0x8000 -#define PHY_BMSR_100BTXFULL 0x4000 -#define PHY_BMSR_100BTXHALF 0x2000 -#define PHY_BMSR_10BTFULL 0x1000 -#define PHY_BMSR_10BTHALF 0x0800 -#define PHY_BMSR_RSVD1 0x0400 /* write as zero, don't care */ -#define PHY_BMSR_RSVD2 0x0200 /* write as zero, don't care */ -#define PHY_BMSR_RSVD3 0x0100 /* write as zero, don't care */ -#define PHY_BMSR_RSVD4 0x0080 /* write as zero, don't care */ -#define PHY_BMSR_MFPRESUP 0x0040 -#define PHY_BMSR_AUTONEGCOMP 0x0020 -#define PHY_BMSR_REMFAULT 0x0010 -#define PHY_BMSR_CANAUTONEG 0x0008 -#define PHY_BMSR_LINKSTAT 0x0004 -#define PHY_BMSR_JABBER 0x0002 -#define PHY_BMSR_EXTENDED 0x0001 - #ifdef __alpha__ #undef vtophys #define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va) diff --git a/sys/pci/if_wb.c b/sys/pci/if_wb.c index fb635b2..8e3b969 100644 --- a/sys/pci/if_wb.c +++ b/sys/pci/if_wb.c @@ -93,6 +93,7 @@ #include <sys/malloc.h> #include <sys/kernel.h> #include <sys/socket.h> +#include <sys/queue.h> #include <net/if.h> #include <net/if_arp.h> @@ -121,9 +122,12 @@ #include <pci/pcireg.h> #include <pci/pcivar.h> -#define WB_USEIOSPACE +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> + +#include "miibus_if.h" -/* #define WB_BACKGROUND_AUTONEG */ +#define WB_USEIOSPACE #include <pci/if_wbreg.h> @@ -143,37 +147,23 @@ static struct wb_type wb_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 wb_type wb_phys[] = { - { TI_PHY_VENDORID, TI_PHY_10BT, "<TI ThunderLAN 10BT (internal)>" }, - { TI_PHY_VENDORID, TI_PHY_100VGPMI, "<TI TNETE211 100VG Any-LAN>" }, - { NS_PHY_VENDORID, NS_PHY_83840A, "<National Semiconductor DP83840A>"}, - { LEVEL1_PHY_VENDORID, LEVEL1_PHY_LXT970, "<Level 1 LXT970>" }, - { INTEL_PHY_VENDORID, INTEL_PHY_82555, "<Intel 82555>" }, - { SEEQ_PHY_VENDORID, SEEQ_PHY_80220, "<SEEQ 80220>" }, - { 0, 0, "<MII-compliant physical interface>" } -}; - static int wb_probe __P((device_t)); static int wb_attach __P((device_t)); static int wb_detach __P((device_t)); +static void wb_bfree __P((caddr_t, u_int)); static int wb_newbuf __P((struct wb_softc *, struct wb_chain_onefrag *, struct mbuf *)); static int wb_encap __P((struct wb_softc *, struct wb_chain *, - struct mbuf *)); + struct mbuf *)); static void wb_rxeof __P((struct wb_softc *)); static void wb_rxeoc __P((struct wb_softc *)); static void wb_txeof __P((struct wb_softc *)); static void wb_txeoc __P((struct wb_softc *)); static void wb_intr __P((void *)); +static void wb_tick __P((void *)); static void wb_start __P((struct ifnet *)); static int wb_ioctl __P((struct ifnet *, u_long, caddr_t)); static void wb_init __P((void *)); @@ -191,20 +181,19 @@ static void wb_mii_sync __P((struct wb_softc *)); static void wb_mii_send __P((struct wb_softc *, u_int32_t, int)); static int wb_mii_readreg __P((struct wb_softc *, struct wb_mii_frame *)); static int wb_mii_writereg __P((struct wb_softc *, struct wb_mii_frame *)); -static u_int16_t wb_phy_readreg __P((struct wb_softc *, int)); -static void wb_phy_writereg __P((struct wb_softc *, int, int)); - -static void wb_autoneg_xmit __P((struct wb_softc *)); -static void wb_autoneg_mii __P((struct wb_softc *, int, int)); -static void wb_setmode_mii __P((struct wb_softc *, int)); -static void wb_getmode_mii __P((struct wb_softc *)); -static void wb_setcfg __P((struct wb_softc *, int)); + +static void wb_setcfg __P((struct wb_softc *, u_int32_t)); static u_int8_t wb_calchash __P((caddr_t)); static void wb_setmulti __P((struct wb_softc *)); static void wb_reset __P((struct wb_softc *)); +static void wb_fixmedia __P((struct wb_softc *)); static int wb_list_rx_init __P((struct wb_softc *)); static int wb_list_tx_init __P((struct wb_softc *)); +static int wb_miibus_readreg __P((device_t, int, int)); +static int wb_miibus_writereg __P((device_t, int, int, int)); +static void wb_miibus_statchg __P((device_t)); + #ifdef WB_USEIOSPACE #define WB_RES SYS_RES_IOPORT #define WB_RID WB_PCI_LOIO @@ -219,6 +208,15 @@ static device_method_t wb_methods[] = { DEVMETHOD(device_attach, wb_attach), DEVMETHOD(device_detach, wb_detach), DEVMETHOD(device_shutdown, wb_shutdown), + + /* bus interface, for miibus */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + + /* MII interface */ + DEVMETHOD(miibus_readreg, wb_miibus_readreg), + DEVMETHOD(miibus_writereg, wb_miibus_writereg), + DEVMETHOD(miibus_statchg, wb_miibus_statchg), { 0, 0 } }; @@ -231,6 +229,7 @@ static driver_t wb_driver = { static devclass_t wb_devclass; DRIVER_MODULE(wb, pci, wb_driver, wb_devclass, 0, 0); +DRIVER_MODULE(miibus, wb, miibus_driver, miibus_devclass, 0, 0); #define WB_SETBIT(sc, reg, x) \ CSR_WRITE_4(sc, reg, \ @@ -534,36 +533,54 @@ static int wb_mii_writereg(sc, frame) return(0); } -static u_int16_t wb_phy_readreg(sc, reg) - struct wb_softc *sc; - int reg; +static int wb_miibus_readreg(dev, phy, reg) + device_t dev; + int phy, reg; { + struct wb_softc *sc; struct wb_mii_frame frame; + sc = device_get_softc(dev); + bzero((char *)&frame, sizeof(frame)); - frame.mii_phyaddr = sc->wb_phy_addr; + frame.mii_phyaddr = phy; frame.mii_regaddr = reg; wb_mii_readreg(sc, &frame); return(frame.mii_data); } -static void wb_phy_writereg(sc, reg, data) - struct wb_softc *sc; - int reg; - int data; +static int wb_miibus_writereg(dev, phy, reg, data) + device_t dev; + int phy, reg, data; { + struct wb_softc *sc; struct wb_mii_frame frame; + sc = device_get_softc(dev); + bzero((char *)&frame, sizeof(frame)); - frame.mii_phyaddr = sc->wb_phy_addr; + frame.mii_phyaddr = phy; frame.mii_regaddr = reg; frame.mii_data = data; wb_mii_writereg(sc, &frame); + return(0); +} + +static void wb_miibus_statchg(dev) + device_t dev; +{ + struct wb_softc *sc; + struct mii_data *mii; + + sc = device_get_softc(dev); + mii = device_get_softc(sc->wb_miibus); + wb_setcfg(sc, mii->mii_media_active); + return; } @@ -653,320 +670,13 @@ static void wb_setmulti(sc) } /* - * Initiate an autonegotiation session. - */ -static void wb_autoneg_xmit(sc) - struct wb_softc *sc; -{ - u_int16_t phy_sts; - - wb_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET); - DELAY(500); - while(wb_phy_readreg(sc, PHY_BMCR) - & PHY_BMCR_RESET); - - phy_sts = wb_phy_readreg(sc, PHY_BMCR); - phy_sts |= PHY_BMCR_AUTONEGENBL|PHY_BMCR_AUTONEGRSTR; - wb_phy_writereg(sc, PHY_BMCR, phy_sts); - - return; -} - -/* - * Invoke autonegotiation on a PHY. - */ -static void wb_autoneg_mii(sc, flag, verbose) - struct wb_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 = wb_phy_readreg(sc, PHY_BMSR); - if (!(phy_sts & PHY_BMSR_CANAUTONEG)) { - if (verbose) - printf("wb%d: autonegotiation not supported\n", - sc->wb_unit); - ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX; - return; - } -#endif - - switch (flag) { - case WB_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. - */ - wb_autoneg_xmit(sc); - DELAY(5000000); - break; - case WB_FLAG_SCHEDDELAY: - /* - * Wait for the transmitter to go idle before starting - * an autoneg session, otherwise wb_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->wb_cdata.wb_tx_head != NULL) { - sc->wb_want_auto = 1; - return; - } - wb_autoneg_xmit(sc); - ifp->if_timer = 5; - sc->wb_autoneg = 1; - sc->wb_want_auto = 0; - return; - break; - case WB_FLAG_DELAYTIMEO: - ifp->if_timer = 0; - sc->wb_autoneg = 0; - break; - default: - printf("wb%d: invalid autoneg flag: %d\n", sc->wb_unit, flag); - return; - } - - if (wb_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_AUTONEGCOMP) { - if (verbose) - printf("wb%d: autoneg complete, ", sc->wb_unit); - phy_sts = wb_phy_readreg(sc, PHY_BMSR); - } else { - if (verbose) - printf("wb%d: autoneg not complete, ", sc->wb_unit); - } - - media = wb_phy_readreg(sc, PHY_BMCR); - - /* Link is good. Report modes and set duplex mode. */ - if (wb_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT) { - if (verbose) - printf("link status good "); - advert = wb_phy_readreg(sc, PHY_ANAR); - ability = wb_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. */ - wb_setcfg(sc, media); - wb_phy_writereg(sc, PHY_BMCR, media); - } else { - if (verbose) - printf("no carrier\n"); - } - - wb_init(sc); - - if (sc->wb_tx_pend) { - sc->wb_autoneg = 0; - sc->wb_tx_pend = 0; - wb_start(ifp); - } - - return; -} - -static void wb_getmode_mii(sc) - struct wb_softc *sc; -{ - u_int16_t bmsr; - struct ifnet *ifp; - - ifp = &sc->arpcom.ac_if; - - bmsr = wb_phy_readreg(sc, PHY_BMSR); - if (bootverbose) - printf("wb%d: PHY status word: %x\n", sc->wb_unit, bmsr); - - /* fallback */ - sc->ifmedia.ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX; - - if (bmsr & PHY_BMSR_10BTHALF) { - if (bootverbose) - printf("wb%d: 10Mbps half-duplex mode supported\n", - sc->wb_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("wb%d: 10Mbps full-duplex mode supported\n", - sc->wb_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("wb%d: 100Mbps half-duplex mode supported\n", - sc->wb_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("wb%d: 100Mbps full-duplex mode supported\n", - sc->wb_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("wb%d: 100baseT4 mode supported\n", sc->wb_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("wb%d: forcing on autoneg support for BT4\n", - sc->wb_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("wb%d: autoneg supported\n", sc->wb_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 wb_setmode_mii(sc, media) - struct wb_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->wb_autoneg) { - printf("wb%d: canceling autoneg session\n", sc->wb_unit); - ifp->if_timer = sc->wb_autoneg = sc->wb_want_auto = 0; - bmcr = wb_phy_readreg(sc, PHY_BMCR); - bmcr &= ~PHY_BMCR_AUTONEGENBL; - wb_phy_writereg(sc, PHY_BMCR, bmcr); - } - - printf("wb%d: selecting MII, ", sc->wb_unit); - - bmcr = wb_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; - } - - wb_setcfg(sc, bmcr); - wb_phy_writereg(sc, PHY_BMCR, bmcr); - - return; -} - -/* * The Winbond manual states that 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 wb_setcfg(sc, bmcr) +static void wb_setcfg(sc, media) struct wb_softc *sc; - int bmcr; + u_int32_t media; { int i, restart = 0; @@ -986,12 +696,12 @@ static void wb_setcfg(sc, bmcr) "rx to idle state\n", sc->wb_unit); } - if (bmcr & PHY_BMCR_SPEEDSEL) - WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_100MBPS); - else + if (IFM_SUBTYPE(media) == IFM_10_T) WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_100MBPS); + else + WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_100MBPS); - if (bmcr & PHY_BMCR_DUPLEX) + if ((media & IFM_GMASK) == IFM_FDX) WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_FULLDUPLEX); else WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_FULLDUPLEX); @@ -1006,8 +716,15 @@ static void wb_reset(sc) struct wb_softc *sc; { register int i; + struct mii_data *mii; + + CSR_WRITE_4(sc, WB_NETCFG, 0); + CSR_WRITE_4(sc, WB_BUSCTL, 0); + CSR_WRITE_4(sc, WB_TXADDR, 0); + CSR_WRITE_4(sc, WB_RXADDR, 0); WB_SETBIT(sc, WB_BUSCTL, WB_BUSCTL_RESET); + WB_SETBIT(sc, WB_BUSCTL, WB_BUSCTL_RESET); for (i = 0; i < WB_TIMEOUT; i++) { DELAY(10); @@ -1020,13 +737,51 @@ static void wb_reset(sc) /* Wait a little while for the chip to get its brains in order. */ DELAY(1000); - /* Reset the damn PHY too. */ - if (sc->wb_pinfo != NULL) - wb_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET); + if (sc->wb_miibus == NULL) + return; + + mii = device_get_softc(sc->wb_miibus); + if (mii == NULL) + return; + + if (mii->mii_instance) { + struct mii_softc *miisc; + for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL; + miisc = LIST_NEXT(miisc, mii_list)) + mii_phy_reset(miisc); + } return; } +static void wb_fixmedia(sc) + struct wb_softc *sc; +{ + struct mii_data *mii = NULL; + struct ifnet *ifp; + u_int32_t media; + + if (sc->wb_miibus == NULL) + return; + + mii = device_get_softc(sc->wb_miibus); + ifp = &sc->arpcom.ac_if; + + mii_pollstat(mii); + if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T) { + media = mii->mii_media_active & ~IFM_10_T; + media |= IFM_100_TX; + } else if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) { + media = mii->mii_media_active & ~IFM_100_TX; + media |= IFM_10_T; + } else + return; + + ifmedia_set(&mii->mii_media, media); + + return; +} + /* * Probe for a Winbond chip. Check the PCI vendor and device * IDs against our list and return a device name if we find a match. @@ -1057,23 +812,17 @@ static int wb_probe(dev) static int wb_attach(dev) device_t dev; { - int s, i; + int s; u_char eaddr[ETHER_ADDR_LEN]; u_int32_t command; struct wb_softc *sc; struct ifnet *ifp; - int media = IFM_ETHER|IFM_100_TX|IFM_FDX; - unsigned int round; - caddr_t roundptr; - struct wb_type *p; - u_int16_t phy_vid, phy_did, phy_sts; int unit, error = 0, rid; s = splimp(); sc = device_get_softc(dev); unit = device_get_unit(dev); - bzero(sc, sizeof(struct wb_softc)); /* * Handle power management nonsense. @@ -1160,7 +909,10 @@ static int wb_attach(dev) printf("wb%d: couldn't set up irq\n", unit); goto fail; } - + + /* Save the cache line size. */ + sc->wb_cachesize = pci_read_config(dev, WB_PCI_CACHELEN, 4) & 0xFF; + /* Reset the adapter. */ wb_reset(sc); @@ -1177,9 +929,10 @@ static int wb_attach(dev) sc->wb_unit = unit; bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); - sc->wb_ldata_ptr = malloc(sizeof(struct wb_list_data) + 8, - M_DEVBUF, M_NOWAIT); - if (sc->wb_ldata_ptr == NULL) { + sc->wb_ldata = contigmalloc(sizeof(struct wb_list_data) + 8, M_DEVBUF, + M_NOWAIT, 0x100000, 0xffffffff, PAGE_SIZE, 0); + + if (sc->wb_ldata == NULL) { printf("wb%d: no memory for list buffers!\n", unit); bus_teardown_intr(dev, sc->wb_irq, sc->wb_intrhand); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->wb_irq); @@ -1188,17 +941,6 @@ static int wb_attach(dev) goto fail; } - sc->wb_ldata = (struct wb_list_data *)sc->wb_ldata_ptr; - round = (uintptr_t)sc->wb_ldata_ptr & 0xF; - roundptr = sc->wb_ldata_ptr; - for (i = 0; i < 8; i++) { - if (round % 8) { - round++; - roundptr++; - } else - break; - } - sc->wb_ldata = (struct wb_list_data *)roundptr; bzero(sc->wb_ldata, sizeof(struct wb_list_data)); ifp = &sc->arpcom.ac_if; @@ -1215,45 +957,11 @@ static int wb_attach(dev) ifp->if_baudrate = 10000000; ifp->if_snd.ifq_maxlen = WB_TX_LIST_CNT - 1; - if (bootverbose) - printf("wb%d: probing for a PHY\n", sc->wb_unit); - for (i = WB_PHYADDR_MIN; i < WB_PHYADDR_MAX + 1; i++) { - if (bootverbose) - printf("wb%d: checking address: %d\n", - sc->wb_unit, i); - sc->wb_phy_addr = i; - wb_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET); - DELAY(500); - while(wb_phy_readreg(sc, PHY_BMCR) - & PHY_BMCR_RESET); - if ((phy_sts = wb_phy_readreg(sc, PHY_BMSR))) - break; - } - if (phy_sts) { - phy_vid = wb_phy_readreg(sc, PHY_VENID); - phy_did = wb_phy_readreg(sc, PHY_DEVID); - if (bootverbose) - printf("wb%d: found PHY at address %d, ", - sc->wb_unit, sc->wb_phy_addr); - if (bootverbose) - printf("vendor id: %x device id: %x\n", - phy_vid, phy_did); - p = wb_phys; - while(p->wb_vid) { - if (phy_vid == p->wb_vid && - (phy_did | 0x000F) == p->wb_did) { - sc->wb_pinfo = p; - break; - } - p++; - } - if (sc->wb_pinfo == NULL) - sc->wb_pinfo = &wb_phys[PHY_UNKNOWN]; - if (bootverbose) - printf("wb%d: PHY type: %s\n", - sc->wb_unit, sc->wb_pinfo->wb_name); - } else { - printf("wb%d: MII without any phy!\n", sc->wb_unit); + /* + * Do MII setup. + */ + if (mii_phy_probe(dev, &sc->wb_miibus, + wb_ifmedia_upd, wb_ifmedia_sts)) { bus_teardown_intr(dev, sc->wb_irq, sc->wb_intrhand); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->wb_irq); bus_release_resource(dev, WB_RES, WB_RID, sc->wb_res); @@ -1263,23 +971,6 @@ static int wb_attach(dev) } /* - * Do ifmedia setup. - */ - ifmedia_init(&sc->ifmedia, 0, wb_ifmedia_upd, wb_ifmedia_sts); - - wb_getmode_mii(sc); - if (cold) { - wb_autoneg_mii(sc, WB_FLAG_FORCEDELAY, 1); - wb_stop(sc); - } else { - wb_init(sc); - wb_autoneg_mii(sc, WB_FLAG_SCHEDDELAY, 1); - } - media = sc->ifmedia.ifm_media; - - ifmedia_set(&sc->ifmedia, media); - - /* * Call MI attach routines. */ if_attach(ifp); @@ -1290,7 +981,10 @@ static int wb_attach(dev) #endif fail: + if (error) + device_delete_child(dev, sc->wb_miibus); splx(s); + return(error); } @@ -1309,12 +1003,15 @@ static int wb_detach(dev) wb_stop(sc); if_detach(ifp); + /* Delete any miibus and phy devices attached to this interface */ + bus_generic_detach(dev); + device_delete_child(dev, sc->wb_miibus); + bus_teardown_intr(dev, sc->wb_irq, sc->wb_intrhand); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->wb_irq); bus_release_resource(dev, WB_RES, WB_RID, sc->wb_res); free(sc->wb_ldata_ptr, M_DEVBUF); - ifmedia_removeall(&sc->ifmedia); splx(s); @@ -1370,6 +1067,7 @@ static int wb_list_rx_init(sc) for (i = 0; i < WB_RX_LIST_CNT; i++) { cd->wb_rx_chain[i].wb_ptr = (struct wb_desc *)&ld->wb_rx_list[i]; + cd->wb_rx_chain[i].wb_buf = (void *)&ld->wb_rxbufs[i]; if (wb_newbuf(sc, &cd->wb_rx_chain[i], NULL) == ENOBUFS) return(ENOBUFS); if (i == (WB_RX_LIST_CNT - 1)) { @@ -1389,6 +1087,13 @@ static int wb_list_rx_init(sc) return(0); } +static void wb_bfree(buf, size) + caddr_t buf; + u_int size; +{ + return; +} + /* * Initialize an RX descriptor and attach an MBUF cluster. */ @@ -1407,17 +1112,15 @@ static int wb_newbuf(sc, c, m) return(ENOBUFS); } - MCLGET(m_new, M_DONTWAIT); - if (!(m_new->m_flags & M_EXT)) { - printf("wb%d: no memory for rx " - "list -- packet dropped!\n", sc->wb_unit); - m_freem(m_new); - return(ENOBUFS); - } - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; + m_new->m_data = m_new->m_ext.ext_buf = c->wb_buf; + m_new->m_flags |= M_EXT; + m_new->m_ext.ext_size = m_new->m_pkthdr.len = + m_new->m_len = WB_BUFBYTES; + m_new->m_ext.ext_free = wb_bfree; + m_new->m_ext.ext_ref = wb_bfree; } else { m_new = m; - m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; + m_new->m_len = m_new->m_pkthdr.len = WB_BUFBYTES; m_new->m_data = m_new->m_ext.ext_buf; } @@ -1425,7 +1128,7 @@ static int wb_newbuf(sc, c, m) c->wb_mbuf = m_new; c->wb_ptr->wb_data = vtophys(mtod(m_new, caddr_t)); - c->wb_ptr->wb_ctl = WB_RXCTL_RLINK | (MCLBYTES - 1); + c->wb_ptr->wb_ctl = WB_RXCTL_RLINK | 1536; c->wb_ptr->wb_status = WB_RXSTAT; return(0); @@ -1439,7 +1142,7 @@ static void wb_rxeof(sc) struct wb_softc *sc; { struct ether_header *eh; - struct mbuf *m; + struct mbuf *m = NULL; struct ifnet *ifp; struct wb_chain_onefrag *cur_rx; int total_len = 0; @@ -1453,23 +1156,28 @@ static void wb_rxeof(sc) cur_rx = sc->wb_cdata.wb_rx_head; sc->wb_cdata.wb_rx_head = cur_rx->wb_nextdesc; + m = cur_rx->wb_mbuf; - if ((rxstat & WB_RXSTAT_MIIERR) - || WB_RXBYTES(cur_rx->wb_ptr->wb_status) == 0) { + if ((rxstat & WB_RXSTAT_MIIERR) || + (WB_RXBYTES(cur_rx->wb_ptr->wb_status) < WB_MIN_FRAMELEN) || + (WB_RXBYTES(cur_rx->wb_ptr->wb_status) > 1536) || + !(rxstat & WB_RXSTAT_LASTFRAG) || + !(rxstat & WB_RXSTAT_RXCMP)) { ifp->if_ierrors++; - wb_reset(sc); + wb_newbuf(sc, cur_rx, m); printf("wb%x: receiver babbling: possible chip " "bug, forcing reset\n", sc->wb_unit); - ifp->if_flags |= IFF_OACTIVE; - ifp->if_timer = 2; + wb_fixmedia(sc); + wb_reset(sc); + wb_init(sc); return; } if (rxstat & WB_RXSTAT_RXERR) { ifp->if_ierrors++; wb_newbuf(sc, cur_rx, m); - continue; + break; } /* No errors; receive the packet. */ @@ -1489,7 +1197,7 @@ static void wb_rxeof(sc) wb_newbuf(sc, cur_rx, m); if (m0 == NULL) { ifp->if_ierrors++; - continue; + break; } m_adj(m0, ETHER_ALIGN); m = m0; @@ -1506,7 +1214,7 @@ static void wb_rxeof(sc) if (((bdg_ifp != BDG_LOCAL) && (bdg_ifp != BDG_BCAST) && (bdg_ifp != BDG_MCAST)) || bdg_ifp == BDG_DROP) { m_freem(m); - continue; + break; } } #endif @@ -1525,7 +1233,7 @@ static void wb_rxeof(sc) ETHER_ADDR_LEN) && (eh->ether_dhost[0] & 1) == 0)) { m_freem(m); - continue; + break; } } #endif @@ -1623,8 +1331,6 @@ static void wb_txeoc(sc) if (sc->wb_cdata.wb_tx_head == NULL) { ifp->if_flags &= ~IFF_OACTIVE; sc->wb_cdata.wb_tx_tail = NULL; - if (sc->wb_want_auto) - wb_autoneg_mii(sc, WB_FLAG_SCHEDDELAY, 1); } else { if (WB_TXOWN(sc->wb_cdata.wb_tx_head) == WB_UNSENT) { WB_TXOWN(sc->wb_cdata.wb_tx_head) = WB_TXSTAT_OWN; @@ -1661,21 +1367,21 @@ static void wb_intr(arg) if ((status & WB_INTRS) == 0) break; - if (status & WB_ISR_RX_OK) - wb_rxeof(sc); - - if (status & WB_ISR_RX_IDLE) - wb_rxeoc(sc); - if ((status & WB_ISR_RX_NOBUF) || (status & WB_ISR_RX_ERR)) { ifp->if_ierrors++; -#ifdef foo - wb_stop(sc); wb_reset(sc); + if (status & WB_ISR_RX_ERR) + wb_fixmedia(sc); wb_init(sc); -#endif + continue; } + if (status & WB_ISR_RX_OK) + wb_rxeof(sc); + + if (status & WB_ISR_RX_IDLE) + wb_rxeoc(sc); + if (status & WB_ISR_TX_OK) wb_txeof(sc); @@ -1718,6 +1424,22 @@ static void wb_intr(arg) return; } +static void wb_tick(xsc) + void *xsc; +{ + struct wb_softc *sc; + struct mii_data *mii; + + sc = xsc; + mii = device_get_softc(sc->wb_miibus); + + mii_tick(mii); + + sc->wb_stat_ch = timeout(wb_tick, sc, hz); + + return; +} + /* * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data * pointers to the fragment pointers. @@ -1829,11 +1551,6 @@ static void wb_start(ifp) sc = ifp->if_softc; - if (sc->wb_autoneg) { - sc->wb_tx_pend = 1; - return; - } - /* * Check for an available queue slot. If there are none, * punt. @@ -1921,15 +1638,11 @@ static void wb_init(xsc) struct wb_softc *sc = xsc; struct ifnet *ifp = &sc->arpcom.ac_if; int s, i; - u_int16_t phy_bmcr = 0; - - if (sc->wb_autoneg) - return; + struct mii_data *mii; s = splimp(); - if (sc->wb_pinfo != NULL) - phy_bmcr = wb_phy_readreg(sc, PHY_BMCR); + mii = device_get_softc(sc->wb_miibus); /* * Cancel pending I/O and free all RX/TX buffers. @@ -1942,15 +1655,33 @@ static void wb_init(xsc) /* * Set cache alignment and burst length. */ +#ifdef foo CSR_WRITE_4(sc, WB_BUSCTL, WB_BUSCTL_CONFIG); WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_THRESH); WB_SETBIT(sc, WB_NETCFG, WB_TXTHRESH(sc->wb_txthresh)); +#endif + + CSR_WRITE_4(sc, WB_BUSCTL, WB_BUSCTL_MUSTBEONE|WB_BUSCTL_ARBITRATION); + WB_SETBIT(sc, WB_BUSCTL, WB_BURSTLEN_16LONG); + switch(sc->wb_cachesize) { + case 32: + WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_32LONG); + break; + case 16: + WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_16LONG); + break; + case 8: + WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_8LONG); + break; + case 0: + default: + WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_NONE); + break; + } /* This doesn't tend to work too well at 100Mbps. */ WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_EARLY_ON); - wb_setcfg(sc, phy_bmcr); - /* Init our MAC address */ for (i = 0; i < ETHER_ADDR_LEN; i++) { CSR_WRITE_1(sc, WB_NODE0 + i, sc->arpcom.ac_enaddr[i]); @@ -2009,15 +1740,15 @@ static void wb_init(xsc) CSR_WRITE_4(sc, WB_TXADDR, vtophys(&sc->wb_ldata->wb_tx_list[0])); WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON); - /* Restore state of BMCR */ - if (sc->wb_pinfo != NULL) - wb_phy_writereg(sc, PHY_BMCR, phy_bmcr); + mii_mediachg(mii); ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; (void)splx(s); + sc->wb_stat_ch = timeout(wb_tick, sc, hz); + return; } @@ -2028,18 +1759,11 @@ static int wb_ifmedia_upd(ifp) struct ifnet *ifp; { struct wb_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) - wb_autoneg_mii(sc, WB_FLAG_SCHEDDELAY, 1); - else - wb_setmode_mii(sc, ifm->ifm_media); + if (ifp->if_flags & IFF_UP) + wb_init(sc); return(0); } @@ -2052,42 +1776,15 @@ static void wb_ifmedia_sts(ifp, ifmr) struct ifmediareq *ifmr; { struct wb_softc *sc; - u_int16_t advert = 0, ability = 0; + struct mii_data *mii; sc = ifp->if_softc; - ifmr->ifm_active = IFM_ETHER; + mii = device_get_softc(sc->wb_miibus); - if (!(wb_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_AUTONEGENBL)) { - if (wb_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 (wb_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_DUPLEX) - ifmr->ifm_active |= IFM_FDX; - else - ifmr->ifm_active |= IFM_HDX; - return; - } - - ability = wb_phy_readreg(sc, PHY_LPAR); - advert = wb_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; } @@ -2098,6 +1795,7 @@ static int wb_ioctl(ifp, command, data) caddr_t data; { struct wb_softc *sc = ifp->if_softc; + struct mii_data *mii; struct ifreq *ifr = (struct ifreq *) data; int s, error = 0; @@ -2125,7 +1823,8 @@ static int wb_ioctl(ifp, command, data) break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); + mii = device_get_softc(sc->wb_miibus); + error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); break; default: error = EINVAL; @@ -2144,20 +1843,13 @@ static void wb_watchdog(ifp) sc = ifp->if_softc; - if (sc->wb_autoneg) { - wb_autoneg_mii(sc, WB_FLAG_DELAYTIMEO, 1); - if (!(ifp->if_flags & IFF_UP)) - wb_stop(sc); - return; - } - ifp->if_oerrors++; printf("wb%d: watchdog timeout\n", sc->wb_unit); - +#ifdef foo if (!(wb_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT)) printf("wb%d: no carrier - transceiver cable problem?\n", sc->wb_unit); - +#endif wb_stop(sc); wb_reset(sc); wb_init(sc); @@ -2181,6 +1873,8 @@ static void wb_stop(sc) ifp = &sc->arpcom.ac_if; ifp->if_timer = 0; + untimeout(wb_tick, sc, sc->wb_stat_ch); + WB_CLRBIT(sc, WB_NETCFG, (WB_NETCFG_RX_ON|WB_NETCFG_TX_ON)); CSR_WRITE_4(sc, WB_IMR, 0x00000000); CSR_WRITE_4(sc, WB_TXADDR, 0x00000000); diff --git a/sys/pci/if_wbreg.h b/sys/pci/if_wbreg.h index 5411339..5bfccd8 100644 --- a/sys/pci/if_wbreg.h +++ b/sys/pci/if_wbreg.h @@ -69,6 +69,7 @@ #define WB_BUSCTL_CACHEALIGN 0x0000C000 #define WB_BUSCTL_DES_BIGENDIAN 0x00100000 #define WB_BUSCTL_WAIT 0x00200000 +#define WB_BUSCTL_MUSTBEONE 0x00400000 #define WB_SKIPLEN_1LONG 0x00000004 #define WB_SKIPLEN_2LONG 0x00000008 @@ -76,6 +77,7 @@ #define WB_SKIPLEN_4LONG 0x00000020 #define WB_SKIPLEN_5LONG 0x00000040 +#define WB_CACHEALIGN_NONE 0x00000000 #define WB_CACHEALIGN_8LONG 0x00004000 #define WB_CACHEALIGN_16LONG 0x00008000 #define WB_CACHEALIGN_32LONG 0x0000C000 @@ -297,7 +299,14 @@ struct wb_txdesc { #define WB_UNSENT 0x1234 +#define WB_BUFBYTES (1024 * sizeof(u_int32_t)) + +struct wb_buf { + u_int32_t wb_data[1024]; +}; + struct wb_list_data { + struct wb_buf wb_rxbufs[WB_RX_LIST_CNT]; struct wb_desc wb_rx_list[WB_RX_LIST_CNT]; struct wb_txdesc wb_tx_list[WB_TX_LIST_CNT]; }; @@ -312,6 +321,7 @@ struct wb_chain { struct wb_chain_onefrag { struct wb_desc *wb_ptr; struct mbuf *wb_mbuf; + void *wb_buf; struct wb_chain_onefrag *wb_nextdesc; u_int8_t wb_rlast; }; @@ -351,30 +361,23 @@ struct wb_mii_frame { #define WB_MII_WRITEOP 0x01 #define WB_MII_TURNAROUND 0x02 -#define WB_FLAG_FORCEDELAY 1 -#define WB_FLAG_SCHEDDELAY 2 -#define WB_FLAG_DELAYTIMEO 3 - struct wb_softc { struct arpcom arpcom; /* interface info */ - struct ifmedia ifmedia; /* media info */ + device_t wb_miibus; bus_space_handle_t wb_bhandle; bus_space_tag_t wb_btag; struct resource *wb_res; struct resource *wb_irq; void *wb_intrhand; struct wb_type *wb_info; /* Winbond adapter info */ - struct wb_type *wb_pinfo; /* phy info */ u_int8_t wb_unit; /* interface number */ u_int8_t wb_type; - u_int8_t wb_phy_addr; /* PHY address */ - u_int8_t wb_tx_pend; /* TX pending */ - u_int8_t wb_want_auto; - u_int8_t wb_autoneg; u_int16_t wb_txthresh; + int wb_cachesize; caddr_t wb_ldata_ptr; struct wb_list_data *wb_ldata; struct wb_chain_data wb_cdata; + struct callout_handle wb_stat_ch; }; /* @@ -419,41 +422,8 @@ struct wb_softc { #define CP_DEVICEID_RL100 0x2011 /* - * Texas Instruments PHY identifiers - */ -#define TI_PHY_VENDORID 0x4000 -#define TI_PHY_10BT 0x501F -#define TI_PHY_100VGPMI 0x502F - -/* - * These ID values are for the NS DP83840A 10/100 PHY - */ -#define NS_PHY_VENDORID 0x2000 -#define NS_PHY_83840A 0x5C0F - -/* - * Level 1 10/100 PHY - */ -#define LEVEL1_PHY_VENDORID 0x7810 -#define LEVEL1_PHY_LXT970 0x000F - -/* - * Intel 82555 10/100 PHY - */ -#define INTEL_PHY_VENDORID 0x0A28 -#define INTEL_PHY_82555 0x015F - -/* - * SEEQ 80220 10/100 PHY - */ -#define SEEQ_PHY_VENDORID 0x0016 -#define SEEQ_PHY_80220 0xF83F - - -/* * PCI low memory base and low I/O base register, and - * other PCI registers. Note: some are only available on - * the 3c905B, in particular those that related to power management. + * other PCI registers. */ #define WB_PCI_VENDOR_ID 0x00 @@ -461,6 +431,7 @@ struct wb_softc { #define WB_PCI_COMMAND 0x04 #define WB_PCI_STATUS 0x06 #define WB_PCI_CLASSCODE 0x09 +#define WB_PCI_CACHELEN 0x0C #define WB_PCI_LATENCY_TIMER 0x0D #define WB_PCI_HEADER_TYPE 0x0E #define WB_PCI_LOIO 0x10 @@ -487,105 +458,6 @@ struct wb_softc { #define WB_PME_EN 0x0010 #define WB_PME_STATUS 0x8000 -#define PHY_UNKNOWN 6 - -#define WB_PHYADDR_MIN 0x00 -#define WB_PHYADDR_MAX 0x1F - -#define PHY_BMCR 0x00 -#define PHY_BMSR 0x01 -#define PHY_VENID 0x02 -#define PHY_DEVID 0x03 -#define PHY_ANAR 0x04 -#define PHY_LPAR 0x05 -#define PHY_ANEXP 0x06 - -#define PHY_ANAR_NEXTPAGE 0x8000 -#define PHY_ANAR_RSVD0 0x4000 -#define PHY_ANAR_TLRFLT 0x2000 -#define PHY_ANAR_RSVD1 0x1000 -#define PHY_ANAR_RSVD2 0x0800 -#define PHY_ANAR_RSVD3 0x0400 -#define PHY_ANAR_100BT4 0x0200 -#define PHY_ANAR_100BTXFULL 0x0100 -#define PHY_ANAR_100BTXHALF 0x0080 -#define PHY_ANAR_10BTFULL 0x0040 -#define PHY_ANAR_10BTHALF 0x0020 -#define PHY_ANAR_PROTO4 0x0010 -#define PHY_ANAR_PROTO3 0x0008 -#define PHY_ANAR_PROTO2 0x0004 -#define PHY_ANAR_PROTO1 0x0002 -#define PHY_ANAR_PROTO0 0x0001 - -/* - * These are the register definitions for the PHY (physical layer - * interface chip). - */ -/* - * PHY BMCR Basic Mode Control Register - */ -#define PHY_BMCR_RESET 0x8000 -#define PHY_BMCR_LOOPBK 0x4000 -#define PHY_BMCR_SPEEDSEL 0x2000 -#define PHY_BMCR_AUTONEGENBL 0x1000 -#define PHY_BMCR_RSVD0 0x0800 /* write as zero */ -#define PHY_BMCR_ISOLATE 0x0400 -#define PHY_BMCR_AUTONEGRSTR 0x0200 -#define PHY_BMCR_DUPLEX 0x0100 -#define PHY_BMCR_COLLTEST 0x0080 -#define PHY_BMCR_RSVD1 0x0040 /* write as zero, don't care */ -#define PHY_BMCR_RSVD2 0x0020 /* write as zero, don't care */ -#define PHY_BMCR_RSVD3 0x0010 /* write as zero, don't care */ -#define PHY_BMCR_RSVD4 0x0008 /* write as zero, don't care */ -#define PHY_BMCR_RSVD5 0x0004 /* write as zero, don't care */ -#define PHY_BMCR_RSVD6 0x0002 /* write as zero, don't care */ -#define PHY_BMCR_RSVD7 0x0001 /* write as zero, don't care */ -/* - * RESET: 1 == software reset, 0 == normal operation - * Resets status and control registers to default values. - * Relatches all hardware config values. - * - * LOOPBK: 1 == loopback operation enabled, 0 == normal operation - * - * SPEEDSEL: 1 == 100Mb/s, 0 == 10Mb/s - * Link speed is selected byt his bit or if auto-negotiation if bit - * 12 (AUTONEGENBL) is set (in which case the value of this register - * is ignored). - * - * AUTONEGENBL: 1 == Autonegotiation enabled, 0 == Autonegotiation disabled - * Bits 8 and 13 are ignored when autoneg is set, otherwise bits 8 and 13 - * determine speed and mode. Should be cleared and then set if PHY configured - * for no autoneg on startup. - * - * ISOLATE: 1 == isolate PHY from MII, 0 == normal operation - * - * AUTONEGRSTR: 1 == restart autonegotiation, 0 = normal operation - * - * DUPLEX: 1 == full duplex mode, 0 == half duplex mode - * - * COLLTEST: 1 == collision test enabled, 0 == normal operation - */ - -/* - * PHY, BMSR Basic Mode Status Register - */ -#define PHY_BMSR_100BT4 0x8000 -#define PHY_BMSR_100BTXFULL 0x4000 -#define PHY_BMSR_100BTXHALF 0x2000 -#define PHY_BMSR_10BTFULL 0x1000 -#define PHY_BMSR_10BTHALF 0x0800 -#define PHY_BMSR_RSVD1 0x0400 /* write as zero, don't care */ -#define PHY_BMSR_RSVD2 0x0200 /* write as zero, don't care */ -#define PHY_BMSR_RSVD3 0x0100 /* write as zero, don't care */ -#define PHY_BMSR_RSVD4 0x0080 /* write as zero, don't care */ -#define PHY_BMSR_MFPRESUP 0x0040 -#define PHY_BMSR_AUTONEGCOMP 0x0020 -#define PHY_BMSR_REMFAULT 0x0010 -#define PHY_BMSR_CANAUTONEG 0x0008 -#define PHY_BMSR_LINKSTAT 0x0004 -#define PHY_BMSR_JABBER 0x0002 -#define PHY_BMSR_EXTENDED 0x0001 - #ifdef __alpha__ #undef vtophys #define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va) |