summaryrefslogtreecommitdiffstats
path: root/sys/pci
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
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')
-rw-r--r--sys/pci/if_sis.c87
-rw-r--r--sys/pci/if_sisreg.h17
2 files changed, 85 insertions, 19 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.
*/
diff --git a/sys/pci/if_sisreg.h b/sys/pci/if_sisreg.h
index a74dc3b..ee46c92 100644
--- a/sys/pci/if_sisreg.h
+++ b/sys/pci/if_sisreg.h
@@ -84,6 +84,14 @@
#define NS_ANER 0x98
#define NS_ANNPTR 0x9C
+#define NS_PHY_CR 0xE4
+#define NS_PHY_10BTSCR 0xE8
+#define NS_PHY_PAGE 0xCC
+#define NS_PHY_EXTCFG 0xF0
+#define NS_PHY_DSPCFG 0xF4
+#define NS_PHY_SDCFG 0xF8
+#define NS_PHY_TDATA 0xFC
+
#define SIS_CSR_TX_ENABLE 0x00000001
#define SIS_CSR_TX_DISABLE 0x00000002
#define SIS_CSR_RX_ENABLE 0x00000004
@@ -205,9 +213,13 @@
#define SIS_TXDMA_128BYTES 0x00600000
#define SIS_TXDMA_256BYTES 0x00700000
-#define SIS_TXCFG \
+#define SIS_TXCFG_100 \
(SIS_TXDMA_64BYTES|SIS_TXCFG_AUTOPAD|\
- SIS_TXCFG_FILL(64)|SIS_TXCFG_DRAIN(1500))
+ SIS_TXCFG_FILL(64)|SIS_TXCFG_DRAIN(1536))
+
+#define SIS_TXCFG_10 \
+ (SIS_TXDMA_32BYTES|SIS_TXCFG_AUTOPAD|\
+ SIS_TXCFG_FILL(64)|SIS_TXCFG_DRAIN(1536))
#define SIS_RXCFG_DRAIN_THRESH 0x0000003E /* 8-byte units */
#define SIS_RXCFG_DMABURST 0x00700000
@@ -373,6 +385,7 @@ struct sis_softc {
device_t sis_miibus;
u_int8_t sis_unit;
u_int8_t sis_type;
+ u_int8_t sis_link;
struct sis_list_data *sis_ldata;
struct sis_ring_data sis_cdata;
struct callout_handle sis_stat_ch;
OpenPOWER on IntegriCloud