summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--release/texts/HARDWARE.TXT3
-rw-r--r--release/texts/alpha/RELNOTES.TXT5
-rw-r--r--release/texts/i386/RELNOTES.TXT6
-rw-r--r--share/man/man4/sis.415
-rw-r--r--sys/pci/if_sis.c218
-rw-r--r--sys/pci/if_sisreg.h32
6 files changed, 256 insertions, 23 deletions
diff --git a/release/texts/HARDWARE.TXT b/release/texts/HARDWARE.TXT
index f120e64..e75f4bf 100644
--- a/release/texts/HARDWARE.TXT
+++ b/release/texts/HARDWARE.TXT
@@ -526,6 +526,9 @@ NICs including the following:
Silicon Integrated Systems SiS 900 and SiS 7016 PCI fast ethernet NICs
+National Semiconductor DP83815 fast ethernet NICs including the following:
+ NetGear FA312-TX
+
Sundance Technologies ST201 PCI fast ethernet NICs including
the following:
D-Link DFE-550TX
diff --git a/release/texts/alpha/RELNOTES.TXT b/release/texts/alpha/RELNOTES.TXT
index 07ee386..4fc427b 100644
--- a/release/texts/alpha/RELNOTES.TXT
+++ b/release/texts/alpha/RELNOTES.TXT
@@ -71,6 +71,8 @@ POSIX.1b Shared Memory Objects are now supported. The implementation
uses regular files, but automatically enables the MAP_NOSYNC flag
when they are mmap(2)ed.
+Added support for PCI ethernet adapters based on the National Semiconductor
+DP83815 chipset, including the NetGear FA312-TX.
1.2. SECURITY FIXES
-------------------
@@ -289,6 +291,9 @@ NICs including the following:
Silicon Integrated Systems SiS 900 and SiS 7016 PCI fast ethernet NICs
+National Semiconductor DP83815 fast ethernet NICs including the following:
+ NetGear FA312-TX
+
Sundance Technologies ST201 PCI fast ethernet NICs including
the following:
D-Link DFE-550TX
diff --git a/release/texts/i386/RELNOTES.TXT b/release/texts/i386/RELNOTES.TXT
index 83aed97..63e1b6c 100644
--- a/release/texts/i386/RELNOTES.TXT
+++ b/release/texts/i386/RELNOTES.TXT
@@ -75,6 +75,9 @@ POSIX.1b Shared Memory Objects are now supported. The implementation
uses regular files, but automatically enables the MAP_NOSYNC flag
when they are mmap(2)ed.
+Added support for PCI ethernet adapters based on the National Semiconductor
+DP83815 chipset, including the NetGear FA312-TX.
+
1.2. SECURITY FIXES
-------------------
@@ -308,6 +311,9 @@ NICs including the following:
Silicon Integrated Systems SiS 900 and SiS 7016 PCI fast ethernet NICs
+National Semiconductor DP83815 fast ethernet NICs including the following:
+ NetGear FA312-TX
+
Sundance Technologies ST201 PCI fast ethernet NICs including
the following:
D-Link DFE-550TX
diff --git a/share/man/man4/sis.4 b/share/man/man4/sis.4
index 15a65cb..27af8ad 100644
--- a/share/man/man4/sis.4
+++ b/share/man/man4/sis.4
@@ -36,7 +36,7 @@
.Sh NAME
.Nm sis
.Nd
-Silicon Integrated Systems fast ethernet device driver
+SiS 900, SiS 7016 and NS DP83815 fast ethernet device driver
.Sh SYNOPSIS
.Cd "device miibus"
.Cd "device sis"
@@ -45,7 +45,9 @@ The
.Nm
driver provides support for PCI ethernet adapters and embedded
controllers based on the Silicon Integrated Systems SiS 900
-and SiS 7016 fast ethernet controller chips.
+and SiS 7016 fast ethernet controller chips, as well as support
+for adapters based on the National Semiconductor DP83815 (MacPhyter)
+PCI ethernet controller chip, including the Netgear FA312-TX.
.Pp
The SiS 900 is a 100Mbps ethernet MAC and MII-compliant transceiver
in a single package.
@@ -57,6 +59,11 @@ to be attached to its MII interface.
The SiS 900 and SiS 7016 both have a 128-bit multicast hash filter
and a single perfect filter entry for the station address.
.Pp
+The NS DP83815 is also a 100Mbps ethernet MAC with integrated PHY.
+The NatSemi chip and the SiS 900 share many of the same features and
+a fairly similar programming interface, hence both chips are supported
+by the same driver.
+.Pp
The
.Nm
driver supports the following media types:
@@ -147,6 +154,10 @@ the card should be configured correctly.
.%T SiS 900 and SiS 7016 datasheets
.%O http://www.sis.com.tw
.Re
+.Rs
+.%T NatSemi DP83815 datasheet
+.%O http://www.national.com
+.Re
.Sh HISTORY
The
.Nm
diff --git a/sys/pci/if_sis.c b/sys/pci/if_sis.c
index b954433..8410a7f 100644
--- a/sys/pci/if_sis.c
+++ b/sys/pci/if_sis.c
@@ -106,6 +106,7 @@ static const char rcsid[] =
static struct sis_type sis_devs[] = {
{ SIS_VENDORID, SIS_DEVICEID_900, "SiS 900 10/100BaseTX" },
{ SIS_VENDORID, SIS_DEVICEID_7016, "SiS 7016 10/100BaseTX" },
+ { NS_VENDORID, NS_DEVICEID_DP83815, "NatSemi DP83815 10/100BaseTX" },
{ 0, 0, NULL }
};
@@ -132,6 +133,7 @@ static void sis_shutdown __P((device_t));
static int sis_ifmedia_upd __P((struct ifnet *));
static void sis_ifmedia_sts __P((struct ifnet *, struct ifmediareq *));
+static u_int16_t sis_reverse __P((u_int16_t));
static void sis_delay __P((struct sis_softc *));
static void sis_eeprom_idle __P((struct sis_softc *));
static void sis_eeprom_putbyte __P((struct sis_softc *, int));
@@ -142,8 +144,9 @@ static int sis_miibus_readreg __P((device_t, int, int));
static int sis_miibus_writereg __P((device_t, int, int, int));
static void sis_miibus_statchg __P((device_t));
-static void sis_setmulti __P((struct sis_softc *));
-static u_int32_t sis_calchash __P((caddr_t));
+static void sis_setmulti_sis __P((struct sis_softc *));
+static void sis_setmulti_ns __P((struct sis_softc *));
+static u_int32_t sis_crc __P((struct sis_softc *, caddr_t));
static void sis_reset __P((struct sis_softc *));
static int sis_list_rx_init __P((struct sis_softc *));
static int sis_list_tx_init __P((struct sis_softc *));
@@ -200,6 +203,21 @@ DRIVER_MODULE(miibus, sis, miibus_driver, miibus_devclass, 0, 0);
#define SIO_CLR(x) \
CSR_WRITE_4(sc, SIS_EECTL, CSR_READ_4(sc, SIS_EECTL) & ~x)
+/*
+ * Routine to reverse the bits in a word. Stolen almost
+ * verbatim from /usr/games/fortune.
+ */
+static u_int16_t sis_reverse(n)
+ u_int16_t n;
+{
+ n = ((n >> 1) & 0x5555) | ((n << 1) & 0xaaaa);
+ n = ((n >> 2) & 0x3333) | ((n << 2) & 0xcccc);
+ n = ((n >> 4) & 0x0f0f) | ((n << 4) & 0xf0f0);
+ n = ((n >> 8) & 0x00ff) | ((n << 8) & 0xff00);
+
+ return(n);
+}
+
static void sis_delay(sc)
struct sis_softc *sc;
{
@@ -283,9 +301,9 @@ static void sis_eeprom_getword(sc, addr, dest)
/* Enter EEPROM access mode. */
sis_delay(sc);
- SIO_SET(SIS_EECTL_CSEL);
+ SIO_CLR(SIS_EECTL_CLK);
sis_delay(sc);
- SIO_SET(SIS_EECTL_CLK);
+ SIO_SET(SIS_EECTL_CSEL);
sis_delay(sc);
/*
@@ -344,10 +362,29 @@ static int sis_miibus_readreg(dev, phy, reg)
int phy, reg;
{
struct sis_softc *sc;
- int i, val;
+ int i, val = 0;
sc = device_get_softc(dev);
+ if (sc->sis_type == SIS_TYPE_83815) {
+ if (phy != 0)
+ return(0);
+ /*
+ * The NatSemi chip can take a while after
+ * a reset to come ready, during which the BMSR
+ * returns a value of 0. This is *never* supposed
+ * to happen: some of the BMSR bits are meant to
+ * be hardwired in the on position, and this can
+ * confuse the miibus code a bit during the probe
+ * and attach phase. So we make an effort to check
+ * for this condition and wait for it to clear.
+ */
+ if (!CSR_READ_4(sc, NS_BMSR))
+ DELAY(1000);
+ val = CSR_READ_4(sc, NS_BMCR + (reg * 4));
+ return(val);
+ }
+
if (sc->sis_type == SIS_TYPE_900 && phy != 0)
return(0);
@@ -381,6 +418,16 @@ static int sis_miibus_writereg(dev, phy, reg, data)
sc = device_get_softc(dev);
+ if (sc->sis_type == SIS_TYPE_83815) {
+ if (phy != 0)
+ return(0);
+ CSR_WRITE_4(sc, NS_BMCR + (reg * 4), data);
+ return(0);
+ }
+
+ if (sc->sis_type == SIS_TYPE_900 && phy != 0)
+ return(0);
+
if (sc->sis_type == SIS_TYPE_900 && phy != 0)
return(0);
@@ -421,7 +468,8 @@ static void sis_miibus_statchg(dev)
return;
}
-static u_int32_t sis_calchash(addr)
+static u_int32_t sis_crc(sc, addr)
+ struct sis_softc *sc;
caddr_t addr;
{
u_int32_t crc, carry;
@@ -442,11 +490,68 @@ static u_int32_t sis_calchash(addr)
}
}
- /* return the filter bit position */
+ /*
+ * return the filter bit position
+ *
+ * The NatSemi chip has a 512-bit filter, which is
+ * different than the SiS, so we special-case it.
+ */
+ if (sc->sis_type == SIS_TYPE_83815)
+ return((crc >> 23) & 0x1FF);
+
return((crc >> 25) & 0x0000007F);
}
-static void sis_setmulti(sc)
+static void sis_setmulti_ns(sc)
+ struct sis_softc *sc;
+{
+ struct ifnet *ifp;
+ struct ifmultiaddr *ifma;
+ u_int32_t h = 0, i, filtsave;
+ int bit, index;
+
+ ifp = &sc->arpcom.ac_if;
+
+ if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
+ SIS_CLRBIT(sc, SIS_RXFILT_CTL, NS_RXFILTCTL_MCHASH);
+ SIS_SETBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ALLMULTI);
+ return;
+ }
+
+ /*
+ * We have to explicitly enable the multicast hash table
+ * on the NatSemi chip if we want to use it, which we do.
+ */
+ SIS_SETBIT(sc, SIS_RXFILT_CTL, NS_RXFILTCTL_MCHASH);
+ SIS_CLRBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ALLMULTI);
+
+ filtsave = CSR_READ_4(sc, SIS_RXFILT_CTL);
+
+ /* first, zot all the existing hash bits */
+ for (i = 0; i < 32; i++) {
+ CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_FMEM_LO + (i*2));
+ CSR_WRITE_4(sc, SIS_RXFILT_DATA, 0);
+ }
+
+ for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL;
+ ifma = ifma->ifma_link.le_next) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ h = sis_crc(sc, LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+ index = h >> 3;
+ bit = h & 0x1F;
+ CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_FMEM_LO + index);
+ if (bit > 0xF)
+ bit -= 0x10;
+ SIS_SETBIT(sc, SIS_RXFILT_DATA, (1 << bit));
+ }
+
+ CSR_WRITE_4(sc, SIS_RXFILT_CTL, filtsave);
+
+ return;
+}
+
+static void sis_setmulti_sis(sc)
struct sis_softc *sc;
{
struct ifnet *ifp;
@@ -475,7 +580,7 @@ static void sis_setmulti(sc)
ifma = ifma->ifma_link.le_next) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
- h = sis_calchash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+ h = sis_crc(sc, LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
CSR_WRITE_4(sc, SIS_RXFILT_CTL, (4 + (h >> 4)) << 16);
SIS_SETBIT(sc, SIS_RXFILT_DATA, (1 << (h & 0xF)));
}
@@ -552,6 +657,8 @@ static int sis_attach(dev)
sc->sis_type = SIS_TYPE_900;
if (pci_get_device(dev) == SIS_DEVICEID_7016)
sc->sis_type = SIS_TYPE_7016;
+ if (pci_get_vendor(dev) == NS_VENDORID)
+ sc->sis_type = SIS_TYPE_83815;
/*
* Handle power management nonsense.
@@ -645,7 +752,47 @@ static int sis_attach(dev)
/*
* Get station address from the EEPROM.
*/
- sis_read_eeprom(sc, (caddr_t)&eaddr, SIS_EE_NODEADDR, 3, 0);
+ switch (pci_get_vendor(dev)) {
+ case NS_VENDORID:
+ /*
+ * Reading the MAC address out of the EEPROM on
+ * the NatSemi chip takes a bit more work than
+ * you'd expect. The address spans 4 16-bit words,
+ * with the first word containing only a single bit.
+ * You have to shift everything over one bit to
+ * get it aligned properly. Also, the bits are
+ * stored backwards (the LSB is really the MSB,
+ * and so on) so you have to reverse them in order
+ * to get the MAC address into the form we want.
+ * Why? Who the hell knows.
+ */
+ {
+ u_int16_t tmp[4];
+
+ sis_read_eeprom(sc, (caddr_t)&tmp,
+ NS_EE_NODEADDR, 4, 0);
+
+ /* Shift everything over one bit. */
+ tmp[3] = tmp[3] >> 1;
+ tmp[3] |= tmp[2] >> 15;
+ tmp[2] = tmp[2] >> 1;
+ tmp[2] |= tmp[1] >> 15;
+ tmp[1] = tmp[1] >> 1;
+ tmp[1] |= tmp[0] >> 15;
+
+ /* Now reverse all the bits. */
+ tmp[3] = sis_reverse(tmp[3]);
+ tmp[2] = sis_reverse(tmp[2]);
+ tmp[1] = sis_reverse(tmp[1]);
+
+ bcopy((char *)&tmp[1], eaddr, ETHER_ADDR_LEN);
+ }
+ break;
+ case SIS_VENDORID:
+ default:
+ sis_read_eeprom(sc, (caddr_t)&eaddr, SIS_EE_NODEADDR, 3, 0);
+ break;
+ }
/*
* A SiS chip was detected. Inform the world.
@@ -1183,15 +1330,27 @@ static void sis_init(xsc)
mii = device_get_softc(sc->sis_miibus);
/* Set MAC address */
- CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR0);
- CSR_WRITE_4(sc, SIS_RXFILT_DATA,
- ((u_int16_t *)sc->arpcom.ac_enaddr)[0]);
- CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR1);
- CSR_WRITE_4(sc, SIS_RXFILT_DATA,
- ((u_int16_t *)sc->arpcom.ac_enaddr)[1]);
- CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR2);
- CSR_WRITE_4(sc, SIS_RXFILT_DATA,
- ((u_int16_t *)sc->arpcom.ac_enaddr)[2]);
+ if (sc->sis_type == SIS_TYPE_83815) {
+ CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_PAR0);
+ CSR_WRITE_4(sc, SIS_RXFILT_DATA,
+ ((u_int16_t *)sc->arpcom.ac_enaddr)[0]);
+ CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_PAR1);
+ CSR_WRITE_4(sc, SIS_RXFILT_DATA,
+ ((u_int16_t *)sc->arpcom.ac_enaddr)[1]);
+ CSR_WRITE_4(sc, SIS_RXFILT_CTL, NS_FILTADDR_PAR2);
+ CSR_WRITE_4(sc, SIS_RXFILT_DATA,
+ ((u_int16_t *)sc->arpcom.ac_enaddr)[2]);
+ } else {
+ CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR0);
+ CSR_WRITE_4(sc, SIS_RXFILT_DATA,
+ ((u_int16_t *)sc->arpcom.ac_enaddr)[0]);
+ CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR1);
+ CSR_WRITE_4(sc, SIS_RXFILT_DATA,
+ ((u_int16_t *)sc->arpcom.ac_enaddr)[1]);
+ CSR_WRITE_4(sc, SIS_RXFILT_CTL, SIS_FILTADDR_PAR2);
+ CSR_WRITE_4(sc, SIS_RXFILT_DATA,
+ ((u_int16_t *)sc->arpcom.ac_enaddr)[2]);
+ }
/* Init circular RX list. */
if (sis_list_rx_init(sc) == ENOBUFS) {
@@ -1207,6 +1366,17 @@ static void sis_init(xsc)
*/
sis_list_tx_init(sc);
+ /*
+ * For the NatSemi chip, we have to explicitly enable the
+ * reception of ARP frames, as well as turn on the 'perfect
+ * match' filter where we store the station address, otherwise
+ * we won't receive unicasts meant for this host.
+ */
+ if (sc->sis_type == SIS_TYPE_83815) {
+ SIS_SETBIT(sc, SIS_RXFILT_CTL, NS_RXFILTCTL_ARP);
+ SIS_SETBIT(sc, SIS_RXFILT_CTL, NS_RXFILTCTL_PERFECT);
+ }
+
/* If we want promiscuous mode, set the allframes bit. */
if (ifp->if_flags & IFF_PROMISC) {
SIS_SETBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ALLPHYS);
@@ -1226,7 +1396,10 @@ static void sis_init(xsc)
/*
* Load the multicast filter.
*/
- sis_setmulti(sc);
+ if (sc->sis_type == SIS_TYPE_83815)
+ sis_setmulti_ns(sc);
+ else
+ sis_setmulti_sis(sc);
/* Turn the receive filter on */
SIS_SETBIT(sc, SIS_RXFILT_CTL, SIS_RXFILTCTL_ENABLE);
@@ -1331,7 +1504,10 @@ static int sis_ioctl(ifp, command, data)
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
- sis_setmulti(sc);
+ if (sc->sis_type == SIS_TYPE_83815)
+ sis_setmulti_ns(sc);
+ else
+ sis_setmulti_sis(sc);
error = 0;
break;
case SIOCGIFMEDIA:
diff --git a/sys/pci/if_sisreg.h b/sys/pci/if_sisreg.h
index cef3a52..a74dc3b 100644
--- a/sys/pci/if_sisreg.h
+++ b/sys/pci/if_sisreg.h
@@ -74,6 +74,16 @@
#define SIS_TIMEUNIT 0xA4
#define SIS_GPIO 0xB8
+/* NS DP83815 registers */
+#define NS_BMCR 0x80
+#define NS_BMSR 0x84
+#define NS_PHYIDR1 0x88
+#define NS_PHYIDR2 0x8C
+#define NS_ANAR 0x90
+#define NS_ANLPAR 0x94
+#define NS_ANER 0x98
+#define NS_ANNPTR 0x9C
+
#define SIS_CSR_TX_ENABLE 0x00000001
#define SIS_CSR_TX_DISABLE 0x00000002
#define SIS_CSR_RX_ENABLE 0x00000004
@@ -100,6 +110,7 @@
#define SIS_EECMD_ERASE 0x1c0
#define SIS_EE_NODEADDR 0x8
+#define NS_EE_NODEADDR 0x6
#define SIS_PCICTL_SRAMADDR 0x0000001F
#define SIS_PCICTL_RAMTSTENB 0x00000020
@@ -220,6 +231,9 @@
(SIS_RXCFG_DRAIN(64)|SIS_RXDMA_256BYTES)
#define SIS_RXFILTCTL_ADDR 0x000F0000
+#define NS_RXFILTCTL_MCHASH 0x00200000
+#define NS_RXFILTCTL_ARP 0x00400000
+#define NS_RXFILTCTL_PERFECT 0x08000000
#define SIS_RXFILTCTL_ALLPHYS 0x10000000
#define SIS_RXFILTCTL_ALLMULTI 0x20000000
#define SIS_RXFILTCTL_BROAD 0x40000000
@@ -237,6 +251,13 @@
#define SIS_FILTADDR_MAR6 0x000A0000
#define SIS_FILTADDR_MAR7 0x000B0000
+#define NS_FILTADDR_PAR0 0x00000000
+#define NS_FILTADDR_PAR1 0x00000002
+#define NS_FILTADDR_PAR2 0x00000004
+
+#define NS_FILTADDR_FMEM_LO 0x00000200
+#define NS_FILTADDR_FMEM_HI 0x000003FE
+
/*
* DMA descriptor structures. The first part of the descriptor
* is the hardware descriptor format, which is just three longwords.
@@ -322,6 +343,16 @@ struct sis_ring_data {
#define SIS_DEVICEID_900 0x0900
#define SIS_DEVICEID_7016 0x7016
+/*
+ * NatSemi vendor ID
+ */
+#define NS_VENDORID 0x100B
+
+/*
+ * DP83815 device ID
+ */
+#define NS_DEVICEID_DP83815 0x0020
+
struct sis_type {
u_int16_t sis_vid;
u_int16_t sis_did;
@@ -330,6 +361,7 @@ struct sis_type {
#define SIS_TYPE_900 1
#define SIS_TYPE_7016 2
+#define SIS_TYPE_83815 3
struct sis_softc {
struct arpcom arpcom; /* interface info */
OpenPOWER on IntegriCloud