diff options
author | wpaul <wpaul@FreeBSD.org> | 2000-08-22 23:26:51 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 2000-08-22 23:26:51 +0000 |
commit | 7370888a4b9f4fe3a8fa8f4c0dbc97f2f1b7686f (patch) | |
tree | c0ce5da06e079bfeed3a4b5ec2203c09c8792455 /sys/pci/if_sis.c | |
parent | df79e3d3c75226317d3b972133053872de7b6e6c (diff) | |
download | FreeBSD-src-7370888a4b9f4fe3a8fa8f4c0dbc97f2f1b7686f.zip FreeBSD-src-7370888a4b9f4fe3a8fa8f4c0dbc97f2f1b7686f.tar.gz |
Fix up the sis driver, largely to improve the NatSemi DP83815 support:
- Modify the driver to poll the link state and positively set the
MAC to full or half duplex as needed. Previously, it was possible
for the MAC to remain in half duplex even though the PHY had negotiated
full duplex with its link partner, which would result in bursty
performance.
- Program some of the NatSemi's registers as specified by the datasheet.
The manual says these are necessary for "optimum perofrmance," though
a couple of them are marked as reserved in the register map. *shrug*
- Select the TX DMA burst size correctly for 10 and 100mbps modes.
Previously I was using 64 bytes in both modes, which worked in
100mbps mode, but resulting in spotty performance in 10mbps.
32 bytes works much better; without this change, the natsemi
chip yields piss poor performance at 10mbps.
With these fixes, the NatSemi chip finally performs to my satisfaction.
I should be merging the support for this controller into -stable shortly.
Phew.
Diffstat (limited to 'sys/pci/if_sis.c')
-rw-r--r-- | sys/pci/if_sis.c | 87 |
1 files changed, 70 insertions, 17 deletions
diff --git a/sys/pci/if_sis.c b/sys/pci/if_sis.c index a8c2e16..cee8639 100644 --- a/sys/pci/if_sis.c +++ b/sys/pci/if_sis.c @@ -36,6 +36,9 @@ * SiS 900/SiS 7016 fast ethernet PCI NIC driver. Datasheets are * available from http://www.sis.com.tw. * + * This driver also supports the NatSemi DP83815. Datasheets are + * available from http://www.national.com. + * * Written by Bill Paul <wpaul@ee.columbia.edu> * Electrical Engineering Department * Columbia University, New York City @@ -447,20 +450,9 @@ static void sis_miibus_statchg(dev) device_t dev; { struct sis_softc *sc; - struct mii_data *mii; sc = device_get_softc(dev); - mii = device_get_softc(sc->sis_miibus); - - if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) { - SIS_SETBIT(sc, SIS_TX_CFG, - (SIS_TXCFG_IGN_HBEAT|SIS_TXCFG_IGN_CARR)); - SIS_SETBIT(sc, SIS_RX_CFG, SIS_RXCFG_RX_TXPKTS); - } else { - SIS_CLRBIT(sc, SIS_TX_CFG, - (SIS_TXCFG_IGN_HBEAT|SIS_TXCFG_IGN_CARR)); - SIS_CLRBIT(sc, SIS_RX_CFG, SIS_RXCFG_RX_TXPKTS); - } + sis_init(sc); return; } @@ -1136,13 +1128,26 @@ static void sis_tick(xsc) { struct sis_softc *sc; struct mii_data *mii; + struct ifnet *ifp; int s; s = splimp(); sc = xsc; + ifp = &sc->arpcom.ac_if; + mii = device_get_softc(sc->sis_miibus); mii_tick(mii); + + if (!sc->sis_link) { + mii_pollstat(mii); + if (mii->mii_media_status & IFM_ACTIVE && + IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) + sc->sis_link++; + if (ifp->if_snd.ifq_head != NULL) + sis_start(ifp); + } + sc->sis_stat_ch = timeout(sis_tick, sc, hz); splx(s); @@ -1176,12 +1181,14 @@ static void sis_intr(arg) if ((status & SIS_INTRS) == 0) break; - if ((status & SIS_ISR_TX_OK) || + if ((status & SIS_ISR_TX_DESC_OK) || (status & SIS_ISR_TX_ERR) || + (status & SIS_ISR_TX_OK) || (status & SIS_ISR_TX_IDLE)) sis_txeof(sc); - if (status & SIS_ISR_RX_OK) + if ((status & SIS_ISR_RX_DESC_OK) || + (status & SIS_ISR_RX_OK)) sis_rxeof(sc); if ((status & SIS_ISR_RX_ERR) || @@ -1269,6 +1276,9 @@ static void sis_start(ifp) sc = ifp->if_softc; + if (!sc->sis_link) + return; + idx = sc->sis_cdata.sis_tx_prod; if (ifp->if_flags & IFF_OACTIVE) @@ -1408,8 +1418,24 @@ static void sis_init(xsc) /* Set RX configuration */ CSR_WRITE_4(sc, SIS_RX_CFG, SIS_RXCFG); + /* Set TX configuration */ - CSR_WRITE_4(sc, SIS_TX_CFG, SIS_TXCFG); + if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T) { + CSR_WRITE_4(sc, SIS_TX_CFG, SIS_TXCFG_10); + } else { + CSR_WRITE_4(sc, SIS_TX_CFG, SIS_TXCFG_100); + } + + /* Set full/half duplex mode. */ + if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) { + SIS_SETBIT(sc, SIS_TX_CFG, + (SIS_TXCFG_IGN_HBEAT|SIS_TXCFG_IGN_CARR)); + SIS_SETBIT(sc, SIS_RX_CFG, SIS_RXCFG_RX_TXPKTS); + } else { + SIS_CLRBIT(sc, SIS_TX_CFG, + (SIS_TXCFG_IGN_HBEAT|SIS_TXCFG_IGN_CARR)); + SIS_CLRBIT(sc, SIS_RX_CFG, SIS_RXCFG_RX_TXPKTS); + } /* * Enable interrupts. @@ -1421,7 +1447,24 @@ static void sis_init(xsc) SIS_CLRBIT(sc, SIS_CSR, SIS_CSR_TX_DISABLE|SIS_CSR_RX_DISABLE); SIS_SETBIT(sc, SIS_CSR, SIS_CSR_RX_ENABLE); +#ifdef notdef mii_mediachg(mii); +#endif + + /* + * Page 75 of the DP83815 manual recommends the + * following register settings "for optimum + * performance." Note however that at least three + * of the registers are listed as "reserved" in + * the register map, so who knows what they do. + */ + if (sc->sis_type == SIS_TYPE_83815) { + CSR_WRITE_4(sc, NS_PHY_PAGE, 0x0001); + CSR_WRITE_4(sc, NS_PHY_CR, 0x189C); + CSR_WRITE_4(sc, NS_PHY_TDATA, 0x0000); + CSR_WRITE_4(sc, NS_PHY_DSPCFG, 0x5040); + CSR_WRITE_4(sc, NS_PHY_SDCFG, 0x008C); + } ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; @@ -1440,11 +1483,19 @@ static int sis_ifmedia_upd(ifp) struct ifnet *ifp; { struct sis_softc *sc; + struct mii_data *mii; sc = ifp->if_softc; - if (ifp->if_flags & IFF_UP) - sis_init(sc); + mii = device_get_softc(sc->sis_miibus); + sc->sis_link = 0; + 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); + } + mii_mediachg(mii); return(0); } @@ -1560,6 +1611,8 @@ static void sis_stop(sc) CSR_WRITE_4(sc, SIS_TX_LISTPTR, 0); CSR_WRITE_4(sc, SIS_RX_LISTPTR, 0); + sc->sis_link = 0; + /* * Free data in the RX lists. */ |