diff options
-rw-r--r-- | sys/pci/if_sis.c | 87 | ||||
-rw-r--r-- | sys/pci/if_sisreg.h | 17 |
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; |