diff options
author | wpaul <wpaul@FreeBSD.org> | 1999-08-29 15:52:19 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 1999-08-29 15:52:19 +0000 |
commit | a7cde9673c19c149f91a247b78e4e261f5682da6 (patch) | |
tree | 5498ea819746fbe8f7a805d83e78c5d436ff97f5 /sys/pci | |
parent | 7cdd93ef08c6f768a31dd4304057bf02fd156a3d (diff) | |
download | FreeBSD-src-a7cde9673c19c149f91a247b78e4e261f5682da6.zip FreeBSD-src-a7cde9673c19c149f91a247b78e4e261f5682da6.tar.gz |
Convert the 3Com XL driver to miibus. This one is a little tricky
due to the fact that there are non-MII cards supported by the same
driver and I don't have all of the cards available for testing. There's
also the 3c905B-COMBO which has MII, AUI and BNC media ports all in one
package. Supporting the COMBO is difficult because we have to add the
10base5 and 10base2 media types to the same ifmedia struct as the
MII-attached types, however there is no way to force the miibus and
child PHYs into existence before xl_attach() completes, so there is
no ifmedia struct available in xl_attach(). What we do inistead is
use the mediainit method as a callback: when a child PHY is attached,
it calls the miibus mediainit routine which selects a default media.
This routing also calls the NIC driver's mediainit method (if it
implements one) at which point we can safely add the other media
types.
Diffstat (limited to 'sys/pci')
-rw-r--r-- | sys/pci/if_xl.c | 764 | ||||
-rw-r--r-- | sys/pci/if_xlreg.h | 155 |
2 files changed, 173 insertions, 746 deletions
diff --git a/sys/pci/if_xl.c b/sys/pci/if_xl.c index 04d76a7..77c5a81 100644 --- a/sys/pci/if_xl.c +++ b/sys/pci/if_xl.c @@ -124,9 +124,14 @@ #include <sys/bus.h> #include <sys/rman.h> +#include <dev/mii/mii.h> +#include <dev/mii/miivar.h> + #include <pci/pcireg.h> #include <pci/pcivar.h> +#include "miibus_if.h" + /* * The following #define causes the code to use PIO to access the * chip's registers instead of memory mapped mode. The reason PIO mode @@ -139,26 +144,6 @@ */ #define XL_USEIOSPACE -/* - * This #define controls the behavior of autonegotiation during the - * bootstrap phase. It's possible to have the driver initiate an - * autonegotiation session and then set a timeout which will cause the - * autoneg results to be polled later, usually once the kernel has - * finished booting. This is clever and all, but it can have bad side - * effects in some cases, particularly where NFS is involved. For - * example, if we're booting diskless with an NFS rootfs, the network - * interface has to be up and running before we hit the mountroot() - * code, otherwise mounting the rootfs will fail and we'll probably - * panic. - * - * Consequently, the 'backgrounded' autoneg behavior is turned off - * by default and we actually sit and wait 5 seconds for autonegotiation - * to complete before proceeding with the other device probes. If you - * choose to use the other behavior, you can uncomment this #define and - * recompile. - */ -/* #define XL_BACKGROUND_AUTONEG */ - #include <pci/if_xlreg.h> #if !defined(lint) @@ -203,22 +188,6 @@ static struct xl_type xl_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 xl_type xl_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 xl_probe __P((device_t)); static int xl_attach __P((device_t)); static int xl_detach __P((device_t)); @@ -249,13 +218,8 @@ static void xl_mii_sync __P((struct xl_softc *)); static void xl_mii_send __P((struct xl_softc *, u_int32_t, int)); static int xl_mii_readreg __P((struct xl_softc *, struct xl_mii_frame *)); static int xl_mii_writereg __P((struct xl_softc *, struct xl_mii_frame *)); -static u_int16_t xl_phy_readreg __P((struct xl_softc *, int)); -static void xl_phy_writereg __P((struct xl_softc *, int, int)); -static void xl_autoneg_xmit __P((struct xl_softc *)); -static void xl_autoneg_mii __P((struct xl_softc *, int, int)); -static void xl_setmode_mii __P((struct xl_softc *, int)); -static void xl_getmode_mii __P((struct xl_softc *)); +static void xl_setcfg __P((struct xl_softc *)); static void xl_setmode __P((struct xl_softc *, int)); static u_int8_t xl_calchash __P((caddr_t)); static void xl_setmulti __P((struct xl_softc *)); @@ -269,6 +233,11 @@ static void xl_mediacheck __P((struct xl_softc *)); static void xl_testpacket __P((struct xl_softc *)); #endif +static int xl_miibus_readreg __P((device_t, int, int)); +static int xl_miibus_writereg __P((device_t, int, int, int)); +static void xl_miibus_statchg __P((device_t)); +static void xl_miibus_mediainit __P((device_t)); + #ifdef XL_USEIOSPACE #define XL_RES SYS_RES_IOPORT #define XL_RID XL_PCI_LOIO @@ -283,6 +252,17 @@ static device_method_t xl_methods[] = { DEVMETHOD(device_attach, xl_attach), DEVMETHOD(device_detach, xl_detach), DEVMETHOD(device_shutdown, xl_shutdown), + + /* bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + + /* MII interface */ + DEVMETHOD(miibus_readreg, xl_miibus_readreg), + DEVMETHOD(miibus_writereg, xl_miibus_writereg), + DEVMETHOD(miibus_statchg, xl_miibus_statchg), + DEVMETHOD(miibus_mediainit, xl_miibus_mediainit), + { 0, 0 } }; @@ -295,6 +275,7 @@ static driver_t xl_driver = { static devclass_t xl_devclass; DRIVER_MODULE(xl, pci, xl_driver, xl_devclass, 0, 0); +DRIVER_MODULE(miibus, xl, miibus_driver, miibus_devclass, 0, 0); /* * Murphy's law says that it's possible the chip can wedge and @@ -536,36 +517,112 @@ static int xl_mii_writereg(sc, frame) return(0); } -static u_int16_t xl_phy_readreg(sc, reg) - struct xl_softc *sc; - int reg; +static int xl_miibus_readreg(dev, phy, reg) + device_t dev; + int phy, reg; { + struct xl_softc *sc; struct xl_mii_frame frame; + sc = device_get_softc(dev); + bzero((char *)&frame, sizeof(frame)); - frame.mii_phyaddr = sc->xl_phy_addr; + frame.mii_phyaddr = phy; frame.mii_regaddr = reg; xl_mii_readreg(sc, &frame); return(frame.mii_data); } -static void xl_phy_writereg(sc, reg, data) - struct xl_softc *sc; - int reg; - int data; +static int xl_miibus_writereg(dev, phy, reg, data) + device_t dev; + int phy, reg, data; { + struct xl_softc *sc; struct xl_mii_frame frame; + sc = device_get_softc(dev); + bzero((char *)&frame, sizeof(frame)); - frame.mii_phyaddr = sc->xl_phy_addr; + frame.mii_phyaddr = phy; frame.mii_regaddr = reg; frame.mii_data = data; xl_mii_writereg(sc, &frame); + return(0); +} + +static void xl_miibus_statchg(dev) + device_t dev; +{ + struct xl_softc *sc; + struct mii_data *mii; + + + sc = device_get_softc(dev); + mii = device_get_softc(sc->xl_miibus); + + /* Set ASIC's duplex mode to match the PHY. */ + XL_SEL_WIN(3); + if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) + CSR_WRITE_1(sc, XL_W3_MAC_CTRL, XL_MACCTRL_DUPLEX); + else + CSR_WRITE_1(sc, XL_W3_MAC_CTRL, + (CSR_READ_1(sc, XL_W3_MAC_CTRL) & ~XL_MACCTRL_DUPLEX)); + + return; +} + +/* + * Special support for the 3c905B-COMBO. This card has 10/100 support + * plus BNC and AUI ports. This means we will have both an miibus attached + * plus some non-MII media settings. In order to allow this, we have to + * add the extra media to the miibus's ifmedia struct, but we can't do + * that during xl_attach() because the miibus hasn't been attached yet. + * So instead, we wait until the miibus probe/attach is done, at which + * point we will get a callback telling is that it's safe to add our + * extra media. + */ +static void xl_miibus_mediainit(dev) + device_t dev; +{ + struct xl_softc *sc; + struct mii_data *mii; + struct ifmedia *ifm; + + sc = device_get_softc(dev); + mii = device_get_softc(sc->xl_miibus); + ifm = &mii->mii_media; + + if (sc->xl_media & (XL_MEDIAOPT_AUI|XL_MEDIAOPT_10FL)) { + /* + * Check for a 10baseFL board in disguise. + */ + if (sc->xl_type == XL_TYPE_905B && + sc->xl_media == XL_MEDIAOPT_10FL) { + if (bootverbose) + printf("xl%d: found 10baseFL\n", sc->xl_unit); + ifmedia_add(ifm, IFM_ETHER|IFM_10_FL, 0, NULL); + ifmedia_add(ifm, IFM_ETHER|IFM_10_FL|IFM_HDX, 0, NULL); + if (sc->xl_caps & XL_CAPS_FULL_DUPLEX) + ifmedia_add(ifm, + IFM_ETHER|IFM_10_FL|IFM_FDX, 0, NULL); + } else { + if (bootverbose) + printf("xl%d: found AUI\n", sc->xl_unit); + ifmedia_add(ifm, IFM_ETHER|IFM_10_5, 0, NULL); + } + } + + if (sc->xl_media & XL_MEDIAOPT_BNC) { + if (bootverbose) + printf("xl%d: found BNC\n", sc->xl_unit); + ifmedia_add(ifm, IFM_ETHER|IFM_10_2, 0, NULL); + } + return; } @@ -783,369 +840,23 @@ static void xl_testpacket(sc) } #endif -/* - * Initiate an autonegotiation session. - */ -static void xl_autoneg_xmit(sc) +static void xl_setcfg(sc) struct xl_softc *sc; { - u_int16_t phy_sts; u_int32_t icfg; - xl_reset(sc); XL_SEL_WIN(3); icfg = CSR_READ_4(sc, XL_W3_INTERNAL_CFG); icfg &= ~XL_ICFG_CONNECTOR_MASK; if (sc->xl_media & XL_MEDIAOPT_MII || - sc->xl_media & XL_MEDIAOPT_BT4) + sc->xl_media & XL_MEDIAOPT_BT4) icfg |= (XL_XCVR_MII << XL_ICFG_CONNECTOR_BITS); if (sc->xl_media & XL_MEDIAOPT_BTX) icfg |= (XL_XCVR_AUTO << XL_ICFG_CONNECTOR_BITS); - if (sc->xl_media & XL_MEDIAOPT_BFX) - icfg |= (XL_XCVR_100BFX << XL_ICFG_CONNECTOR_BITS); - CSR_WRITE_4(sc, XL_W3_INTERNAL_CFG, icfg); - CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP); - - xl_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET); - DELAY(500); - while(xl_phy_readreg(sc, XL_PHY_GENCTL) - & PHY_BMCR_RESET); - - phy_sts = xl_phy_readreg(sc, PHY_BMCR); - phy_sts |= PHY_BMCR_AUTONEGENBL|PHY_BMCR_AUTONEGRSTR; - xl_phy_writereg(sc, PHY_BMCR, phy_sts); - - return; -} - -/* - * Invoke autonegotiation on a PHY. Also used with the 3Com internal - * autoneg logic which is mapped onto the MII. - */ -static void xl_autoneg_mii(sc, flag, verbose) - struct xl_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 = xl_phy_readreg(sc, PHY_BMSR); - if (!(phy_sts & PHY_BMSR_CANAUTONEG)) { - if (verbose) - printf("xl%d: autonegotiation not supported\n", - sc->xl_unit); - ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX; - media = xl_phy_readreg(sc, PHY_BMCR); - media &= ~PHY_BMCR_SPEEDSEL; - media &= ~PHY_BMCR_DUPLEX; - xl_phy_writereg(sc, PHY_BMCR, media); - CSR_WRITE_1(sc, XL_W3_MAC_CTRL, - (CSR_READ_1(sc, XL_W3_MAC_CTRL) & - ~XL_MACCTRL_DUPLEX)); - return; - } -#endif - - switch (flag) { - case XL_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. - */ - xl_autoneg_xmit(sc); - DELAY(5000000); - break; - case XL_FLAG_SCHEDDELAY: - /* - * Wait for the transmitter to go idle before starting - * an autoneg session, otherwise xl_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->xl_cdata.xl_tx_head != NULL) { - sc->xl_want_auto = 1; - return; - } - xl_autoneg_xmit(sc); - ifp->if_timer = 5; - sc->xl_autoneg = 1; - sc->xl_want_auto = 0; - return; - break; - case XL_FLAG_DELAYTIMEO: - ifp->if_timer = 0; - sc->xl_autoneg = 0; - break; - default: - printf("xl%d: invalid autoneg flag: %d\n", sc->xl_unit, flag); - return; - } - - if (xl_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_AUTONEGCOMP) { - if (verbose) - printf("xl%d: autoneg complete, ", sc->xl_unit); - phy_sts = xl_phy_readreg(sc, PHY_BMSR); - } else { - if (verbose) - printf("xl%d: autoneg not complete, ", sc->xl_unit); - } - - media = xl_phy_readreg(sc, PHY_BMCR); - - /* Link is good. Report modes and set duplex mode. */ - if (xl_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT) { - if (verbose) - printf("link status good "); - advert = xl_phy_readreg(sc, XL_PHY_ANAR); - ability = xl_phy_readreg(sc, XL_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"); - } - - /* Set ASIC's duplex mode to match the PHY. */ - XL_SEL_WIN(3); - if (media & PHY_BMCR_DUPLEX) - CSR_WRITE_1(sc, XL_W3_MAC_CTRL, XL_MACCTRL_DUPLEX); - else - CSR_WRITE_1(sc, XL_W3_MAC_CTRL, - (CSR_READ_1(sc, XL_W3_MAC_CTRL) & - ~XL_MACCTRL_DUPLEX)); - xl_phy_writereg(sc, PHY_BMCR, media); - } else { - if (verbose) - printf("no carrier (forcing half-duplex, 10Mbps)\n"); - ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX; - media &= ~PHY_BMCR_SPEEDSEL; - media &= ~PHY_BMCR_DUPLEX; - xl_phy_writereg(sc, PHY_BMCR, media); - CSR_WRITE_1(sc, XL_W3_MAC_CTRL, - (CSR_READ_1(sc, XL_W3_MAC_CTRL) & - ~XL_MACCTRL_DUPLEX)); - } - - xl_init(sc); - - if (sc->xl_tx_pend) { - sc->xl_autoneg = 0; - sc->xl_tx_pend = 0; - xl_start(ifp); - } - - return; -} - -static void xl_getmode_mii(sc) - struct xl_softc *sc; -{ - u_int16_t bmsr; - struct ifnet *ifp; - - ifp = &sc->arpcom.ac_if; - - bmsr = xl_phy_readreg(sc, PHY_BMSR); - if (bootverbose) - printf("xl%d: PHY status word: %x\n", sc->xl_unit, bmsr); - - /* fallback */ - sc->ifmedia.ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX; - - if (bmsr & PHY_BMSR_10BTHALF) { - if (bootverbose) - printf("xl%d: 10Mbps half-duplex mode supported\n", - sc->xl_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("xl%d: 10Mbps full-duplex mode supported\n", - sc->xl_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("xl%d: 100Mbps half-duplex mode supported\n", - sc->xl_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("xl%d: 100Mbps full-duplex mode supported\n", - sc->xl_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("xl%d: 100baseT4 mode supported\n", sc->xl_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("xl%d: forcing on autoneg support for BT4\n", - sc->xl_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("xl%d: autoneg supported\n", sc->xl_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 xl_setmode_mii(sc, media) - struct xl_softc *sc; - int media; -{ - u_int16_t bmcr; - u_int32_t icfg; - struct ifnet *ifp; - - ifp = &sc->arpcom.ac_if; - /* - * If an autoneg session is in progress, stop it. - */ - if (sc->xl_autoneg) { - printf("xl%d: canceling autoneg session\n", sc->xl_unit); - ifp->if_timer = sc->xl_autoneg = sc->xl_want_auto = 0; - bmcr = xl_phy_readreg(sc, PHY_BMCR); - bmcr &= ~PHY_BMCR_AUTONEGENBL; - xl_phy_writereg(sc, PHY_BMCR, bmcr); - } - - printf("xl%d: selecting MII, ", sc->xl_unit); - - XL_SEL_WIN(3); - icfg = CSR_READ_4(sc, XL_W3_INTERNAL_CFG); - icfg &= ~XL_ICFG_CONNECTOR_MASK; - if (sc->xl_media & XL_MEDIAOPT_MII || sc->xl_media & XL_MEDIAOPT_BT4) - icfg |= (XL_XCVR_MII << XL_ICFG_CONNECTOR_BITS); - if (sc->xl_media & XL_MEDIAOPT_BTX) { - if (sc->xl_type == XL_TYPE_905B) - icfg |= (XL_XCVR_AUTO << XL_ICFG_CONNECTOR_BITS); - else - icfg |= (XL_XCVR_MII << XL_ICFG_CONNECTOR_BITS); - } CSR_WRITE_4(sc, XL_W3_INTERNAL_CFG, icfg); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP); - if (IFM_SUBTYPE(media) == IFM_100_FX) { - icfg |= (XL_XCVR_100BFX << XL_ICFG_CONNECTOR_BITS); - CSR_WRITE_4(sc, XL_W3_INTERNAL_CFG, icfg); - return; - } - - bmcr = xl_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; - XL_SEL_WIN(3); - CSR_WRITE_1(sc, XL_W3_MAC_CTRL, XL_MACCTRL_DUPLEX); - } else { - printf("half duplex\n"); - bmcr &= ~PHY_BMCR_DUPLEX; - XL_SEL_WIN(3); - CSR_WRITE_1(sc, XL_W3_MAC_CTRL, - (CSR_READ_1(sc, XL_W3_MAC_CTRL) & ~XL_MACCTRL_DUPLEX)); - } - - xl_phy_writereg(sc, PHY_BMCR, bmcr); - return; } @@ -1301,7 +1012,7 @@ static int xl_probe(dev) * This routine is a kludge to work around possible hardware faults * or manufacturing defects that can cause the media options register * (or reset options register, as it's called for the first generation - * 3cx90x adapters) to return an incorrect result. I have encountered + * 3c90x adapters) to return an incorrect result. I have encountered * one Dell Latitude laptop docking station with an integrated 3c905-TX * which doesn't have any of the 'mediaopt' bits set. This screws up * the attach routine pretty badly because it doesn't know what media @@ -1425,15 +1136,12 @@ static int xl_attach(dev) int media = IFM_ETHER|IFM_100_TX|IFM_FDX; unsigned int round; caddr_t roundptr; - struct xl_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 xl_softc)); /* * If this is a 3c905B, we have to check one extra thing. @@ -1626,76 +1334,27 @@ static int xl_attach(dev) if (sc->xl_media & XL_MEDIAOPT_MII || sc->xl_media & XL_MEDIAOPT_BTX || sc->xl_media & XL_MEDIAOPT_BT4) { - /* - * In theory I shouldn't need this, but... if this - * card supports an MII, either an external one or - * an internal fake one, select it in the internal - * config register before trying to probe it. - */ - u_int32_t icfg; - - XL_SEL_WIN(3); - icfg = CSR_READ_4(sc, XL_W3_INTERNAL_CFG); - icfg &= ~XL_ICFG_CONNECTOR_MASK; - if (sc->xl_media & XL_MEDIAOPT_MII || - sc->xl_media & XL_MEDIAOPT_BT4) - icfg |= (XL_XCVR_MII << XL_ICFG_CONNECTOR_BITS); - if (sc->xl_media & XL_MEDIAOPT_BTX) - icfg |= (XL_XCVR_AUTO << XL_ICFG_CONNECTOR_BITS); - if (sc->xl_media & XL_MEDIAOPT_BFX) - icfg |= (XL_XCVR_100BFX << XL_ICFG_CONNECTOR_BITS); - CSR_WRITE_4(sc, XL_W3_INTERNAL_CFG, icfg); - if (bootverbose) - printf("xl%d: probing for a PHY\n", sc->xl_unit); - for (i = XL_PHYADDR_MIN; i < XL_PHYADDR_MAX + 1; i++) { - if (bootverbose) - printf("xl%d: checking address: %d\n", - sc->xl_unit, i); - sc->xl_phy_addr = i; - xl_phy_writereg(sc, XL_PHY_GENCTL, PHY_BMCR_RESET); - DELAY(500); - while(xl_phy_readreg(sc, XL_PHY_GENCTL) - & PHY_BMCR_RESET); - if ((phy_sts = xl_phy_readreg(sc, XL_PHY_GENSTS))) - break; - } - if (phy_sts) { - phy_vid = xl_phy_readreg(sc, XL_PHY_VENID); - phy_did = xl_phy_readreg(sc, XL_PHY_DEVID); - if (bootverbose) - printf("xl%d: found PHY at address %d, ", - sc->xl_unit, sc->xl_phy_addr); - if (bootverbose) - printf("vendor id: %x device id: %x\n", - phy_vid, phy_did); - p = xl_phys; - while(p->xl_vid) { - if (phy_vid == p->xl_vid && - (phy_did | 0x000F) == p->xl_did) { - sc->xl_pinfo = p; - break; - } - p++; - } - if (sc->xl_pinfo == NULL) - sc->xl_pinfo = &xl_phys[PHY_UNKNOWN]; - if (bootverbose) - printf("xl%d: PHY type: %s\n", - sc->xl_unit, sc->xl_pinfo->xl_name); - } else { - printf("xl%d: MII without any phy!\n", sc->xl_unit); + printf("xl%d: found MII/AUTO\n", sc->xl_unit); + xl_setcfg(sc); + if (mii_phy_probe(dev, &sc->xl_miibus, + xl_ifmedia_upd, xl_ifmedia_sts)) { + printf("xl%d: no PHY found!\n", sc->xl_unit); bus_teardown_intr(dev, sc->xl_irq, sc->xl_intrhand); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->xl_irq); bus_release_resource(dev, XL_RES, XL_RID, sc->xl_res); + free(sc->xl_ldata_ptr, M_DEVBUF); error = ENXIO; goto fail; } + + goto done; } /* * Do ifmedia setup. */ + ifmedia_init(&sc->ifmedia, 0, xl_ifmedia_upd, xl_ifmedia_sts); if (sc->xl_media & XL_MEDIAOPT_BT) { @@ -1735,26 +1394,6 @@ static int xl_attach(dev) ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_2, 0, NULL); } - /* - * Technically we could use xl_getmode_mii() to scan the - * modes, but the built-in BTX mode on the 3c905B implies - * 10/100 full/half duplex support anyway, so why not just - * do it and get it over with. - */ - if (sc->xl_media & XL_MEDIAOPT_BTX) { - if (bootverbose) - printf("xl%d: found 100baseTX\n", sc->xl_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); - if (sc->xl_caps & XL_CAPS_FULL_DUPLEX) - ifmedia_add(&sc->ifmedia, - IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); - if (sc->xl_pinfo != NULL) - ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL); - } - if (sc->xl_media & XL_MEDIAOPT_BFX) { if (bootverbose) printf("xl%d: found 100baseFX\n", sc->xl_unit); @@ -1762,16 +1401,6 @@ static int xl_attach(dev) ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_FX, 0, NULL); } - /* - * If there's an MII, we have to probe its modes - * separately. - */ - if (sc->xl_media & XL_MEDIAOPT_MII || sc->xl_media & XL_MEDIAOPT_BT4) { - if (bootverbose) - printf("xl%d: found MII\n", sc->xl_unit); - xl_getmode_mii(sc); - } - /* Choose a default media. */ switch(sc->xl_xcvr) { case XL_XCVR_10BT: @@ -1793,35 +1422,9 @@ static int xl_attach(dev) xl_setmode(sc, media); break; case XL_XCVR_AUTO: -#ifdef XL_BACKGROUND_AUTONEG - xl_autoneg_mii(sc, XL_FLAG_SCHEDDELAY, 1); - xl_stop(sc); -#else - if (cold) { - xl_autoneg_mii(sc, XL_FLAG_FORCEDELAY, 1); - xl_stop(sc); - } else { - xl_init(sc); - xl_autoneg_mii(sc, XL_FLAG_SCHEDDELAY, 1); - } -#endif - media = sc->ifmedia.ifm_media; - break; case XL_XCVR_100BTX: case XL_XCVR_MII: -#ifdef XL_BACKGROUND_AUTONEG - xl_autoneg_mii(sc, XL_FLAG_SCHEDDELAY, 1); - xl_stop(sc); -#else - if (cold) { - xl_autoneg_mii(sc, XL_FLAG_FORCEDELAY, 1); - xl_stop(sc); - } else { - xl_init(sc); - xl_autoneg_mii(sc, XL_FLAG_SCHEDDELAY, 1); - } -#endif - media = sc->ifmedia.ifm_media; + /* Chosen by miibus */ break; case XL_XCVR_100BFX: media = IFM_ETHER|IFM_100_FX; @@ -1837,7 +1440,10 @@ static int xl_attach(dev) break; } - ifmedia_set(&sc->ifmedia, media); + if (sc->xl_miibus == NULL) + ifmedia_set(&sc->ifmedia, media); + +done: /* * Call MI attach routines. @@ -1869,12 +1475,18 @@ static int xl_detach(dev) xl_stop(sc); if_detach(ifp); + /* Delete any miibus and phy devices attached to this interface */ + if (sc->xl_miibus != NULL) { + bus_generic_detach(dev); + device_delete_child(dev, sc->xl_miibus); + } + bus_teardown_intr(dev, sc->xl_irq, sc->xl_intrhand); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->xl_irq); bus_release_resource(dev, XL_RES, XL_RID, sc->xl_res); - free(sc->xl_ldata_ptr, M_DEVBUF); ifmedia_removeall(&sc->ifmedia); + free(sc->xl_ldata_ptr, M_DEVBUF); splx(s); @@ -1990,7 +1602,7 @@ static void xl_rxeof(sc) struct ifnet *ifp; struct xl_chain_onefrag *cur_rx; int total_len = 0; - u_int32_t rxstat; + u_int16_t rxstat; ifp = &sc->arpcom.ac_if; @@ -2157,8 +1769,6 @@ static void xl_txeof(sc) if (sc->xl_cdata.xl_tx_head == NULL) { ifp->if_flags &= ~IFF_OACTIVE; sc->xl_cdata.xl_tx_tail = NULL; - if (sc->xl_want_auto) - xl_autoneg_mii(sc, XL_FLAG_SCHEDDELAY, 1); } else { if (CSR_READ_4(sc, XL_DMACTL) & XL_DMACTL_DOWN_STALLED || !CSR_READ_4(sc, XL_DOWNLIST_PTR)) { @@ -2290,11 +1900,14 @@ static void xl_stats_update(xsc) struct xl_stats xl_stats; u_int8_t *p; int i; + struct mii_data *mii = NULL; bzero((char *)&xl_stats, sizeof(struct xl_stats)); sc = xsc; ifp = &sc->arpcom.ac_if; + if (sc->xl_miibus != NULL) + mii = device_get_softc(sc->xl_miibus); p = (u_int8_t *)&xl_stats; @@ -2319,6 +1932,9 @@ static void xl_stats_update(xsc) XL_SEL_WIN(4); CSR_READ_1(sc, XL_W4_BADSSD); + if (mii != NULL) + mii_tick(mii); + XL_SEL_WIN(7); if (!sc->xl_stats_no_timeout) @@ -2420,11 +2036,6 @@ static void xl_start(ifp) sc = ifp->if_softc; - if (sc->xl_autoneg) { - sc->xl_tx_pend = 1; - return; - } - /* * Check for an available queue slot. If there are none, * punt. @@ -2543,29 +2154,20 @@ static void xl_init(xsc) struct ifnet *ifp = &sc->arpcom.ac_if; int s, i; u_int16_t rxfilt = 0; - u_int16_t phy_bmcr = 0; - - if (sc->xl_autoneg) - return; + struct mii_data *mii = NULL; s = splimp(); /* - * XXX Hack for the 3c905B: the built-in autoneg logic's state - * gets reset by xl_init() when we don't want it to. Try - * to preserve it. (For 3c905 cards with real external PHYs, - * the BMCR register doesn't change, but this doesn't hurt.) - */ - if (sc->xl_pinfo != NULL) - phy_bmcr = xl_phy_readreg(sc, PHY_BMCR); - - /* * Cancel pending I/O and free all RX/TX buffers. */ xl_stop(sc); xl_wait(sc); + if (sc->xl_miibus != NULL) + mii = device_get_softc(sc->xl_miibus); + /* Init our MAC address */ XL_SEL_WIN(2); for (i = 0; i < ETHER_ADDR_LEN; i++) { @@ -2706,9 +2308,8 @@ static void xl_init(xsc) CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_ENABLE); CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_ENABLE); - /* Restore state of BMCR */ - if (sc->xl_pinfo != NULL) - xl_phy_writereg(sc, PHY_BMCR, phy_bmcr); + if (mii != NULL) + mii_mediachg(mii); /* Select window 7 for normal operations. */ XL_SEL_WIN(7); @@ -2730,13 +2331,16 @@ static int xl_ifmedia_upd(ifp) struct ifnet *ifp; { struct xl_softc *sc; - struct ifmedia *ifm; + struct ifmedia *ifm = NULL; + struct mii_data *mii = NULL; sc = ifp->if_softc; - ifm = &sc->ifmedia; - - if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) - return(EINVAL); + if (sc->xl_miibus != NULL) + mii = device_get_softc(sc->xl_miibus); + if (mii == NULL) + ifm = &sc->ifmedia; + else + ifm = &mii->mii_media; switch(IFM_SUBTYPE(ifm->ifm_media)) { case IFM_100_FX: @@ -2751,10 +2355,9 @@ static int xl_ifmedia_upd(ifp) if (sc->xl_media & XL_MEDIAOPT_MII || sc->xl_media & XL_MEDIAOPT_BTX || sc->xl_media & XL_MEDIAOPT_BT4) { - if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) - xl_autoneg_mii(sc, XL_FLAG_SCHEDDELAY, 1); - else - xl_setmode_mii(sc, ifm->ifm_media); + xl_setcfg(sc); + if (mii != NULL) + mii_mediachg(mii); } else { xl_setmode(sc, ifm->ifm_media); } @@ -2770,10 +2373,12 @@ static void xl_ifmedia_sts(ifp, ifmr) struct ifmediareq *ifmr; { struct xl_softc *sc; - u_int16_t advert = 0, ability = 0; u_int32_t icfg; + struct mii_data *mii = NULL; sc = ifp->if_softc; + if (sc->xl_miibus != NULL) + mii = device_get_softc(sc->xl_miibus); XL_SEL_WIN(3); icfg = CSR_READ_4(sc, XL_W3_INTERNAL_CFG) & XL_ICFG_CONNECTOR_MASK; @@ -2810,36 +2415,10 @@ static void xl_ifmedia_sts(ifp, ifmr) case XL_XCVR_100BTX: case XL_XCVR_AUTO: case XL_XCVR_MII: - if (!(xl_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_AUTONEGENBL)) { - if (xl_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; - XL_SEL_WIN(3); - if (CSR_READ_2(sc, XL_W3_MAC_CTRL) & - XL_MACCTRL_DUPLEX) - ifmr->ifm_active |= IFM_FDX; - else - ifmr->ifm_active |= IFM_HDX; - break; - } - ability = xl_phy_readreg(sc, XL_PHY_LPAR); - advert = xl_phy_readreg(sc, XL_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; + if (mii != NULL) { + mii_pollstat(mii); + ifmr->ifm_active = mii->mii_media_active; + ifmr->ifm_status = mii->mii_media_status; } break; case XL_XCVR_100BFX: @@ -2861,6 +2440,7 @@ static int xl_ioctl(ifp, command, data) struct xl_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *) data; int s, error = 0; + struct mii_data *mii = NULL; s = splimp(); @@ -2889,7 +2469,14 @@ static int xl_ioctl(ifp, command, data) break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); + if (sc->xl_miibus != NULL) + mii = device_get_softc(sc->xl_miibus); + if (mii == NULL) + error = ifmedia_ioctl(ifp, ifr, + &sc->ifmedia, command); + else + error = ifmedia_ioctl(ifp, ifr, + &mii->mii_media, command); break; default: error = EINVAL; @@ -2909,13 +2496,6 @@ static void xl_watchdog(ifp) sc = ifp->if_softc; - if (sc->xl_autoneg) { - xl_autoneg_mii(sc, XL_FLAG_DELAYTIMEO, 1); - if (!(ifp->if_flags & IFF_UP)) - xl_stop(sc); - return; - } - ifp->if_oerrors++; XL_SEL_WIN(4); status = CSR_READ_2(sc, XL_W4_MEDIA_STATUS); diff --git a/sys/pci/if_xlreg.h b/sys/pci/if_xlreg.h index b50f068..3bdf32d 100644 --- a/sys/pci/if_xlreg.h +++ b/sys/pci/if_xlreg.h @@ -532,10 +532,6 @@ struct xl_mii_frame { #define XL_TYPE_905B 1 #define XL_TYPE_90X 2 -#define XL_FLAG_FORCEDELAY 1 -#define XL_FLAG_SCHEDDELAY 2 -#define XL_FLAG_DELAYTIMEO 3 - struct xl_softc { struct arpcom arpcom; /* interface info */ struct ifmedia ifmedia; /* media info */ @@ -544,17 +540,13 @@ struct xl_softc { void *xl_intrhand; struct resource *xl_irq; struct resource *xl_res; + device_t xl_miibus; struct xl_type *xl_info; /* 3Com adapter info */ - struct xl_type *xl_pinfo; /* phy info */ u_int8_t xl_unit; /* interface number */ u_int8_t xl_type; - u_int8_t xl_phy_addr; /* PHY address */ u_int32_t xl_xcvr; u_int16_t xl_media; u_int16_t xl_caps; - u_int8_t xl_tx_pend; /* TX pending */ - u_int8_t xl_want_auto; - u_int8_t xl_autoneg; u_int8_t xl_stats_no_timeout; u_int16_t xl_tx_thresh; caddr_t xl_ldata_ptr; @@ -633,50 +625,6 @@ struct xl_stats { #define TC_DEVICEID_HURRICANE_SOHO100TX 0x7646 /* - * Texas Instruments PHY identifiers - * - * The ThunderLAN manual has a curious and confusing error in it. - * In chapter 7, which describes PHYs, it says that TI PHYs have - * the following ID codes, where xx denotes a revision: - * - * 0x4000501xx internal 10baseT PHY - * 0x4000502xx TNETE211 100VG-AnyLan PMI - * - * The problem here is that these are not valid 32-bit hex numbers: - * there's one digit too many. My guess is that they mean the internal - * 10baseT PHY is 0x4000501x and the TNETE211 is 0x4000502x since these - * are the only numbers that make sense. - */ -#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. @@ -713,107 +661,6 @@ struct xl_stats { #define XL_PME_EN 0x0010 #define XL_PME_STATUS 0x8000 -#define PHY_UNKNOWN 6 - -#define XL_PHYADDR_MIN 0x00 -#define XL_PHYADDR_MAX 0x1F - -#define XL_PHY_GENCTL 0x00 -#define XL_PHY_GENSTS 0x01 -#define XL_PHY_VENID 0x02 -#define XL_PHY_DEVID 0x03 -#define XL_PHY_ANAR 0x04 -#define XL_PHY_LPAR 0x05 -#define XL_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 0x00 -#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 0x01 -#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) |