summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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