From 9b84774432ee6bff5a53f80a4dbca7b2a48dd9ee Mon Sep 17 00:00:00 2001 From: Jason Wright Date: Wed, 18 Nov 1998 20:11:34 +0000 Subject: dev/mii'fy RTL driver and add new phy driver for the 8139 internal phy --- sys/dev/mii/files.mii | 6 +- sys/dev/mii/rlphy.c | 217 ++++++++++ sys/dev/pci/if_rl.c | 1044 ++++++------------------------------------------ sys/dev/pci/if_rlreg.h | 46 +-- 4 files changed, 345 insertions(+), 968 deletions(-) create mode 100644 sys/dev/mii/rlphy.c diff --git a/sys/dev/mii/files.mii b/sys/dev/mii/files.mii index d7929a20a23..13a5a12c5f5 100644 --- a/sys/dev/mii/files.mii +++ b/sys/dev/mii/files.mii @@ -1,4 +1,4 @@ -# $OpenBSD: files.mii,v 1.2 1998/11/11 19:34:45 jason Exp $ +# $OpenBSD: files.mii,v 1.3 1998/11/18 20:11:31 jason Exp $ # $NetBSD: files.mii,v 1.13 1998/11/05 00:36:48 thorpej Exp $ file dev/mii/mii.c mii @@ -29,6 +29,10 @@ device exphy: mii_phy, ukphy_subr attach exphy at mii file dev/mii/exphy.c exphy +device rlphy: mii_phy, ukphy_subr +attach rlphy at mii +file dev/mii/rlphy.c rlphy + device lxtphy: mii_phy attach lxtphy at mii file dev/mii/lxtphy.c lxtphy diff --git a/sys/dev/mii/rlphy.c b/sys/dev/mii/rlphy.c new file mode 100644 index 00000000000..061ece97d6f --- /dev/null +++ b/sys/dev/mii/rlphy.c @@ -0,0 +1,217 @@ +/* $OpenBSD: rlphy.c,v 1.1 1998/11/18 20:11:31 jason Exp $ */ + +/* + * Copyright (c) 1998 Jason L. Wright (jason@thought.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Jason L. Wright + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Driver for the internal PHY found on RTL8139 based nics, based + * on drivers for the 'exphy' (Internal 3Com phys) and 'nsphy' + * (National Semiconductor DP83840). + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +int rlphymatch __P((struct device *, void *, void *)); +void rlphyattach __P((struct device *, struct device *, void *)); + +struct cfattach rlphy_ca = { + sizeof(struct mii_softc), rlphymatch, rlphyattach +}; + +struct cfdriver rlphy_cd = { + NULL, "rlphy", DV_DULL +}; + +int rlphy_service __P((struct mii_softc *, struct mii_data *, int)); +void rlphy_reset __P((struct mii_softc *)); + +int +rlphymatch(parent, match, aux) + struct device *parent; + void *match; + void *aux; +{ + struct mii_attach_args *ma = aux; + + if (MII_OUI(ma->mii_id1, ma->mii_id2) != 0 || + MII_MODEL(ma->mii_id2) != 0) + return (0); + + if (strcmp(parent->dv_cfdata->cf_driver->cd_name, "rl") != 0) + return (0); + + /* + * A "real" phy should get preference, but on the 8139 there + * is no phyid register. + */ + return (5); +} + +void +rlphyattach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct mii_softc *sc = (struct mii_softc *)self; + struct mii_attach_args *ma = aux; + struct mii_data *mii = ma->mii_data; + + printf(": RTL internal phy\n"); + + sc->mii_inst = mii->mii_instance; + sc->mii_phy = ma->mii_phyno; + sc->mii_service = rlphy_service; + sc->mii_pdata = mii; + + ifmedia_add(&mii->mii_media, + IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), + BMCR_ISO, NULL); + ifmedia_add(&mii->mii_media, + IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst), + BMCR_LOOP | BMCR_S100, NULL); + + rlphy_reset(sc); + + sc->mii_capabilities = + PHY_READ(sc, MII_BMSR) & ma->mii_capmask; + printf("%s: ", sc->mii_dev.dv_xname); + if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) + printf("no media present"); + else + mii_add_media(mii, sc->mii_capabilities, + sc->mii_inst); + printf("\n"); +} + +int +rlphy_service(sc, mii, cmd) + struct mii_softc *sc; + struct mii_data *mii; + int cmd; +{ + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; + + /* + * Can't isolate the RTL8139 phy, so it has to be the only one. + */ + if (IFM_INST(ife->ifm_media) != sc->mii_inst) + panic("rlphy_service: attempt to isolate phy"); + + switch (cmd) { + case MII_POLLSTAT: + break; + + case MII_MEDIACHG: + /* + * If the interface is not up, don't do anything. + */ + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) + break; + + switch (IFM_SUBTYPE(ife->ifm_media)) { + case IFM_AUTO: + /* + * If we're already in auto mode, just return. + */ + if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) + return (0); + (void) mii_phy_auto(sc); + break; + case IFM_100_T4: + /* + * XXX Not supported as a manual setting right now. + */ + return (EINVAL); + default: + /* + * BMCR data is stored in the ifmedia entry. + */ + PHY_WRITE(sc, MII_ANAR, + mii_anar(ife->ifm_media)); + PHY_WRITE(sc, MII_BMCR, ife->ifm_data); + } + break; + + case MII_TICK: + /* + * Only used for autonegotiation. + */ + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + return (0); + + /* + * Is the interface even up? + */ + if ((mii->mii_ifp->if_flags & IFF_UP) == 0) + return (0); + + /* + * The RTL8139 autonegotiation doesn't need to be + * kicked; it continues in the background. + */ + break; + } + + /* Update the media status. */ + ukphy_status(sc); + + /* Callback if something changed. */ + if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { + (*mii->mii_statchg)(sc->mii_dev.dv_parent); + sc->mii_active = mii->mii_media_active; + } + return (0); +} + +void +rlphy_reset(sc) + struct mii_softc *sc; +{ + mii_phy_reset(sc); + + /* + * XXX The RTL8139 doesn't set the BMCR properly + * XXX after reset, which breaks autoneg. + */ + PHY_WRITE(sc, MII_BMCR, BMCR_S100 | BMCR_AUTOEN | BMCR_FDX); +} diff --git a/sys/dev/pci/if_rl.c b/sys/dev/pci/if_rl.c index 830fbc56b94..1b92724bc39 100644 --- a/sys/dev/pci/if_rl.c +++ b/sys/dev/pci/if_rl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_rl.c,v 1.3 1998/11/16 15:44:36 jason Exp $ */ +/* $OpenBSD: if_rl.c,v 1.4 1998/11/18 20:11:32 jason Exp $ */ /* * Copyright (c) 1997, 1998 @@ -103,17 +103,8 @@ #include #include #include -#ifdef __OpenBSD__ #include -#endif - -#ifdef __FreeBSD__ -#include -#include -#include -#endif -#ifdef __OpenBSD__ #include #include #include @@ -126,31 +117,22 @@ #include #endif -#endif - #include #if NBPFILTER > 0 #include #endif -#include - #include /* for vtophys */ #include /* for vtophys */ -#ifdef __FreeBSD__ -#include /* for DELAY */ -#include -#include -#endif - -#ifdef __OpenBSD__ #include #include + +#include +#include #include #include #include -#endif /* * Default to using PIO access for this driver. On SMP systems, @@ -162,31 +144,7 @@ */ #define RL_USEIOSPACE -#ifdef __FreeBSD_ -#include -#else #include -#endif - -#if !defined(lint) && defined(__FreeBSD__) -static char rcsid[] = - "$FreeBSD: if_rl.c,v 1.1 1998/10/18 16:24:30 wpaul Exp $"; -#endif - -#ifdef __FreeBSD__ -/* - * Various supported device vendors/types and their names. - */ -static struct rl_type rl_devs[] = { - { RT_VENDORID, RT_DEVICEID_8129, - "RealTek 8129 10/100BaseTX" }, - { RT_VENDORID, RT_DEVICEID_8139, - "RealTek 8139 10/100BaseTX" }, - { RT_VENDORID_ALT, RT_DEVICEID_8139_ALT, - "RealTek 8139 10/100BaseTX" }, - { 0, 0, NULL } -}; -#endif /* * Various supported PHY vendors/types and their names. Note that @@ -194,30 +152,18 @@ static struct rl_type rl_devs[] = { * so failure to positively identify the chip is not a fatal error. */ -static struct rl_type rl_phys[] = { - { TI_PHY_VENDORID, TI_PHY_10BT, "" }, - { TI_PHY_VENDORID, TI_PHY_100VGPMI, "" }, - { NS_PHY_VENDORID, NS_PHY_83840A, ""}, - { LEVEL1_PHY_VENDORID, LEVEL1_PHY_LXT970, "" }, - { INTEL_PHY_VENDORID, INTEL_PHY_82555, "" }, - { SEEQ_PHY_VENDORID, SEEQ_PHY_80220, "" }, - { 0, 0, "" } -}; - -#ifdef __FreeBSD__ -static unsigned long rl_count = 0; -static char *rl_probe __P((pcici_t, pcidi_t)); -static void rl_attach __P((pcici_t, int)); -#endif - -#ifdef __OpenBSD__ - #define bootverbose 0 static int rl_probe __P((struct device *, void *, void *)); static void rl_attach __P((struct device *, struct device *, void *)); static int rl_intr __P((void *)); static void rl_shutdown __P((void *)); -#endif + +/* + * MII glue + */ +static int rl_mii_read __P((struct device *, int, int)); +static void rl_mii_write __P((struct device *, int, int, int)); +static void rl_mii_statchg __P((struct device *)); static int rl_encap __P((struct rl_softc *, struct rl_chain *, struct mbuf * )); @@ -225,17 +171,11 @@ static int rl_encap __P((struct rl_softc *, struct rl_chain *, static void rl_rxeof __P((struct rl_softc *)); static void rl_txeof __P((struct rl_softc *)); static void rl_txeoc __P((struct rl_softc *)); -#ifdef __FreeBSD__ -static void rl_intr __P((void *)); -#endif static void rl_start __P((struct ifnet *)); static int rl_ioctl __P((struct ifnet *, u_long, caddr_t)); static void rl_init __P((void *)); static void rl_stop __P((struct rl_softc *)); static void rl_watchdog __P((struct ifnet *)); -#ifdef __FreeBSD__ -static void rl_shutdown __P((int, void *)); -#endif static int rl_ifmedia_upd __P((struct ifnet *)); static void rl_ifmedia_sts __P((struct ifnet *, struct ifmediareq *)); @@ -248,13 +188,6 @@ static void rl_mii_send __P((struct rl_softc *, u_int32_t, int)); static int rl_mii_readreg __P((struct rl_softc *, struct rl_mii_frame *)); static int rl_mii_writereg __P((struct rl_softc *, struct rl_mii_frame *)); -static u_int16_t rl_phy_readreg __P((struct rl_softc *, int)); -static void rl_phy_writereg __P((struct rl_softc *, u_int16_t, u_int16_t)); - -static void rl_autoneg_xmit __P((struct rl_softc *)); -static void rl_autoneg_mii __P((struct rl_softc *, int, int)); -static void rl_setmode_mii __P((struct rl_softc *, int)); -static void rl_getmode_mii __P((struct rl_softc *)); static u_int8_t rl_calchash __P((u_int8_t *)); static void rl_setmulti __P((struct rl_softc *)); static void rl_reset __P((struct rl_softc *)); @@ -566,85 +499,6 @@ static int rl_mii_writereg(sc, frame) return(0); } -static u_int16_t rl_phy_readreg(sc, reg) - struct rl_softc *sc; - int reg; -{ - struct rl_mii_frame frame; - u_int16_t rval = 0; - u_int16_t rl8139_reg = 0; - - if (sc->rl_type == RL_8139) { - switch(reg) { - case PHY_BMCR: - rl8139_reg = RL_BMCR; - break; - case PHY_BMSR: - rl8139_reg = RL_BMSR; - break; - case PHY_ANAR: - rl8139_reg = RL_ANAR; - break; - case PHY_LPAR: - rl8139_reg = RL_LPAR; - break; - default: - printf("rl%d: bad phy register\n", sc->rl_unit); - return(0); - } - rval = CSR_READ_2(sc, rl8139_reg); - return(rval); - } - - bzero((char *)&frame, sizeof(frame)); - - frame.mii_phyaddr = sc->rl_phy_addr; - frame.mii_regaddr = reg; - rl_mii_readreg(sc, &frame); - - return(frame.mii_data); -} - -static void rl_phy_writereg(sc, reg, data) - struct rl_softc *sc; - u_int16_t reg; - u_int16_t data; -{ - struct rl_mii_frame frame; - u_int16_t rl8139_reg = 0; - - if (sc->rl_type == RL_8139) { - switch(reg) { - case PHY_BMCR: - rl8139_reg = RL_BMCR; - break; - case PHY_BMSR: - rl8139_reg = RL_BMSR; - break; - case PHY_ANAR: - rl8139_reg = RL_ANAR; - break; - case PHY_LPAR: - rl8139_reg = RL_LPAR; - break; - default: - printf("rl%d: bad phy register\n", sc->rl_unit); - return; - } - CSR_WRITE_2(sc, rl8139_reg, data); - } - - bzero((char *)&frame, sizeof(frame)); - - frame.mii_phyaddr = sc->rl_phy_addr; - frame.mii_regaddr = reg; - frame.mii_data = data; - - rl_mii_writereg(sc, &frame); - - return; -} - /* * Calculate CRC of a multicast group address, return the lower 6 bits. */ @@ -682,13 +536,9 @@ static void rl_setmulti(sc) struct ifnet *ifp; int h = 0; u_int32_t hashes[2] = { 0, 0 }; -#ifdef __FreeBSD__ - struct ifmultiaddr *ifma; -#else - struct arpcom *ac = &sc->arpcom; - struct ether_multi *enm; - struct ether_multistep step; -#endif + struct arpcom *ac = &sc->arpcom; + struct ether_multi *enm; + struct ether_multistep step; u_int32_t rxfilt; int mcnt = 0; @@ -709,19 +559,6 @@ static void rl_setmulti(sc) CSR_WRITE_4(sc, RL_MAR4, 0); /* now program new ones */ -#ifdef __FreeBSD__ - for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL; - ifma = ifma->ifma_link.le_next) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - h = rl_calchash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); - if (h < 32) - hashes[0] |= (1 << h); - else - hashes[1] |= (1 << (h - 32)); - mcnt++; - } -#else ETHER_FIRST_MULTI(step, ac, enm); while (enm != NULL) { mcnt++; @@ -733,7 +570,6 @@ static void rl_setmulti(sc) mcnt++; ETHER_NEXT_MULTI(step, enm); } -#endif if (mcnt) rxfilt |= RL_RXCFG_RX_MULTI; @@ -747,298 +583,6 @@ static void rl_setmulti(sc) return; } -/* - * Initiate an autonegotiation session. - */ -static void rl_autoneg_xmit(sc) - struct rl_softc *sc; -{ - u_int16_t phy_sts; - - rl_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET); - DELAY(500); - while(rl_phy_readreg(sc, PHY_BMCR) - & PHY_BMCR_RESET); - - phy_sts = rl_phy_readreg(sc, PHY_BMCR); - phy_sts |= PHY_BMCR_AUTONEGENBL|PHY_BMCR_AUTONEGRSTR; - rl_phy_writereg(sc, PHY_BMCR, phy_sts); - - return; -} - -/* - * Invoke autonegotiation on a PHY. Also used with the 8139 internal - * transceiver. - */ -static void rl_autoneg_mii(sc, flag, verbose) - struct rl_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; - - /* - * The 100baseT4 PHY sometimes 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 = rl_phy_readreg(sc, PHY_BMSR); - if (!(phy_sts & PHY_BMSR_CANAUTONEG)) { - if (verbose) - printf("rl%d: autonegotiation not supported\n", - sc->rl_unit); - return; - } -#endif - - switch (flag) { - case RL_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. - */ - rl_autoneg_xmit(sc); - DELAY(5000000); - break; - case RL_FLAG_SCHEDDELAY: - /* - * Wait for the transmitter to go idle before starting - * an autoneg session, otherwise rl_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->rl_cdata.rl_tx_cnt) { - sc->rl_want_auto = 1; - return; - } - rl_autoneg_xmit(sc); - ifp->if_timer = 5; - sc->rl_autoneg = 1; - sc->rl_want_auto = 0; - return; - break; - case RL_FLAG_DELAYTIMEO: - ifp->if_timer = 0; - sc->rl_autoneg = 0; - break; - default: - printf("rl%d: invalid autoneg flag: %d\n", sc->rl_unit, flag); - return; - } - - if (rl_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_AUTONEGCOMP) { - if (verbose) - printf("rl%d: autoneg complete, ", sc->rl_unit); - phy_sts = rl_phy_readreg(sc, PHY_BMSR); - } else { - if (verbose) - printf("rl%d: autoneg not complete, ", sc->rl_unit); - } - - media = rl_phy_readreg(sc, PHY_BMCR); - - /* Link is good. Report modes and set duplex mode. */ - if (rl_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT) { - if (verbose) - printf("link status good "); - advert = rl_phy_readreg(sc, PHY_ANAR); - ability = rl_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"); - } else { - ifm->ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX; - media &= ~PHY_BMCR_SPEEDSEL; - media &= ~PHY_BMCR_DUPLEX; - printf("(unknown mode! forcing half-duplex, 10Mbps)\n"); - } - - /* Set ASIC's duplex mode to match the PHY. */ - rl_phy_writereg(sc, PHY_BMCR, media); - } else { - if (verbose) - printf("no carrier\n"); - } - - rl_init(sc); - - if (sc->rl_tx_pend) { - sc->rl_autoneg = 0; - sc->rl_tx_pend = 0; - rl_start(ifp); - } - - return; -} - -static void rl_getmode_mii(sc) - struct rl_softc *sc; -{ - u_int16_t bmsr; - struct ifnet *ifp; - - ifp = &sc->arpcom.ac_if; - - bmsr = rl_phy_readreg(sc, PHY_BMSR); - if (bootverbose) - printf("rl%d: PHY status word: %x\n", sc->rl_unit, bmsr); - - /* fallback */ - sc->ifmedia.ifm_media = IFM_ETHER|IFM_10_T|IFM_HDX; - - if (bmsr & PHY_BMSR_10BTHALF) { - if (bootverbose) - printf("rl%d: 10Mbps half-duplex mode supported\n", - sc->rl_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("rl%d: 10Mbps full-duplex mode supported\n", - sc->rl_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("rl%d: 100Mbps half-duplex mode supported\n", - sc->rl_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("rl%d: 100Mbps full-duplex mode supported\n", - sc->rl_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("rl%d: 100baseT4 mode supported\n", sc->rl_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("rl%d: forcing on autoneg support for BT4\n", - sc->rl_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("rl%d: autoneg supported\n", sc->rl_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 rl_setmode_mii(sc, media) - struct rl_softc *sc; - int media; -{ - u_int16_t bmcr; - - printf("rl%d: selecting MII, ", sc->rl_unit); - - bmcr = rl_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; - } - - rl_phy_writereg(sc, PHY_BMCR, bmcr); - - return; -} - static void rl_reset(sc) struct rl_softc *sc; { @@ -1057,253 +601,6 @@ static void rl_reset(sc) return; } -#ifdef __FreeBSD__ -/* - * Probe for a RealTek 8129/8139 chip. Check the PCI vendor and device - * IDs against our list and return a device name if we find a match. - */ -static char * -rl_probe(config_id, device_id) - pcici_t config_id; - pcidi_t device_id; -{ - struct rl_type *t; - - t = rl_devs; - - while(t->rl_name != NULL) { - if ((device_id & 0xFFFF) == t->rl_vid && - ((device_id >> 16) & 0xFFFF) == t->rl_did) { - return(t->rl_name); - } - t++; - } - - return(NULL); -} - -/* - * Attach the interface. Allocate softc structures, do ifmedia - * setup and ethernet/BPF attach. - */ -static void -rl_attach(config_id, unit) - pcici_t config_id; - int unit; -{ - int s, i; -#ifndef RL_USEIOSPACE - vm_offset_t pbase, vbase; -#endif - u_char eaddr[ETHER_ADDR_LEN]; - u_int32_t command; - struct rl_softc *sc; - struct ifnet *ifp; - int media = IFM_ETHER|IFM_100_TX|IFM_FDX; - struct rl_type *p; - u_int16_t phy_vid, phy_did, phy_sts; - u_int16_t rl_did = 0; - - s = splimp(); - - sc = malloc(sizeof(struct rl_softc), M_DEVBUF, M_NOWAIT); - if (sc == NULL) { - printf("rl%d: no memory for softc struct!\n", unit); - return; - } - bzero(sc, sizeof(struct rl_softc)); - - /* - * Handle power management nonsense. - */ - - command = pci_conf_read(config_id, RL_PCI_CAPID) & 0x000000FF; - if (command == 0x01) { - - command = pci_conf_read(config_id, RL_PCI_PWRMGMTCTRL); - if (command & RL_PSTATE_MASK) { - u_int32_t iobase, membase, irq; - - /* Save important PCI config data. */ - iobase = pci_conf_read(config_id, RL_PCI_LOIO); - membase = pci_conf_read(config_id, RL_PCI_LOMEM); - irq = pci_conf_read(config_id, RL_PCI_INTLINE); - - /* Reset the power state. */ - printf("rl%d: chip is is in D%d power mode " - "-- setting to D0\n", unit, command & RL_PSTATE_MASK); - command &= 0xFFFFFFFC; - pci_conf_write(config_id, RL_PCI_PWRMGMTCTRL, command); - - /* Restore PCI config data. */ - pci_conf_write(config_id, RL_PCI_LOIO, iobase); - pci_conf_write(config_id, RL_PCI_LOMEM, membase); - pci_conf_write(config_id, RL_PCI_INTLINE, irq); - } - } - - /* - * Map control/status registers. - */ - command = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG); - command |= (PCIM_CMD_PORTEN|PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); - pci_conf_write(config_id, PCI_COMMAND_STATUS_REG, command); - command = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG); - -#ifdef RL_USEIOSPACE - if (!(command & PCIM_CMD_PORTEN)) { - printf("rl%d: failed to enable I/O ports!\n", unit); - free(sc, M_DEVBUF); - goto fail; - } - - sc->iobase = pci_conf_read(config_id, RL_PCI_LOIO) & 0xFFFFFFFC; -#else - if (!(command & PCIM_CMD_MEMEN)) { - printf("rl%d: failed to enable memory mapping!\n", unit); - goto fail; - } - - if (!pci_map_mem(config_id, RL_PCI_LOMEM, &vbase, &pbase)) { - printf ("rl%d: couldn't map memory\n", unit); - goto fail; - } - sc->csr = (volatile caddr_t)vbase; -#endif - - /* Allocate interrupt */ - if (!pci_map_int(config_id, rl_intr, sc, &net_imask)) { - printf("rl%d: couldn't map interrupt\n", unit); - goto fail; - } - - /* Reset the adapter. */ - rl_reset(sc); - - /* - * Get station address from the EEPROM. - */ - rl_read_eeprom(sc, (caddr_t)&eaddr, RL_EE_EADDR, 3, 0); - - /* - * A RealTek chip was detected. Inform the world. - */ - printf("rl%d: Ethernet address: %6D\n", unit, eaddr, ":"); - - sc->rl_unit = unit; - bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); - - /* - * Now read the exact device type from the EEPROM to find - * out if it's an 8129 or 8139. - */ - rl_read_eeprom(sc, (caddr_t)&rl_did, RL_EE_PCI_DID, 1, 0); - - if (rl_did == RT_DEVICEID_8139) - sc->rl_type = RL_8139; - else if (rl_did == RT_DEVICEID_8129) - sc->rl_type = RL_8129; - else { - printf("rl%d: unknown device ID: %x\n", unit, rl_did); - free(sc, M_DEVBUF); - goto fail; - } - - sc->rl_cdata.rl_rx_buf = contigmalloc(RL_RXBUFLEN + 16, M_DEVBUF, - M_NOWAIT, 0x100000, 0xffffffff, PAGE_SIZE, 0); - - if (sc->rl_cdata.rl_rx_buf == NULL) { - free(sc, M_DEVBUF); - printf("rl%d: no memory for list buffers!\n", unit); - goto fail; - } - - ifp = &sc->arpcom.ac_if; - ifp->if_softc = sc; - ifp->if_unit = unit; - ifp->if_name = "rl"; - ifp->if_mtu = ETHERMTU; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = rl_ioctl; - ifp->if_output = ether_output; - ifp->if_start = rl_start; - ifp->if_watchdog = rl_watchdog; - ifp->if_init = rl_init; - ifp->if_baudrate = 10000000; - - if (sc->rl_type == RL_8129) { - if (bootverbose) - printf("rl%d: probing for a PHY\n", sc->rl_unit); - for (i = RL_PHYADDR_MIN; i < RL_PHYADDR_MAX + 1; i++) { - if (bootverbose) - printf("rl%d: checking address: %d\n", - sc->rl_unit, i); - sc->rl_phy_addr = i; - rl_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET); - DELAY(500); - while(rl_phy_readreg(sc, PHY_BMCR) - & PHY_BMCR_RESET); - if ((phy_sts = rl_phy_readreg(sc, PHY_BMSR))) - break; - } - if (phy_sts) { - phy_vid = rl_phy_readreg(sc, PHY_VENID); - phy_did = rl_phy_readreg(sc, PHY_DEVID); - if (bootverbose) - printf("rl%d: found PHY at address %d, ", - sc->rl_unit, sc->rl_phy_addr); - if (bootverbose) - printf("vendor id: %x device id: %x\n", - phy_vid, phy_did); - p = rl_phys; - while(p->rl_vid) { - if (phy_vid == p->rl_vid && - (phy_did | 0x000F) == p->rl_did) { - sc->rl_pinfo = p; - break; - } - p++; - } - if (sc->rl_pinfo == NULL) - sc->rl_pinfo = &rl_phys[PHY_UNKNOWN]; - if (bootverbose) - printf("rl%d: PHY type: %s\n", - sc->rl_unit, sc->rl_pinfo->rl_name); - } else { - printf("rl%d: MII without any phy!\n", sc->rl_unit); - } - } - - /* - * Do ifmedia setup. - */ - ifmedia_init(&sc->ifmedia, 0, rl_ifmedia_upd, rl_ifmedia_sts); - - rl_getmode_mii(sc); - - /* Choose a default media. */ - media = IFM_ETHER|IFM_AUTO; - ifmedia_set(&sc->ifmedia, media); - - rl_autoneg_mii(sc, RL_FLAG_FORCEDELAY, 1); - - /* - * Call MI attach routines. - */ - if_attach(ifp); - ether_ifattach(ifp); - -#if NBPFILTER > 0 - bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); -#endif - at_shutdown(rl_shutdown, sc, SHUTDOWN_POST_SYNC); - -fail: - splx(s); - return; -} -#endif - /* * Initialize the transmit descriptors. */ @@ -1465,11 +762,7 @@ static void rl_rxeof(sc) * address or the interface is in promiscuous mode. */ if (ifp->if_bpf) { -#ifdef __FreeBSD__ - bpf_mtap(ifp, m); -#else bpf_mtap(ifp->if_bpf, m); -#endif if (ifp->if_flags & IFF_PROMISC && (bcmp(eh->ether_dhost, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN) && @@ -1531,8 +824,6 @@ static void rl_txeof(sc) if (!sc->rl_cdata.rl_tx_cnt) { ifp->if_flags &= ~IFF_OACTIVE; - if (sc->rl_want_auto) - rl_autoneg_mii(sc, RL_FLAG_SCHEDDELAY, 1); } else { if (ifp->if_snd.ifq_head != NULL) rl_start(ifp); @@ -1590,18 +881,12 @@ static void rl_txeoc(sc) return; } -#ifdef __FreeBSD__ -static void rl_intr(arg) -#elif defined(__OpenBSD__) static int rl_intr(arg) -#endif void *arg; { struct rl_softc *sc; struct ifnet *ifp; -#ifdef __OpenBSD__ int claimed = 0; -#endif u_int16_t status; sc = arg; @@ -1635,10 +920,7 @@ static int rl_intr(arg) rl_reset(sc); rl_init(sc); } -#ifdef __OpenBSD__ claimed = 1; -#endif - } /* Re-enable interrupts. */ @@ -1648,11 +930,7 @@ static int rl_intr(arg) rl_start(ifp); } -#ifdef __OpenBSD__ return claimed; -#else - return; -#endif } /* @@ -1728,11 +1006,6 @@ static void rl_start(ifp) sc = ifp->if_softc; - if (sc->rl_autoneg) { - sc->rl_tx_pend = 1; - return; - } - /* * Check for an available queue slot. If there are none, * punt. @@ -1762,11 +1035,7 @@ static void rl_start(ifp) * to him. */ if (ifp->if_bpf) -#ifdef __FreeBSD__ - bpf_mtap(ifp, cur_tx->rl_mbuf); -#else bpf_mtap(ifp->if_bpf, cur_tx->rl_mbuf); -#endif #endif /* * Transmit the frame. @@ -1792,22 +1061,9 @@ static void rl_init(xsc) struct ifnet *ifp = &sc->arpcom.ac_if; int s, i; u_int32_t rxcfg = 0; - u_int16_t phy_bmcr = 0; - - if (sc->rl_autoneg) - return; s = splimp(); - /* - * XXX Hack for the 8139: the built-in autoneg logic's state - * gets reset by rl_init() when we don't want it to. Try - * to preserve it. (For 8129 cards with real external PHYs, - * the BMCR register doesn't change, but this doesn't hurt.) - */ - if (sc->rl_type == RL_8139) - phy_bmcr = rl_phy_readreg(sc, PHY_BMCR); - /* * Cancel pending I/O and free all RX/TX buffers. */ @@ -1874,10 +1130,6 @@ static void rl_init(xsc) /* Enable receiver and transmitter. */ CSR_WRITE_1(sc, RL_COMMAND, RL_CMD_TX_ENB|RL_CMD_RX_ENB); - /* Restore state of BMCR */ - if (sc->rl_pinfo != NULL) - rl_phy_writereg(sc, PHY_BMCR, phy_bmcr); - CSR_WRITE_1(sc, RL_CFG1, RL_CFG1_DRVLOAD|RL_CFG1_FULLDUPLEX); ifp->if_flags |= IFF_RUNNING; @@ -1894,21 +1146,9 @@ static void rl_init(xsc) static int rl_ifmedia_upd(ifp) struct ifnet *ifp; { - struct rl_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) - rl_autoneg_mii(sc, RL_FLAG_SCHEDDELAY, 1); - else - rl_setmode_mii(sc, ifm->ifm_media); - - return(0); + if (ifp->if_flags & IFF_UP) + rl_init(ifp->if_softc); + return (0); } /* @@ -1918,44 +1158,11 @@ static void rl_ifmedia_sts(ifp, ifmr) struct ifnet *ifp; struct ifmediareq *ifmr; { - struct rl_softc *sc; - u_int16_t advert = 0, ability = 0; - - sc = ifp->if_softc; + struct rl_softc *sc = ifp->if_softc; - if (!(rl_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_AUTONEGENBL)) { - if (rl_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 (rl_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_DUPLEX) - ifmr->ifm_active |= IFM_FDX; - else - ifmr->ifm_active |= IFM_HDX; - return; - } - - ability = rl_phy_readreg(sc, PHY_LPAR); - advert = rl_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; - } - - return; + mii_pollstat(&sc->sc_mii); + ifmr->ifm_status = sc->sc_mii.mii_media_status; + ifmr->ifm_active = sc->sc_mii.mii_media_active; } static int rl_ioctl(ifp, command, data) @@ -1965,28 +1172,17 @@ static int rl_ioctl(ifp, command, data) { struct rl_softc *sc = ifp->if_softc; struct ifreq *ifr = (struct ifreq *) data; -#ifdef __OpenBSD__ struct ifaddr *ifa = (struct ifaddr *)data; -#endif int s, error = 0; s = splimp(); -#ifdef __OpenBSD__ if ((error = ether_ioctl(ifp, &sc->arpcom, command, data)) > 0) { splx(s); return error; } -#endif switch(command) { -#ifdef __FreeBSD__ - case SIOCSIFADDR: - case SIOCGIFADDR: - case SIOCSIFMTU: - error = ether_ioctl(ifp, command, data); - break; -#else case SIOCSIFADDR: ifp->if_flags |= IFF_UP; switch (ifa->ifa_addr->sa_family) { @@ -2001,7 +1197,6 @@ static int rl_ioctl(ifp, command, data) break; } break; -#endif case SIOCSIFFLAGS: if (ifp->if_flags & IFF_UP) { rl_init(sc); @@ -2018,7 +1213,7 @@ static int rl_ioctl(ifp, command, data) break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command); + error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command); break; default: error = EINVAL; @@ -2037,16 +1232,8 @@ static void rl_watchdog(ifp) sc = ifp->if_softc; - if (sc->rl_autoneg) { - rl_autoneg_mii(sc, RL_FLAG_DELAYTIMEO, 1); - return; - } - printf("rl%d: watchdog timeout\n", sc->rl_unit); ifp->if_oerrors++; - if (!(rl_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT)) - printf("rl%d: no carrier - transceiver cable problem?\n", - sc->rl_unit); rl_txeoc(sc); rl_txeof(sc); rl_rxeof(sc); @@ -2088,35 +1275,6 @@ static void rl_stop(sc) return; } -#ifdef __FreeBSD__ -/* - * Stop all chip I/O so that the kernel's probe routines don't - * get confused by errant DMAs when rebooting. - */ -static void rl_shutdown(howto, arg) - int howto; - void *arg; -{ - struct rl_softc *sc = (struct rl_softc *)arg; - - rl_stop(sc); - - return; -} - - -static struct pci_device rl_device = { - "rl", - rl_probe, - rl_attach, - &rl_count, - NULL -}; -DATA_SET(pcidevice_set, rl_device); -#endif - -#if defined(__OpenBSD__) - static int rl_probe(parent, match, aux) struct device *parent; @@ -2162,9 +1320,7 @@ rl_attach(parent, self, aux) int rseg; caddr_t kva; u_int32_t command; - u_int16_t phy_vid, phy_did, phy_sts, rl_did; - int media; - struct rl_type *p; + u_int16_t rl_did; sc->rl_unit = sc->sc_dev.dv_unit; @@ -2284,61 +1440,20 @@ rl_attach(parent, self, aux) ifp->if_baudrate = 10000000; bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); - if (sc->rl_type == RL_8129) { - int i; - - if (bootverbose) - printf("%s: probing for a PHY\n", sc->sc_dev.dv_xname); - for (i = RL_PHYADDR_MIN; i < RL_PHYADDR_MAX + 1; i++) { - if (bootverbose) - printf("%s: checking address: %d\n", - sc->sc_dev.dv_xname, i); - sc->rl_phy_addr = i; - rl_phy_writereg(sc, PHY_BMCR, PHY_BMCR_RESET); - DELAY(500); - while (rl_phy_readreg(sc, PHY_BMCR) & PHY_BMCR_RESET); - if ((phy_sts = rl_phy_readreg(sc, PHY_BMSR))) - break; - } - if (phy_sts) { - phy_vid = rl_phy_readreg(sc, PHY_VENID); - phy_did = rl_phy_readreg(sc, PHY_DEVID); - if (bootverbose) - printf("%s: found PHY at address %d, ", - sc->sc_dev.dv_xname, sc->rl_phy_addr); - if (bootverbose) - printf("vendor id: %x device id: %x\n", - phy_vid, phy_did); - p = rl_phys; - while (p->rl_vid) { - if (phy_vid == p->rl_vid && - (phy_did | 0xf) == p->rl_did) { - sc->rl_pinfo = p; - break; - } - p++; - } - if (sc->rl_pinfo == NULL) - sc->rl_pinfo = &rl_phys[PHY_UNKNOWN]; - if (bootverbose) - printf("%s: PHY type: %s\n", - sc->sc_dev.dv_xname, sc->rl_pinfo->rl_name); - } - else { - printf("%s: MII without any phy!\n", - sc->rl_pinfo->rl_name); - } - } - - ifmedia_init(&sc->ifmedia, 0, rl_ifmedia_upd, rl_ifmedia_sts); - rl_getmode_mii(sc); - /* - * Choose default media. + * Initialize our media structures and probe the MII. */ - media = IFM_ETHER | IFM_AUTO; - ifmedia_set(&sc->ifmedia, media); - rl_autoneg_mii(sc, RL_FLAG_FORCEDELAY, 1); + sc->sc_mii.mii_ifp = ifp; + sc->sc_mii.mii_readreg = rl_mii_read; + sc->sc_mii.mii_writereg = rl_mii_write; + sc->sc_mii.mii_statchg = rl_mii_statchg; + ifmedia_init(&sc->sc_mii.mii_media, 0, rl_ifmedia_upd, rl_ifmedia_sts); + mii_phy_probe(self, &sc->sc_mii, 0xffffffff); + if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { + ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL); + ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE); + } else + ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO); /* * Attach us everywhere @@ -2360,8 +1475,93 @@ static void rl_shutdown(arg) struct rl_softc *sc = (struct rl_softc *)arg; rl_stop(sc); +} - return; +static int +rl_mii_read(self, phy, reg) + struct device *self; + int phy, reg; +{ + struct rl_softc *sc = (struct rl_softc *)self; + struct rl_mii_frame frame; + + if (sc->rl_type == RL_8139) { + /* + * The RTL8139 PHY is mapped into PCI registers, unforunately + * it has no phyid, or phyaddr, so assume it is phyaddr 0. + */ + if (phy != 0) + return(0); + + DELAY(100); + switch (reg) { + case MII_BMCR: + return CSR_READ_2(sc, RL_BMCR); + case MII_BMSR: + return CSR_READ_2(sc, RL_BMSR); + case MII_ANAR: + return CSR_READ_2(sc, RL_ANAR); + case MII_ANLPAR: + return CSR_READ_2(sc, RL_LPAR); + case MII_ANER: + return CSR_READ_2(sc, RL_ANER); + } + return (0); + } + + bzero((char *)&frame, sizeof(frame)); + + frame.mii_phyaddr = sc->rl_phy_addr; + frame.mii_regaddr = reg; + rl_mii_readreg(sc, &frame); + + return(frame.mii_data); +} + +static void +rl_mii_write(self, phy, reg, val) + struct device *self; + int phy, reg, val; +{ + struct rl_softc *sc = (struct rl_softc *)self; + struct rl_mii_frame frame; + + if (sc->rl_type == RL_8139) { + if (phy != 0) + return; + + switch (reg) { + case MII_BMCR: + CSR_WRITE_2(sc, RL_BMCR, val); + break; + case MII_BMSR: + CSR_WRITE_2(sc, RL_BMSR, val); + break; + case MII_ANAR: + CSR_WRITE_2(sc, RL_ANAR, val); + break; + case MII_ANLPAR: + CSR_WRITE_2(sc, RL_LPAR, val); + break; + case MII_ANER: + CSR_WRITE_2(sc, RL_ANER, val); + break; + } + return; + } + + bzero((char *)&frame, sizeof(frame)); + frame.mii_phyaddr = phy; + frame.mii_regaddr = reg; + frame.mii_data = val; + rl_mii_writereg(sc, &frame); +} + +static void +rl_mii_statchg(self) + struct device *self; +{ + /* Nothing to do */ } struct cfattach rl_ca = { @@ -2371,5 +1571,3 @@ struct cfattach rl_ca = { struct cfdriver rl_cd = { 0, "rl", DV_IFNET }; - -#endif diff --git a/sys/dev/pci/if_rlreg.h b/sys/dev/pci/if_rlreg.h index 268ffc7700e..57d73b30134 100644 --- a/sys/dev/pci/if_rlreg.h +++ b/sys/dev/pci/if_rlreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_rlreg.h,v 1.1 1998/11/11 20:51:39 jason Exp $ */ +/* $OpenBSD: if_rlreg.h,v 1.2 1998/11/18 20:11:33 jason Exp $ */ /* * Copyright (c) 1997, 1998 @@ -331,7 +331,6 @@ struct rl_mii_frame { #define RL_8139 2 struct rl_softc { -#ifdef __OpenBSD__ struct device sc_dev; void * sc_ih; bus_space_tag_t sc_st; @@ -341,15 +340,8 @@ struct rl_softc { bus_dmamap_t sc_dma_oprog; bus_dmamap_t sc_dma_mem; size_t sc_dma_mapsize; -#endif struct arpcom arpcom; /* interface info */ - struct ifmedia ifmedia; /* media info */ -#ifdef __FreeBSD__ - u_int32_t iobase; /* pointer to PIO space */ -#ifndef RL_USEIOSPACE - volatile caddr_t csr; /* pointer to register map */ -#endif -#endif + struct mii_data sc_mii; /* MII information */ struct rl_type *rl_pinfo; /* phy info */ u_int8_t rl_unit; /* interface number */ u_int8_t rl_type; @@ -364,39 +356,6 @@ struct rl_softc { /* * register space access macros */ -#ifdef __FreeBSD__ -#ifdef RL_USEIOSPACE -#define CSR_WRITE_4(sc, reg, val) \ - outl(sc->iobase + (u_int32_t)(reg), val) -#define CSR_WRITE_2(sc, reg, val) \ - outw(sc->iobase + (u_int32_t)(reg), val) -#define CSR_WRITE_1(sc, reg, val) \ - outb(sc->iobase + (u_int32_t)(reg), val) - -#define CSR_READ_4(sc, reg) \ - inl(sc->iobase + (u_int32_t)(reg)) -#define CSR_READ_2(sc, reg) \ - inw(sc->iobase + (u_int32_t)(reg)) -#define CSR_READ_1(sc, reg) \ - inb(sc->iobase + (u_int32_t)(reg)) -#else -#define CSR_WRITE_4(sc, reg, val) \ - ((*(u_int32_t*)((sc)->csr + (u_int32_t)(reg))) = (u_int32_t)(val)) -#define CSR_WRITE_2(sc, reg, val) \ - ((*(u_int16_t*)((sc)->csr + (u_int32_t)(reg))) = (u_int16_t)(val)) -#define CSR_WRITE_1(sc, reg, val) \ - ((*(u_int8_t*)((sc)->csr + (u_int32_t)(reg))) = (u_int8_t)(val)) - -#define CSR_READ_4(sc, reg) \ - (*(u_int32_t *)((sc)->csr + (u_int32_t)(reg))) -#define CSR_READ_2(sc, reg) \ - (*(u_int16_t *)((sc)->csr + (u_int32_t)(reg))) -#define CSR_READ_1(sc, reg) \ - (*(u_int8_t *)((sc)->csr + (u_int32_t)(reg))) -#endif -#endif - -#ifdef __OpenBSD__ #define CSR_WRITE_4(sc, csr, val) \ bus_space_write_4((sc)->sc_st, (sc)->sc_sh, csr, (val)) #define CSR_WRITE_2(sc, csr, val) \ @@ -410,7 +369,6 @@ struct rl_softc { bus_space_read_2((sc)->sc_st, (sc)->sc_sh, csr) #define CSR_READ_1(sc, csr) \ bus_space_read_1((sc)->sc_st, (sc)->sc_sh, csr) -#endif #define RL_TIMEOUT 1000 -- cgit v1.2.3