summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>1999-08-30 23:08:32 +0000
committerwpaul <wpaul@FreeBSD.org>1999-08-30 23:08:32 +0000
commit67e37159de11fce7443692e5c1fe7f16b01ec091 (patch)
treeec7143d79d90671e26c26b6ba9731b99593460f5 /sys
parent56842578ac635aaac2ea2af6459b06fba2c3a3f1 (diff)
downloadFreeBSD-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.c528
-rw-r--r--sys/dev/sf/if_sfreg.h142
-rw-r--r--sys/modules/sf/Makefile6
-rw-r--r--sys/modules/wb/Makefile9
-rw-r--r--sys/pci/if_sf.c528
-rw-r--r--sys/pci/if_sfreg.h142
-rw-r--r--sys/pci/if_wb.c752
-rw-r--r--sys/pci/if_wbreg.h158
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)
OpenPOWER on IntegriCloud