summaryrefslogtreecommitdiffstats
path: root/sys/pci/if_sis.c
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2000-08-22 23:26:51 +0000
committerwpaul <wpaul@FreeBSD.org>2000-08-22 23:26:51 +0000
commit7370888a4b9f4fe3a8fa8f4c0dbc97f2f1b7686f (patch)
treec0ce5da06e079bfeed3a4b5ec2203c09c8792455 /sys/pci/if_sis.c
parentdf79e3d3c75226317d3b972133053872de7b6e6c (diff)
downloadFreeBSD-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.c87
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.
*/
OpenPOWER on IntegriCloud