Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-1-4]: src/sys/dev/pci Pull up revisions 1.1-1.2 + patch (requeste...
details: https://anonhg.NetBSD.org/src/rev/037c8c36d413
branches: netbsd-1-4
changeset: 469627:037c8c36d413
user: he <he%NetBSD.org@localhost>
date: Wed Oct 20 23:39:22 1999 +0000
description:
Pull up revisions 1.1-1.2 + patch (requested by bouyer):
Back-port of the Realtek ethernet driver.
diffstat:
sys/dev/pci/if_rl.c | 1694 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1694 insertions(+), 0 deletions(-)
diffs (truncated from 1698 to 300 lines):
diff -r dd91fb203c7b -r 037c8c36d413 sys/dev/pci/if_rl.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/pci/if_rl.c Wed Oct 20 23:39:22 1999 +0000
@@ -0,0 +1,1694 @@
+/* $NetBSD: if_rl.c,v 1.2.6.2 1999/10/20 23:39:22 he Exp $ */
+
+/*
+ * Copyright (c) 1997, 1998
+ * Bill Paul <wpaul%ctr.columbia.edu@localhost>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * FreeBSD Id: if_rl.c,v 1.17 1999/06/19 20:17:37 wpaul Exp
+ */
+
+/*
+ * RealTek 8129/8139 PCI NIC driver
+ *
+ * Supports several extremely cheap PCI 10/100 adapters based on
+ * the RealTek chipset. Datasheets can be obtained from
+ * www.realtek.com.tw.
+ *
+ * Written by Bill Paul <wpaul%ctr.columbia.edu@localhost>
+ * Electrical Engineering Department
+ * Columbia University, New York City
+ */
+
+/*
+ * The RealTek 8139 PCI NIC redefines the meaning of 'low end.' This is
+ * probably the worst PCI ethernet controller ever made, with the possible
+ * exception of the FEAST chip made by SMC. The 8139 supports bus-master
+ * DMA, but it has a terrible interface that nullifies any performance
+ * gains that bus-master DMA usually offers.
+ *
+ * For transmission, the chip offers a series of four TX descriptor
+ * registers. Each transmit frame must be in a contiguous buffer, aligned
+ * on a longword (32-bit) boundary. This means we almost always have to
+ * do mbuf copies in order to transmit a frame, except in the unlikely
+ * case where a) the packet fits into a single mbuf, and b) the packet
+ * is 32-bit aligned within the mbuf's data area. The presence of only
+ * four descriptor registers means that we can never have more than four
+ * packets queued for transmission at any one time.
+ *
+ * Reception is not much better. The driver has to allocate a single large
+ * buffer area (up to 64K in size) into which the chip will DMA received
+ * frames. Because we don't know where within this region received packets
+ * will begin or end, we have no choice but to copy data from the buffer
+ * area into mbufs in order to pass the packets up to the higher protocol
+ * levels.
+ *
+ * It's impossible given this rotten design to really achieve decent
+ * performance at 100Mbps, unless you happen to have a 400Mhz PII or
+ * some equally overmuscled CPU to drive it.
+ *
+ * On the bright side, the 8139 does have a built-in PHY, although
+ * rather than using an MDIO serial interface like most other NICs, the
+ * PHY registers are directly accessible through the 8139's register
+ * space. The 8139 supports autonegotiation, as well as a 64-bit multicast
+ * filter.
+ *
+ * The 8129 chip is an older version of the 8139 that uses an external PHY
+ * chip. The 8129 has a serial MDIO interface for accessing the MII where
+ * the 8139 lets you directly access the on-board PHY registers. We need
+ * to select which interface to use depending on the chip type.
+ */
+
+#include "opt_inet.h"
+#include "opt_ns.h"
+#include "bpfilter.h"
+#include "rnd.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_ether.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_inarp.h>
+#endif
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+#if NRND > 0
+#include <sys/rnd.h>
+#endif
+
+#include <machine/bus.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+/*
+ * Default to using PIO access for this driver. On SMP systems,
+ * there appear to be problems with memory mapped mode: it looks like
+ * doing too many memory mapped access back to back in rapid succession
+ * can hang the bus. I'm inclined to blame this on crummy design/construction
+ * on the part of RealTek. Memory mapped mode does appear to work on
+ * uniprocessor systems though.
+ */
+#define RL_USEIOSPACE
+
+#include <dev/pci/if_rlreg.h>
+
+/*
+ * Various supported device vendors/types and their names.
+ */
+static struct rl_type rl_devs[] = {
+ { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8129,
+ "RealTek 8129 10/100BaseTX" },
+ { PCI_VENDOR_REALTEK, PCI_PRODUCT_REALTEK_RT8139,
+ "RealTek 8139 10/100BaseTX" },
+ { PCI_VENDOR_ACCTON, PCI_PRODUCT_ACCTON_MPX5030,
+ "Accton MPX 5030/5038 10/100BaseTX" },
+ { PCI_VENDOR_DELTA, PCI_PRODUCT_DELTA_8139,
+ "Delta Electronics 8139 10/100BaseTX" },
+ { PCI_VENDOR_ADDTRON, PCI_PRODUCT_ADDTRON_8139,
+ "Addtron Technology 8139 10/100BaseTX" },
+#if 0
+ { SIS_VENDORID, SIS_DEVICEID_8139,
+ "SiS 900 10/100BaseTX" },
+#endif
+ { 0, 0, NULL }
+};
+
+static int rl_match __P((struct device *, struct cfdata *, void *));
+static void rl_attach __P((struct device *, struct device *, void *));
+
+static int rl_encap __P((struct rl_softc *, struct mbuf * ));
+
+static void rl_rxeof __P((struct rl_softc *));
+static void rl_txeof __P((struct rl_softc *));
+static int rl_intr __P((void *));
+static void rl_start __P((struct ifnet *));
+static int rl_ioctl __P((struct ifnet *, u_long, caddr_t));
+static void rl_init __P((void *));
+static void rl_stop __P((struct rl_softc *));
+static void rl_watchdog __P((struct ifnet *));
+static void rl_shutdown __P((void *));
+static int rl_ifmedia_upd __P((struct ifnet *));
+static void rl_ifmedia_sts __P((struct ifnet *, struct ifmediareq *));
+
+static void rl_eeprom_putbyte __P((struct rl_softc *, int));
+static void rl_eeprom_getword __P((struct rl_softc *, int, u_int16_t *));
+static void rl_read_eeprom __P((struct rl_softc *, caddr_t,
+ int, int, int));
+static void rl_mii_sync __P((struct rl_softc *));
+static void rl_mii_send __P((struct rl_softc *, u_int32_t, int));
+static int rl_mii_readreg __P((struct rl_softc *, struct rl_mii_frame *));
+static int rl_mii_writereg __P((struct rl_softc *, struct rl_mii_frame *));
+
+static int rl_phy_readreg __P((struct device *, int, int));
+static void rl_phy_writereg __P((struct device *, int, int, int));
+static void rl_phy_statchg __P((struct device *));
+static void rl_tick __P((void *));
+
+static u_int8_t rl_calchash __P((caddr_t));
+static void rl_setmulti __P((struct rl_softc *));
+static void rl_reset __P((struct rl_softc *));
+static int rl_list_tx_init __P((struct rl_softc *));
+
+static int rl_ether_ioctl __P((struct ifnet *, u_long, caddr_t));
+static int rl_allocsndbuf __P((struct rl_softc *, int));
+
+struct cfattach rl_ca = {
+ sizeof(struct rl_softc), rl_match, rl_attach
+};
+
+#define EE_SET(x) \
+ CSR_WRITE_1(sc, RL_EECMD, \
+ CSR_READ_1(sc, RL_EECMD) | x)
+
+#define EE_CLR(x) \
+ CSR_WRITE_1(sc, RL_EECMD, \
+ CSR_READ_1(sc, RL_EECMD) & ~x)
+
+/*
+ * Send a read command and address to the EEPROM, check for ACK.
+ */
+static void rl_eeprom_putbyte(sc, addr)
+ struct rl_softc *sc;
+ int addr;
+{
+ register int d, i;
+
+ d = addr | RL_EECMD_READ;
+
+ /*
+ * Feed in each bit and stobe the clock.
+ */
+ for (i = 0x400; i; i >>= 1) {
+ if (d & i) {
+ EE_SET(RL_EE_DATAIN);
+ } else {
+ EE_CLR(RL_EE_DATAIN);
+ }
+ DELAY(100);
+ EE_SET(RL_EE_CLK);
+ DELAY(150);
+ EE_CLR(RL_EE_CLK);
+ DELAY(100);
+ }
+
+ return;
+}
+
+/*
+ * Read a word of data stored in the EEPROM at address 'addr.'
+ */
+static void rl_eeprom_getword(sc, addr, dest)
+ struct rl_softc *sc;
+ int addr;
+ u_int16_t *dest;
+{
+ register int i;
+ u_int16_t word = 0;
+
+ /* Enter EEPROM access mode. */
+ CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_PROGRAM|RL_EE_SEL);
+
+ /*
+ * Send address of word we want to read.
+ */
+ rl_eeprom_putbyte(sc, addr);
+
+ CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_PROGRAM|RL_EE_SEL);
+
+ /*
+ * Start reading bits from EEPROM.
+ */
+ for (i = 0x8000; i; i >>= 1) {
+ EE_SET(RL_EE_CLK);
+ DELAY(100);
+ if (CSR_READ_1(sc, RL_EECMD) & RL_EE_DATAOUT)
+ word |= i;
+ EE_CLR(RL_EE_CLK);
+ DELAY(100);
+ }
+
+ /* Turn off EEPROM access mode. */
+ CSR_WRITE_1(sc, RL_EECMD, RL_EEMODE_OFF);
+
+ *dest = word;
+
+ return;
+}
+
+/*
+ * Read a sequence of words from the EEPROM.
+ */
+static void rl_read_eeprom(sc, dest, off, cnt, swap)
+ struct rl_softc *sc;
+ caddr_t dest;
+ int off;
+ int cnt;
+ int swap;
+{
Home |
Main Index |
Thread Index |
Old Index