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