Deleted Added
full compact
32c32
< * $FreeBSD: head/sys/pci/if_wb.c 50477 1999-08-28 01:08:13Z peter $
---
> * $FreeBSD: head/sys/pci/if_wb.c 50675 1999-08-30 23:08:32Z wpaul $
95a96
> #include <sys/queue.h>
124c125,126
< #define WB_USEIOSPACE
---
> #include <dev/mii/mii.h>
> #include <dev/mii/miivar.h>
126c128
< /* #define WB_BACKGROUND_AUTONEG */
---
> #include "miibus_if.h"
127a130,131
> #define WB_USEIOSPACE
>
132c136
< "$FreeBSD: head/sys/pci/if_wb.c 50477 1999-08-28 01:08:13Z peter $";
---
> "$FreeBSD: head/sys/pci/if_wb.c 50675 1999-08-30 23:08:32Z wpaul $";
146,161d149
< /*
< * 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>" }
< };
<
165a154
> static void wb_bfree __P((caddr_t, u_int));
170c159
< struct mbuf *));
---
> struct mbuf *));
176a166
> static void wb_tick __P((void *));
194,195d183
< static u_int16_t wb_phy_readreg __P((struct wb_softc *, int));
< static void wb_phy_writereg __P((struct wb_softc *, int, int));
197,201c185
< 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));
204a189
> static void wb_fixmedia __P((struct wb_softc *));
207a193,196
> 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));
>
221a211,219
>
> /* 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),
233a232
> DRIVER_MODULE(miibus, wb, miibus_driver, miibus_devclass, 0, 0);
537,539c536,538
< 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;
540a540
> struct wb_softc *sc;
542a543,544
> sc = device_get_softc(dev);
>
545c547
< frame.mii_phyaddr = sc->wb_phy_addr;
---
> frame.mii_phyaddr = phy;
552,555c554,556
< 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;
556a558
> struct wb_softc *sc;
558a561,562
> sc = device_get_softc(dev);
>
561c565
< frame.mii_phyaddr = sc->wb_phy_addr;
---
> frame.mii_phyaddr = phy;
566a571,583
> 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);
>
656,962d672
< * 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;
< }
<
< /*
967c677
< static void wb_setcfg(sc, bmcr)
---
> static void wb_setcfg(sc, media)
969c679
< int bmcr;
---
> u_int32_t media;
989,991c699
< if (bmcr & PHY_BMCR_SPEEDSEL)
< WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_100MBPS);
< else
---
> if (IFM_SUBTYPE(media) == IFM_10_T)
992a701,702
> else
> WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_100MBPS);
994c704
< if (bmcr & PHY_BMCR_DUPLEX)
---
> if ((media & IFM_GMASK) == IFM_FDX)
1008a719
> struct mii_data *mii;
1009a721,725
> 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);
>
1010a727
> WB_SETBIT(sc, WB_BUSCTL, WB_BUSCTL_RESET);
1023,1025c740,741
< /* 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;
1026a743,753
> 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);
> }
>
1029a757,784
> 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;
> }
>
1060c815
< int s, i;
---
> int s;
1065,1069d819
< 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;
1076d825
< bzero(sc, sizeof(struct wb_softc));
1163c912,915
<
---
>
> /* Save the cache line size. */
> sc->wb_cachesize = pci_read_config(dev, WB_PCI_CACHELEN, 4) & 0xFF;
>
1180,1182c932,935
< 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) {
1191,1201d943
< 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;
1218,1256c960,964
< 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)) {
1266,1282d973
< * 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);
<
< /*
1292a984,985
> if (error)
> device_delete_child(dev, sc->wb_miibus);
1293a987
>
1311a1006,1009
> /* Delete any miibus and phy devices attached to this interface */
> bus_generic_detach(dev);
> device_delete_child(dev, sc->wb_miibus);
>
1317d1014
< ifmedia_removeall(&sc->ifmedia);
1372a1070
> cd->wb_rx_chain[i].wb_buf = (void *)&ld->wb_rxbufs[i];
1391a1090,1096
> static void wb_bfree(buf, size)
> caddr_t buf;
> u_int size;
> {
> return;
> }
>
1410,1417c1115,1120
< 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;
1420c1123
< m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
---
> m_new->m_len = m_new->m_pkthdr.len = WB_BUFBYTES;
1428c1131
< c->wb_ptr->wb_ctl = WB_RXCTL_RLINK | (MCLBYTES - 1);
---
> c->wb_ptr->wb_ctl = WB_RXCTL_RLINK | 1536;
1442c1145
< struct mbuf *m;
---
> struct mbuf *m = NULL;
1455a1159
>
1458,1459c1162,1166
< 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)) {
1461c1168
< wb_reset(sc);
---
> wb_newbuf(sc, cur_rx, m);
1464,1465c1171,1173
< ifp->if_flags |= IFF_OACTIVE;
< ifp->if_timer = 2;
---
> wb_fixmedia(sc);
> wb_reset(sc);
> wb_init(sc);
1472c1180
< continue;
---
> break;
1492c1200
< continue;
---
> break;
1509c1217
< continue;
---
> break;
1528c1236
< continue;
---
> break;
1626,1627d1333
< if (sc->wb_want_auto)
< wb_autoneg_mii(sc, WB_FLAG_SCHEDDELAY, 1);
1664,1669d1369
< if (status & WB_ISR_RX_OK)
< wb_rxeof(sc);
<
< if (status & WB_ISR_RX_IDLE)
< wb_rxeoc(sc);
<
1672,1673d1371
< #ifdef foo
< wb_stop(sc);
1674a1373,1374
> if (status & WB_ISR_RX_ERR)
> wb_fixmedia(sc);
1676c1376
< #endif
---
> continue;
1678a1379,1384
> if (status & WB_ISR_RX_OK)
> wb_rxeof(sc);
>
> if (status & WB_ISR_RX_IDLE)
> wb_rxeoc(sc);
>
1720a1427,1442
> 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;
> }
>
1832,1836d1553
< if (sc->wb_autoneg) {
< sc->wb_tx_pend = 1;
< return;
< }
<
1924c1641
< u_int16_t phy_bmcr = 0;
---
> struct mii_data *mii;
1926,1928d1642
< if (sc->wb_autoneg)
< return;
<
1931,1932c1645
< if (sc->wb_pinfo != NULL)
< phy_bmcr = wb_phy_readreg(sc, PHY_BMCR);
---
> mii = device_get_softc(sc->wb_miibus);
1944a1658
> #ifdef foo
1947a1662
> #endif
1948a1664,1681
> 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;
> }
>
1952,1953d1684
< wb_setcfg(sc, phy_bmcr);
<
2012,2014c1743
< /* Restore state of BMCR */
< if (sc->wb_pinfo != NULL)
< wb_phy_writereg(sc, PHY_BMCR, phy_bmcr);
---
> mii_mediachg(mii);
2020a1750,1751
> sc->wb_stat_ch = timeout(wb_tick, sc, hz);
>
2031d1761
< struct ifmedia *ifm;
2034d1763
< ifm = &sc->ifmedia;
2036,2037c1765,1766
< if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
< return(EINVAL);
---
> if (ifp->if_flags & IFF_UP)
> wb_init(sc);
2039,2043d1767
< if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO)
< wb_autoneg_mii(sc, WB_FLAG_SCHEDDELAY, 1);
< else
< wb_setmode_mii(sc, ifm->ifm_media);
<
2055c1779
< u_int16_t advert = 0, ability = 0;
---
> struct mii_data *mii;
2059c1783
< ifmr->ifm_active = IFM_ETHER;
---
> mii = device_get_softc(sc->wb_miibus);
2061,2071c1785,1787
< 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;
< }
---
> mii_pollstat(mii);
> ifmr->ifm_active = mii->mii_media_active;
> ifmr->ifm_status = mii->mii_media_status;
2073,2091d1788
< 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;
< }
<
2100a1798
> struct mii_data *mii;
2128c1826,1827
< error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
---
> mii = device_get_softc(sc->wb_miibus);
> error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
2147,2153d1845
< if (sc->wb_autoneg) {
< wb_autoneg_mii(sc, WB_FLAG_DELAYTIMEO, 1);
< if (!(ifp->if_flags & IFF_UP))
< wb_stop(sc);
< return;
< }
<
2156c1848
<
---
> #ifdef foo
2160c1852
<
---
> #endif
2183a1876,1877
> untimeout(wb_tick, sc, sc->wb_stat_ch);
>