diff options
-rw-r--r-- | release/texts/HARDWARE.TXT | 3 | ||||
-rw-r--r-- | release/texts/alpha/RELNOTES.TXT | 5 | ||||
-rw-r--r-- | release/texts/i386/RELNOTES.TXT | 6 | ||||
-rw-r--r-- | share/man/man4/sis.4 | 15 | ||||
-rw-r--r-- | sys/pci/if_sis.c | 218 | ||||
-rw-r--r-- | sys/pci/if_sisreg.h | 32 |
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 */ |