8390: Move the 8390 related drivers
authorJeff Kirsher <jeffrey.t.kirsher@intel.com>
Sat, 2 Apr 2011 13:20:12 +0000 (06:20 -0700)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Thu, 11 Aug 2011 02:54:25 +0000 (19:54 -0700)
Moves the drivers for the National Semi-conductor 8390 chipset into
drivers/net/ethernet/8390/ and the necessary Kconfig and Makefile
changes.

CC: Donald Becker <becker@scyld.com>
CC: Paul Gortmaker <paul.gortmaker@windriver.com>
CC: Alain Malek <alain.malek@cryogen.com>
CC: Peter De Schrijver <p2@mind.be>
CC: "David Huggins-Daines" <dhd@debian.org>
CC: Wim Dumon <wimpie@kotnet.org>
CC: Yoshinori Sato <ysato@users.sourceforge.jp>
CC: David Hinds <dahinds@users.sourceforge.net>
CC: Russell King <linux@arm.linux.org.uk>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
71 files changed:
MAINTAINERS
drivers/net/3c503.c [deleted file]
drivers/net/3c503.h [deleted file]
drivers/net/8390.c [deleted file]
drivers/net/8390.h [deleted file]
drivers/net/8390p.c [deleted file]
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/ac3200.c [deleted file]
drivers/net/apne.c [deleted file]
drivers/net/arm/Kconfig
drivers/net/arm/Makefile
drivers/net/arm/etherh.c [deleted file]
drivers/net/ax88796.c [deleted file]
drivers/net/e2100.c [deleted file]
drivers/net/es3210.c [deleted file]
drivers/net/ethernet/8390/3c503.c [new file with mode: 0644]
drivers/net/ethernet/8390/3c503.h [new file with mode: 0644]
drivers/net/ethernet/8390/8390.c [new file with mode: 0644]
drivers/net/ethernet/8390/8390.h [new file with mode: 0644]
drivers/net/ethernet/8390/8390p.c [new file with mode: 0644]
drivers/net/ethernet/8390/Kconfig [new file with mode: 0644]
drivers/net/ethernet/8390/Makefile [new file with mode: 0644]
drivers/net/ethernet/8390/ac3200.c [new file with mode: 0644]
drivers/net/ethernet/8390/apne.c [new file with mode: 0644]
drivers/net/ethernet/8390/ax88796.c [new file with mode: 0644]
drivers/net/ethernet/8390/axnet_cs.c [new file with mode: 0644]
drivers/net/ethernet/8390/e2100.c [new file with mode: 0644]
drivers/net/ethernet/8390/es3210.c [new file with mode: 0644]
drivers/net/ethernet/8390/etherh.c [new file with mode: 0644]
drivers/net/ethernet/8390/hp-plus.c [new file with mode: 0644]
drivers/net/ethernet/8390/hp.c [new file with mode: 0644]
drivers/net/ethernet/8390/hydra.c [new file with mode: 0644]
drivers/net/ethernet/8390/lib8390.c [new file with mode: 0644]
drivers/net/ethernet/8390/lne390.c [new file with mode: 0644]
drivers/net/ethernet/8390/mac8390.c [new file with mode: 0644]
drivers/net/ethernet/8390/ne-h8300.c [new file with mode: 0644]
drivers/net/ethernet/8390/ne.c [new file with mode: 0644]
drivers/net/ethernet/8390/ne2.c [new file with mode: 0644]
drivers/net/ethernet/8390/ne2k-pci.c [new file with mode: 0644]
drivers/net/ethernet/8390/ne3210.c [new file with mode: 0644]
drivers/net/ethernet/8390/pcnet_cs.c [new file with mode: 0644]
drivers/net/ethernet/8390/smc-mca.c [new file with mode: 0644]
drivers/net/ethernet/8390/smc-ultra.c [new file with mode: 0644]
drivers/net/ethernet/8390/smc-ultra32.c [new file with mode: 0644]
drivers/net/ethernet/8390/stnic.c [new file with mode: 0644]
drivers/net/ethernet/8390/wd.c [new file with mode: 0644]
drivers/net/ethernet/8390/zorro8390.c [new file with mode: 0644]
drivers/net/ethernet/Kconfig
drivers/net/ethernet/Makefile
drivers/net/hp-plus.c [deleted file]
drivers/net/hp.c [deleted file]
drivers/net/hydra.c [deleted file]
drivers/net/lib8390.c [deleted file]
drivers/net/lne390.c [deleted file]
drivers/net/mac8390.c [deleted file]
drivers/net/ne-h8300.c [deleted file]
drivers/net/ne.c [deleted file]
drivers/net/ne2.c [deleted file]
drivers/net/ne2k-pci.c [deleted file]
drivers/net/ne3210.c [deleted file]
drivers/net/pcmcia/Kconfig
drivers/net/pcmcia/Makefile
drivers/net/pcmcia/axnet_cs.c [deleted file]
drivers/net/pcmcia/pcnet_cs.c [deleted file]
drivers/net/smc-mca.c [deleted file]
drivers/net/smc-ultra.c [deleted file]
drivers/net/smc-ultra32.c [deleted file]
drivers/net/stnic.c [deleted file]
drivers/net/wd.c [deleted file]
drivers/net/zorro8390.c [deleted file]

index 6f9dc946fc9bef1d883baa2623feee923a0e60f6..c6945830ea46d59bb073ff07d5b6c0b87f53710f 100644 (file)
@@ -170,8 +170,7 @@ F:  include/linux/serial_8250.h
 8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.]
 L:     netdev@vger.kernel.org
 S:     Orphan / Obsolete
-F:     drivers/net/*8390*
-F:     drivers/net/ax88796.c
+F:     drivers/net/ethernet/8390/
 
 9P FILE SYSTEM
 M:     Eric Van Hensbergen <ericvh@gmail.com>
@@ -6568,7 +6567,7 @@ W:        http://uclinux-h8.sourceforge.jp/
 S:     Supported
 F:     arch/h8300/
 F:     drivers/ide/ide-h8300.c
-F:     drivers/net/ne-h8300.c
+F:     drivers/net/ethernet/8390/ne-h8300.c
 
 UDF FILESYSTEM
 M:     Jan Kara <jack@suse.cz>
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
deleted file mode 100644 (file)
index 84e68f1..0000000
+++ /dev/null
@@ -1,778 +0,0 @@
-/* 3c503.c: A shared-memory NS8390 ethernet driver for linux. */
-/*
-    Written 1992-94 by Donald Becker.
-
-    Copyright 1993 United States Government as represented by the
-    Director, National Security Agency.  This software may be used and
-    distributed according to the terms of the GNU General Public License,
-    incorporated herein by reference.
-
-    The author may be reached as becker@scyld.com, or C/O
-       Scyld Computing Corporation
-       410 Severn Ave., Suite 210
-       Annapolis MD 21403
-
-
-    This driver should work with the 3c503 and 3c503/16.  It should be used
-    in shared memory mode for best performance, although it may also work
-    in programmed-I/O mode.
-
-    Sources:
-    EtherLink II Technical Reference Manual,
-    EtherLink II/16 Technical Reference Manual Supplement,
-    3Com Corporation, 5400 Bayfront Plaza, Santa Clara CA 95052-8145
-
-    The Crynwr 3c503 packet driver.
-
-    Changelog:
-
-    Paul Gortmaker     : add support for the 2nd 8kB of RAM on 16 bit cards.
-    Paul Gortmaker     : multiple card support for module users.
-    rjohnson@analogic.com : Fix up PIO interface for efficient operation.
-    Jeff Garzik                : ethtool support
-
-*/
-
-#define DRV_NAME       "3c503"
-#define DRV_VERSION    "1.10a"
-#define DRV_RELDATE    "11/17/2001"
-
-
-static const char version[] =
-    DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Donald Becker (becker@scyld.com)\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ethtool.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/byteorder.h>
-
-#include "8390.h"
-#include "3c503.h"
-#define WRD_COUNT 4
-
-static int el2_pio_probe(struct net_device *dev);
-static int el2_probe1(struct net_device *dev, int ioaddr);
-
-/* A zero-terminated list of I/O addresses to be probed in PIO mode. */
-static unsigned int netcard_portlist[] __initdata =
-       { 0x300,0x310,0x330,0x350,0x250,0x280,0x2a0,0x2e0,0};
-
-#define EL2_IO_EXTENT  16
-
-static int el2_open(struct net_device *dev);
-static int el2_close(struct net_device *dev);
-static void el2_reset_8390(struct net_device *dev);
-static void el2_init_card(struct net_device *dev);
-static void el2_block_output(struct net_device *dev, int count,
-                            const unsigned char *buf, int start_page);
-static void el2_block_input(struct net_device *dev, int count, struct sk_buff *skb,
-                          int ring_offset);
-static void el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                        int ring_page);
-static const struct ethtool_ops netdev_ethtool_ops;
-
-
-/* This routine probes for a memory-mapped 3c503 board by looking for
-   the "location register" at the end of the jumpered boot PROM space.
-   This works even if a PROM isn't there.
-
-   If the ethercard isn't found there is an optional probe for
-   ethercard jumpered to programmed-I/O mode.
-   */
-static int __init do_el2_probe(struct net_device *dev)
-{
-    int *addr, addrs[] = { 0xddffe, 0xd9ffe, 0xcdffe, 0xc9ffe, 0};
-    int base_addr = dev->base_addr;
-    int irq = dev->irq;
-
-    if (base_addr > 0x1ff)     /* Check a single specified location. */
-       return el2_probe1(dev, base_addr);
-    else if (base_addr != 0)           /* Don't probe at all. */
-       return -ENXIO;
-
-    for (addr = addrs; *addr; addr++) {
-       void __iomem *p = ioremap(*addr, 1);
-       unsigned base_bits;
-       int i;
-
-       if (!p)
-               continue;
-       base_bits = readb(p);
-       iounmap(p);
-       i = ffs(base_bits) - 1;
-       if (i == -1 || base_bits != (1 << i))
-           continue;
-       if (el2_probe1(dev, netcard_portlist[i]) == 0)
-           return 0;
-       dev->irq = irq;
-    }
-#if ! defined(no_probe_nonshared_memory)
-    return el2_pio_probe(dev);
-#else
-    return -ENODEV;
-#endif
-}
-
-/*  Try all of the locations that aren't obviously empty.  This touches
-    a lot of locations, and is much riskier than the code above. */
-static int __init
-el2_pio_probe(struct net_device *dev)
-{
-    int i;
-    int base_addr = dev->base_addr;
-    int irq = dev->irq;
-
-    if (base_addr > 0x1ff)     /* Check a single specified location. */
-       return el2_probe1(dev, base_addr);
-    else if (base_addr != 0)   /* Don't probe at all. */
-       return -ENXIO;
-
-    for (i = 0; netcard_portlist[i]; i++) {
-       if (el2_probe1(dev, netcard_portlist[i]) == 0)
-           return 0;
-       dev->irq = irq;
-    }
-
-    return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init el2_probe(int unit)
-{
-       struct net_device *dev = alloc_eip_netdev();
-       int err;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       sprintf(dev->name, "eth%d", unit);
-       netdev_boot_setup_check(dev);
-
-       err = do_el2_probe(dev);
-       if (err)
-               goto out;
-       return dev;
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-#endif
-
-static const struct net_device_ops el2_netdev_ops = {
-       .ndo_open               = el2_open,
-       .ndo_stop               = el2_close,
-
-       .ndo_start_xmit         = eip_start_xmit,
-       .ndo_tx_timeout         = eip_tx_timeout,
-       .ndo_get_stats          = eip_get_stats,
-       .ndo_set_multicast_list = eip_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = eip_poll,
-#endif
-};
-
-/* Probe for the Etherlink II card at I/O port base IOADDR,
-   returning non-zero on success.  If found, set the station
-   address and memory parameters in DEVICE. */
-static int __init
-el2_probe1(struct net_device *dev, int ioaddr)
-{
-    int i, iobase_reg, membase_reg, saved_406, wordlength, retval;
-    static unsigned version_printed;
-    unsigned long vendor_id;
-
-    if (!request_region(ioaddr, EL2_IO_EXTENT, DRV_NAME))
-       return -EBUSY;
-
-    if (!request_region(ioaddr + 0x400, 8, DRV_NAME)) {
-       retval = -EBUSY;
-       goto out;
-    }
-
-    /* Reset and/or avoid any lurking NE2000 */
-    if (inb(ioaddr + 0x408) == 0xff) {
-       mdelay(1);
-       retval = -ENODEV;
-       goto out1;
-    }
-
-    /* We verify that it's a 3C503 board by checking the first three octets
-       of its ethernet address. */
-    iobase_reg = inb(ioaddr+0x403);
-    membase_reg = inb(ioaddr+0x404);
-    /* ASIC location registers should be 0 or have only a single bit set. */
-    if ((iobase_reg  & (iobase_reg - 1)) ||
-       (membase_reg & (membase_reg - 1))) {
-       retval = -ENODEV;
-       goto out1;
-    }
-    saved_406 = inb_p(ioaddr + 0x406);
-    outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */
-    outb_p(ECNTRL_THIN, ioaddr + 0x406);
-    /* Map the station addr PROM into the lower I/O ports. We now check
-       for both the old and new 3Com prefix */
-    outb(ECNTRL_SAPROM|ECNTRL_THIN, ioaddr + 0x406);
-    vendor_id = inb(ioaddr)*0x10000 + inb(ioaddr + 1)*0x100 + inb(ioaddr + 2);
-    if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID)) {
-       /* Restore the register we frobbed. */
-       outb(saved_406, ioaddr + 0x406);
-       retval = -ENODEV;
-       goto out1;
-    }
-
-    if (ei_debug  &&  version_printed++ == 0)
-       pr_debug("%s", version);
-
-    dev->base_addr = ioaddr;
-
-    pr_info("%s: 3c503 at i/o base %#3x, node ", dev->name, ioaddr);
-
-    /* Retrieve and print the ethernet address. */
-    for (i = 0; i < 6; i++)
-       dev->dev_addr[i] = inb(ioaddr + i);
-    pr_cont("%pM", dev->dev_addr);
-
-    /* Map the 8390 back into the window. */
-    outb(ECNTRL_THIN, ioaddr + 0x406);
-
-    /* Check for EL2/16 as described in tech. man. */
-    outb_p(E8390_PAGE0, ioaddr + E8390_CMD);
-    outb_p(0, ioaddr + EN0_DCFG);
-    outb_p(E8390_PAGE2, ioaddr + E8390_CMD);
-    wordlength = inb_p(ioaddr + EN0_DCFG) & ENDCFG_WTS;
-    outb_p(E8390_PAGE0, ioaddr + E8390_CMD);
-
-    /* Probe for, turn on and clear the board's shared memory. */
-    if (ei_debug > 2)
-       pr_cont(" memory jumpers %2.2x ", membase_reg);
-    outb(EGACFR_NORM, ioaddr + 0x405); /* Enable RAM */
-
-    /* This should be probed for (or set via an ioctl()) at run-time.
-       Right now we use a sleazy hack to pass in the interface number
-       at boot-time via the low bits of the mem_end field.  That value is
-       unused, and the low bits would be discarded even if it was used. */
-#if defined(EI8390_THICK) || defined(EL2_AUI)
-    ei_status.interface_num = 1;
-#else
-    ei_status.interface_num = dev->mem_end & 0xf;
-#endif
-    pr_cont(", using %sternal xcvr.\n", ei_status.interface_num == 0 ? "in" : "ex");
-
-    if ((membase_reg & 0xf0) == 0) {
-       dev->mem_start = 0;
-       ei_status.name = "3c503-PIO";
-       ei_status.mem = NULL;
-    } else {
-       dev->mem_start = ((membase_reg & 0xc0) ? 0xD8000 : 0xC8000) +
-           ((membase_reg & 0xA0) ? 0x4000 : 0);
-#define EL2_MEMSIZE (EL2_MB1_STOP_PG - EL2_MB1_START_PG)*256
-       ei_status.mem = ioremap(dev->mem_start, EL2_MEMSIZE);
-
-#ifdef EL2MEMTEST
-       /* This has never found an error, but someone might care.
-          Note that it only tests the 2nd 8kB on 16kB 3c503/16
-          cards between card addr. 0x2000 and 0x3fff. */
-       {                       /* Check the card's memory. */
-           void __iomem *mem_base = ei_status.mem;
-           unsigned int test_val = 0xbbadf00d;
-           writel(0xba5eba5e, mem_base);
-           for (i = sizeof(test_val); i < EL2_MEMSIZE; i+=sizeof(test_val)) {
-               writel(test_val, mem_base + i);
-               if (readl(mem_base) != 0xba5eba5e ||
-                   readl(mem_base + i) != test_val) {
-                   pr_warning("3c503: memory failure or memory address conflict.\n");
-                   dev->mem_start = 0;
-                   ei_status.name = "3c503-PIO";
-                   iounmap(mem_base);
-                   ei_status.mem = NULL;
-                   break;
-               }
-               test_val += 0x55555555;
-               writel(0, mem_base + i);
-           }
-       }
-#endif  /* EL2MEMTEST */
-
-       if (dev->mem_start)
-               dev->mem_end = dev->mem_start + EL2_MEMSIZE;
-
-       if (wordlength) {       /* No Tx pages to skip over to get to Rx */
-               ei_status.priv = 0;
-               ei_status.name = "3c503/16";
-       } else {
-               ei_status.priv = TX_PAGES * 256;
-               ei_status.name = "3c503";
-       }
-    }
-
-    /*
-       Divide up the memory on the card. This is the same regardless of
-       whether shared-mem or PIO is used. For 16 bit cards (16kB RAM),
-       we use the entire 8k of bank1 for an Rx ring. We only use 3k
-       of the bank0 for 2 full size Tx packet slots. For 8 bit cards,
-       (8kB RAM) we use 3kB of bank1 for two Tx slots, and the remaining
-       5kB for an Rx ring.  */
-
-    if (wordlength) {
-       ei_status.tx_start_page = EL2_MB0_START_PG;
-       ei_status.rx_start_page = EL2_MB1_START_PG;
-    } else {
-       ei_status.tx_start_page = EL2_MB1_START_PG;
-       ei_status.rx_start_page = EL2_MB1_START_PG + TX_PAGES;
-    }
-
-    /* Finish setting the board's parameters. */
-    ei_status.stop_page = EL2_MB1_STOP_PG;
-    ei_status.word16 = wordlength;
-    ei_status.reset_8390 = el2_reset_8390;
-    ei_status.get_8390_hdr = el2_get_8390_hdr;
-    ei_status.block_input = el2_block_input;
-    ei_status.block_output = el2_block_output;
-
-    if (dev->irq == 2)
-       dev->irq = 9;
-    else if (dev->irq > 5 && dev->irq != 9) {
-       pr_warning("3c503: configured interrupt %d invalid, will use autoIRQ.\n",
-              dev->irq);
-       dev->irq = 0;
-    }
-
-    ei_status.saved_irq = dev->irq;
-
-    dev->netdev_ops = &el2_netdev_ops;
-    dev->ethtool_ops = &netdev_ethtool_ops;
-
-    retval = register_netdev(dev);
-    if (retval)
-       goto out1;
-
-    if (dev->mem_start)
-       pr_info("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n",
-               dev->name, ei_status.name, (wordlength+1)<<3,
-               dev->mem_start, dev->mem_end-1);
-
-    else
-    {
-       ei_status.tx_start_page = EL2_MB1_START_PG;
-       ei_status.rx_start_page = EL2_MB1_START_PG + TX_PAGES;
-       pr_info("%s: %s, %dkB RAM, using programmed I/O (REJUMPER for SHARED MEMORY).\n",
-              dev->name, ei_status.name, (wordlength+1)<<3);
-    }
-    release_region(ioaddr + 0x400, 8);
-    return 0;
-out1:
-    release_region(ioaddr + 0x400, 8);
-out:
-    release_region(ioaddr, EL2_IO_EXTENT);
-    return retval;
-}
-
-static irqreturn_t el2_probe_interrupt(int irq, void *seen)
-{
-       *(bool *)seen = true;
-       return IRQ_HANDLED;
-}
-
-static int
-el2_open(struct net_device *dev)
-{
-    int retval;
-
-    if (dev->irq < 2) {
-       static const int irqlist[] = {5, 9, 3, 4, 0};
-       const int *irqp = irqlist;
-
-       outb(EGACFR_NORM, E33G_GACFR);  /* Enable RAM and interrupts. */
-       do {
-               bool seen;
-
-               retval = request_irq(*irqp, el2_probe_interrupt, 0,
-                                    dev->name, &seen);
-               if (retval == -EBUSY)
-                       continue;
-               if (retval < 0)
-                       goto err_disable;
-
-               /* Twinkle the interrupt, and check if it's seen. */
-               seen = false;
-               smp_wmb();
-               outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
-               outb_p(0x00, E33G_IDCFR);
-               msleep(1);
-               free_irq(*irqp, &seen);
-               if (!seen)
-                       continue;
-
-               retval = request_irq(dev->irq = *irqp, eip_interrupt, 0,
-                                    dev->name, dev);
-               if (retval == -EBUSY)
-                       continue;
-               if (retval < 0)
-                       goto err_disable;
-               break;
-       } while (*++irqp);
-
-       if (*irqp == 0) {
-       err_disable:
-           outb(EGACFR_IRQOFF, E33G_GACFR);    /* disable interrupts. */
-           return -EAGAIN;
-       }
-    } else {
-       if ((retval = request_irq(dev->irq, eip_interrupt, 0, dev->name, dev))) {
-           return retval;
-       }
-    }
-
-    el2_init_card(dev);
-    eip_open(dev);
-    return 0;
-}
-
-static int
-el2_close(struct net_device *dev)
-{
-    free_irq(dev->irq, dev);
-    dev->irq = ei_status.saved_irq;
-    outb(EGACFR_IRQOFF, E33G_GACFR);   /* disable interrupts. */
-
-    eip_close(dev);
-    return 0;
-}
-
-/* This is called whenever we have a unrecoverable failure:
-       transmit timeout
-       Bad ring buffer packet header
- */
-static void
-el2_reset_8390(struct net_device *dev)
-{
-    if (ei_debug > 1) {
-       pr_debug("%s: Resetting the 3c503 board...", dev->name);
-       pr_cont(" %#lx=%#02x %#lx=%#02x %#lx=%#02x...", E33G_IDCFR, inb(E33G_IDCFR),
-              E33G_CNTRL, inb(E33G_CNTRL), E33G_GACFR, inb(E33G_GACFR));
-    }
-    outb_p(ECNTRL_RESET|ECNTRL_THIN, E33G_CNTRL);
-    ei_status.txing = 0;
-    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
-    el2_init_card(dev);
-    if (ei_debug > 1)
-       pr_cont("done\n");
-}
-
-/* Initialize the 3c503 GA registers after a reset. */
-static void
-el2_init_card(struct net_device *dev)
-{
-    /* Unmap the station PROM and select the DIX or BNC connector. */
-    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
-
-    /* Set ASIC copy of rx's first and last+1 buffer pages */
-    /* These must be the same as in the 8390. */
-    outb(ei_status.rx_start_page, E33G_STARTPG);
-    outb(ei_status.stop_page,  E33G_STOPPG);
-
-    /* Point the vector pointer registers somewhere ?harmless?. */
-    outb(0xff, E33G_VP2);      /* Point at the ROM restart location 0xffff0 */
-    outb(0xff, E33G_VP1);
-    outb(0x00, E33G_VP0);
-    /* Turn off all interrupts until we're opened. */
-    outb_p(0x00,  dev->base_addr + EN0_IMR);
-    /* Enable IRQs iff started. */
-    outb(EGACFR_NORM, E33G_GACFR);
-
-    /* Set the interrupt line. */
-    outb_p((0x04 << (dev->irq == 9 ? 2 : dev->irq)), E33G_IDCFR);
-    outb_p((WRD_COUNT << 1), E33G_DRQCNT);     /* Set burst size to 8 */
-    outb_p(0x20, E33G_DMAAH);  /* Put a valid addr in the GA DMA */
-    outb_p(0x00, E33G_DMAAL);
-    return;                    /* We always succeed */
-}
-
-/*
- * Either use the shared memory (if enabled on the board) or put the packet
- * out through the ASIC FIFO.
- */
-static void
-el2_block_output(struct net_device *dev, int count,
-                const unsigned char *buf, int start_page)
-{
-    unsigned short int *wrd;
-    int boguscount;            /* timeout counter */
-    unsigned short word;       /* temporary for better machine code */
-    void __iomem *base = ei_status.mem;
-
-    if (ei_status.word16)      /* Tx packets go into bank 0 on EL2/16 card */
-       outb(EGACFR_RSEL|EGACFR_TCM, E33G_GACFR);
-    else
-       outb(EGACFR_NORM, E33G_GACFR);
-
-    if (base) {        /* Shared memory transfer */
-       memcpy_toio(base + ((start_page - ei_status.tx_start_page) << 8),
-                       buf, count);
-       outb(EGACFR_NORM, E33G_GACFR);  /* Back to bank1 in case on bank0 */
-       return;
-    }
-
-/*
- *  No shared memory, put the packet out the other way.
- *  Set up then start the internal memory transfer to Tx Start Page
- */
-
-    word = (unsigned short)start_page;
-    outb(word&0xFF, E33G_DMAAH);
-    outb(word>>8, E33G_DMAAL);
-
-    outb_p((ei_status.interface_num ? ECNTRL_AUI : ECNTRL_THIN ) | ECNTRL_OUTPUT
-          | ECNTRL_START, E33G_CNTRL);
-
-/*
- *  Here I am going to write data to the FIFO as quickly as possible.
- *  Note that E33G_FIFOH is defined incorrectly. It is really
- *  E33G_FIFOL, the lowest port address for both the byte and
- *  word write. Variable 'count' is NOT checked. Caller must supply a
- *  valid count. Note that I may write a harmless extra byte to the
- *  8390 if the byte-count was not even.
- */
-    wrd = (unsigned short int *) buf;
-    count  = (count + 1) >> 1;
-    for(;;)
-    {
-        boguscount = 0x1000;
-        while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
-        {
-            if(!boguscount--)
-            {
-                pr_notice("%s: FIFO blocked in el2_block_output.\n", dev->name);
-                el2_reset_8390(dev);
-                goto blocked;
-            }
-        }
-        if(count > WRD_COUNT)
-        {
-            outsw(E33G_FIFOH, wrd, WRD_COUNT);
-            wrd   += WRD_COUNT;
-            count -= WRD_COUNT;
-        }
-        else
-        {
-            outsw(E33G_FIFOH, wrd, count);
-            break;
-        }
-    }
-    blocked:;
-    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
-}
-
-/* Read the 4 byte, page aligned 8390 specific header. */
-static void
-el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-    int boguscount;
-    void __iomem *base = ei_status.mem;
-    unsigned short word;
-
-    if (base) {       /* Use the shared memory. */
-       void __iomem *hdr_start = base + ((ring_page - EL2_MB1_START_PG)<<8);
-       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
-       hdr->count = le16_to_cpu(hdr->count);
-       return;
-    }
-
-/*
- *  No shared memory, use programmed I/O.
- */
-
-    word = (unsigned short)ring_page;
-    outb(word&0xFF, E33G_DMAAH);
-    outb(word>>8, E33G_DMAAL);
-
-    outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT
-          | ECNTRL_START, E33G_CNTRL);
-    boguscount = 0x1000;
-    while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
-    {
-        if(!boguscount--)
-        {
-            pr_notice("%s: FIFO blocked in el2_get_8390_hdr.\n", dev->name);
-            memset(hdr, 0x00, sizeof(struct e8390_pkt_hdr));
-            el2_reset_8390(dev);
-            goto blocked;
-        }
-    }
-    insw(E33G_FIFOH, hdr, (sizeof(struct e8390_pkt_hdr))>> 1);
-    blocked:;
-    outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
-}
-
-
-static void
-el2_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-    int boguscount = 0;
-    void __iomem *base = ei_status.mem;
-    unsigned short int *buf;
-    unsigned short word;
-
-    /* Maybe enable shared memory just be to be safe... nahh.*/
-    if (base) {        /* Use the shared memory. */
-       ring_offset -= (EL2_MB1_START_PG<<8);
-       if (ring_offset + count > EL2_MEMSIZE) {
-           /* We must wrap the input move. */
-           int semi_count = EL2_MEMSIZE - ring_offset;
-           memcpy_fromio(skb->data, base + ring_offset, semi_count);
-           count -= semi_count;
-           memcpy_fromio(skb->data + semi_count, base + ei_status.priv, count);
-       } else {
-               memcpy_fromio(skb->data, base + ring_offset, count);
-       }
-       return;
-    }
-
-/*
- *  No shared memory, use programmed I/O.
- */
-    word = (unsigned short) ring_offset;
-    outb(word>>8, E33G_DMAAH);
-    outb(word&0xFF, E33G_DMAAL);
-
-    outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT
-          | ECNTRL_START, E33G_CNTRL);
-
-/*
- *  Here I also try to get data as fast as possible. I am betting that I
- *  can read one extra byte without clobbering anything in the kernel because
- *  this would only occur on an odd byte-count and allocation of skb->data
- *  is word-aligned. Variable 'count' is NOT checked. Caller must check
- *  for a valid count.
- *  [This is currently quite safe.... but if one day the 3c503 explodes
- *   you know where to come looking ;)]
- */
-
-    buf =  (unsigned short int *) skb->data;
-    count =  (count + 1) >> 1;
-    for(;;)
-    {
-        boguscount = 0x1000;
-        while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
-        {
-            if(!boguscount--)
-            {
-                pr_notice("%s: FIFO blocked in el2_block_input.\n", dev->name);
-                el2_reset_8390(dev);
-                goto blocked;
-            }
-        }
-        if(count > WRD_COUNT)
-        {
-            insw(E33G_FIFOH, buf, WRD_COUNT);
-            buf   += WRD_COUNT;
-            count -= WRD_COUNT;
-        }
-        else
-        {
-            insw(E33G_FIFOH, buf, count);
-            break;
-        }
-    }
-    blocked:;
-    outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
-}
-
-
-static void netdev_get_drvinfo(struct net_device *dev,
-                              struct ethtool_drvinfo *info)
-{
-       strcpy(info->driver, DRV_NAME);
-       strcpy(info->version, DRV_VERSION);
-       sprintf(info->bus_info, "ISA 0x%lx", dev->base_addr);
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-       .get_drvinfo            = netdev_get_drvinfo,
-};
-
-#ifdef MODULE
-#define MAX_EL2_CARDS  4       /* Max number of EL2 cards per module */
-
-static struct net_device *dev_el2[MAX_EL2_CARDS];
-static int io[MAX_EL2_CARDS];
-static int irq[MAX_EL2_CARDS];
-static int xcvr[MAX_EL2_CARDS];        /* choose int. or ext. xcvr */
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(xcvr, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
-MODULE_PARM_DESC(xcvr, "transceiver(s) (0=internal, 1=external)");
-MODULE_DESCRIPTION("3Com ISA EtherLink II, II/16 (3c503, 3c503/16) driver");
-MODULE_LICENSE("GPL");
-
-/* This is set up so that only a single autoprobe takes place per call.
-ISA device autoprobes on a running machine are not recommended. */
-int __init
-init_module(void)
-{
-       struct net_device *dev;
-       int this_dev, found = 0;
-
-       for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) {
-               if (io[this_dev] == 0)  {
-                       if (this_dev != 0) break; /* only autoprobe 1st one */
-                       pr_notice("3c503.c: Presently autoprobing (not recommended) for a single card.\n");
-               }
-               dev = alloc_eip_netdev();
-               if (!dev)
-                       break;
-               dev->irq = irq[this_dev];
-               dev->base_addr = io[this_dev];
-               dev->mem_end = xcvr[this_dev];  /* low 4bits = xcvr sel. */
-               if (do_el2_probe(dev) == 0) {
-                       dev_el2[found++] = dev;
-                       continue;
-               }
-               free_netdev(dev);
-               pr_warning("3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]);
-               break;
-       }
-       if (found)
-               return 0;
-       return -ENXIO;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-       /* NB: el2_close() handles free_irq */
-       release_region(dev->base_addr, EL2_IO_EXTENT);
-       if (ei_status.mem)
-               iounmap(ei_status.mem);
-}
-
-void __exit
-cleanup_module(void)
-{
-       int this_dev;
-
-       for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) {
-               struct net_device *dev = dev_el2[this_dev];
-               if (dev) {
-                       unregister_netdev(dev);
-                       cleanup_card(dev);
-                       free_netdev(dev);
-               }
-       }
-}
-#endif /* MODULE */
diff --git a/drivers/net/3c503.h b/drivers/net/3c503.h
deleted file mode 100644 (file)
index e2367b8..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/* Definitions for the 3Com 3c503 Etherlink 2. */
-/* This file is distributed under the GPL.
-   Many of these names and comments are directly from the Crynwr packet
-   drivers, which are released under the GPL. */
-
-#define EL2H (dev->base_addr + 0x400)
-#define EL2L (dev->base_addr)
-
-/* Vendor unique hardware addr. prefix. 3Com has 2 because they ran
-   out of available addresses on the first one... */
-
-#define OLD_3COM_ID    0x02608c
-#define NEW_3COM_ID    0x0020af
-
-/* Shared memory management parameters. NB: The 8 bit cards have only
-   one bank (MB1) which serves both Tx and Rx packet space. The 16bit
-   cards have 2 banks, MB0 for Tx packets, and MB1 for Rx packets.
-   You choose which bank appears in the sh. mem window with EGACFR_MBSn */
-
-#define EL2_MB0_START_PG       (0x00)  /* EL2/16 Tx packets go in bank 0 */
-#define EL2_MB1_START_PG       (0x20)  /* First page of bank 1 */
-#define EL2_MB1_STOP_PG                (0x40)  /* Last page +1 of bank 1 */
-
-/* 3Com 3c503 ASIC registers */
-#define E33G_STARTPG   (EL2H+0)        /* Start page, matching EN0_STARTPG */
-#define E33G_STOPPG    (EL2H+1)        /* Stop page, must match EN0_STOPPG */
-#define E33G_DRQCNT    (EL2H+2)        /* DMA burst count */
-#define E33G_IOBASE    (EL2H+3)        /* Read of I/O base jumpers. */
-       /* (non-useful, but it also appears at the end of EPROM space) */
-#define E33G_ROMBASE   (EL2H+4)        /* Read of memory base jumpers. */
-#define E33G_GACFR     (EL2H+5)        /* Config/setup bits for the ASIC GA */
-#define E33G_CNTRL     (EL2H+6)        /* Board's main control register */
-#define E33G_STATUS    (EL2H+7)        /* Status on completions. */
-#define E33G_IDCFR     (EL2H+8)        /* Interrupt/DMA config register */
-                               /* (Which IRQ to assert, DMA chan to use) */
-#define E33G_DMAAH     (EL2H+9)        /* High byte of DMA address reg */
-#define E33G_DMAAL     (EL2H+10)       /* Low byte of DMA address reg */
-/* "Vector pointer" - if this address matches a read, the EPROM (rather than
-   shared RAM) is mapped into memory space. */
-#define E33G_VP2       (EL2H+11)
-#define E33G_VP1       (EL2H+12)
-#define E33G_VP0       (EL2H+13)
-#define E33G_FIFOH     (EL2H+14)       /* FIFO for programmed I/O moves */
-#define E33G_FIFOL     (EL2H+15)       /* ... low byte of above. */
-
-/* Bits in E33G_CNTRL register: */
-
-#define ECNTRL_RESET   (0x01)  /* Software reset of the ASIC and 8390 */
-#define ECNTRL_THIN    (0x02)  /* Onboard xcvr enable, AUI disable */
-#define ECNTRL_AUI     (0x00)  /* Onboard xcvr disable, AUI enable */
-#define ECNTRL_SAPROM  (0x04)  /* Map the station address prom */
-#define ECNTRL_DBLBFR  (0x20)  /* FIFO configuration bit */
-#define ECNTRL_OUTPUT  (0x40)  /* PC-to-3C503 direction if 1 */
-#define ECNTRL_INPUT   (0x00)  /* 3C503-to-PC direction if 0 */
-#define ECNTRL_START   (0x80)  /* Start the DMA logic */
-
-/* Bits in E33G_STATUS register: */
-
-#define ESTAT_DPRDY    (0x80)  /* Data port (of FIFO) ready */
-#define ESTAT_UFLW     (0x40)  /* Tried to read FIFO when it was empty */
-#define ESTAT_OFLW     (0x20)  /* Tried to write FIFO when it was full */
-#define ESTAT_DTC      (0x10)  /* Terminal Count from PC bus DMA logic */
-#define ESTAT_DIP      (0x08)  /* DMA In Progress */
-
-/* Bits in E33G_GACFR register: */
-
-#define EGACFR_NIM     (0x80)  /* NIC interrupt mask */
-#define EGACFR_TCM     (0x40)  /* DMA term. count interrupt mask */
-#define EGACFR_RSEL    (0x08)  /* Map a bank of card mem into system mem */
-#define EGACFR_MBS2    (0x04)  /* Memory bank select, bit 2. */
-#define EGACFR_MBS1    (0x02)  /* Memory bank select, bit 1. */
-#define EGACFR_MBS0    (0x01)  /* Memory bank select, bit 0. */
-
-#define EGACFR_NORM    (0x49)  /* TCM | RSEL | MBS0 */
-#define EGACFR_IRQOFF  (0xc9)  /* TCM | RSEL | MBS0 | NIM */
-
-/*
-       MBS2    MBS1    MBS0    Sh. mem windows card mem at:
-       ----    ----    ----    -----------------------------
-       0       0       0       0x0000 -- bank 0
-       0       0       1       0x2000 -- bank 1 (only choice for 8bit card)
-       0       1       0       0x4000 -- bank 2, not used
-       0       1       1       0x6000 -- bank 3, not used
-
-There was going to be a 32k card that used bank 2 and 3, but it
-never got produced.
-
-*/
-
-
-/* End of 3C503 parameter definitions */
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
deleted file mode 100644 (file)
index 7c7518b..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/* 8390 core for usual drivers */
-
-static const char version[] =
-    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include "lib8390.c"
-
-int ei_open(struct net_device *dev)
-{
-       return __ei_open(dev);
-}
-EXPORT_SYMBOL(ei_open);
-
-int ei_close(struct net_device *dev)
-{
-       return __ei_close(dev);
-}
-EXPORT_SYMBOL(ei_close);
-
-netdev_tx_t ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-       return __ei_start_xmit(skb, dev);
-}
-EXPORT_SYMBOL(ei_start_xmit);
-
-struct net_device_stats *ei_get_stats(struct net_device *dev)
-{
-       return __ei_get_stats(dev);
-}
-EXPORT_SYMBOL(ei_get_stats);
-
-void ei_set_multicast_list(struct net_device *dev)
-{
-       __ei_set_multicast_list(dev);
-}
-EXPORT_SYMBOL(ei_set_multicast_list);
-
-void ei_tx_timeout(struct net_device *dev)
-{
-       __ei_tx_timeout(dev);
-}
-EXPORT_SYMBOL(ei_tx_timeout);
-
-irqreturn_t ei_interrupt(int irq, void *dev_id)
-{
-       return __ei_interrupt(irq, dev_id);
-}
-EXPORT_SYMBOL(ei_interrupt);
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-void ei_poll(struct net_device *dev)
-{
-       __ei_poll(dev);
-}
-EXPORT_SYMBOL(ei_poll);
-#endif
-
-const struct net_device_ops ei_netdev_ops = {
-       .ndo_open               = ei_open,
-       .ndo_stop               = ei_close,
-       .ndo_start_xmit         = ei_start_xmit,
-       .ndo_tx_timeout         = ei_tx_timeout,
-       .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = ei_poll,
-#endif
-};
-EXPORT_SYMBOL(ei_netdev_ops);
-
-struct net_device *__alloc_ei_netdev(int size)
-{
-       struct net_device *dev = ____alloc_ei_netdev(size);
-       if (dev)
-               dev->netdev_ops = &ei_netdev_ops;
-       return dev;
-}
-EXPORT_SYMBOL(__alloc_ei_netdev);
-
-void NS8390_init(struct net_device *dev, int startp)
-{
-       __NS8390_init(dev, startp);
-}
-EXPORT_SYMBOL(NS8390_init);
-
-#if defined(MODULE)
-
-static int __init ns8390_module_init(void)
-{
-       return 0;
-}
-
-static void __exit ns8390_module_exit(void)
-{
-}
-
-module_init(ns8390_module_init);
-module_exit(ns8390_module_exit);
-#endif /* MODULE */
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
deleted file mode 100644 (file)
index 58a12e4..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/* Generic NS8390 register definitions. */
-/* This file is part of Donald Becker's 8390 drivers, and is distributed
-   under the same license. Auto-loading of 8390.o only in v2.2 - Paul G.
-   Some of these names and comments originated from the Crynwr
-   packet drivers, which are distributed under the GPL. */
-
-#ifndef _8390_h
-#define _8390_h
-
-#include <linux/if_ether.h>
-#include <linux/ioport.h>
-#include <linux/irqreturn.h>
-#include <linux/skbuff.h>
-
-#define TX_PAGES 12    /* Two Tx slots */
-
-#define ETHER_ADDR_LEN 6
-
-/* The 8390 specific per-packet-header format. */
-struct e8390_pkt_hdr {
-  unsigned char status; /* status */
-  unsigned char next;   /* pointer to next packet. */
-  unsigned short count; /* header + packet length in bytes */
-};
-
-#ifdef notdef
-extern int ei_debug;
-#else
-#define ei_debug 1
-#endif
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-extern void ei_poll(struct net_device *dev);
-extern void eip_poll(struct net_device *dev);
-#endif
-
-
-/* Without I/O delay - non ISA or later chips */
-extern void NS8390_init(struct net_device *dev, int startp);
-extern int ei_open(struct net_device *dev);
-extern int ei_close(struct net_device *dev);
-extern irqreturn_t ei_interrupt(int irq, void *dev_id);
-extern void ei_tx_timeout(struct net_device *dev);
-extern netdev_tx_t ei_start_xmit(struct sk_buff *skb, struct net_device *dev);
-extern void ei_set_multicast_list(struct net_device *dev);
-extern struct net_device_stats *ei_get_stats(struct net_device *dev);
-
-extern const struct net_device_ops ei_netdev_ops;
-
-extern struct net_device *__alloc_ei_netdev(int size);
-static inline struct net_device *alloc_ei_netdev(void)
-{
-       return __alloc_ei_netdev(0);
-}
-
-/* With I/O delay form */
-extern void NS8390p_init(struct net_device *dev, int startp);
-extern int eip_open(struct net_device *dev);
-extern int eip_close(struct net_device *dev);
-extern irqreturn_t eip_interrupt(int irq, void *dev_id);
-extern void eip_tx_timeout(struct net_device *dev);
-extern netdev_tx_t eip_start_xmit(struct sk_buff *skb, struct net_device *dev);
-extern void eip_set_multicast_list(struct net_device *dev);
-extern struct net_device_stats *eip_get_stats(struct net_device *dev);
-
-extern const struct net_device_ops eip_netdev_ops;
-
-extern struct net_device *__alloc_eip_netdev(int size);
-static inline struct net_device *alloc_eip_netdev(void)
-{
-       return __alloc_eip_netdev(0);
-}
-
-/* You have one of these per-board */
-struct ei_device {
-       const char *name;
-       void (*reset_8390)(struct net_device *);
-       void (*get_8390_hdr)(struct net_device *, struct e8390_pkt_hdr *, int);
-       void (*block_output)(struct net_device *, int, const unsigned char *, int);
-       void (*block_input)(struct net_device *, int, struct sk_buff *, int);
-       unsigned long rmem_start;
-       unsigned long rmem_end;
-       void __iomem *mem;
-       unsigned char mcfilter[8];
-       unsigned open:1;
-       unsigned word16:1;              /* We have the 16-bit (vs 8-bit) version of the card. */
-       unsigned bigendian:1;           /* 16-bit big endian mode. Do NOT */
-                                       /* set this on random 8390 clones! */
-       unsigned txing:1;               /* Transmit Active */
-       unsigned irqlock:1;             /* 8390's intrs disabled when '1'. */
-       unsigned dmaing:1;              /* Remote DMA Active */
-       unsigned char tx_start_page, rx_start_page, stop_page;
-       unsigned char current_page;     /* Read pointer in buffer  */
-       unsigned char interface_num;    /* Net port (AUI, 10bT.) to use. */
-       unsigned char txqueue;          /* Tx Packet buffer queue length. */
-       short tx1, tx2;                 /* Packet lengths for ping-pong tx. */
-       short lasttx;                   /* Alpha version consistency check. */
-       unsigned char reg0;             /* Register '0' in a WD8013 */
-       unsigned char reg5;             /* Register '5' in a WD8013 */
-       unsigned char saved_irq;        /* Original dev->irq value. */
-       u32 *reg_offset;                /* Register mapping table */
-       spinlock_t page_lock;           /* Page register locks */
-       unsigned long priv;             /* Private field to store bus IDs etc. */
-#ifdef AX88796_PLATFORM
-       unsigned char rxcr_base;        /* default value for RXCR */
-#endif
-};
-
-/* The maximum number of 8390 interrupt service routines called per IRQ. */
-#define MAX_SERVICE 12
-
-/* The maximum time waited (in jiffies) before assuming a Tx failed. (20ms) */
-#define TX_TIMEOUT (20*HZ/100)
-
-#define ei_status (*(struct ei_device *)netdev_priv(dev))
-
-/* Some generic ethernet register configurations. */
-#define E8390_TX_IRQ_MASK      0xa     /* For register EN0_ISR */
-#define E8390_RX_IRQ_MASK      0x5
-
-#ifdef AX88796_PLATFORM
-#define E8390_RXCONFIG         (ei_status.rxcr_base | 0x04)
-#define E8390_RXOFF            (ei_status.rxcr_base | 0x20)
-#else
-#define E8390_RXCONFIG         0x4     /* EN0_RXCR: broadcasts, no multicast,errors */
-#define E8390_RXOFF            0x20    /* EN0_RXCR: Accept no packets */
-#endif
-
-#define E8390_TXCONFIG         0x00    /* EN0_TXCR: Normal transmit mode */
-#define E8390_TXOFF            0x02    /* EN0_TXCR: Transmitter off */
-
-
-/*  Register accessed at EN_CMD, the 8390 base addr.  */
-#define E8390_STOP     0x01    /* Stop and reset the chip */
-#define E8390_START    0x02    /* Start the chip, clear reset */
-#define E8390_TRANS    0x04    /* Transmit a frame */
-#define E8390_RREAD    0x08    /* Remote read */
-#define E8390_RWRITE   0x10    /* Remote write  */
-#define E8390_NODMA    0x20    /* Remote DMA */
-#define E8390_PAGE0    0x00    /* Select page chip registers */
-#define E8390_PAGE1    0x40    /* using the two high-order bits */
-#define E8390_PAGE2    0x80    /* Page 3 is invalid. */
-
-/*
- *     Only generate indirect loads given a machine that needs them.
- *      - removed AMIGA_PCMCIA from this list, handled as ISA io now
- *     - the _p for generates no delay by default 8390p.c overrides this.
- */
-
-#ifndef ei_inb
-#define ei_inb(_p)     inb(_p)
-#define ei_outb(_v,_p) outb(_v,_p)
-#define ei_inb_p(_p)   inb(_p)
-#define ei_outb_p(_v,_p) outb(_v,_p)
-#endif
-
-#ifndef EI_SHIFT
-#define EI_SHIFT(x)    (x)
-#endif
-
-#define E8390_CMD      EI_SHIFT(0x00)  /* The command register (for all pages) */
-/* Page 0 register offsets. */
-#define EN0_CLDALO     EI_SHIFT(0x01)  /* Low byte of current local dma addr  RD */
-#define EN0_STARTPG    EI_SHIFT(0x01)  /* Starting page of ring bfr WR */
-#define EN0_CLDAHI     EI_SHIFT(0x02)  /* High byte of current local dma addr  RD */
-#define EN0_STOPPG     EI_SHIFT(0x02)  /* Ending page +1 of ring bfr WR */
-#define EN0_BOUNDARY   EI_SHIFT(0x03)  /* Boundary page of ring bfr RD WR */
-#define EN0_TSR                EI_SHIFT(0x04)  /* Transmit status reg RD */
-#define EN0_TPSR       EI_SHIFT(0x04)  /* Transmit starting page WR */
-#define EN0_NCR                EI_SHIFT(0x05)  /* Number of collision reg RD */
-#define EN0_TCNTLO     EI_SHIFT(0x05)  /* Low  byte of tx byte count WR */
-#define EN0_FIFO       EI_SHIFT(0x06)  /* FIFO RD */
-#define EN0_TCNTHI     EI_SHIFT(0x06)  /* High byte of tx byte count WR */
-#define EN0_ISR                EI_SHIFT(0x07)  /* Interrupt status reg RD WR */
-#define EN0_CRDALO     EI_SHIFT(0x08)  /* low byte of current remote dma address RD */
-#define EN0_RSARLO     EI_SHIFT(0x08)  /* Remote start address reg 0 */
-#define EN0_CRDAHI     EI_SHIFT(0x09)  /* high byte, current remote dma address RD */
-#define EN0_RSARHI     EI_SHIFT(0x09)  /* Remote start address reg 1 */
-#define EN0_RCNTLO     EI_SHIFT(0x0a)  /* Remote byte count reg WR */
-#define EN0_RCNTHI     EI_SHIFT(0x0b)  /* Remote byte count reg WR */
-#define EN0_RSR                EI_SHIFT(0x0c)  /* rx status reg RD */
-#define EN0_RXCR       EI_SHIFT(0x0c)  /* RX configuration reg WR */
-#define EN0_TXCR       EI_SHIFT(0x0d)  /* TX configuration reg WR */
-#define EN0_COUNTER0   EI_SHIFT(0x0d)  /* Rcv alignment error counter RD */
-#define EN0_DCFG       EI_SHIFT(0x0e)  /* Data configuration reg WR */
-#define EN0_COUNTER1   EI_SHIFT(0x0e)  /* Rcv CRC error counter RD */
-#define EN0_IMR                EI_SHIFT(0x0f)  /* Interrupt mask reg WR */
-#define EN0_COUNTER2   EI_SHIFT(0x0f)  /* Rcv missed frame error counter RD */
-
-/* Bits in EN0_ISR - Interrupt status register */
-#define ENISR_RX       0x01    /* Receiver, no error */
-#define ENISR_TX       0x02    /* Transmitter, no error */
-#define ENISR_RX_ERR   0x04    /* Receiver, with error */
-#define ENISR_TX_ERR   0x08    /* Transmitter, with error */
-#define ENISR_OVER     0x10    /* Receiver overwrote the ring */
-#define ENISR_COUNTERS 0x20    /* Counters need emptying */
-#define ENISR_RDC      0x40    /* remote dma complete */
-#define ENISR_RESET    0x80    /* Reset completed */
-#define ENISR_ALL      0x3f    /* Interrupts we will enable */
-
-/* Bits in EN0_DCFG - Data config register */
-#define ENDCFG_WTS     0x01    /* word transfer mode selection */
-#define ENDCFG_BOS     0x02    /* byte order selection */
-
-/* Page 1 register offsets. */
-#define EN1_PHYS   EI_SHIFT(0x01)      /* This board's physical enet addr RD WR */
-#define EN1_PHYS_SHIFT(i)  EI_SHIFT(i+1) /* Get and set mac address */
-#define EN1_CURPAG EI_SHIFT(0x07)      /* Current memory page RD WR */
-#define EN1_MULT   EI_SHIFT(0x08)      /* Multicast filter mask array (8 bytes) RD WR */
-#define EN1_MULT_SHIFT(i)  EI_SHIFT(8+i) /* Get and set multicast filter */
-
-/* Bits in received packet status byte and EN0_RSR*/
-#define ENRSR_RXOK     0x01    /* Received a good packet */
-#define ENRSR_CRC      0x02    /* CRC error */
-#define ENRSR_FAE      0x04    /* frame alignment error */
-#define ENRSR_FO       0x08    /* FIFO overrun */
-#define ENRSR_MPA      0x10    /* missed pkt */
-#define ENRSR_PHY      0x20    /* physical/multicast address */
-#define ENRSR_DIS      0x40    /* receiver disable. set in monitor mode */
-#define ENRSR_DEF      0x80    /* deferring */
-
-/* Transmitted packet status, EN0_TSR. */
-#define ENTSR_PTX 0x01 /* Packet transmitted without error */
-#define ENTSR_ND  0x02 /* The transmit wasn't deferred. */
-#define ENTSR_COL 0x04 /* The transmit collided at least once. */
-#define ENTSR_ABT 0x08  /* The transmit collided 16 times, and was deferred. */
-#define ENTSR_CRS 0x10 /* The carrier sense was lost. */
-#define ENTSR_FU  0x20  /* A "FIFO underrun" occurred during transmit. */
-#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */
-#define ENTSR_OWC 0x80  /* There was an out-of-window collision. */
-
-#endif /* _8390_h */
diff --git a/drivers/net/8390p.c b/drivers/net/8390p.c
deleted file mode 100644 (file)
index a2a64ea..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/* 8390 core for ISA devices needing bus delays */
-
-static const char version[] =
-    "8390p.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#define ei_inb(_p)     inb(_p)
-#define ei_outb(_v, _p)        outb(_v, _p)
-#define ei_inb_p(_p)   inb_p(_p)
-#define ei_outb_p(_v, _p) outb_p(_v, _p)
-
-#include "lib8390.c"
-
-int eip_open(struct net_device *dev)
-{
-       return __ei_open(dev);
-}
-EXPORT_SYMBOL(eip_open);
-
-int eip_close(struct net_device *dev)
-{
-       return __ei_close(dev);
-}
-EXPORT_SYMBOL(eip_close);
-
-netdev_tx_t eip_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-       return __ei_start_xmit(skb, dev);
-}
-EXPORT_SYMBOL(eip_start_xmit);
-
-struct net_device_stats *eip_get_stats(struct net_device *dev)
-{
-       return __ei_get_stats(dev);
-}
-EXPORT_SYMBOL(eip_get_stats);
-
-void eip_set_multicast_list(struct net_device *dev)
-{
-       __ei_set_multicast_list(dev);
-}
-EXPORT_SYMBOL(eip_set_multicast_list);
-
-void eip_tx_timeout(struct net_device *dev)
-{
-       __ei_tx_timeout(dev);
-}
-EXPORT_SYMBOL(eip_tx_timeout);
-
-irqreturn_t eip_interrupt(int irq, void *dev_id)
-{
-       return __ei_interrupt(irq, dev_id);
-}
-EXPORT_SYMBOL(eip_interrupt);
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-void eip_poll(struct net_device *dev)
-{
-       __ei_poll(dev);
-}
-EXPORT_SYMBOL(eip_poll);
-#endif
-
-const struct net_device_ops eip_netdev_ops = {
-       .ndo_open               = eip_open,
-       .ndo_stop               = eip_close,
-       .ndo_start_xmit         = eip_start_xmit,
-       .ndo_tx_timeout         = eip_tx_timeout,
-       .ndo_get_stats          = eip_get_stats,
-       .ndo_set_multicast_list = eip_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = eip_poll,
-#endif
-};
-EXPORT_SYMBOL(eip_netdev_ops);
-
-struct net_device *__alloc_eip_netdev(int size)
-{
-       struct net_device *dev = ____alloc_ei_netdev(size);
-       if (dev)
-               dev->netdev_ops = &eip_netdev_ops;
-       return dev;
-}
-EXPORT_SYMBOL(__alloc_eip_netdev);
-
-void NS8390p_init(struct net_device *dev, int startp)
-{
-       __NS8390_init(dev, startp);
-}
-EXPORT_SYMBOL(NS8390p_init);
-
-static int __init NS8390p_init_module(void)
-{
-       return 0;
-}
-
-static void __exit NS8390p_cleanup_module(void)
-{
-}
-
-module_init(NS8390p_init_module);
-module_exit(NS8390p_cleanup_module);
-MODULE_LICENSE("GPL");
index b686dab54ec68fc4258c3cfc726e5d052cdbf517..c877f4114e042631b8eb88358af26801a94e63a7 100644 (file)
@@ -237,22 +237,6 @@ config MACB
 
 source "drivers/net/arm/Kconfig"
 
-config AX88796
-       tristate "ASIX AX88796 NE2000 clone support"
-       depends on ARM || MIPS || SUPERH
-       select PHYLIB
-       select MDIO_BITBANG
-       help
-         AX88796 driver, using platform bus to provide
-         chip detection and resources
-
-config AX88796_93CX6
-       bool "ASIX AX88796 external 93CX6 eeprom support"
-       depends on AX88796
-       select EEPROM_93CX6
-       help
-         Select this if your platform comes with an external 93CX6 eeprom.
-
 config MACE
        tristate "MACE (Power Mac ethernet) support"
        depends on PPC_PMAC && PPC32
@@ -287,50 +271,6 @@ config BMAC
          To compile this driver as a module, choose M here: the module
          will be called bmac.
 
-config HYDRA
-       tristate "Hydra support"
-       depends on ZORRO
-       select CRC32
-       help
-         If you have a Hydra Ethernet adapter, say Y. Otherwise, say N.
-
-         To compile this driver as a module, choose M here: the module
-         will be called hydra.
-
-config ZORRO8390
-       tristate "Zorro NS8390-based Ethernet support"
-       depends on ZORRO
-       select CRC32
-       help
-         This driver is for Zorro Ethernet cards using an NS8390-compatible
-         chipset, like the Village Tronic Ariadne II and the Individual
-         Computers X-Surf Ethernet cards. If you have such a card, say Y.
-         Otherwise, say N.
-
-         To compile this driver as a module, choose M here: the module
-         will be called zorro8390.
-
-config APNE
-       tristate "PCMCIA NE2000 support"
-       depends on AMIGA_PCMCIA
-       select CRC32
-       help
-         If you have a PCMCIA NE2000 compatible adapter, say Y.  Otherwise,
-         say N.
-
-         To compile this driver as a module, choose M here: the module
-         will be called apne.
-
-config MAC8390
-       bool "Macintosh NS 8390 based ethernet cards"
-       depends on MAC
-       select CRC32
-       help
-         If you want to include a driver to support Nubus or LC-PDS
-         Ethernet cards using an NS8390 chipset or its equivalent, say Y
-         and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
 config MAC89x0
        tristate "Macintosh CS89x0 based ethernet cards"
        depends on MAC
@@ -449,18 +389,6 @@ config SGI_O2MACE_ETH
        tristate "SGI O2 MACE Fast Ethernet support"
        depends on SGI_IP32=y
 
-config STNIC
-       tristate "National DP83902AV  support"
-       depends on SUPERH
-       select CRC32
-       help
-         Support for cards based on the National Semiconductor DP83902AV
-         ST-NIC Serial Network Interface Controller for Twisted Pair.  This
-         is a 10Mbit/sec Ethernet controller.  Product overview and specs at
-         <http://www.national.com/pf/DP/DP83902A.html>.
-
-         If unsure, say N.
-
 config SH_ETH
        tristate "Renesas SuperH Ethernet support"
        depends on SUPERH && \
@@ -591,74 +519,6 @@ config ELMC_II
          To compile this driver as a module, choose M here. The module
          will be called 3c527.
 
-config NET_VENDOR_SMC
-       bool "Western Digital/SMC cards"
-       depends on ISA || MCA || EISA || MAC
-       help
-         If you have a network (Ethernet) card belonging to this class, say Y
-         and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         Note that the answer to this question doesn't directly affect the
-         kernel: saying N will just cause the configurator to skip all
-         the questions about Western Digital cards. If you say Y, you will be
-         asked for your specific card in the following questions.
-
-config WD80x3
-       tristate "WD80*3 support"
-       depends on NET_VENDOR_SMC && ISA
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called wd.
-
-config ULTRAMCA
-       tristate "SMC Ultra MCA support"
-       depends on NET_VENDOR_SMC && MCA
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type and are running
-         an MCA based system (PS/2), say Y and read the Ethernet-HOWTO,
-         available from <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called smc-mca.
-
-config ULTRA
-       tristate "SMC Ultra support"
-       depends on NET_VENDOR_SMC && ISA
-       select CRC32
-       ---help---
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         Important: There have been many reports that, with some motherboards
-         mixing an SMC Ultra and an Adaptec AHA154x SCSI card (or compatible,
-         such as some BusLogic models) causes corruption problems with many
-         operating systems. The Linux smc-ultra driver has a work-around for
-         this but keep it in mind if you have such a SCSI card and have
-         problems.
-
-         To compile this driver as a module, choose M here. The module
-         will be called smc-ultra.
-
-config ULTRA32
-       tristate "SMC Ultra32 EISA support"
-       depends on NET_VENDOR_SMC && EISA
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called smc-ultra32.
-
 config BFIN_MAC
        tristate "Blackfin on-chip MAC support"
        depends on NET_ETHERNET && (BF516 || BF518 || BF526 || BF527 || BF536 || BF537)
@@ -979,18 +839,6 @@ config NET_ISA
          the remaining ISA network card questions. If you say Y, you will be
          asked for your specific card in the following questions.
 
-config E2100
-       tristate "Cabletron E21xx support"
-       depends on NET_ISA
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called e2100.
-
 config EWRK3
        tristate "EtherWORKS 3 (DE203, DE204, DE205) support"
        depends on NET_ISA
@@ -1032,30 +880,6 @@ config EEXPRESS_PRO
          To compile this driver as a module, choose M here. The module
          will be called eepro.
 
-config HPLAN_PLUS
-       tristate "HP PCLAN+ (27247B and 27252A) support"
-       depends on NET_ISA
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called hp-plus.
-
-config HPLAN
-       tristate "HP PCLAN (27245 and other 27xxx series) support"
-       depends on NET_ISA
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called hp.
-
 config LP486E
        tristate "LP486E on board Ethernet"
        depends on NET_ISA
@@ -1075,26 +899,6 @@ config ETH16I
          To compile this driver as a module, choose M here. The module
          will be called eth16i.
 
-config NE2000
-       tristate "NE2000/NE1000 support"
-       depends on NET_ISA || (Q40 && m) || M32R || MACH_TX49XX
-       select CRC32
-       ---help---
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.  Many Ethernet cards
-         without a specific driver are compatible with NE2000.
-
-         If you have a PCI NE2000 card however, say N here and Y to "PCI
-         NE2000 and clone support" under "EISA, VLB, PCI and on board
-         controllers" below. If you have a NE2000 card and are running on
-         an MCA system (a bus system used on some IBM PS/2 computers and
-         laptops), say N here and Y to "NE/2 (ne2000 MCA version) support",
-         below.
-
-         To compile this driver as a module, choose M here. The module
-         will be called ne.
-
 config ZNET
        tristate "Zenith Z-Note support (EXPERIMENTAL)"
        depends on NET_ISA && EXPERIMENTAL && ISA_DMA_API
@@ -1116,18 +920,6 @@ config SEEQ8005
          To compile this driver as a module, choose M here. The module
          will be called seeq8005.
 
-config NE2_MCA
-       tristate "NE/2 (ne2000 MCA version) support"
-       depends on MCA_LEGACY
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called ne2.
-
 config IBMLANA
        tristate "IBM LAN Adapter/A support"
        depends on MCA
@@ -1183,18 +975,6 @@ config ADAPTEC_STARFIRE
          To compile this driver as a module, choose M here: the module
          will be called starfire.  This is recommended.
 
-config AC3200
-       tristate "Ansel Communications EISA 3200 support (EXPERIMENTAL)"
-       depends on NET_PCI && (ISA || EISA) && EXPERIMENTAL
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called ac3200.
-
 config KSZ884X_PCI
        tristate "Micrel KSZ8841/2 PCI"
        depends on NET_PCI && PCI
@@ -1310,18 +1090,6 @@ config E100
          To compile this driver as a module, choose M here. The module
          will be called e100.
 
-config LNE390
-       tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)"
-       depends on NET_PCI && EISA && EXPERIMENTAL
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called lne390.
-
 config FEALNX
        tristate "Myson MTD-8xx PCI Ethernet support"
        depends on NET_PCI && PCI
@@ -1342,50 +1110,6 @@ config NATSEMI
          More specific information and updates are available from
          <http://www.scyld.com/network/natsemi.html>.
 
-config NE2K_PCI
-       tristate "PCI NE2000 and clones support (see help)"
-       depends on NET_PCI && PCI
-       select CRC32
-       ---help---
-         This driver is for NE2000 compatible PCI cards. It will not work
-         with ISA NE2000 cards (they have their own driver, "NE2000/NE1000
-         support" below). If you have a PCI NE2000 network (Ethernet) card,
-         say Y and read the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         This driver also works for the following NE2000 clone cards:
-         RealTek RTL-8029  Winbond 89C940  Compex RL2000  KTI ET32P2
-         NetVin NV5000SC   Via 86C926      SureCom NE34   Winbond
-         Holtek HT80232    Holtek HT80229
-
-         To compile this driver as a module, choose M here. The module
-         will be called ne2k-pci.
-
-config NE3210
-       tristate "Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)"
-       depends on NET_PCI && EISA && EXPERIMENTAL
-       select CRC32
-       ---help---
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.  Note that this driver
-         will NOT WORK for NE3200 cards as they are completely different.
-
-         To compile this driver as a module, choose M here. The module
-         will be called ne3210.
-
-config ES3210
-       tristate "Racal-Interlan EISA ES3210 support (EXPERIMENTAL)"
-       depends on NET_PCI && EISA && EXPERIMENTAL
-       select CRC32
-       help
-         If you have a network (Ethernet) card of this type, say Y and read
-         the Ethernet-HOWTO, available from
-         <http://www.tldp.org/docs.html#howto>.
-
-         To compile this driver as a module, choose M here. The module
-         will be called es3210.
-
 config 8139CP
        tristate "RealTek RTL-8139 C+ PCI Fast Ethernet Adapter support (EXPERIMENTAL)"
        depends on NET_PCI && PCI && EXPERIMENTAL
@@ -1723,13 +1447,6 @@ config FEC_MPC52xx_MDIO
          If not sure, enable.
          If compiled as module, it will be called fec_mpc52xx_phy.
 
-config NE_H8300
-       tristate "NE2000 compatible support for H8/300"
-       depends on H8300
-       help
-         Say Y here if you want to use the NE2000 compatible
-         controller on the Renesas H8/300 processor.
-
 config ATL2
        tristate "Atheros L2 Fast Ethernet support"
        depends on PCI
index 59b6cc9320379cb84b688ccecdbe0474a3d45a85..4e8fa7372242802025aaaf2b814795dc182c3bda 100644 (file)
@@ -65,7 +65,6 @@ obj-$(CONFIG_SUNVNET) += sunvnet.o
 obj-$(CONFIG_MACE) += mace.o
 obj-$(CONFIG_BMAC) += bmac.o
 
-obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
 obj-$(CONFIG_E100) += e100.o
 obj-$(CONFIG_TLAN) += tlan.o
 obj-$(CONFIG_EPIC100) += epic100.o
@@ -77,7 +76,6 @@ obj-$(CONFIG_YELLOWFIN) += yellowfin.o
 obj-$(CONFIG_ISERIES_VETH) += iseries_veth.o
 obj-$(CONFIG_NATSEMI) += natsemi.o
 obj-$(CONFIG_NS83820) += ns83820.o
-obj-$(CONFIG_STNIC) += stnic.o 8390.o
 obj-$(CONFIG_FEALNX) += fealnx.o
 obj-$(CONFIG_TIGON3) += tg3.o
 obj-$(CONFIG_BNX2) += bnx2.o
@@ -112,9 +110,6 @@ obj-$(CONFIG_HAMACHI) += hamachi.o
 obj-$(CONFIG_NET) += Space.o loopback.o
 obj-$(CONFIG_SEEQ8005) += seeq8005.o
 obj-$(CONFIG_NET_SB1000) += sb1000.o
-obj-$(CONFIG_MAC8390) += mac8390.o
-obj-$(CONFIG_APNE) += apne.o 8390.o
-obj-$(CONFIG_PCMCIA_PCNET) += 8390.o
 obj-$(CONFIG_HP100) += hp100.o
 obj-$(CONFIG_SMC9194) += smc9194.o
 obj-$(CONFIG_FEC) += fec.o
@@ -122,24 +117,9 @@ obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
 ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
        obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
 endif
-obj-$(CONFIG_WD80x3) += wd.o 8390.o
-obj-$(CONFIG_EL2) += 3c503.o 8390p.o
-obj-$(CONFIG_NE2000) += ne.o 8390p.o
-obj-$(CONFIG_NE2_MCA) += ne2.o 8390p.o
-obj-$(CONFIG_HPLAN) += hp.o 8390p.o
-obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390p.o
-obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o
-obj-$(CONFIG_ULTRAMCA) += smc-mca.o 8390.o
-obj-$(CONFIG_ULTRA32) += smc-ultra32.o 8390.o
-obj-$(CONFIG_E2100) += e2100.o 8390.o
-obj-$(CONFIG_ES3210) += es3210.o 8390.o
-obj-$(CONFIG_LNE390) += lne390.o 8390.o
-obj-$(CONFIG_NE3210) += ne3210.o 8390.o
 obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o
 obj-$(CONFIG_B44) += b44.o
 obj-$(CONFIG_FORCEDETH) += forcedeth.o
-obj-$(CONFIG_NE_H8300) += ne-h8300.o
-obj-$(CONFIG_AX88796) += ax88796.o
 obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
 obj-$(CONFIG_FTGMAC100) += ftgmac100.o
 obj-$(CONFIG_FTMAC100) += ftmac100.o
@@ -195,7 +175,6 @@ obj-$(CONFIG_ATP) += atp.o
 obj-$(CONFIG_NI5010) += ni5010.o
 obj-$(CONFIG_NI52) += ni52.o
 obj-$(CONFIG_ELPLUS) += 3c505.o
-obj-$(CONFIG_AC3200) += ac3200.o 8390.o
 obj-$(CONFIG_APRICOT) += 82596.o
 obj-$(CONFIG_LASI_82596) += lasi_82596.o
 obj-$(CONFIG_SNI_82596) += sni_82596.o
@@ -207,13 +186,11 @@ obj-$(CONFIG_SC92031) += sc92031.o
 obj-$(CONFIG_LP486E) += lp486e.o
 
 obj-$(CONFIG_ETH16I) += eth16i.o
-obj-$(CONFIG_ZORRO8390) += zorro8390.o
 obj-$(CONFIG_EQUALIZER) += eql.o
 obj-$(CONFIG_KORINA) += korina.o
 obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
 obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
 obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
-obj-$(CONFIG_HYDRA) += hydra.o
 obj-$(CONFIG_CS89x0) += cs89x0.o
 obj-$(CONFIG_MACSONIC) += macsonic.o
 obj-$(CONFIG_MACMACE) += macmace.o
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
deleted file mode 100644 (file)
index f07b2e9..0000000
+++ /dev/null
@@ -1,432 +0,0 @@
-/* ac3200.c: A driver for the Ansel Communications EISA ethernet adaptor. */
-/*
-       Written 1993, 1994 by Donald Becker.
-       Copyright 1993 United States Government as represented by the Director,
-       National Security Agency.  This software may only be used and distributed
-       according to the terms of the GNU General Public License as modified by SRC,
-       incorporated herein by reference.
-
-       The author may be reached as becker@scyld.com, or C/O
-       Scyld Computing Corporation
-       410 Severn Ave., Suite 210
-       Annapolis MD 21403
-
-       This is driver for the Ansel Communications Model 3200 EISA Ethernet LAN
-       Adapter.  The programming information is from the users manual, as related
-       by glee@ardnassak.math.clemson.edu.
-
-       Changelog:
-
-       Paul Gortmaker 05/98    : add support for shared mem above 1MB.
-
-  */
-
-static const char version[] =
-       "ac3200.c:v1.01 7/1/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include <linux/module.h>
-#include <linux/eisa.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include "8390.h"
-
-#define DRV_NAME       "ac3200"
-
-/* Offsets from the base address. */
-#define AC_NIC_BASE    0x00
-#define AC_SA_PROM     0x16                    /* The station address PROM. */
-#define AC_ADDR0       0x00                    /* Prefix station address values. */
-#define AC_ADDR1       0x40
-#define AC_ADDR2       0x90
-#define AC_ID_PORT     0xC80
-#define AC_EISA_ID     0x0110d305
-#define AC_RESET_PORT  0xC84
-#define AC_RESET       0x00
-#define AC_ENABLE      0x01
-#define AC_CONFIG      0xC90   /* The configuration port. */
-
-#define AC_IO_EXTENT 0x20
-                                /* Actually accessed is:
-                                                                * AC_NIC_BASE (0-15)
-                                                                * AC_SA_PROM (0-5)
-                                                                * AC_ID_PORT (0-3)
-                                                                * AC_RESET_PORT
-                                                                * AC_CONFIG
-                                                                */
-
-/* Decoding of the configuration register. */
-static unsigned char config2irqmap[8] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
-static int addrmap[8] =
-{0xFF0000, 0xFE0000, 0xFD0000, 0xFFF0000, 0xFFE0000, 0xFFC0000,  0xD0000, 0 };
-static const char *port_name[4] = { "10baseT", "invalid", "AUI", "10base2"};
-
-#define config2irq(configval)  config2irqmap[((configval) >> 3) & 7]
-#define config2mem(configval)  addrmap[(configval) & 7]
-#define config2name(configval) port_name[((configval) >> 6) & 3]
-
-/* First and last 8390 pages. */
-#define AC_START_PG            0x00    /* First page of 8390 TX buffer */
-#define AC_STOP_PG             0x80    /* Last page +1 of the 8390 RX ring */
-
-static int ac_probe1(int ioaddr, struct net_device *dev);
-
-static int ac_open(struct net_device *dev);
-static void ac_reset_8390(struct net_device *dev);
-static void ac_block_input(struct net_device *dev, int count,
-                                       struct sk_buff *skb, int ring_offset);
-static void ac_block_output(struct net_device *dev, const int count,
-                                                       const unsigned char *buf, const int start_page);
-static void ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                                       int ring_page);
-
-static int ac_close_card(struct net_device *dev);
-
-
-/*     Probe for the AC3200.
-
-       The AC3200 can be identified by either the EISA configuration registers,
-       or the unique value in the station address PROM.
-       */
-
-static int __init do_ac3200_probe(struct net_device *dev)
-{
-       unsigned short ioaddr = dev->base_addr;
-       int irq = dev->irq;
-       int mem_start = dev->mem_start;
-
-       if (ioaddr > 0x1ff)             /* Check a single specified location. */
-               return ac_probe1(ioaddr, dev);
-       else if (ioaddr > 0)            /* Don't probe at all. */
-               return -ENXIO;
-
-       if ( ! EISA_bus)
-               return -ENXIO;
-
-       for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
-               if (ac_probe1(ioaddr, dev) == 0)
-                       return 0;
-               dev->irq = irq;
-               dev->mem_start = mem_start;
-       }
-
-       return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init ac3200_probe(int unit)
-{
-       struct net_device *dev = alloc_ei_netdev();
-       int err;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       sprintf(dev->name, "eth%d", unit);
-       netdev_boot_setup_check(dev);
-
-       err = do_ac3200_probe(dev);
-       if (err)
-               goto out;
-       return dev;
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-#endif
-
-static const struct net_device_ops ac_netdev_ops = {
-       .ndo_open               = ac_open,
-       .ndo_stop               = ac_close_card,
-
-       .ndo_start_xmit         = ei_start_xmit,
-       .ndo_tx_timeout         = ei_tx_timeout,
-       .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = ei_poll,
-#endif
-};
-
-static int __init ac_probe1(int ioaddr, struct net_device *dev)
-{
-       int i, retval;
-
-       if (!request_region(ioaddr, AC_IO_EXTENT, DRV_NAME))
-               return -EBUSY;
-
-       if (inb_p(ioaddr + AC_ID_PORT) == 0xff) {
-               retval = -ENODEV;
-               goto out;
-       }
-
-       if (inl(ioaddr + AC_ID_PORT) != AC_EISA_ID) {
-               retval = -ENODEV;
-               goto out;
-       }
-
-#ifndef final_version
-       printk(KERN_DEBUG "AC3200 ethercard configuration register is %#02x,"
-                  " EISA ID %02x %02x %02x %02x.\n", inb(ioaddr + AC_CONFIG),
-                  inb(ioaddr + AC_ID_PORT + 0), inb(ioaddr + AC_ID_PORT + 1),
-                  inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3));
-#endif
-
-       for (i = 0; i < 6; i++)
-               dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i);
-
-       printk(KERN_DEBUG "AC3200 in EISA slot %d, node %pM",
-              ioaddr/0x1000, dev->dev_addr);
-#if 0
-       /* Check the vendor ID/prefix. Redundant after checking the EISA ID */
-       if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
-               || inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1
-               || inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) {
-               printk(", not found (invalid prefix).\n");
-               retval = -ENODEV;
-               goto out;
-       }
-#endif
-
-       /* Assign and allocate the interrupt now. */
-       if (dev->irq == 0) {
-               dev->irq = config2irq(inb(ioaddr + AC_CONFIG));
-               printk(", using");
-       } else {
-               dev->irq = irq_canonicalize(dev->irq);
-               printk(", assigning");
-       }
-
-       retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
-       if (retval) {
-               printk (" nothing! Unable to get IRQ %d.\n", dev->irq);
-               goto out;
-       }
-
-       printk(" IRQ %d, %s port\n", dev->irq, port_name[dev->if_port]);
-
-       dev->base_addr = ioaddr;
-
-#ifdef notyet
-       if (dev->mem_start)     {               /* Override the value from the board. */
-               for (i = 0; i < 7; i++)
-                       if (addrmap[i] == dev->mem_start)
-                               break;
-               if (i >= 7)
-                       i = 0;
-               outb((inb(ioaddr + AC_CONFIG) & ~7) | i, ioaddr + AC_CONFIG);
-       }
-#endif
-
-       dev->if_port = inb(ioaddr + AC_CONFIG) >> 6;
-       dev->mem_start = config2mem(inb(ioaddr + AC_CONFIG));
-
-       printk("%s: AC3200 at %#3x with %dkB memory at physical address %#lx.\n",
-                       dev->name, ioaddr, AC_STOP_PG/4, dev->mem_start);
-
-       /*
-        *  BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
-        *  the card mem within the region covered by `normal' RAM  !!!
-        *
-        *  ioremap() will fail in that case.
-        */
-       ei_status.mem = ioremap(dev->mem_start, AC_STOP_PG*0x100);
-       if (!ei_status.mem) {
-               printk(KERN_ERR "ac3200.c: Unable to remap card memory above 1MB !!\n");
-               printk(KERN_ERR "ac3200.c: Try using EISA SCU to set memory below 1MB.\n");
-               printk(KERN_ERR "ac3200.c: Driver NOT installed.\n");
-               retval = -EINVAL;
-               goto out1;
-       }
-       printk("ac3200.c: remapped %dkB card memory to virtual address %p\n",
-                       AC_STOP_PG/4, ei_status.mem);
-
-       dev->mem_start = (unsigned long)ei_status.mem;
-       dev->mem_end = dev->mem_start + (AC_STOP_PG - AC_START_PG)*256;
-
-       ei_status.name = "AC3200";
-       ei_status.tx_start_page = AC_START_PG;
-       ei_status.rx_start_page = AC_START_PG + TX_PAGES;
-       ei_status.stop_page = AC_STOP_PG;
-       ei_status.word16 = 1;
-
-       if (ei_debug > 0)
-               printk(version);
-
-       ei_status.reset_8390 = &ac_reset_8390;
-       ei_status.block_input = &ac_block_input;
-       ei_status.block_output = &ac_block_output;
-       ei_status.get_8390_hdr = &ac_get_8390_hdr;
-
-       dev->netdev_ops = &ac_netdev_ops;
-       NS8390_init(dev, 0);
-
-       retval = register_netdev(dev);
-       if (retval)
-               goto out2;
-       return 0;
-out2:
-       if (ei_status.reg0)
-               iounmap(ei_status.mem);
-out1:
-       free_irq(dev->irq, dev);
-out:
-       release_region(ioaddr, AC_IO_EXTENT);
-       return retval;
-}
-
-static int ac_open(struct net_device *dev)
-{
-#ifdef notyet
-       /* Someday we may enable the IRQ and shared memory here. */
-       int ioaddr = dev->base_addr;
-#endif
-
-       ei_open(dev);
-       return 0;
-}
-
-static void ac_reset_8390(struct net_device *dev)
-{
-       ushort ioaddr = dev->base_addr;
-
-       outb(AC_RESET, ioaddr + AC_RESET_PORT);
-       if (ei_debug > 1) printk("resetting AC3200, t=%ld...", jiffies);
-
-       ei_status.txing = 0;
-       outb(AC_ENABLE, ioaddr + AC_RESET_PORT);
-       if (ei_debug > 1) printk("reset done\n");
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
-   we don't need to be concerned with ring wrap as the header will be at
-   the start of a page, so we optimize accordingly. */
-
-static void
-ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-       void __iomem *hdr_start = ei_status.mem + ((ring_page - AC_START_PG)<<8);
-       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
-}
-
-/*  Block input and output are easy on shared memory ethercards, the only
-       complication is when the ring buffer wraps. */
-
-static void ac_block_input(struct net_device *dev, int count, struct sk_buff *skb,
-                                                 int ring_offset)
-{
-       void __iomem *start = ei_status.mem + ring_offset - AC_START_PG*256;
-
-       if (ring_offset + count > AC_STOP_PG*256) {
-               /* We must wrap the input move. */
-               int semi_count = AC_STOP_PG*256 - ring_offset;
-               memcpy_fromio(skb->data, start, semi_count);
-               count -= semi_count;
-               memcpy_fromio(skb->data + semi_count,
-                               ei_status.mem + TX_PAGES*256, count);
-       } else {
-               memcpy_fromio(skb->data, start, count);
-       }
-}
-
-static void ac_block_output(struct net_device *dev, int count,
-                                                       const unsigned char *buf, int start_page)
-{
-       void __iomem *shmem = ei_status.mem + ((start_page - AC_START_PG)<<8);
-
-       memcpy_toio(shmem, buf, count);
-}
-
-static int ac_close_card(struct net_device *dev)
-{
-       if (ei_debug > 1)
-               printk("%s: Shutting down ethercard.\n", dev->name);
-
-#ifdef notyet
-       /* We should someday disable shared memory and interrupts. */
-       outb(0x00, ioaddr + 6); /* Disable interrupts. */
-       free_irq(dev->irq, dev);
-#endif
-
-       ei_close(dev);
-       return 0;
-}
-
-#ifdef MODULE
-#define MAX_AC32_CARDS 4       /* Max number of AC32 cards per module */
-static struct net_device *dev_ac32[MAX_AC32_CARDS];
-static int io[MAX_AC32_CARDS];
-static int irq[MAX_AC32_CARDS];
-static int mem[MAX_AC32_CARDS];
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(mem, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s)");
-MODULE_PARM_DESC(mem, "Memory base address(es)");
-MODULE_DESCRIPTION("Ansel AC3200 EISA ethernet driver");
-MODULE_LICENSE("GPL");
-
-static int __init ac3200_module_init(void)
-{
-       struct net_device *dev;
-       int this_dev, found = 0;
-
-       for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
-               if (io[this_dev] == 0 && this_dev != 0)
-                       break;
-               dev = alloc_ei_netdev();
-               if (!dev)
-                       break;
-               dev->irq = irq[this_dev];
-               dev->base_addr = io[this_dev];
-               dev->mem_start = mem[this_dev];         /* Currently ignored by driver */
-               if (do_ac3200_probe(dev) == 0) {
-                       dev_ac32[found++] = dev;
-                       continue;
-               }
-               free_netdev(dev);
-               printk(KERN_WARNING "ac3200.c: No ac3200 card found (i/o = 0x%x).\n", io[this_dev]);
-               break;
-       }
-       if (found)
-               return 0;
-       return -ENXIO;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-       /* Someday free_irq may be in ac_close_card() */
-       free_irq(dev->irq, dev);
-       release_region(dev->base_addr, AC_IO_EXTENT);
-       iounmap(ei_status.mem);
-}
-
-static void __exit ac3200_module_exit(void)
-{
-       int this_dev;
-
-       for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
-               struct net_device *dev = dev_ac32[this_dev];
-               if (dev) {
-                       unregister_netdev(dev);
-                       cleanup_card(dev);
-                       free_netdev(dev);
-               }
-       }
-}
-module_init(ac3200_module_init);
-module_exit(ac3200_module_exit);
-#endif /* MODULE */
diff --git a/drivers/net/apne.c b/drivers/net/apne.c
deleted file mode 100644 (file)
index 5477373..0000000
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * Amiga Linux/68k 8390 based PCMCIA Ethernet Driver for the Amiga 1200
- *
- * (C) Copyright 1997 Alain Malek
- *                    (Alain.Malek@cryogen.com)
- *
- * ----------------------------------------------------------------------------
- *
- * This program is based on
- *
- * ne.c:       A general non-shared-memory NS8390 ethernet driver for linux
- *             Written 1992-94 by Donald Becker.
- *
- * 8390.c:     A general NS8390 ethernet driver core for linux.
- *             Written 1992-94 by Donald Becker.
- *
- * cnetdevice: A Sana-II ethernet driver for AmigaOS
- *             Written by Bruce Abbott (bhabbott@inhb.co.nz)
- *
- * ----------------------------------------------------------------------------
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of the Linux
- * distribution for more details.
- *
- * ----------------------------------------------------------------------------
- *
- */
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/interrupt.h>
-#include <linux/jiffies.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/setup.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-#include <asm/amigayle.h>
-#include <asm/amipcmcia.h>
-
-#include "8390.h"
-
-/* ---- No user-serviceable parts below ---- */
-
-#define DRV_NAME "apne"
-
-#define NE_BASE         (dev->base_addr)
-#define NE_CMD                 0x00
-#define NE_DATAPORT            0x10            /* NatSemi-defined port window offset. */
-#define NE_RESET               0x1f            /* Issue a read to reset, a write to clear. */
-#define NE_IO_EXTENT           0x20
-
-#define NE_EN0_ISR             0x07
-#define NE_EN0_DCFG            0x0e
-
-#define NE_EN0_RSARLO          0x08
-#define NE_EN0_RSARHI          0x09
-#define NE_EN0_RCNTLO          0x0a
-#define NE_EN0_RXCR            0x0c
-#define NE_EN0_TXCR            0x0d
-#define NE_EN0_RCNTHI          0x0b
-#define NE_EN0_IMR             0x0f
-
-#define NE1SM_START_PG 0x20    /* First page of TX buffer */
-#define NE1SM_STOP_PG  0x40    /* Last page +1 of RX ring */
-#define NESM_START_PG  0x40    /* First page of TX buffer */
-#define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
-
-
-struct net_device * __init apne_probe(int unit);
-static int apne_probe1(struct net_device *dev, int ioaddr);
-
-static void apne_reset_8390(struct net_device *dev);
-static void apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                         int ring_page);
-static void apne_block_input(struct net_device *dev, int count,
-                                                               struct sk_buff *skb, int ring_offset);
-static void apne_block_output(struct net_device *dev, const int count,
-                                                       const unsigned char *buf, const int start_page);
-static irqreturn_t apne_interrupt(int irq, void *dev_id);
-
-static int init_pcmcia(void);
-
-/* IO base address used for nic */
-
-#define IOBASE 0x300
-
-/*
-   use MANUAL_CONFIG and MANUAL_OFFSET for enabling IO by hand
-   you can find the values to use by looking at the cnet.device
-   config file example (the default values are for the CNET40BC card)
-*/
-
-/*
-#define MANUAL_CONFIG 0x20
-#define MANUAL_OFFSET 0x3f8
-
-#define MANUAL_HWADDR0 0x00
-#define MANUAL_HWADDR1 0x12
-#define MANUAL_HWADDR2 0x34
-#define MANUAL_HWADDR3 0x56
-#define MANUAL_HWADDR4 0x78
-#define MANUAL_HWADDR5 0x9a
-*/
-
-static const char version[] =
-    "apne.c:v1.1 7/10/98 Alain Malek (Alain.Malek@cryogen.ch)\n";
-
-static int apne_owned; /* signal if card already owned */
-
-struct net_device * __init apne_probe(int unit)
-{
-       struct net_device *dev;
-#ifndef MANUAL_CONFIG
-       char tuple[8];
-#endif
-       int err;
-
-       if (!MACH_IS_AMIGA)
-               return ERR_PTR(-ENODEV);
-
-       if (apne_owned)
-               return ERR_PTR(-ENODEV);
-
-       if ( !(AMIGAHW_PRESENT(PCMCIA)) )
-               return ERR_PTR(-ENODEV);
-
-       printk("Looking for PCMCIA ethernet card : ");
-
-       /* check if a card is inserted */
-       if (!(PCMCIA_INSERTED)) {
-               printk("NO PCMCIA card inserted\n");
-               return ERR_PTR(-ENODEV);
-       }
-
-       dev = alloc_ei_netdev();
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-       if (unit >= 0) {
-               sprintf(dev->name, "eth%d", unit);
-               netdev_boot_setup_check(dev);
-       }
-
-       /* disable pcmcia irq for readtuple */
-       pcmcia_disable_irq();
-
-#ifndef MANUAL_CONFIG
-       if ((pcmcia_copy_tuple(CISTPL_FUNCID, tuple, 8) < 3) ||
-               (tuple[2] != CISTPL_FUNCID_NETWORK)) {
-               printk("not an ethernet card\n");
-               /* XXX: shouldn't we re-enable irq here? */
-               free_netdev(dev);
-               return ERR_PTR(-ENODEV);
-       }
-#endif
-
-       printk("ethernet PCMCIA card inserted\n");
-
-       if (!init_pcmcia()) {
-               /* XXX: shouldn't we re-enable irq here? */
-               free_netdev(dev);
-               return ERR_PTR(-ENODEV);
-       }
-
-       if (!request_region(IOBASE, 0x20, DRV_NAME)) {
-               free_netdev(dev);
-               return ERR_PTR(-EBUSY);
-       }
-
-       err = apne_probe1(dev, IOBASE);
-       if (err) {
-               release_region(IOBASE, 0x20);
-               free_netdev(dev);
-               return ERR_PTR(err);
-       }
-       err = register_netdev(dev);
-       if (!err)
-               return dev;
-
-       pcmcia_disable_irq();
-       free_irq(IRQ_AMIGA_PORTS, dev);
-       pcmcia_reset();
-       release_region(IOBASE, 0x20);
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-
-static int __init apne_probe1(struct net_device *dev, int ioaddr)
-{
-    int i;
-    unsigned char SA_prom[32];
-    int wordlength = 2;
-    const char *name = NULL;
-    int start_page, stop_page;
-#ifndef MANUAL_HWADDR0
-    int neX000, ctron;
-#endif
-    static unsigned version_printed;
-
-    if (ei_debug  &&  version_printed++ == 0)
-       printk(version);
-
-    printk("PCMCIA NE*000 ethercard probe");
-
-    /* Reset card. Who knows what dain-bramaged state it was left in. */
-    {  unsigned long reset_start_time = jiffies;
-
-       outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
-
-       while ((inb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
-               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
-                       printk(" not found (no reset ack).\n");
-                       return -ENODEV;
-               }
-
-       outb(0xff, ioaddr + NE_EN0_ISR);                /* Ack all intr. */
-    }
-
-#ifndef MANUAL_HWADDR0
-
-    /* Read the 16 bytes of station address PROM.
-       We must first initialize registers, similar to NS8390_init(eifdev, 0).
-       We can't reliably read the SAPROM address without this.
-       (I learned the hard way!). */
-    {
-       struct {unsigned long value, offset; } program_seq[] = {
-           {E8390_NODMA+E8390_PAGE0+E8390_STOP, NE_CMD}, /* Select page 0*/
-           {0x48,      NE_EN0_DCFG},   /* Set byte-wide (0x48) access. */
-           {0x00,      NE_EN0_RCNTLO}, /* Clear the count regs. */
-           {0x00,      NE_EN0_RCNTHI},
-           {0x00,      NE_EN0_IMR},    /* Mask completion irq. */
-           {0xFF,      NE_EN0_ISR},
-           {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20  Set to monitor */
-           {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02  and loopback mode. */
-           {32,        NE_EN0_RCNTLO},
-           {0x00,      NE_EN0_RCNTHI},
-           {0x00,      NE_EN0_RSARLO}, /* DMA starting at 0x0000. */
-           {0x00,      NE_EN0_RSARHI},
-           {E8390_RREAD+E8390_START, NE_CMD},
-       };
-       for (i = 0; i < ARRAY_SIZE(program_seq); i++) {
-           outb(program_seq[i].value, ioaddr + program_seq[i].offset);
-       }
-
-    }
-    for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
-       SA_prom[i] = inb(ioaddr + NE_DATAPORT);
-       SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
-       if (SA_prom[i] != SA_prom[i+1])
-           wordlength = 1;
-    }
-
-    /* At this point, wordlength *only* tells us if the SA_prom is doubled
-       up or not because some broken PCI cards don't respect the byte-wide
-       request in program_seq above, and hence don't have doubled up values.
-       These broken cards would otherwise be detected as an ne1000.  */
-
-    if (wordlength == 2)
-       for (i = 0; i < 16; i++)
-               SA_prom[i] = SA_prom[i+i];
-
-    if (wordlength == 2) {
-       /* We must set the 8390 for word mode. */
-       outb(0x49, ioaddr + NE_EN0_DCFG);
-       start_page = NESM_START_PG;
-       stop_page = NESM_STOP_PG;
-    } else {
-       start_page = NE1SM_START_PG;
-       stop_page = NE1SM_STOP_PG;
-    }
-
-    neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
-    ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
-
-    /* Set up the rest of the parameters. */
-    if (neX000) {
-       name = (wordlength == 2) ? "NE2000" : "NE1000";
-    } else if (ctron) {
-       name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
-       start_page = 0x01;
-       stop_page = (wordlength == 2) ? 0x40 : 0x20;
-    } else {
-       printk(" not found.\n");
-       return -ENXIO;
-
-    }
-
-#else
-    wordlength = 2;
-    /* We must set the 8390 for word mode. */
-    outb(0x49, ioaddr + NE_EN0_DCFG);
-    start_page = NESM_START_PG;
-    stop_page = NESM_STOP_PG;
-
-    SA_prom[0] = MANUAL_HWADDR0;
-    SA_prom[1] = MANUAL_HWADDR1;
-    SA_prom[2] = MANUAL_HWADDR2;
-    SA_prom[3] = MANUAL_HWADDR3;
-    SA_prom[4] = MANUAL_HWADDR4;
-    SA_prom[5] = MANUAL_HWADDR5;
-    name = "NE2000";
-#endif
-
-    dev->base_addr = ioaddr;
-    dev->irq = IRQ_AMIGA_PORTS;
-    dev->netdev_ops = &ei_netdev_ops;
-
-    /* Install the Interrupt handler */
-    i = request_irq(dev->irq, apne_interrupt, IRQF_SHARED, DRV_NAME, dev);
-    if (i) return i;
-
-    for(i = 0; i < ETHER_ADDR_LEN; i++)
-       dev->dev_addr[i] = SA_prom[i];
-
-    printk(" %pM\n", dev->dev_addr);
-
-    printk("%s: %s found.\n", dev->name, name);
-
-    ei_status.name = name;
-    ei_status.tx_start_page = start_page;
-    ei_status.stop_page = stop_page;
-    ei_status.word16 = (wordlength == 2);
-
-    ei_status.rx_start_page = start_page + TX_PAGES;
-
-    ei_status.reset_8390 = &apne_reset_8390;
-    ei_status.block_input = &apne_block_input;
-    ei_status.block_output = &apne_block_output;
-    ei_status.get_8390_hdr = &apne_get_8390_hdr;
-
-    NS8390_init(dev, 0);
-
-    pcmcia_ack_int(pcmcia_get_intreq());               /* ack PCMCIA int req */
-    pcmcia_enable_irq();
-
-    apne_owned = 1;
-
-    return 0;
-}
-
-/* Hard reset the card.  This used to pause for the same period that a
-   8390 reset command required, but that shouldn't be necessary. */
-static void
-apne_reset_8390(struct net_device *dev)
-{
-    unsigned long reset_start_time = jiffies;
-
-    init_pcmcia();
-
-    if (ei_debug > 1) printk("resetting the 8390 t=%ld...", jiffies);
-
-    outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
-    ei_status.txing = 0;
-    ei_status.dmaing = 0;
-
-    /* This check _should_not_ be necessary, omit eventually. */
-    while ((inb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
-       if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
-           printk("%s: ne_reset_8390() did not complete.\n", dev->name);
-           break;
-       }
-    outb(ENISR_RESET, NE_BASE + NE_EN0_ISR);   /* Ack intr. */
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
-   we don't need to be concerned with ring wrap as the header will be at
-   the start of a page, so we optimize accordingly. */
-
-static void
-apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-
-    int nic_base = dev->base_addr;
-    int cnt;
-    char *ptrc;
-    short *ptrs;
-
-    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-    if (ei_status.dmaing) {
-       printk("%s: DMAing conflict in ne_get_8390_hdr "
-          "[DMAstat:%d][irqlock:%d][intr:%d].\n",
-          dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
-       return;
-    }
-
-    ei_status.dmaing |= 0x01;
-    outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-    outb(ENISR_RDC, nic_base + NE_EN0_ISR);
-    outb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
-    outb(0, nic_base + NE_EN0_RCNTHI);
-    outb(0, nic_base + NE_EN0_RSARLO);         /* On page boundary */
-    outb(ring_page, nic_base + NE_EN0_RSARHI);
-    outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
-    if (ei_status.word16) {
-        ptrs = (short*)hdr;
-        for(cnt = 0; cnt < (sizeof(struct e8390_pkt_hdr)>>1); cnt++)
-            *ptrs++ = inw(NE_BASE + NE_DATAPORT);
-    } else {
-        ptrc = (char*)hdr;
-        for(cnt = 0; cnt < sizeof(struct e8390_pkt_hdr); cnt++)
-            *ptrc++ = inb(NE_BASE + NE_DATAPORT);
-    }
-
-    outb(ENISR_RDC, nic_base + NE_EN0_ISR);    /* Ack intr. */
-    ei_status.dmaing &= ~0x01;
-
-    le16_to_cpus(&hdr->count);
-}
-
-/* Block input and output, similar to the Crynwr packet driver.  If you
-   are porting to a new ethercard, look at the packet driver source for hints.
-   The NEx000 doesn't share the on-board packet memory -- you have to put
-   the packet out through the "remote DMA" dataport using outb. */
-
-static void
-apne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-    int nic_base = dev->base_addr;
-    char *buf = skb->data;
-    char *ptrc;
-    short *ptrs;
-    int cnt;
-
-    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-    if (ei_status.dmaing) {
-       printk("%s: DMAing conflict in ne_block_input "
-          "[DMAstat:%d][irqlock:%d][intr:%d].\n",
-          dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
-       return;
-    }
-    ei_status.dmaing |= 0x01;
-    outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-    outb(ENISR_RDC, nic_base + NE_EN0_ISR);
-    outb(count & 0xff, nic_base + NE_EN0_RCNTLO);
-    outb(count >> 8, nic_base + NE_EN0_RCNTHI);
-    outb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
-    outb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
-    outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-    if (ei_status.word16) {
-      ptrs = (short*)buf;
-      for (cnt = 0; cnt < (count>>1); cnt++)
-        *ptrs++ = inw(NE_BASE + NE_DATAPORT);
-      if (count & 0x01) {
-       buf[count-1] = inb(NE_BASE + NE_DATAPORT);
-      }
-    } else {
-      ptrc = (char*)buf;
-      for (cnt = 0; cnt < count; cnt++)
-        *ptrc++ = inb(NE_BASE + NE_DATAPORT);
-    }
-
-    outb(ENISR_RDC, nic_base + NE_EN0_ISR);    /* Ack intr. */
-    ei_status.dmaing &= ~0x01;
-}
-
-static void
-apne_block_output(struct net_device *dev, int count,
-               const unsigned char *buf, const int start_page)
-{
-    int nic_base = NE_BASE;
-    unsigned long dma_start;
-    char *ptrc;
-    short *ptrs;
-    int cnt;
-
-    /* Round the count up for word writes.  Do we need to do this?
-       What effect will an odd byte count have on the 8390?
-       I should check someday. */
-    if (ei_status.word16 && (count & 0x01))
-      count++;
-
-    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-    if (ei_status.dmaing) {
-       printk("%s: DMAing conflict in ne_block_output."
-          "[DMAstat:%d][irqlock:%d][intr:%d]\n",
-          dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
-       return;
-    }
-    ei_status.dmaing |= 0x01;
-    /* We should already be in page 0, but to be safe... */
-    outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
-    outb(ENISR_RDC, nic_base + NE_EN0_ISR);
-
-   /* Now the normal output. */
-    outb(count & 0xff, nic_base + NE_EN0_RCNTLO);
-    outb(count >> 8,   nic_base + NE_EN0_RCNTHI);
-    outb(0x00, nic_base + NE_EN0_RSARLO);
-    outb(start_page, nic_base + NE_EN0_RSARHI);
-
-    outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
-    if (ei_status.word16) {
-        ptrs = (short*)buf;
-        for (cnt = 0; cnt < count>>1; cnt++)
-            outw(*ptrs++, NE_BASE+NE_DATAPORT);
-    } else {
-        ptrc = (char*)buf;
-        for (cnt = 0; cnt < count; cnt++)
-           outb(*ptrc++, NE_BASE + NE_DATAPORT);
-    }
-
-    dma_start = jiffies;
-
-    while ((inb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
-       if (time_after(jiffies, dma_start + 2*HZ/100)) {        /* 20ms */
-               printk("%s: timeout waiting for Tx RDC.\n", dev->name);
-               apne_reset_8390(dev);
-               NS8390_init(dev,1);
-               break;
-       }
-
-    outb(ENISR_RDC, nic_base + NE_EN0_ISR);    /* Ack intr. */
-    ei_status.dmaing &= ~0x01;
-}
-
-static irqreturn_t apne_interrupt(int irq, void *dev_id)
-{
-    unsigned char pcmcia_intreq;
-
-    if (!(gayle.inten & GAYLE_IRQ_IRQ))
-        return IRQ_NONE;
-
-    pcmcia_intreq = pcmcia_get_intreq();
-
-    if (!(pcmcia_intreq & GAYLE_IRQ_IRQ)) {
-        pcmcia_ack_int(pcmcia_intreq);
-        return IRQ_NONE;
-    }
-    if (ei_debug > 3)
-        printk("pcmcia intreq = %x\n", pcmcia_intreq);
-    pcmcia_disable_irq();                      /* to get rid of the sti() within ei_interrupt */
-    ei_interrupt(irq, dev_id);
-    pcmcia_ack_int(pcmcia_get_intreq());
-    pcmcia_enable_irq();
-    return IRQ_HANDLED;
-}
-
-#ifdef MODULE
-static struct net_device *apne_dev;
-
-static int __init apne_module_init(void)
-{
-       apne_dev = apne_probe(-1);
-       if (IS_ERR(apne_dev))
-               return PTR_ERR(apne_dev);
-       return 0;
-}
-
-static void __exit apne_module_exit(void)
-{
-       unregister_netdev(apne_dev);
-
-       pcmcia_disable_irq();
-
-       free_irq(IRQ_AMIGA_PORTS, apne_dev);
-
-       pcmcia_reset();
-
-       release_region(IOBASE, 0x20);
-
-       free_netdev(apne_dev);
-}
-module_init(apne_module_init);
-module_exit(apne_module_exit);
-#endif
-
-static int init_pcmcia(void)
-{
-       u_char config;
-#ifndef MANUAL_CONFIG
-       u_char tuple[32];
-       int offset_len;
-#endif
-       u_long offset;
-
-       pcmcia_reset();
-       pcmcia_program_voltage(PCMCIA_0V);
-       pcmcia_access_speed(PCMCIA_SPEED_250NS);
-       pcmcia_write_enable();
-
-#ifdef MANUAL_CONFIG
-       config = MANUAL_CONFIG;
-#else
-       /* get and write config byte to enable IO port */
-
-       if (pcmcia_copy_tuple(CISTPL_CFTABLE_ENTRY, tuple, 32) < 3)
-               return 0;
-
-       config = tuple[2] & 0x3f;
-#endif
-#ifdef MANUAL_OFFSET
-       offset = MANUAL_OFFSET;
-#else
-       if (pcmcia_copy_tuple(CISTPL_CONFIG, tuple, 32) < 6)
-               return 0;
-
-       offset_len = (tuple[2] & 0x3) + 1;
-       offset = 0;
-       while(offset_len--) {
-               offset = (offset << 8) | tuple[4+offset_len];
-       }
-#endif
-
-       out_8(GAYLE_ATTRIBUTE+offset, config);
-
-       return 1;
-}
-
-MODULE_LICENSE("GPL");
index d0c8cf254cb017bd91945aa13550ebc01d129315..715bf2acc24b643d856da4f1fdcbadbd6f526d5f 100644 (file)
@@ -17,14 +17,6 @@ config ARM_ETHER3
          If you have an Acorn system with one of these network cards, you
          should say Y to this option if you wish to use it with Linux.
 
-config ARM_ETHERH
-       tristate "I-cubed EtherH/ANT EtherM support"
-       depends on ARM && ARCH_ACORN
-       select CRC32
-       help
-         If you have an Acorn system with one of these network cards, you
-         should say Y to this option if you wish to use it with Linux.
-
 config ARM_AT91_ETHER
        tristate "AT91RM9200 Ethernet support"
        depends on ARM && ARCH_AT91RM9200
index 63c57be34abfeb836d14ad793ad32ba30d3406d6..f1e6150b6757b24f422e01cc24ab53c54a98125d 100644 (file)
@@ -3,7 +3,6 @@
 # Makefile for the ARM network device drivers
 #
 
-obj-$(CONFIG_ARM_ETHERH)       += etherh.o
 obj-$(CONFIG_ARM_ETHER3)       += ether3.o
 obj-$(CONFIG_ARM_ETHER1)       += ether1.o
 obj-$(CONFIG_ARM_AT91_ETHER)   += at91_ether.o
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
deleted file mode 100644 (file)
index 03e217a..0000000
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- *  linux/drivers/acorn/net/etherh.c
- *
- *  Copyright (C) 2000-2002 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * NS8390 I-cubed EtherH and ANT EtherM specific driver
- * Thanks to I-Cubed for information on their cards.
- * EtherM conversion (C) 1999 Chris Kemp and Tim Watterton
- * EtherM integration (C) 2000 Aleph One Ltd (Tak-Shing Chan)
- * EtherM integration re-engineered by Russell King.
- *
- * Changelog:
- *  08-12-1996 RMK     1.00    Created
- *             RMK     1.03    Added support for EtherLan500 cards
- *  23-11-1997 RMK     1.04    Added media autodetection
- *  16-04-1998 RMK     1.05    Improved media autodetection
- *  10-02-2000 RMK     1.06    Updated for 2.3.43
- *  13-05-2000 RMK     1.07    Updated for 2.3.99-pre8
- *  12-10-1999  CK/TEW         EtherM driver first release
- *  21-12-2000 TTC             EtherH/EtherM integration
- *  25-12-2000 RMK     1.08    Clean integration of EtherM into this driver.
- *  03-01-2002 RMK     1.09    Always enable IRQs if we're in the nic slot.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/jiffies.h>
-
-#include <asm/system.h>
-#include <asm/ecard.h>
-#include <asm/io.h>
-
-#define EI_SHIFT(x)    (ei_local->reg_offset[x])
-
-#define ei_inb(_p)      readb((void __iomem *)_p)
-#define ei_outb(_v,_p)  writeb(_v,(void __iomem *)_p)
-#define ei_inb_p(_p)    readb((void __iomem *)_p)
-#define ei_outb_p(_v,_p) writeb(_v,(void __iomem *)_p)
-
-#define NET_DEBUG  0
-#define DEBUG_INIT 2
-
-#define DRV_NAME       "etherh"
-#define DRV_VERSION    "1.11"
-
-static char version[] __initdata =
-       "EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n";
-
-#include "../lib8390.c"
-
-static unsigned int net_debug = NET_DEBUG;
-
-struct etherh_priv {
-       void __iomem    *ioc_fast;
-       void __iomem    *memc;
-       void __iomem    *dma_base;
-       unsigned int    id;
-       void __iomem    *ctrl_port;
-       unsigned char   ctrl;
-       u32             supported;
-};
-
-struct etherh_data {
-       unsigned long   ns8390_offset;
-       unsigned long   dataport_offset;
-       unsigned long   ctrlport_offset;
-       int             ctrl_ioc;
-       const char      name[16];
-       u32             supported;
-       unsigned char   tx_start_page;
-       unsigned char   stop_page;
-};
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("EtherH/EtherM driver");
-MODULE_LICENSE("GPL");
-
-#define ETHERH500_DATAPORT     0x800   /* MEMC */
-#define ETHERH500_NS8390       0x000   /* MEMC */
-#define ETHERH500_CTRLPORT     0x800   /* IOC  */
-
-#define ETHERH600_DATAPORT     0x040   /* MEMC */
-#define ETHERH600_NS8390       0x800   /* MEMC */
-#define ETHERH600_CTRLPORT     0x200   /* MEMC */
-
-#define ETHERH_CP_IE           1
-#define ETHERH_CP_IF           2
-#define ETHERH_CP_HEARTBEAT    2
-
-#define ETHERH_TX_START_PAGE   1
-#define ETHERH_STOP_PAGE       127
-
-/*
- * These came from CK/TEW
- */
-#define ETHERM_DATAPORT                0x200   /* MEMC */
-#define ETHERM_NS8390          0x800   /* MEMC */
-#define ETHERM_CTRLPORT                0x23c   /* MEMC */
-
-#define ETHERM_TX_START_PAGE   64
-#define ETHERM_STOP_PAGE       127
-
-/* ------------------------------------------------------------------------ */
-
-#define etherh_priv(dev) \
- ((struct etherh_priv *)(((char *)netdev_priv(dev)) + sizeof(struct ei_device)))
-
-static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned char mask)
-{
-       unsigned char ctrl = eh->ctrl | mask;
-       eh->ctrl = ctrl;
-       writeb(ctrl, eh->ctrl_port);
-}
-
-static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned char mask)
-{
-       unsigned char ctrl = eh->ctrl & ~mask;
-       eh->ctrl = ctrl;
-       writeb(ctrl, eh->ctrl_port);
-}
-
-static inline unsigned int etherh_get_stat(struct etherh_priv *eh)
-{
-       return readb(eh->ctrl_port);
-}
-
-
-
-
-static void etherh_irq_enable(ecard_t *ec, int irqnr)
-{
-       struct etherh_priv *eh = ec->irq_data;
-
-       etherh_set_ctrl(eh, ETHERH_CP_IE);
-}
-
-static void etherh_irq_disable(ecard_t *ec, int irqnr)
-{
-       struct etherh_priv *eh = ec->irq_data;
-
-       etherh_clr_ctrl(eh, ETHERH_CP_IE);
-}
-
-static expansioncard_ops_t etherh_ops = {
-       .irqenable      = etherh_irq_enable,
-       .irqdisable     = etherh_irq_disable,
-};
-
-
-
-
-static void
-etherh_setif(struct net_device *dev)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       unsigned long flags;
-       void __iomem *addr;
-
-       local_irq_save(flags);
-
-       /* set the interface type */
-       switch (etherh_priv(dev)->id) {
-       case PROD_I3_ETHERLAN600:
-       case PROD_I3_ETHERLAN600A:
-               addr = (void __iomem *)dev->base_addr + EN0_RCNTHI;
-
-               switch (dev->if_port) {
-               case IF_PORT_10BASE2:
-                       writeb((readb(addr) & 0xf8) | 1, addr);
-                       break;
-               case IF_PORT_10BASET:
-                       writeb((readb(addr) & 0xf8), addr);
-                       break;
-               }
-               break;
-
-       case PROD_I3_ETHERLAN500:
-               switch (dev->if_port) {
-               case IF_PORT_10BASE2:
-                       etherh_clr_ctrl(etherh_priv(dev), ETHERH_CP_IF);
-                       break;
-
-               case IF_PORT_10BASET:
-                       etherh_set_ctrl(etherh_priv(dev), ETHERH_CP_IF);
-                       break;
-               }
-               break;
-
-       default:
-               break;
-       }
-
-       local_irq_restore(flags);
-}
-
-static int
-etherh_getifstat(struct net_device *dev)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       void __iomem *addr;
-       int stat = 0;
-
-       switch (etherh_priv(dev)->id) {
-       case PROD_I3_ETHERLAN600:
-       case PROD_I3_ETHERLAN600A:
-               addr = (void __iomem *)dev->base_addr + EN0_RCNTHI;
-               switch (dev->if_port) {
-               case IF_PORT_10BASE2:
-                       stat = 1;
-                       break;
-               case IF_PORT_10BASET:
-                       stat = readb(addr) & 4;
-                       break;
-               }
-               break;
-
-       case PROD_I3_ETHERLAN500:
-               switch (dev->if_port) {
-               case IF_PORT_10BASE2:
-                       stat = 1;
-                       break;
-               case IF_PORT_10BASET:
-                       stat = etherh_get_stat(etherh_priv(dev)) & ETHERH_CP_HEARTBEAT;
-                       break;
-               }
-               break;
-
-       default:
-               stat = 0;
-               break;
-       }
-
-       return stat != 0;
-}
-
-/*
- * Configure the interface.  Note that we ignore the other
- * parts of ifmap, since its mostly meaningless for this driver.
- */
-static int etherh_set_config(struct net_device *dev, struct ifmap *map)
-{
-       switch (map->port) {
-       case IF_PORT_10BASE2:
-       case IF_PORT_10BASET:
-               /*
-                * If the user explicitly sets the interface
-                * media type, turn off automedia detection.
-                */
-               dev->flags &= ~IFF_AUTOMEDIA;
-               dev->if_port = map->port;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       etherh_setif(dev);
-
-       return 0;
-}
-
-/*
- * Reset the 8390 (hard reset).  Note that we can't actually do this.
- */
-static void
-etherh_reset(struct net_device *dev)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       void __iomem *addr = (void __iomem *)dev->base_addr;
-
-       writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr);
-
-       /*
-        * See if we need to change the interface type.
-        * Note that we use 'interface_num' as a flag
-        * to indicate that we need to change the media.
-        */
-       if (dev->flags & IFF_AUTOMEDIA && ei_local->interface_num) {
-               ei_local->interface_num = 0;
-
-               if (dev->if_port == IF_PORT_10BASET)
-                       dev->if_port = IF_PORT_10BASE2;
-               else
-                       dev->if_port = IF_PORT_10BASET;
-
-               etherh_setif(dev);
-       }
-}
-
-/*
- * Write a block of data out to the 8390
- */
-static void
-etherh_block_output (struct net_device *dev, int count, const unsigned char *buf, int start_page)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       unsigned long dma_start;
-       void __iomem *dma_base, *addr;
-
-       if (ei_local->dmaing) {
-               printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: "
-                       " DMAstat %d irqlock %d\n", dev->name,
-                       ei_local->dmaing, ei_local->irqlock);
-               return;
-       }
-
-       /*
-        * Make sure we have a round number of bytes if we're in word mode.
-        */
-       if (count & 1 && ei_local->word16)
-               count++;
-
-       ei_local->dmaing = 1;
-
-       addr = (void __iomem *)dev->base_addr;
-       dma_base = etherh_priv(dev)->dma_base;
-
-       count = (count + 1) & ~1;
-       writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
-
-       writeb (0x42, addr + EN0_RCNTLO);
-       writeb (0x00, addr + EN0_RCNTHI);
-       writeb (0x42, addr + EN0_RSARLO);
-       writeb (0x00, addr + EN0_RSARHI);
-       writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
-
-       udelay (1);
-
-       writeb (ENISR_RDC, addr + EN0_ISR);
-       writeb (count, addr + EN0_RCNTLO);
-       writeb (count >> 8, addr + EN0_RCNTHI);
-       writeb (0, addr + EN0_RSARLO);
-       writeb (start_page, addr + EN0_RSARHI);
-       writeb (E8390_RWRITE | E8390_START, addr + E8390_CMD);
-
-       if (ei_local->word16)
-               writesw (dma_base, buf, count >> 1);
-       else
-               writesb (dma_base, buf, count);
-
-       dma_start = jiffies;
-
-       while ((readb (addr + EN0_ISR) & ENISR_RDC) == 0)
-               if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
-                       printk(KERN_ERR "%s: timeout waiting for TX RDC\n",
-                               dev->name);
-                       etherh_reset (dev);
-                       __NS8390_init (dev, 1);
-                       break;
-               }
-
-       writeb (ENISR_RDC, addr + EN0_ISR);
-       ei_local->dmaing = 0;
-}
-
-/*
- * Read a block of data from the 8390
- */
-static void
-etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       unsigned char *buf;
-       void __iomem *dma_base, *addr;
-
-       if (ei_local->dmaing) {
-               printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: "
-                       " DMAstat %d irqlock %d\n", dev->name,
-                       ei_local->dmaing, ei_local->irqlock);
-               return;
-       }
-
-       ei_local->dmaing = 1;
-
-       addr = (void __iomem *)dev->base_addr;
-       dma_base = etherh_priv(dev)->dma_base;
-
-       buf = skb->data;
-       writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
-       writeb (count, addr + EN0_RCNTLO);
-       writeb (count >> 8, addr + EN0_RCNTHI);
-       writeb (ring_offset, addr + EN0_RSARLO);
-       writeb (ring_offset >> 8, addr + EN0_RSARHI);
-       writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
-
-       if (ei_local->word16) {
-               readsw (dma_base, buf, count >> 1);
-               if (count & 1)
-                       buf[count - 1] = readb (dma_base);
-       } else
-               readsb (dma_base, buf, count);
-
-       writeb (ENISR_RDC, addr + EN0_ISR);
-       ei_local->dmaing = 0;
-}
-
-/*
- * Read a header from the 8390
- */
-static void
-etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       void __iomem *dma_base, *addr;
-
-       if (ei_local->dmaing) {
-               printk(KERN_ERR "%s: DMAing conflict in etherh_get_header: "
-                       " DMAstat %d irqlock %d\n", dev->name,
-                       ei_local->dmaing, ei_local->irqlock);
-               return;
-       }
-
-       ei_local->dmaing = 1;
-
-       addr = (void __iomem *)dev->base_addr;
-       dma_base = etherh_priv(dev)->dma_base;
-
-       writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
-       writeb (sizeof (*hdr), addr + EN0_RCNTLO);
-       writeb (0, addr + EN0_RCNTHI);
-       writeb (0, addr + EN0_RSARLO);
-       writeb (ring_page, addr + EN0_RSARHI);
-       writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
-
-       if (ei_local->word16)
-               readsw (dma_base, hdr, sizeof (*hdr) >> 1);
-       else
-               readsb (dma_base, hdr, sizeof (*hdr));
-
-       writeb (ENISR_RDC, addr + EN0_ISR);
-       ei_local->dmaing = 0;
-}
-
-/*
- * Open/initialize the board.  This is called (in the current kernel)
- * sometime after booting when the 'ifconfig' program is run.
- *
- * This routine should set everything up anew at each open, even
- * registers that "should" only need to be set once at boot, so that
- * there is non-reboot way to recover if something goes wrong.
- */
-static int
-etherh_open(struct net_device *dev)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-
-       if (!is_valid_ether_addr(dev->dev_addr)) {
-               printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
-                       dev->name);
-               return -EINVAL;
-       }
-
-       if (request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev))
-               return -EAGAIN;
-
-       /*
-        * Make sure that we aren't going to change the
-        * media type on the next reset - we are about to
-        * do automedia manually now.
-        */
-       ei_local->interface_num = 0;
-
-       /*
-        * If we are doing automedia detection, do it now.
-        * This is more reliable than the 8390's detection.
-        */
-       if (dev->flags & IFF_AUTOMEDIA) {
-               dev->if_port = IF_PORT_10BASET;
-               etherh_setif(dev);
-               mdelay(1);
-               if (!etherh_getifstat(dev)) {
-                       dev->if_port = IF_PORT_10BASE2;
-                       etherh_setif(dev);
-               }
-       } else
-               etherh_setif(dev);
-
-       etherh_reset(dev);
-       __ei_open(dev);
-
-       return 0;
-}
-
-/*
- * The inverse routine to etherh_open().
- */
-static int
-etherh_close(struct net_device *dev)
-{
-       __ei_close (dev);
-       free_irq (dev->irq, dev);
-       return 0;
-}
-
-/*
- * Initialisation
- */
-
-static void __init etherh_banner(void)
-{
-       static int version_printed;
-
-       if (net_debug && version_printed++ == 0)
-               printk(KERN_INFO "%s", version);
-}
-
-/*
- * Read the ethernet address string from the on board rom.
- * This is an ascii string...
- */
-static int __devinit etherh_addr(char *addr, struct expansion_card *ec)
-{
-       struct in_chunk_dir cd;
-       char *s;
-       
-       if (!ecard_readchunk(&cd, ec, 0xf5, 0)) {
-               printk(KERN_ERR "%s: unable to read podule description string\n",
-                      dev_name(&ec->dev));
-               goto no_addr;
-       }
-
-       s = strchr(cd.d.string, '(');
-       if (s) {
-               int i;
-
-               for (i = 0; i < 6; i++) {
-                       addr[i] = simple_strtoul(s + 1, &s, 0x10);
-                       if (*s != (i == 5? ')' : ':'))
-                               break;
-               }
-
-               if (i == 6)
-                       return 0;
-       }
-
-       printk(KERN_ERR "%s: unable to parse MAC address: %s\n",
-              dev_name(&ec->dev), cd.d.string);
-
- no_addr:
-       return -ENODEV;
-}
-
-/*
- * Create an ethernet address from the system serial number.
- */
-static int __init etherm_addr(char *addr)
-{
-       unsigned int serial;
-
-       if (system_serial_low == 0 && system_serial_high == 0)
-               return -ENODEV;
-
-       serial = system_serial_low | system_serial_high;
-
-       addr[0] = 0;
-       addr[1] = 0;
-       addr[2] = 0xa4;
-       addr[3] = 0x10 + (serial >> 24);
-       addr[4] = serial >> 16;
-       addr[5] = serial >> 8;
-       return 0;
-}
-
-static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, dev_name(dev->dev.parent),
-               sizeof(info->bus_info));
-}
-
-static int etherh_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-       cmd->supported  = etherh_priv(dev)->supported;
-       ethtool_cmd_speed_set(cmd, SPEED_10);
-       cmd->duplex     = DUPLEX_HALF;
-       cmd->port       = dev->if_port == IF_PORT_10BASET ? PORT_TP : PORT_BNC;
-       cmd->autoneg    = (dev->flags & IFF_AUTOMEDIA ?
-                          AUTONEG_ENABLE : AUTONEG_DISABLE);
-       return 0;
-}
-
-static int etherh_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-       switch (cmd->autoneg) {
-       case AUTONEG_ENABLE:
-               dev->flags |= IFF_AUTOMEDIA;
-               break;
-
-       case AUTONEG_DISABLE:
-               switch (cmd->port) {
-               case PORT_TP:
-                       dev->if_port = IF_PORT_10BASET;
-                       break;
-
-               case PORT_BNC:
-                       dev->if_port = IF_PORT_10BASE2;
-                       break;
-
-               default:
-                       return -EINVAL;
-               }
-               dev->flags &= ~IFF_AUTOMEDIA;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       etherh_setif(dev);
-
-       return 0;
-}
-
-static const struct ethtool_ops etherh_ethtool_ops = {
-       .get_settings   = etherh_get_settings,
-       .set_settings   = etherh_set_settings,
-       .get_drvinfo    = etherh_get_drvinfo,
-};
-
-static const struct net_device_ops etherh_netdev_ops = {
-       .ndo_open               = etherh_open,
-       .ndo_stop               = etherh_close,
-       .ndo_set_config         = etherh_set_config,
-       .ndo_start_xmit         = __ei_start_xmit,
-       .ndo_tx_timeout         = __ei_tx_timeout,
-       .ndo_get_stats          = __ei_get_stats,
-       .ndo_set_multicast_list = __ei_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = __ei_poll,
-#endif
-};
-
-static u32 etherh_regoffsets[16];
-static u32 etherm_regoffsets[16];
-
-static int __devinit
-etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
-{
-       const struct etherh_data *data = id->data;
-       struct ei_device *ei_local;
-       struct net_device *dev;
-       struct etherh_priv *eh;
-       int ret;
-
-       etherh_banner();
-
-       ret = ecard_request_resources(ec);
-       if (ret)
-               goto out;
-
-       dev = ____alloc_ei_netdev(sizeof(struct etherh_priv));
-       if (!dev) {
-               ret = -ENOMEM;
-               goto release;
-       }
-
-       SET_NETDEV_DEV(dev, &ec->dev);
-
-       dev->netdev_ops         = &etherh_netdev_ops;
-       dev->irq                = ec->irq;
-       dev->ethtool_ops        = &etherh_ethtool_ops;
-
-       if (data->supported & SUPPORTED_Autoneg)
-               dev->flags |= IFF_AUTOMEDIA;
-       if (data->supported & SUPPORTED_TP) {
-               dev->flags |= IFF_PORTSEL;
-               dev->if_port = IF_PORT_10BASET;
-       } else if (data->supported & SUPPORTED_BNC) {
-               dev->flags |= IFF_PORTSEL;
-               dev->if_port = IF_PORT_10BASE2;
-       } else
-               dev->if_port = IF_PORT_UNKNOWN;
-
-       eh = etherh_priv(dev);
-       eh->supported           = data->supported;
-       eh->ctrl                = 0;
-       eh->id                  = ec->cid.product;
-       eh->memc                = ecardm_iomap(ec, ECARD_RES_MEMC, 0, PAGE_SIZE);
-       if (!eh->memc) {
-               ret = -ENOMEM;
-               goto free;
-       }
-
-       eh->ctrl_port = eh->memc;
-       if (data->ctrl_ioc) {
-               eh->ioc_fast = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, PAGE_SIZE);
-               if (!eh->ioc_fast) {
-                       ret = -ENOMEM;
-                       goto free;
-               }
-               eh->ctrl_port = eh->ioc_fast;
-       }
-
-       dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset;
-       eh->dma_base = eh->memc + data->dataport_offset;
-       eh->ctrl_port += data->ctrlport_offset;
-
-       /*
-        * IRQ and control port handling - only for non-NIC slot cards.
-        */
-       if (ec->slot_no != 8) {
-               ecard_setirq(ec, &etherh_ops, eh);
-       } else {
-               /*
-                * If we're in the NIC slot, make sure the IRQ is enabled
-                */
-               etherh_set_ctrl(eh, ETHERH_CP_IE);
-       }
-
-       ei_local = netdev_priv(dev);
-       spin_lock_init(&ei_local->page_lock);
-
-       if (ec->cid.product == PROD_ANT_ETHERM) {
-               etherm_addr(dev->dev_addr);
-               ei_local->reg_offset = etherm_regoffsets;
-       } else {
-               etherh_addr(dev->dev_addr, ec);
-               ei_local->reg_offset = etherh_regoffsets;
-       }
-
-       ei_local->name          = dev->name;
-       ei_local->word16        = 1;
-       ei_local->tx_start_page = data->tx_start_page;
-       ei_local->rx_start_page = ei_local->tx_start_page + TX_PAGES;
-       ei_local->stop_page     = data->stop_page;
-       ei_local->reset_8390    = etherh_reset;
-       ei_local->block_input   = etherh_block_input;
-       ei_local->block_output  = etherh_block_output;
-       ei_local->get_8390_hdr  = etherh_get_header;
-       ei_local->interface_num = 0;
-
-       etherh_reset(dev);
-       __NS8390_init(dev, 0);
-
-       ret = register_netdev(dev);
-       if (ret)
-               goto free;
-
-       printk(KERN_INFO "%s: %s in slot %d, %pM\n",
-               dev->name, data->name, ec->slot_no, dev->dev_addr);
-
-       ecard_set_drvdata(ec, dev);
-
-       return 0;
-
- free:
-       free_netdev(dev);
- release:
-       ecard_release_resources(ec);
- out:
-       return ret;
-}
-
-static void __devexit etherh_remove(struct expansion_card *ec)
-{
-       struct net_device *dev = ecard_get_drvdata(ec);
-
-       ecard_set_drvdata(ec, NULL);
-
-       unregister_netdev(dev);
-
-       free_netdev(dev);
-
-       ecard_release_resources(ec);
-}
-
-static struct etherh_data etherm_data = {
-       .ns8390_offset          = ETHERM_NS8390,
-       .dataport_offset        = ETHERM_NS8390 + ETHERM_DATAPORT,
-       .ctrlport_offset        = ETHERM_NS8390 + ETHERM_CTRLPORT,
-       .name                   = "ANT EtherM",
-       .supported              = SUPPORTED_10baseT_Half,
-       .tx_start_page          = ETHERM_TX_START_PAGE,
-       .stop_page              = ETHERM_STOP_PAGE,
-};
-
-static struct etherh_data etherlan500_data = {
-       .ns8390_offset          = ETHERH500_NS8390,
-       .dataport_offset        = ETHERH500_NS8390 + ETHERH500_DATAPORT,
-       .ctrlport_offset        = ETHERH500_CTRLPORT,
-       .ctrl_ioc               = 1,
-       .name                   = "i3 EtherH 500",
-       .supported              = SUPPORTED_10baseT_Half,
-       .tx_start_page          = ETHERH_TX_START_PAGE,
-       .stop_page              = ETHERH_STOP_PAGE,
-};
-
-static struct etherh_data etherlan600_data = {
-       .ns8390_offset          = ETHERH600_NS8390,
-       .dataport_offset        = ETHERH600_NS8390 + ETHERH600_DATAPORT,
-       .ctrlport_offset        = ETHERH600_NS8390 + ETHERH600_CTRLPORT,
-       .name                   = "i3 EtherH 600",
-       .supported              = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg,
-       .tx_start_page          = ETHERH_TX_START_PAGE,
-       .stop_page              = ETHERH_STOP_PAGE,
-};
-
-static struct etherh_data etherlan600a_data = {
-       .ns8390_offset          = ETHERH600_NS8390,
-       .dataport_offset        = ETHERH600_NS8390 + ETHERH600_DATAPORT,
-       .ctrlport_offset        = ETHERH600_NS8390 + ETHERH600_CTRLPORT,
-       .name                   = "i3 EtherH 600A",
-       .supported              = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg,
-       .tx_start_page          = ETHERH_TX_START_PAGE,
-       .stop_page              = ETHERH_STOP_PAGE,
-};
-
-static const struct ecard_id etherh_ids[] = {
-       { MANU_ANT, PROD_ANT_ETHERM,      &etherm_data       },
-       { MANU_I3,  PROD_I3_ETHERLAN500,  &etherlan500_data  },
-       { MANU_I3,  PROD_I3_ETHERLAN600,  &etherlan600_data  },
-       { MANU_I3,  PROD_I3_ETHERLAN600A, &etherlan600a_data },
-       { 0xffff,   0xffff }
-};
-
-static struct ecard_driver etherh_driver = {
-       .probe          = etherh_probe,
-       .remove         = __devexit_p(etherh_remove),
-       .id_table       = etherh_ids,
-       .drv = {
-               .name   = DRV_NAME,
-       },
-};
-
-static int __init etherh_init(void)
-{
-       int i;
-
-       for (i = 0; i < 16; i++) {
-               etherh_regoffsets[i] = i << 2;
-               etherm_regoffsets[i] = i << 5;
-       }
-
-       return ecard_register_driver(&etherh_driver);
-}
-
-static void __exit etherh_exit(void)
-{
-       ecard_remove_driver(&etherh_driver);
-}
-
-module_init(etherh_init);
-module_exit(etherh_exit);
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
deleted file mode 100644 (file)
index e7cb8c8..0000000
+++ /dev/null
@@ -1,1010 +0,0 @@
-/* drivers/net/ax88796.c
- *
- * Copyright 2005,2007 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *
- * Asix AX88796 10/100 Ethernet controller support
- *     Based on ne.c, by Donald Becker, et-al.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/isapnp.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/mdio-bitbang.h>
-#include <linux/phy.h>
-#include <linux/eeprom_93cx6.h>
-#include <linux/slab.h>
-
-#include <net/ax88796.h>
-
-#include <asm/system.h>
-
-/* Rename the lib8390.c functions to show that they are in this driver */
-#define __ei_open ax_ei_open
-#define __ei_close ax_ei_close
-#define __ei_poll ax_ei_poll
-#define __ei_start_xmit ax_ei_start_xmit
-#define __ei_tx_timeout ax_ei_tx_timeout
-#define __ei_get_stats ax_ei_get_stats
-#define __ei_set_multicast_list ax_ei_set_multicast_list
-#define __ei_interrupt ax_ei_interrupt
-#define ____alloc_ei_netdev ax__alloc_ei_netdev
-#define __NS8390_init ax_NS8390_init
-
-/* force unsigned long back to 'void __iomem *' */
-#define ax_convert_addr(_a) ((void __force __iomem *)(_a))
-
-#define ei_inb(_a) readb(ax_convert_addr(_a))
-#define ei_outb(_v, _a) writeb(_v, ax_convert_addr(_a))
-
-#define ei_inb_p(_a) ei_inb(_a)
-#define ei_outb_p(_v, _a) ei_outb(_v, _a)
-
-/* define EI_SHIFT() to take into account our register offsets */
-#define EI_SHIFT(x) (ei_local->reg_offset[(x)])
-
-/* Ensure we have our RCR base value */
-#define AX88796_PLATFORM
-
-static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electronics\n";
-
-#include "lib8390.c"
-
-#define DRV_NAME "ax88796"
-#define DRV_VERSION "1.00"
-
-/* from ne.c */
-#define NE_CMD         EI_SHIFT(0x00)
-#define NE_RESET       EI_SHIFT(0x1f)
-#define NE_DATAPORT    EI_SHIFT(0x10)
-
-#define NE1SM_START_PG 0x20    /* First page of TX buffer */
-#define NE1SM_STOP_PG  0x40    /* Last page +1 of RX ring */
-#define NESM_START_PG  0x40    /* First page of TX buffer */
-#define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
-
-#define AX_GPOC_PPDSET BIT(6)
-
-/* device private data */
-
-struct ax_device {
-       struct mii_bus *mii_bus;
-       struct mdiobb_ctrl bb_ctrl;
-       struct phy_device *phy_dev;
-       void __iomem *addr_memr;
-       u8 reg_memr;
-       int link;
-       int speed;
-       int duplex;
-
-       void __iomem *map2;
-       const struct ax_plat_data *plat;
-
-       unsigned char running;
-       unsigned char resume_open;
-       unsigned int irqflags;
-
-       u32 reg_offsets[0x20];
-};
-
-static inline struct ax_device *to_ax_dev(struct net_device *dev)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       return (struct ax_device *)(ei_local + 1);
-}
-
-/*
- * ax_initial_check
- *
- * do an initial probe for the card to check wether it exists
- * and is functional
- */
-static int ax_initial_check(struct net_device *dev)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       void __iomem *ioaddr = ei_local->mem;
-       int reg0;
-       int regd;
-
-       reg0 = ei_inb(ioaddr);
-       if (reg0 == 0xFF)
-               return -ENODEV;
-
-       ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP, ioaddr + E8390_CMD);
-       regd = ei_inb(ioaddr + 0x0d);
-       ei_outb(0xff, ioaddr + 0x0d);
-       ei_outb(E8390_NODMA + E8390_PAGE0, ioaddr + E8390_CMD);
-       ei_inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
-       if (ei_inb(ioaddr + EN0_COUNTER0) != 0) {
-               ei_outb(reg0, ioaddr);
-               ei_outb(regd, ioaddr + 0x0d);   /* Restore the old values. */
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-/*
- * Hard reset the card. This used to pause for the same period that a
- * 8390 reset command required, but that shouldn't be necessary.
- */
-static void ax_reset_8390(struct net_device *dev)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       unsigned long reset_start_time = jiffies;
-       void __iomem *addr = (void __iomem *)dev->base_addr;
-
-       if (ei_debug > 1)
-               netdev_dbg(dev, "resetting the 8390 t=%ld\n", jiffies);
-
-       ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
-
-       ei_local->txing = 0;
-       ei_local->dmaing = 0;
-
-       /* This check _should_not_ be necessary, omit eventually. */
-       while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) {
-               if (jiffies - reset_start_time > 2 * HZ / 100) {
-                       netdev_warn(dev, "%s: did not complete.\n", __func__);
-                       break;
-               }
-       }
-
-       ei_outb(ENISR_RESET, addr + EN0_ISR);   /* Ack intr. */
-}
-
-
-static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                           int ring_page)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       void __iomem *nic_base = ei_local->mem;
-
-       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-       if (ei_local->dmaing) {
-               netdev_err(dev, "DMAing conflict in %s "
-                       "[DMAstat:%d][irqlock:%d].\n",
-                       __func__,
-                       ei_local->dmaing, ei_local->irqlock);
-               return;
-       }
-
-       ei_local->dmaing |= 0x01;
-       ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
-       ei_outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
-       ei_outb(0, nic_base + EN0_RCNTHI);
-       ei_outb(0, nic_base + EN0_RSARLO);              /* On page boundary */
-       ei_outb(ring_page, nic_base + EN0_RSARHI);
-       ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
-       if (ei_local->word16)
-               readsw(nic_base + NE_DATAPORT, hdr,
-                      sizeof(struct e8390_pkt_hdr) >> 1);
-       else
-               readsb(nic_base + NE_DATAPORT, hdr,
-                      sizeof(struct e8390_pkt_hdr));
-
-       ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
-       ei_local->dmaing &= ~0x01;
-
-       le16_to_cpus(&hdr->count);
-}
-
-
-/*
- * Block input and output, similar to the Crynwr packet driver. If
- * you are porting to a new ethercard, look at the packet driver
- * source for hints. The NEx000 doesn't share the on-board packet
- * memory -- you have to put the packet out through the "remote DMA"
- * dataport using ei_outb.
- */
-static void ax_block_input(struct net_device *dev, int count,
-                          struct sk_buff *skb, int ring_offset)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       void __iomem *nic_base = ei_local->mem;
-       char *buf = skb->data;
-
-       if (ei_local->dmaing) {
-               netdev_err(dev,
-                       "DMAing conflict in %s "
-                       "[DMAstat:%d][irqlock:%d].\n",
-                       __func__,
-                       ei_local->dmaing, ei_local->irqlock);
-               return;
-       }
-
-       ei_local->dmaing |= 0x01;
-
-       ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + NE_CMD);
-       ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
-       ei_outb(count >> 8, nic_base + EN0_RCNTHI);
-       ei_outb(ring_offset & 0xff, nic_base + EN0_RSARLO);
-       ei_outb(ring_offset >> 8, nic_base + EN0_RSARHI);
-       ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
-       if (ei_local->word16) {
-               readsw(nic_base + NE_DATAPORT, buf, count >> 1);
-               if (count & 0x01)
-                       buf[count-1] = ei_inb(nic_base + NE_DATAPORT);
-
-       } else {
-               readsb(nic_base + NE_DATAPORT, buf, count);
-       }
-
-       ei_local->dmaing &= ~1;
-}
-
-static void ax_block_output(struct net_device *dev, int count,
-                           const unsigned char *buf, const int start_page)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       void __iomem *nic_base = ei_local->mem;
-       unsigned long dma_start;
-
-       /*
-        * Round the count up for word writes. Do we need to do this?
-        * What effect will an odd byte count have on the 8390?  I
-        * should check someday.
-        */
-       if (ei_local->word16 && (count & 0x01))
-               count++;
-
-       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-       if (ei_local->dmaing) {
-               netdev_err(dev, "DMAing conflict in %s."
-                       "[DMAstat:%d][irqlock:%d]\n",
-                       __func__,
-                      ei_local->dmaing, ei_local->irqlock);
-               return;
-       }
-
-       ei_local->dmaing |= 0x01;
-       /* We should already be in page 0, but to be safe... */
-       ei_outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
-       ei_outb(ENISR_RDC, nic_base + EN0_ISR);
-
-       /* Now the normal output. */
-       ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
-       ei_outb(count >> 8, nic_base + EN0_RCNTHI);
-       ei_outb(0x00, nic_base + EN0_RSARLO);
-       ei_outb(start_page, nic_base + EN0_RSARHI);
-
-       ei_outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
-       if (ei_local->word16)
-               writesw(nic_base + NE_DATAPORT, buf, count >> 1);
-       else
-               writesb(nic_base + NE_DATAPORT, buf, count);
-
-       dma_start = jiffies;
-
-       while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) {
-               if (jiffies - dma_start > 2 * HZ / 100) {               /* 20ms */
-                       netdev_warn(dev, "timeout waiting for Tx RDC.\n");
-                       ax_reset_8390(dev);
-                       ax_NS8390_init(dev, 1);
-                       break;
-               }
-       }
-
-       ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
-       ei_local->dmaing &= ~0x01;
-}
-
-/* definitions for accessing MII/EEPROM interface */
-
-#define AX_MEMR                        EI_SHIFT(0x14)
-#define AX_MEMR_MDC            BIT(0)
-#define AX_MEMR_MDIR           BIT(1)
-#define AX_MEMR_MDI            BIT(2)
-#define AX_MEMR_MDO            BIT(3)
-#define AX_MEMR_EECS           BIT(4)
-#define AX_MEMR_EEI            BIT(5)
-#define AX_MEMR_EEO            BIT(6)
-#define AX_MEMR_EECLK          BIT(7)
-
-static void ax_handle_link_change(struct net_device *dev)
-{
-       struct ax_device  *ax = to_ax_dev(dev);
-       struct phy_device *phy_dev = ax->phy_dev;
-       int status_change = 0;
-
-       if (phy_dev->link && ((ax->speed != phy_dev->speed) ||
-                            (ax->duplex != phy_dev->duplex))) {
-
-               ax->speed = phy_dev->speed;
-               ax->duplex = phy_dev->duplex;
-               status_change = 1;
-       }
-
-       if (phy_dev->link != ax->link) {
-               if (!phy_dev->link) {
-                       ax->speed = 0;
-                       ax->duplex = -1;
-               }
-               ax->link = phy_dev->link;
-
-               status_change = 1;
-       }
-
-       if (status_change)
-               phy_print_status(phy_dev);
-}
-
-static int ax_mii_probe(struct net_device *dev)
-{
-       struct ax_device  *ax = to_ax_dev(dev);
-       struct phy_device *phy_dev = NULL;
-       int ret;
-
-       /* find the first phy */
-       phy_dev = phy_find_first(ax->mii_bus);
-       if (!phy_dev) {
-               netdev_err(dev, "no PHY found\n");
-               return -ENODEV;
-       }
-
-       ret = phy_connect_direct(dev, phy_dev, ax_handle_link_change, 0,
-                                PHY_INTERFACE_MODE_MII);
-       if (ret) {
-               netdev_err(dev, "Could not attach to PHY\n");
-               return ret;
-       }
-
-       /* mask with MAC supported features */
-       phy_dev->supported &= PHY_BASIC_FEATURES;
-       phy_dev->advertising = phy_dev->supported;
-
-       ax->phy_dev = phy_dev;
-
-       netdev_info(dev, "PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
-                   phy_dev->drv->name, dev_name(&phy_dev->dev), phy_dev->irq);
-
-       return 0;
-}
-
-static void ax_phy_switch(struct net_device *dev, int on)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       struct ax_device *ax = to_ax_dev(dev);
-
-       u8 reg_gpoc =  ax->plat->gpoc_val;
-
-       if (!!on)
-               reg_gpoc &= ~AX_GPOC_PPDSET;
-       else
-               reg_gpoc |= AX_GPOC_PPDSET;
-
-       ei_outb(reg_gpoc, ei_local->mem + EI_SHIFT(0x17));
-}
-
-static int ax_open(struct net_device *dev)
-{
-       struct ax_device *ax = to_ax_dev(dev);
-       int ret;
-
-       netdev_dbg(dev, "open\n");
-
-       ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags,
-                         dev->name, dev);
-       if (ret)
-               goto failed_request_irq;
-
-       /* turn the phy on (if turned off) */
-       ax_phy_switch(dev, 1);
-
-       ret = ax_mii_probe(dev);
-       if (ret)
-               goto failed_mii_probe;
-       phy_start(ax->phy_dev);
-
-       ret = ax_ei_open(dev);
-       if (ret)
-               goto failed_ax_ei_open;
-
-       ax->running = 1;
-
-       return 0;
-
- failed_ax_ei_open:
-       phy_disconnect(ax->phy_dev);
- failed_mii_probe:
-       ax_phy_switch(dev, 0);
-       free_irq(dev->irq, dev);
- failed_request_irq:
-       return ret;
-}
-
-static int ax_close(struct net_device *dev)
-{
-       struct ax_device *ax = to_ax_dev(dev);
-
-       netdev_dbg(dev, "close\n");
-
-       ax->running = 0;
-       wmb();
-
-       ax_ei_close(dev);
-
-       /* turn the phy off */
-       ax_phy_switch(dev, 0);
-       phy_disconnect(ax->phy_dev);
-
-       free_irq(dev->irq, dev);
-       return 0;
-}
-
-static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
-{
-       struct ax_device *ax = to_ax_dev(dev);
-       struct phy_device *phy_dev = ax->phy_dev;
-
-       if (!netif_running(dev))
-               return -EINVAL;
-
-       if (!phy_dev)
-               return -ENODEV;
-
-       return phy_mii_ioctl(phy_dev, req, cmd);
-}
-
-/* ethtool ops */
-
-static void ax_get_drvinfo(struct net_device *dev,
-                          struct ethtool_drvinfo *info)
-{
-       struct platform_device *pdev = to_platform_device(dev->dev.parent);
-
-       strcpy(info->driver, DRV_NAME);
-       strcpy(info->version, DRV_VERSION);
-       strcpy(info->bus_info, pdev->name);
-}
-
-static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-       struct ax_device *ax = to_ax_dev(dev);
-       struct phy_device *phy_dev = ax->phy_dev;
-
-       if (!phy_dev)
-               return -ENODEV;
-
-       return phy_ethtool_gset(phy_dev, cmd);
-}
-
-static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-       struct ax_device *ax = to_ax_dev(dev);
-       struct phy_device *phy_dev = ax->phy_dev;
-
-       if (!phy_dev)
-               return -ENODEV;
-
-       return phy_ethtool_sset(phy_dev, cmd);
-}
-
-static const struct ethtool_ops ax_ethtool_ops = {
-       .get_drvinfo            = ax_get_drvinfo,
-       .get_settings           = ax_get_settings,
-       .set_settings           = ax_set_settings,
-       .get_link               = ethtool_op_get_link,
-};
-
-#ifdef CONFIG_AX88796_93CX6
-static void ax_eeprom_register_read(struct eeprom_93cx6 *eeprom)
-{
-       struct ei_device *ei_local = eeprom->data;
-       u8 reg = ei_inb(ei_local->mem + AX_MEMR);
-
-       eeprom->reg_data_in = reg & AX_MEMR_EEI;
-       eeprom->reg_data_out = reg & AX_MEMR_EEO; /* Input pin */
-       eeprom->reg_data_clock = reg & AX_MEMR_EECLK;
-       eeprom->reg_chip_select = reg & AX_MEMR_EECS;
-}
-
-static void ax_eeprom_register_write(struct eeprom_93cx6 *eeprom)
-{
-       struct ei_device *ei_local = eeprom->data;
-       u8 reg = ei_inb(ei_local->mem + AX_MEMR);
-
-       reg &= ~(AX_MEMR_EEI | AX_MEMR_EECLK | AX_MEMR_EECS);
-
-       if (eeprom->reg_data_in)
-               reg |= AX_MEMR_EEI;
-       if (eeprom->reg_data_clock)
-               reg |= AX_MEMR_EECLK;
-       if (eeprom->reg_chip_select)
-               reg |= AX_MEMR_EECS;
-
-       ei_outb(reg, ei_local->mem + AX_MEMR);
-       udelay(10);
-}
-#endif
-
-static const struct net_device_ops ax_netdev_ops = {
-       .ndo_open               = ax_open,
-       .ndo_stop               = ax_close,
-       .ndo_do_ioctl           = ax_ioctl,
-
-       .ndo_start_xmit         = ax_ei_start_xmit,
-       .ndo_tx_timeout         = ax_ei_tx_timeout,
-       .ndo_get_stats          = ax_ei_get_stats,
-       .ndo_set_multicast_list = ax_ei_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = ax_ei_poll,
-#endif
-};
-
-static void ax_bb_mdc(struct mdiobb_ctrl *ctrl, int level)
-{
-       struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
-
-       if (level)
-               ax->reg_memr |= AX_MEMR_MDC;
-       else
-               ax->reg_memr &= ~AX_MEMR_MDC;
-
-       ei_outb(ax->reg_memr, ax->addr_memr);
-}
-
-static void ax_bb_dir(struct mdiobb_ctrl *ctrl, int output)
-{
-       struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
-
-       if (output)
-               ax->reg_memr &= ~AX_MEMR_MDIR;
-       else
-               ax->reg_memr |= AX_MEMR_MDIR;
-
-       ei_outb(ax->reg_memr, ax->addr_memr);
-}
-
-static void ax_bb_set_data(struct mdiobb_ctrl *ctrl, int value)
-{
-       struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
-
-       if (value)
-               ax->reg_memr |= AX_MEMR_MDO;
-       else
-               ax->reg_memr &= ~AX_MEMR_MDO;
-
-       ei_outb(ax->reg_memr, ax->addr_memr);
-}
-
-static int ax_bb_get_data(struct mdiobb_ctrl *ctrl)
-{
-       struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
-       int reg_memr = ei_inb(ax->addr_memr);
-
-       return reg_memr & AX_MEMR_MDI ? 1 : 0;
-}
-
-static struct mdiobb_ops bb_ops = {
-       .owner = THIS_MODULE,
-       .set_mdc = ax_bb_mdc,
-       .set_mdio_dir = ax_bb_dir,
-       .set_mdio_data = ax_bb_set_data,
-       .get_mdio_data = ax_bb_get_data,
-};
-
-/* setup code */
-
-static int ax_mii_init(struct net_device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev->dev.parent);
-       struct ei_device *ei_local = netdev_priv(dev);
-       struct ax_device *ax = to_ax_dev(dev);
-       int err, i;
-
-       ax->bb_ctrl.ops = &bb_ops;
-       ax->addr_memr = ei_local->mem + AX_MEMR;
-       ax->mii_bus = alloc_mdio_bitbang(&ax->bb_ctrl);
-       if (!ax->mii_bus) {
-               err = -ENOMEM;
-               goto out;
-       }
-
-       ax->mii_bus->name = "ax88796_mii_bus";
-       ax->mii_bus->parent = dev->dev.parent;
-       snprintf(ax->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
-
-       ax->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
-       if (!ax->mii_bus->irq) {
-               err = -ENOMEM;
-               goto out_free_mdio_bitbang;
-       }
-
-       for (i = 0; i < PHY_MAX_ADDR; i++)
-               ax->mii_bus->irq[i] = PHY_POLL;
-
-       err = mdiobus_register(ax->mii_bus);
-       if (err)
-               goto out_free_irq;
-
-       return 0;
-
- out_free_irq:
-       kfree(ax->mii_bus->irq);
- out_free_mdio_bitbang:
-       free_mdio_bitbang(ax->mii_bus);
- out:
-       return err;
-}
-
-static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local)
-{
-       void __iomem *ioaddr = ei_local->mem;
-       struct ax_device *ax = to_ax_dev(dev);
-
-       /* Select page 0 */
-       ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_STOP, ioaddr + E8390_CMD);
-
-       /* set to byte access */
-       ei_outb(ax->plat->dcr_val & ~1, ioaddr + EN0_DCFG);
-       ei_outb(ax->plat->gpoc_val, ioaddr + EI_SHIFT(0x17));
-}
-
-/*
- * ax_init_dev
- *
- * initialise the specified device, taking care to note the MAC
- * address it may already have (if configured), ensure
- * the device is ready to be used by lib8390.c and registerd with
- * the network layer.
- */
-static int ax_init_dev(struct net_device *dev)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       struct ax_device *ax = to_ax_dev(dev);
-       void __iomem *ioaddr = ei_local->mem;
-       unsigned int start_page;
-       unsigned int stop_page;
-       int ret;
-       int i;
-
-       ret = ax_initial_check(dev);
-       if (ret)
-               goto err_out;
-
-       /* setup goes here */
-
-       ax_initial_setup(dev, ei_local);
-
-       /* read the mac from the card prom if we need it */
-
-       if (ax->plat->flags & AXFLG_HAS_EEPROM) {
-               unsigned char SA_prom[32];
-
-               for (i = 0; i < sizeof(SA_prom); i += 2) {
-                       SA_prom[i] = ei_inb(ioaddr + NE_DATAPORT);
-                       SA_prom[i + 1] = ei_inb(ioaddr + NE_DATAPORT);
-               }
-
-               if (ax->plat->wordlength == 2)
-                       for (i = 0; i < 16; i++)
-                               SA_prom[i] = SA_prom[i+i];
-
-               memcpy(dev->dev_addr, SA_prom, 6);
-       }
-
-#ifdef CONFIG_AX88796_93CX6
-       if (ax->plat->flags & AXFLG_HAS_93CX6) {
-               unsigned char mac_addr[6];
-               struct eeprom_93cx6 eeprom;
-
-               eeprom.data = ei_local;
-               eeprom.register_read = ax_eeprom_register_read;
-               eeprom.register_write = ax_eeprom_register_write;
-               eeprom.width = PCI_EEPROM_WIDTH_93C56;
-
-               eeprom_93cx6_multiread(&eeprom, 0,
-                                      (__le16 __force *)mac_addr,
-                                      sizeof(mac_addr) >> 1);
-
-               memcpy(dev->dev_addr, mac_addr, 6);
-       }
-#endif
-       if (ax->plat->wordlength == 2) {
-               /* We must set the 8390 for word mode. */
-               ei_outb(ax->plat->dcr_val, ei_local->mem + EN0_DCFG);
-               start_page = NESM_START_PG;
-               stop_page = NESM_STOP_PG;
-       } else {
-               start_page = NE1SM_START_PG;
-               stop_page = NE1SM_STOP_PG;
-       }
-
-       /* load the mac-address from the device */
-       if (ax->plat->flags & AXFLG_MAC_FROMDEV) {
-               ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
-                       ei_local->mem + E8390_CMD); /* 0x61 */
-               for (i = 0; i < ETHER_ADDR_LEN; i++)
-                       dev->dev_addr[i] =
-                               ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
-       }
-
-       if ((ax->plat->flags & AXFLG_MAC_FROMPLATFORM) &&
-           ax->plat->mac_addr)
-               memcpy(dev->dev_addr, ax->plat->mac_addr,
-                      ETHER_ADDR_LEN);
-
-       ax_reset_8390(dev);
-
-       ei_local->name = "AX88796";
-       ei_local->tx_start_page = start_page;
-       ei_local->stop_page = stop_page;
-       ei_local->word16 = (ax->plat->wordlength == 2);
-       ei_local->rx_start_page = start_page + TX_PAGES;
-
-#ifdef PACKETBUF_MEMSIZE
-       /* Allow the packet buffer size to be overridden by know-it-alls. */
-       ei_local->stop_page = ei_local->tx_start_page + PACKETBUF_MEMSIZE;
-#endif
-
-       ei_local->reset_8390 = &ax_reset_8390;
-       ei_local->block_input = &ax_block_input;
-       ei_local->block_output = &ax_block_output;
-       ei_local->get_8390_hdr = &ax_get_8390_hdr;
-       ei_local->priv = 0;
-
-       dev->netdev_ops = &ax_netdev_ops;
-       dev->ethtool_ops = &ax_ethtool_ops;
-
-       ret = ax_mii_init(dev);
-       if (ret)
-               goto out_irq;
-
-       ax_NS8390_init(dev, 0);
-
-       ret = register_netdev(dev);
-       if (ret)
-               goto out_irq;
-
-       netdev_info(dev, "%dbit, irq %d, %lx, MAC: %pM\n",
-                   ei_local->word16 ? 16 : 8, dev->irq, dev->base_addr,
-                   dev->dev_addr);
-
-       return 0;
-
- out_irq:
-       /* cleanup irq */
-       free_irq(dev->irq, dev);
- err_out:
-       return ret;
-}
-
-static int ax_remove(struct platform_device *pdev)
-{
-       struct net_device *dev = platform_get_drvdata(pdev);
-       struct ei_device *ei_local = netdev_priv(dev);
-       struct ax_device *ax = to_ax_dev(dev);
-       struct resource *mem;
-
-       unregister_netdev(dev);
-       free_irq(dev->irq, dev);
-
-       iounmap(ei_local->mem);
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(mem->start, resource_size(mem));
-
-       if (ax->map2) {
-               iounmap(ax->map2);
-               mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-               release_mem_region(mem->start, resource_size(mem));
-       }
-
-       free_netdev(dev);
-
-       return 0;
-}
-
-/*
- * ax_probe
- *
- * This is the entry point when the platform device system uses to
- * notify us of a new device to attach to. Allocate memory, find the
- * resources and information passed, and map the necessary registers.
- */
-static int ax_probe(struct platform_device *pdev)
-{
-       struct net_device *dev;
-       struct ei_device *ei_local;
-       struct ax_device *ax;
-       struct resource *irq, *mem, *mem2;
-       resource_size_t mem_size, mem2_size = 0;
-       int ret = 0;
-
-       dev = ax__alloc_ei_netdev(sizeof(struct ax_device));
-       if (dev == NULL)
-               return -ENOMEM;
-
-       /* ok, let's setup our device */
-       SET_NETDEV_DEV(dev, &pdev->dev);
-       ei_local = netdev_priv(dev);
-       ax = to_ax_dev(dev);
-
-       ax->plat = pdev->dev.platform_data;
-       platform_set_drvdata(pdev, dev);
-
-       ei_local->rxcr_base = ax->plat->rcr_val;
-
-       /* find the platform resources */
-       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!irq) {
-               dev_err(&pdev->dev, "no IRQ specified\n");
-               ret = -ENXIO;
-               goto exit_mem;
-       }
-
-       dev->irq = irq->start;
-       ax->irqflags = irq->flags & IRQF_TRIGGER_MASK;
-
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!mem) {
-               dev_err(&pdev->dev, "no MEM specified\n");
-               ret = -ENXIO;
-               goto exit_mem;
-       }
-
-       mem_size = resource_size(mem);
-
-       /*
-        * setup the register offsets from either the platform data or
-        * by using the size of the resource provided
-        */
-       if (ax->plat->reg_offsets)
-               ei_local->reg_offset = ax->plat->reg_offsets;
-       else {
-               ei_local->reg_offset = ax->reg_offsets;
-               for (ret = 0; ret < 0x18; ret++)
-                       ax->reg_offsets[ret] = (mem_size / 0x18) * ret;
-       }
-
-       if (!request_mem_region(mem->start, mem_size, pdev->name)) {
-               dev_err(&pdev->dev, "cannot reserve registers\n");
-               ret = -ENXIO;
-               goto exit_mem;
-       }
-
-       ei_local->mem = ioremap(mem->start, mem_size);
-       dev->base_addr = (unsigned long)ei_local->mem;
-
-       if (ei_local->mem == NULL) {
-               dev_err(&pdev->dev, "Cannot ioremap area %pR\n", mem);
-
-               ret = -ENXIO;
-               goto exit_req;
-       }
-
-       /* look for reset area */
-       mem2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!mem2) {
-               if (!ax->plat->reg_offsets) {
-                       for (ret = 0; ret < 0x20; ret++)
-                               ax->reg_offsets[ret] = (mem_size / 0x20) * ret;
-               }
-       } else {
-               mem2_size = resource_size(mem2);
-
-               if (!request_mem_region(mem2->start, mem2_size, pdev->name)) {
-                       dev_err(&pdev->dev, "cannot reserve registers\n");
-                       ret = -ENXIO;
-                       goto exit_mem1;
-               }
-
-               ax->map2 = ioremap(mem2->start, mem2_size);
-               if (!ax->map2) {
-                       dev_err(&pdev->dev, "cannot map reset register\n");
-                       ret = -ENXIO;
-                       goto exit_mem2;
-               }
-
-               ei_local->reg_offset[0x1f] = ax->map2 - ei_local->mem;
-       }
-
-       /* got resources, now initialise and register device */
-       ret = ax_init_dev(dev);
-       if (!ret)
-               return 0;
-
-       if (!ax->map2)
-               goto exit_mem1;
-
-       iounmap(ax->map2);
-
- exit_mem2:
-       release_mem_region(mem2->start, mem2_size);
-
- exit_mem1:
-       iounmap(ei_local->mem);
-
- exit_req:
-       release_mem_region(mem->start, mem_size);
-
- exit_mem:
-       free_netdev(dev);
-
-       return ret;
-}
-
-/* suspend and resume */
-
-#ifdef CONFIG_PM
-static int ax_suspend(struct platform_device *dev, pm_message_t state)
-{
-       struct net_device *ndev = platform_get_drvdata(dev);
-       struct ax_device *ax = to_ax_dev(ndev);
-
-       ax->resume_open = ax->running;
-
-       netif_device_detach(ndev);
-       ax_close(ndev);
-
-       return 0;
-}
-
-static int ax_resume(struct platform_device *pdev)
-{
-       struct net_device *ndev = platform_get_drvdata(pdev);
-       struct ax_device *ax = to_ax_dev(ndev);
-
-       ax_initial_setup(ndev, netdev_priv(ndev));
-       ax_NS8390_init(ndev, ax->resume_open);
-       netif_device_attach(ndev);
-
-       if (ax->resume_open)
-               ax_open(ndev);
-
-       return 0;
-}
-
-#else
-#define ax_suspend NULL
-#define ax_resume NULL
-#endif
-
-static struct platform_driver axdrv = {
-       .driver = {
-               .name           = "ax88796",
-               .owner          = THIS_MODULE,
-       },
-       .probe          = ax_probe,
-       .remove         = ax_remove,
-       .suspend        = ax_suspend,
-       .resume         = ax_resume,
-};
-
-static int __init axdrv_init(void)
-{
-       return platform_driver_register(&axdrv);
-}
-
-static void __exit axdrv_exit(void)
-{
-       platform_driver_unregister(&axdrv);
-}
-
-module_init(axdrv_init);
-module_exit(axdrv_exit);
-
-MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
-MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:ax88796");
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
deleted file mode 100644 (file)
index d50a999..0000000
+++ /dev/null
@@ -1,490 +0,0 @@
-/* e2100.c: A Cabletron E2100 series ethernet driver for linux. */
-/*
-       Written 1993-1994 by Donald Becker.
-
-       Copyright 1994 by Donald Becker.
-       Copyright 1993 United States Government as represented by the
-       Director, National Security Agency.  This software may be used and
-       distributed according to the terms of the GNU General Public License,
-       incorporated herein by reference.
-
-       This is a driver for the Cabletron E2100 series ethercards.
-
-       The Author may be reached as becker@scyld.com, or C/O
-       Scyld Computing Corporation
-       410 Severn Ave., Suite 210
-       Annapolis MD 21403
-
-       The E2100 series ethercard is a fairly generic shared memory 8390
-       implementation.  The only unusual aspect is the way the shared memory
-       registers are set: first you do an inb() in what is normally the
-       station address region, and the low three bits of next outb() *address*
-       is used as the write value for that register.  Either someone wasn't
-       too used to dem bit en bites, or they were trying to obfuscate the
-       programming interface.
-
-       There is an additional complication when setting the window on the packet
-       buffer.  You must first do a read into the packet buffer region with the
-       low 8 address bits the address setting the page for the start of the packet
-       buffer window, and then do the above operation.  See mem_on() for details.
-
-       One bug on the chip is that even a hard reset won't disable the memory
-       window, usually resulting in a hung machine if mem_off() isn't called.
-       If this happens, you must power down the machine for about 30 seconds.
-*/
-
-static const char version[] =
-       "e2100.c:v1.01 7/21/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include "8390.h"
-
-#define DRV_NAME "e2100"
-
-static int e21_probe_list[] = {0x300, 0x280, 0x380, 0x220, 0};
-
-/* Offsets from the base_addr.
-   Read from the ASIC register, and the low three bits of the next outb()
-   address is used to set the corresponding register. */
-#define E21_NIC_OFFSET  0              /* Offset to the 8390 NIC. */
-#define E21_ASIC               0x10
-#define E21_MEM_ENABLE 0x10
-#define  E21_MEM_ON            0x05    /* Enable memory in 16 bit mode. */
-#define  E21_MEM_ON_8  0x07    /* Enable memory in  8 bit mode. */
-#define E21_MEM_BASE   0x11
-#define E21_IRQ_LOW            0x12    /* The low three bits of the IRQ number. */
-#define E21_IRQ_HIGH   0x14    /* The high IRQ bit and media select ...  */
-#define E21_MEDIA              0x14    /* (alias). */
-#define  E21_ALT_IFPORT 0x02   /* Set to use the other (BNC,AUI) port. */
-#define  E21_BIG_MEM   0x04    /* Use a bigger (64K) buffer (we don't) */
-#define E21_SAPROM             0x10    /* Offset to station address data. */
-#define E21_IO_EXTENT   0x20
-
-static inline void mem_on(short port, volatile char __iomem *mem_base,
-                                                 unsigned char start_page )
-{
-       /* This is a little weird: set the shared memory window by doing a
-          read.  The low address bits specify the starting page. */
-       readb(mem_base+start_page);
-       inb(port + E21_MEM_ENABLE);
-       outb(E21_MEM_ON, port + E21_MEM_ENABLE + E21_MEM_ON);
-}
-
-static inline void mem_off(short port)
-{
-       inb(port + E21_MEM_ENABLE);
-       outb(0x00, port + E21_MEM_ENABLE);
-}
-
-/* In other drivers I put the TX pages first, but the E2100 window circuitry
-   is designed to have a 4K Tx region last. The windowing circuitry wraps the
-   window at 0x2fff->0x0000 so that the packets at e.g. 0x2f00 in the RX ring
-   appear contiguously in the window. */
-#define E21_RX_START_PG                0x00    /* First page of RX buffer */
-#define E21_RX_STOP_PG         0x30    /* Last page +1 of RX ring */
-#define E21_BIG_RX_STOP_PG     0xF0    /* Last page +1 of RX ring */
-#define E21_TX_START_PG                E21_RX_STOP_PG  /* First page of TX buffer */
-
-static int e21_probe1(struct net_device *dev, int ioaddr);
-
-static int e21_open(struct net_device *dev);
-static void e21_reset_8390(struct net_device *dev);
-static void e21_block_input(struct net_device *dev, int count,
-                                                  struct sk_buff *skb, int ring_offset);
-static void e21_block_output(struct net_device *dev, int count,
-                                                        const unsigned char *buf, int start_page);
-static void e21_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                                                       int ring_page);
-static int e21_open(struct net_device *dev);
-static int e21_close(struct net_device *dev);
-
-
-/*  Probe for the E2100 series ethercards.  These cards have an 8390 at the
-       base address and the station address at both offset 0x10 and 0x18.  I read
-       the station address from offset 0x18 to avoid the dataport of NE2000
-       ethercards, and look for Ctron's unique ID (first three octets of the
-       station address).
- */
-
-static int  __init do_e2100_probe(struct net_device *dev)
-{
-       int *port;
-       int base_addr = dev->base_addr;
-       int irq = dev->irq;
-
-       if (base_addr > 0x1ff)          /* Check a single specified location. */
-               return e21_probe1(dev, base_addr);
-       else if (base_addr != 0)        /* Don't probe at all. */
-               return -ENXIO;
-
-       for (port = e21_probe_list; *port; port++) {
-               dev->irq = irq;
-               if (e21_probe1(dev, *port) == 0)
-                       return 0;
-       }
-
-       return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init e2100_probe(int unit)
-{
-       struct net_device *dev = alloc_ei_netdev();
-       int err;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       sprintf(dev->name, "eth%d", unit);
-       netdev_boot_setup_check(dev);
-
-       err = do_e2100_probe(dev);
-       if (err)
-               goto out;
-       return dev;
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-#endif
-
-static const struct net_device_ops e21_netdev_ops = {
-       .ndo_open               = e21_open,
-       .ndo_stop               = e21_close,
-
-       .ndo_start_xmit         = ei_start_xmit,
-       .ndo_tx_timeout         = ei_tx_timeout,
-       .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = ei_poll,
-#endif
-};
-
-static int __init e21_probe1(struct net_device *dev, int ioaddr)
-{
-       int i, status, retval;
-       unsigned char *station_addr = dev->dev_addr;
-       static unsigned version_printed;
-
-       if (!request_region(ioaddr, E21_IO_EXTENT, DRV_NAME))
-               return -EBUSY;
-
-       /* First check the station address for the Ctron prefix. */
-       if (inb(ioaddr + E21_SAPROM + 0) != 0x00 ||
-           inb(ioaddr + E21_SAPROM + 1) != 0x00 ||
-           inb(ioaddr + E21_SAPROM + 2) != 0x1d) {
-               retval = -ENODEV;
-               goto out;
-       }
-
-       /* Verify by making certain that there is a 8390 at there. */
-       outb(E8390_NODMA + E8390_STOP, ioaddr);
-       udelay(1);      /* we want to delay one I/O cycle - which is 2MHz */
-       status = inb(ioaddr);
-       if (status != 0x21 && status != 0x23) {
-               retval = -ENODEV;
-               goto out;
-       }
-
-       /* Read the station address PROM.  */
-       for (i = 0; i < 6; i++)
-               station_addr[i] = inb(ioaddr + E21_SAPROM + i);
-
-       inb(ioaddr + E21_MEDIA);                /* Point to media selection. */
-       outb(0, ioaddr + E21_ASIC);     /* and disable the secondary interface. */
-
-       if (ei_debug  &&  version_printed++ == 0)
-               printk(version);
-
-       for (i = 0; i < 6; i++)
-               printk(" %02X", station_addr[i]);
-
-       if (dev->irq < 2) {
-               static const int irqlist[] = {15, 11, 10, 12, 5, 9, 3, 4};
-               for (i = 0; i < ARRAY_SIZE(irqlist); i++)
-                       if (request_irq (irqlist[i], NULL, 0, "bogus", NULL) != -EBUSY) {
-                               dev->irq = irqlist[i];
-                               break;
-                       }
-               if (i >= ARRAY_SIZE(irqlist)) {
-                       printk(" unable to get IRQ %d.\n", dev->irq);
-                       retval = -EAGAIN;
-                       goto out;
-               }
-       } else if (dev->irq == 2)       /* Fixup luser bogosity: IRQ2 is really IRQ9 */
-               dev->irq = 9;
-
-       /* The 8390 is at the base address. */
-       dev->base_addr = ioaddr;
-
-       ei_status.name = "E2100";
-       ei_status.word16 = 1;
-       ei_status.tx_start_page = E21_TX_START_PG;
-       ei_status.rx_start_page = E21_RX_START_PG;
-       ei_status.stop_page = E21_RX_STOP_PG;
-       ei_status.saved_irq = dev->irq;
-
-       /* Check the media port used.  The port can be passed in on the
-          low mem_end bits. */
-       if (dev->mem_end & 15)
-               dev->if_port = dev->mem_end & 7;
-       else {
-               dev->if_port = 0;
-               inb(ioaddr + E21_MEDIA);        /* Turn automatic media detection on. */
-               for(i = 0; i < 6; i++)
-                       if (station_addr[i] != inb(ioaddr + E21_SAPROM + 8 + i)) {
-                               dev->if_port = 1;
-                               break;
-                       }
-       }
-
-       /* Never map in the E21 shared memory unless you are actively using it.
-          Also, the shared memory has effective only one setting -- spread all
-          over the 128K region! */
-       if (dev->mem_start == 0)
-               dev->mem_start = 0xd0000;
-
-       ei_status.mem = ioremap(dev->mem_start, 2*1024);
-       if (!ei_status.mem) {
-               printk("unable to remap memory\n");
-               retval = -EAGAIN;
-               goto out;
-       }
-
-#ifdef notdef
-       /* These values are unused.  The E2100 has a 2K window into the packet
-          buffer.  The window can be set to start on any page boundary. */
-       ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
-       dev->mem_end = ei_status.rmem_end = dev->mem_start + 2*1024;
-#endif
-
-       printk(", IRQ %d, %s media, memory @ %#lx.\n", dev->irq,
-                  dev->if_port ? "secondary" : "primary", dev->mem_start);
-
-       ei_status.reset_8390 = &e21_reset_8390;
-       ei_status.block_input = &e21_block_input;
-       ei_status.block_output = &e21_block_output;
-       ei_status.get_8390_hdr = &e21_get_8390_hdr;
-
-       dev->netdev_ops = &e21_netdev_ops;
-       NS8390_init(dev, 0);
-
-       retval = register_netdev(dev);
-       if (retval)
-               goto out;
-       return 0;
-out:
-       release_region(ioaddr, E21_IO_EXTENT);
-       return retval;
-}
-
-static int
-e21_open(struct net_device *dev)
-{
-       short ioaddr = dev->base_addr;
-       int retval;
-
-       if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev)))
-               return retval;
-
-       /* Set the interrupt line and memory base on the hardware. */
-       inb(ioaddr + E21_IRQ_LOW);
-       outb(0, ioaddr + E21_ASIC + (dev->irq & 7));
-       inb(ioaddr + E21_IRQ_HIGH);                     /* High IRQ bit, and if_port. */
-       outb(0, ioaddr + E21_ASIC + (dev->irq > 7 ? 1:0)
-                  + (dev->if_port ? E21_ALT_IFPORT : 0));
-       inb(ioaddr + E21_MEM_BASE);
-       outb(0, ioaddr + E21_ASIC + ((dev->mem_start >> 17) & 7));
-
-       ei_open(dev);
-       return 0;
-}
-
-static void
-e21_reset_8390(struct net_device *dev)
-{
-       short ioaddr = dev->base_addr;
-
-       outb(0x01, ioaddr);
-       if (ei_debug > 1) printk("resetting the E2180x3 t=%ld...", jiffies);
-       ei_status.txing = 0;
-
-       /* Set up the ASIC registers, just in case something changed them. */
-
-       if (ei_debug > 1) printk("reset done\n");
-}
-
-/* Grab the 8390 specific header. We put the 2k window so the header page
-   appears at the start of the shared memory. */
-
-static void
-e21_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-
-       short ioaddr = dev->base_addr;
-       char __iomem *shared_mem = ei_status.mem;
-
-       mem_on(ioaddr, shared_mem, ring_page);
-
-#ifdef notdef
-       /* Officially this is what we are doing, but the readl() is faster */
-       memcpy_fromio(hdr, shared_mem, sizeof(struct e8390_pkt_hdr));
-#else
-       ((unsigned int*)hdr)[0] = readl(shared_mem);
-#endif
-
-       /* Turn off memory access: we would need to reprogram the window anyway. */
-       mem_off(ioaddr);
-
-}
-
-/*  Block input and output are easy on shared memory ethercards.
-       The E21xx makes block_input() especially easy by wrapping the top
-       ring buffer to the bottom automatically. */
-static void
-e21_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-       short ioaddr = dev->base_addr;
-       char __iomem *shared_mem = ei_status.mem;
-
-       mem_on(ioaddr, shared_mem, (ring_offset>>8));
-
-       memcpy_fromio(skb->data, ei_status.mem + (ring_offset & 0xff), count);
-
-       mem_off(ioaddr);
-}
-
-static void
-e21_block_output(struct net_device *dev, int count, const unsigned char *buf,
-                                int start_page)
-{
-       short ioaddr = dev->base_addr;
-       volatile char __iomem *shared_mem = ei_status.mem;
-
-       /* Set the shared memory window start by doing a read, with the low address
-          bits specifying the starting page. */
-       readb(shared_mem + start_page);
-       mem_on(ioaddr, shared_mem, start_page);
-
-       memcpy_toio(shared_mem, buf, count);
-       mem_off(ioaddr);
-}
-
-static int
-e21_close(struct net_device *dev)
-{
-       short ioaddr = dev->base_addr;
-
-       if (ei_debug > 1)
-               printk("%s: Shutting down ethercard.\n", dev->name);
-
-       free_irq(dev->irq, dev);
-       dev->irq = ei_status.saved_irq;
-
-       /* Shut off the interrupt line and secondary interface. */
-       inb(ioaddr + E21_IRQ_LOW);
-       outb(0, ioaddr + E21_ASIC);
-       inb(ioaddr + E21_IRQ_HIGH);                     /* High IRQ bit, and if_port. */
-       outb(0, ioaddr + E21_ASIC);
-
-       ei_close(dev);
-
-       /* Double-check that the memory has been turned off, because really
-          really bad things happen if it isn't. */
-       mem_off(ioaddr);
-
-       return 0;
-}
-
-
-#ifdef MODULE
-#define MAX_E21_CARDS  4       /* Max number of E21 cards per module */
-static struct net_device *dev_e21[MAX_E21_CARDS];
-static int io[MAX_E21_CARDS];
-static int irq[MAX_E21_CARDS];
-static int mem[MAX_E21_CARDS];
-static int xcvr[MAX_E21_CARDS];                /* choose int. or ext. xcvr */
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(mem, int, NULL, 0);
-module_param_array(xcvr, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s)");
-MODULE_PARM_DESC(mem, " memory base address(es)");
-MODULE_PARM_DESC(xcvr, "transceiver(s) (0=internal, 1=external)");
-MODULE_DESCRIPTION("Cabletron E2100 ISA ethernet driver");
-MODULE_LICENSE("GPL");
-
-/* This is set up so that only a single autoprobe takes place per call.
-ISA device autoprobes on a running machine are not recommended. */
-
-int __init init_module(void)
-{
-       struct net_device *dev;
-       int this_dev, found = 0;
-
-       for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
-               if (io[this_dev] == 0)  {
-                       if (this_dev != 0) break; /* only autoprobe 1st one */
-                       printk(KERN_NOTICE "e2100.c: Presently autoprobing (not recommended) for a single card.\n");
-               }
-               dev = alloc_ei_netdev();
-               if (!dev)
-                       break;
-               dev->irq = irq[this_dev];
-               dev->base_addr = io[this_dev];
-               dev->mem_start = mem[this_dev];
-               dev->mem_end = xcvr[this_dev];  /* low 4bits = xcvr sel. */
-               if (do_e2100_probe(dev) == 0) {
-                       dev_e21[found++] = dev;
-                       continue;
-               }
-               free_netdev(dev);
-               printk(KERN_WARNING "e2100.c: No E2100 card found (i/o = 0x%x).\n", io[this_dev]);
-               break;
-       }
-       if (found)
-               return 0;
-       return -ENXIO;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-       /* NB: e21_close() handles free_irq */
-       iounmap(ei_status.mem);
-       release_region(dev->base_addr, E21_IO_EXTENT);
-}
-
-void __exit
-cleanup_module(void)
-{
-       int this_dev;
-
-       for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
-               struct net_device *dev = dev_e21[this_dev];
-               if (dev) {
-                       unregister_netdev(dev);
-                       cleanup_card(dev);
-                       free_netdev(dev);
-               }
-       }
-}
-#endif /* MODULE */
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
deleted file mode 100644 (file)
index 7a09575..0000000
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
-       es3210.c
-
-       Linux driver for Racal-Interlan ES3210 EISA Network Adapter
-
-       Copyright (C) 1996, Paul Gortmaker.
-
-       This software may be used and distributed according to the terms
-       of the GNU General Public License, incorporated herein by reference.
-
-       Information and Code Sources:
-
-       1) The existing myriad of Linux 8390 drivers written by Donald Becker.
-
-       2) Once again Russ Nelson's asm packet driver provided additional info.
-
-       3) Info for getting IRQ and sh-mem gleaned from the EISA cfg files.
-          Too bad it doesn't work -- see below.
-
-       The ES3210 is an EISA shared memory NS8390 implementation. Note
-       that all memory copies to/from the board must be 32bit transfers.
-       Which rules out using eth_io_copy_and_sum() in this driver.
-
-       Apparently there are two slightly different revisions of the
-       card, since there are two distinct EISA cfg files (!rii0101.cfg
-       and !rii0102.cfg) One has media select in the cfg file and the
-       other doesn't. Hopefully this will work with either.
-
-       That is about all I can tell you about it, having never actually
-       even seen one of these cards. :)  Try http://www.interlan.com
-       if you want more info.
-
-       Thanks go to Mark Salazar for testing v0.02 of this driver.
-
-       Bugs, to-fix, etc:
-
-       1) The EISA cfg ports that are *supposed* to have the IRQ and shared
-          mem values just read 0xff all the time. Hrrmpf. Apparently the
-          same happens with the packet driver as the code for reading
-          these registers is disabled there. In the meantime, boot with:
-          ether=<IRQ>,0,0x<shared_mem_addr>,eth0 to override the IRQ and
-          shared memory detection. (The i/o port detection is okay.)
-
-       2) Module support currently untested. Probably works though.
-
-*/
-
-static const char version[] =
-       "es3210.c: Driver revision v0.03, 14/09/96\n";
-
-#include <linux/module.h>
-#include <linux/eisa.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include "8390.h"
-
-static int es_probe1(struct net_device *dev, int ioaddr);
-
-static void es_reset_8390(struct net_device *dev);
-
-static void es_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
-static void es_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset);
-static void es_block_output(struct net_device *dev, int count, const unsigned char *buf, int start_page);
-
-#define ES_START_PG    0x00    /* First page of TX buffer              */
-#define ES_STOP_PG     0x40    /* Last page +1 of RX ring              */
-
-#define ES_IO_EXTENT   0x37    /* The cfg file says 0xc90 -> 0xcc7     */
-#define ES_ID_PORT     0xc80   /* Same for all EISA cards              */
-#define ES_SA_PROM     0xc90   /* Start of e'net addr.                 */
-#define ES_RESET_PORT  0xc84   /* From the packet driver source        */
-#define ES_NIC_OFFSET  0xca0   /* Hello, the 8390 is *here*            */
-
-#define ES_ADDR0       0x02    /* 3 byte vendor prefix                 */
-#define ES_ADDR1       0x07
-#define ES_ADDR2       0x01
-
-/*
- * Two card revisions. EISA ID's are always rev. minor, rev. major,, and
- * then the three vendor letters stored in 5 bits each, with an "a" = 1.
- * For eg: "rii" = 10010 01001 01001 = 0x4929, which is how the EISA
- * config utility determines automagically what config file(s) to use.
- */
-#define ES_EISA_ID1    0x01012949      /* !rii0101.cfg                 */
-#define ES_EISA_ID2    0x02012949      /* !rii0102.cfg                 */
-
-#define ES_CFG1                0xcc0   /* IOPORT(1) --> IOPORT(6) in cfg file  */
-#define ES_CFG2                0xcc1
-#define ES_CFG3                0xcc2
-#define ES_CFG4                0xcc3
-#define ES_CFG5                0xcc4
-#define ES_CFG6                0xc84   /* NB: 0xc84 is also "reset" port.      */
-
-/*
- *     You can OR any of the following bits together and assign it
- *     to ES_DEBUG to get verbose driver info during operation.
- *     Some of these don't do anything yet.
- */
-
-#define ES_D_PROBE     0x01
-#define ES_D_RX_PKT    0x02
-#define ES_D_TX_PKT    0x04
-#define ED_D_IRQ       0x08
-
-#define ES_DEBUG       0
-
-static unsigned char lo_irq_map[] __initdata = {3, 4, 5, 6, 7, 9, 10};
-static unsigned char hi_irq_map[] __initdata = {11, 12, 0, 14, 0, 0, 0, 15};
-
-/*
- *     Probe for the card. The best way is to read the EISA ID if it
- *     is known. Then we check the prefix of the station address
- *     PROM for a match against the Racal-Interlan assigned value.
- */
-
-static int __init do_es_probe(struct net_device *dev)
-{
-       unsigned short ioaddr = dev->base_addr;
-       int irq = dev->irq;
-       int mem_start = dev->mem_start;
-
-       if (ioaddr > 0x1ff)             /* Check a single specified location. */
-               return es_probe1(dev, ioaddr);
-       else if (ioaddr > 0)            /* Don't probe at all. */
-               return -ENXIO;
-
-       if (!EISA_bus) {
-#if ES_DEBUG & ES_D_PROBE
-               printk("es3210.c: Not EISA bus. Not probing high ports.\n");
-#endif
-               return -ENXIO;
-       }
-
-       /* EISA spec allows for up to 16 slots, but 8 is typical. */
-       for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
-               if (es_probe1(dev, ioaddr) == 0)
-                       return 0;
-               dev->irq = irq;
-               dev->mem_start = mem_start;
-       }
-
-       return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init es_probe(int unit)
-{
-       struct net_device *dev = alloc_ei_netdev();
-       int err;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       sprintf(dev->name, "eth%d", unit);
-       netdev_boot_setup_check(dev);
-
-       err = do_es_probe(dev);
-       if (err)
-               goto out;
-       return dev;
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-#endif
-
-static int __init es_probe1(struct net_device *dev, int ioaddr)
-{
-       int i, retval;
-       unsigned long eisa_id;
-
-       if (!request_region(ioaddr + ES_SA_PROM, ES_IO_EXTENT, "es3210"))
-               return -ENODEV;
-
-#if ES_DEBUG & ES_D_PROBE
-       printk("es3210.c: probe at %#x, ID %#8x\n", ioaddr, inl(ioaddr + ES_ID_PORT));
-       printk("es3210.c: config regs: %#x %#x %#x %#x %#x %#x\n",
-               inb(ioaddr + ES_CFG1), inb(ioaddr + ES_CFG2), inb(ioaddr + ES_CFG3),
-               inb(ioaddr + ES_CFG4), inb(ioaddr + ES_CFG5), inb(ioaddr + ES_CFG6));
-#endif
-
-/*     Check the EISA ID of the card. */
-       eisa_id = inl(ioaddr + ES_ID_PORT);
-       if ((eisa_id != ES_EISA_ID1) && (eisa_id != ES_EISA_ID2)) {
-               retval = -ENODEV;
-               goto out;
-       }
-
-       for (i = 0; i < ETHER_ADDR_LEN ; i++)
-               dev->dev_addr[i] = inb(ioaddr + ES_SA_PROM + i);
-
-/*     Check the Racal vendor ID as well. */
-       if (dev->dev_addr[0] != ES_ADDR0 ||
-           dev->dev_addr[1] != ES_ADDR1 ||
-           dev->dev_addr[2] != ES_ADDR2) {
-               printk("es3210.c: card not found %pM (invalid_prefix).\n",
-                      dev->dev_addr);
-               retval = -ENODEV;
-               goto out;
-       }
-
-       printk("es3210.c: ES3210 rev. %ld at %#x, node %pM",
-              eisa_id>>24, ioaddr, dev->dev_addr);
-
-       /* Snarf the interrupt now. */
-       if (dev->irq == 0) {
-               unsigned char hi_irq = inb(ioaddr + ES_CFG2) & 0x07;
-               unsigned char lo_irq = inb(ioaddr + ES_CFG1) & 0xfe;
-
-               if (hi_irq != 0) {
-                       dev->irq = hi_irq_map[hi_irq - 1];
-               } else {
-                       int i = 0;
-                       while (lo_irq > (1<<i)) i++;
-                       dev->irq = lo_irq_map[i];
-               }
-               printk(" using IRQ %d", dev->irq);
-#if ES_DEBUG & ES_D_PROBE
-               printk("es3210.c: hi_irq %#x, lo_irq %#x, dev->irq = %d\n",
-                                       hi_irq, lo_irq, dev->irq);
-#endif
-       } else {
-               if (dev->irq == 2)
-                       dev->irq = 9;                   /* Doh! */
-               printk(" assigning IRQ %d", dev->irq);
-       }
-
-       if (request_irq(dev->irq, ei_interrupt, 0, "es3210", dev)) {
-               printk (" unable to get IRQ %d.\n", dev->irq);
-               retval = -EAGAIN;
-               goto out;
-       }
-
-       if (dev->mem_start == 0) {
-               unsigned char mem_enabled = inb(ioaddr + ES_CFG2) & 0xc0;
-               unsigned char mem_bits = inb(ioaddr + ES_CFG3) & 0x07;
-
-               if (mem_enabled != 0x80) {
-                       printk(" shared mem disabled - giving up\n");
-                       retval = -ENXIO;
-                       goto out1;
-               }
-               dev->mem_start = 0xC0000 + mem_bits*0x4000;
-               printk(" using ");
-       } else {
-               printk(" assigning ");
-       }
-
-       ei_status.mem = ioremap(dev->mem_start, (ES_STOP_PG - ES_START_PG)*256);
-       if (!ei_status.mem) {
-               printk("ioremap failed - giving up\n");
-               retval = -ENXIO;
-               goto out1;
-       }
-
-       dev->mem_end = dev->mem_start + (ES_STOP_PG - ES_START_PG)*256;
-
-       printk("mem %#lx-%#lx\n", dev->mem_start, dev->mem_end-1);
-
-#if ES_DEBUG & ES_D_PROBE
-       if (inb(ioaddr + ES_CFG5))
-               printk("es3210: Warning - DMA channel enabled, but not used here.\n");
-#endif
-       /* Note, point at the 8390, and not the card... */
-       dev->base_addr = ioaddr + ES_NIC_OFFSET;
-
-       ei_status.name = "ES3210";
-       ei_status.tx_start_page = ES_START_PG;
-       ei_status.rx_start_page = ES_START_PG + TX_PAGES;
-       ei_status.stop_page = ES_STOP_PG;
-       ei_status.word16 = 1;
-
-       if (ei_debug > 0)
-               printk(version);
-
-       ei_status.reset_8390 = &es_reset_8390;
-       ei_status.block_input = &es_block_input;
-       ei_status.block_output = &es_block_output;
-       ei_status.get_8390_hdr = &es_get_8390_hdr;
-
-       dev->netdev_ops = &ei_netdev_ops;
-       NS8390_init(dev, 0);
-
-       retval = register_netdev(dev);
-       if (retval)
-               goto out1;
-       return 0;
-out1:
-       free_irq(dev->irq, dev);
-out:
-       release_region(ioaddr + ES_SA_PROM, ES_IO_EXTENT);
-       return retval;
-}
-
-/*
- *     Reset as per the packet driver method. Judging by the EISA cfg
- *     file, this just toggles the "Board Enable" bits (bit 2 and 0).
- */
-
-static void es_reset_8390(struct net_device *dev)
-{
-       unsigned short ioaddr = dev->base_addr;
-       unsigned long end;
-
-       outb(0x04, ioaddr + ES_RESET_PORT);
-       if (ei_debug > 1) printk("%s: resetting the ES3210...", dev->name);
-
-       end = jiffies + 2*HZ/100;
-        while ((signed)(end - jiffies) > 0) continue;
-
-       ei_status.txing = 0;
-       outb(0x01, ioaddr + ES_RESET_PORT);
-       if (ei_debug > 1) printk("reset done\n");
-}
-
-/*
- *     Note: In the following three functions is the implicit assumption
- *     that the associated memcpy will only use "rep; movsl" as long as
- *     we keep the counts as some multiple of doublewords. This is a
- *     requirement of the hardware, and also prevents us from using
- *     eth_io_copy_and_sum() since we can't guarantee it will limit
- *     itself to doubleword access.
- */
-
-/*
- *     Grab the 8390 specific header. Similar to the block_input routine, but
- *     we don't need to be concerned with ring wrap as the header will be at
- *     the start of a page, so we optimize accordingly. (A single doubleword.)
- */
-
-static void
-es_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-       void __iomem *hdr_start = ei_status.mem + ((ring_page - ES_START_PG)<<8);
-       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
-       hdr->count = (hdr->count + 3) & ~3;     /* Round up allocation. */
-}
-
-/*
- *     Block input and output are easy on shared memory ethercards, the only
- *     complication is when the ring buffer wraps. The count will already
- *     be rounded up to a doubleword value via es_get_8390_hdr() above.
- */
-
-static void es_block_input(struct net_device *dev, int count, struct sk_buff *skb,
-                                                 int ring_offset)
-{
-       void __iomem *xfer_start = ei_status.mem + ring_offset - ES_START_PG*256;
-
-       if (ring_offset + count > ES_STOP_PG*256) {
-               /* Packet wraps over end of ring buffer. */
-               int semi_count = ES_STOP_PG*256 - ring_offset;
-               memcpy_fromio(skb->data, xfer_start, semi_count);
-               count -= semi_count;
-               memcpy_fromio(skb->data + semi_count, ei_status.mem, count);
-       } else {
-               /* Packet is in one chunk. */
-               memcpy_fromio(skb->data, xfer_start, count);
-       }
-}
-
-static void es_block_output(struct net_device *dev, int count,
-                               const unsigned char *buf, int start_page)
-{
-       void __iomem *shmem = ei_status.mem + ((start_page - ES_START_PG)<<8);
-
-       count = (count + 3) & ~3;     /* Round up to doubleword */
-       memcpy_toio(shmem, buf, count);
-}
-
-#ifdef MODULE
-#define MAX_ES_CARDS   4       /* Max number of ES3210 cards per module */
-#define NAMELEN                8       /* # of chars for storing dev->name */
-static struct net_device *dev_es3210[MAX_ES_CARDS];
-static int io[MAX_ES_CARDS];
-static int irq[MAX_ES_CARDS];
-static int mem[MAX_ES_CARDS];
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(mem, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s)");
-MODULE_PARM_DESC(mem, "memory base address(es)");
-MODULE_DESCRIPTION("Racal-Interlan ES3210 EISA ethernet driver");
-MODULE_LICENSE("GPL");
-
-int __init init_module(void)
-{
-       struct net_device *dev;
-       int this_dev, found = 0;
-
-       for (this_dev = 0; this_dev < MAX_ES_CARDS; this_dev++) {
-               if (io[this_dev] == 0 && this_dev != 0)
-                       break;
-               dev = alloc_ei_netdev();
-               if (!dev)
-                       break;
-               dev->irq = irq[this_dev];
-               dev->base_addr = io[this_dev];
-               dev->mem_start = mem[this_dev];
-               if (do_es_probe(dev) == 0) {
-                       dev_es3210[found++] = dev;
-                       continue;
-               }
-               free_netdev(dev);
-               printk(KERN_WARNING "es3210.c: No es3210 card found (i/o = 0x%x).\n", io[this_dev]);
-               break;
-       }
-       if (found)
-               return 0;
-       return -ENXIO;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-       free_irq(dev->irq, dev);
-       release_region(dev->base_addr, ES_IO_EXTENT);
-       iounmap(ei_status.mem);
-}
-
-void __exit
-cleanup_module(void)
-{
-       int this_dev;
-
-       for (this_dev = 0; this_dev < MAX_ES_CARDS; this_dev++) {
-               struct net_device *dev = dev_es3210[this_dev];
-               if (dev) {
-                       unregister_netdev(dev);
-                       cleanup_card(dev);
-                       free_netdev(dev);
-               }
-       }
-}
-#endif /* MODULE */
-
diff --git a/drivers/net/ethernet/8390/3c503.c b/drivers/net/ethernet/8390/3c503.c
new file mode 100644 (file)
index 0000000..84e68f1
--- /dev/null
@@ -0,0 +1,778 @@
+/* 3c503.c: A shared-memory NS8390 ethernet driver for linux. */
+/*
+    Written 1992-94 by Donald Becker.
+
+    Copyright 1993 United States Government as represented by the
+    Director, National Security Agency.  This software may be used and
+    distributed according to the terms of the GNU General Public License,
+    incorporated herein by reference.
+
+    The author may be reached as becker@scyld.com, or C/O
+       Scyld Computing Corporation
+       410 Severn Ave., Suite 210
+       Annapolis MD 21403
+
+
+    This driver should work with the 3c503 and 3c503/16.  It should be used
+    in shared memory mode for best performance, although it may also work
+    in programmed-I/O mode.
+
+    Sources:
+    EtherLink II Technical Reference Manual,
+    EtherLink II/16 Technical Reference Manual Supplement,
+    3Com Corporation, 5400 Bayfront Plaza, Santa Clara CA 95052-8145
+
+    The Crynwr 3c503 packet driver.
+
+    Changelog:
+
+    Paul Gortmaker     : add support for the 2nd 8kB of RAM on 16 bit cards.
+    Paul Gortmaker     : multiple card support for module users.
+    rjohnson@analogic.com : Fix up PIO interface for efficient operation.
+    Jeff Garzik                : ethtool support
+
+*/
+
+#define DRV_NAME       "3c503"
+#define DRV_VERSION    "1.10a"
+#define DRV_RELDATE    "11/17/2001"
+
+
+static const char version[] =
+    DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Donald Becker (becker@scyld.com)\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ethtool.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+
+#include "8390.h"
+#include "3c503.h"
+#define WRD_COUNT 4
+
+static int el2_pio_probe(struct net_device *dev);
+static int el2_probe1(struct net_device *dev, int ioaddr);
+
+/* A zero-terminated list of I/O addresses to be probed in PIO mode. */
+static unsigned int netcard_portlist[] __initdata =
+       { 0x300,0x310,0x330,0x350,0x250,0x280,0x2a0,0x2e0,0};
+
+#define EL2_IO_EXTENT  16
+
+static int el2_open(struct net_device *dev);
+static int el2_close(struct net_device *dev);
+static void el2_reset_8390(struct net_device *dev);
+static void el2_init_card(struct net_device *dev);
+static void el2_block_output(struct net_device *dev, int count,
+                            const unsigned char *buf, int start_page);
+static void el2_block_input(struct net_device *dev, int count, struct sk_buff *skb,
+                          int ring_offset);
+static void el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                        int ring_page);
+static const struct ethtool_ops netdev_ethtool_ops;
+
+
+/* This routine probes for a memory-mapped 3c503 board by looking for
+   the "location register" at the end of the jumpered boot PROM space.
+   This works even if a PROM isn't there.
+
+   If the ethercard isn't found there is an optional probe for
+   ethercard jumpered to programmed-I/O mode.
+   */
+static int __init do_el2_probe(struct net_device *dev)
+{
+    int *addr, addrs[] = { 0xddffe, 0xd9ffe, 0xcdffe, 0xc9ffe, 0};
+    int base_addr = dev->base_addr;
+    int irq = dev->irq;
+
+    if (base_addr > 0x1ff)     /* Check a single specified location. */
+       return el2_probe1(dev, base_addr);
+    else if (base_addr != 0)           /* Don't probe at all. */
+       return -ENXIO;
+
+    for (addr = addrs; *addr; addr++) {
+       void __iomem *p = ioremap(*addr, 1);
+       unsigned base_bits;
+       int i;
+
+       if (!p)
+               continue;
+       base_bits = readb(p);
+       iounmap(p);
+       i = ffs(base_bits) - 1;
+       if (i == -1 || base_bits != (1 << i))
+           continue;
+       if (el2_probe1(dev, netcard_portlist[i]) == 0)
+           return 0;
+       dev->irq = irq;
+    }
+#if ! defined(no_probe_nonshared_memory)
+    return el2_pio_probe(dev);
+#else
+    return -ENODEV;
+#endif
+}
+
+/*  Try all of the locations that aren't obviously empty.  This touches
+    a lot of locations, and is much riskier than the code above. */
+static int __init
+el2_pio_probe(struct net_device *dev)
+{
+    int i;
+    int base_addr = dev->base_addr;
+    int irq = dev->irq;
+
+    if (base_addr > 0x1ff)     /* Check a single specified location. */
+       return el2_probe1(dev, base_addr);
+    else if (base_addr != 0)   /* Don't probe at all. */
+       return -ENXIO;
+
+    for (i = 0; netcard_portlist[i]; i++) {
+       if (el2_probe1(dev, netcard_portlist[i]) == 0)
+           return 0;
+       dev->irq = irq;
+    }
+
+    return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init el2_probe(int unit)
+{
+       struct net_device *dev = alloc_eip_netdev();
+       int err;
+
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       sprintf(dev->name, "eth%d", unit);
+       netdev_boot_setup_check(dev);
+
+       err = do_el2_probe(dev);
+       if (err)
+               goto out;
+       return dev;
+out:
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops el2_netdev_ops = {
+       .ndo_open               = el2_open,
+       .ndo_stop               = el2_close,
+
+       .ndo_start_xmit         = eip_start_xmit,
+       .ndo_tx_timeout         = eip_tx_timeout,
+       .ndo_get_stats          = eip_get_stats,
+       .ndo_set_multicast_list = eip_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = eip_poll,
+#endif
+};
+
+/* Probe for the Etherlink II card at I/O port base IOADDR,
+   returning non-zero on success.  If found, set the station
+   address and memory parameters in DEVICE. */
+static int __init
+el2_probe1(struct net_device *dev, int ioaddr)
+{
+    int i, iobase_reg, membase_reg, saved_406, wordlength, retval;
+    static unsigned version_printed;
+    unsigned long vendor_id;
+
+    if (!request_region(ioaddr, EL2_IO_EXTENT, DRV_NAME))
+       return -EBUSY;
+
+    if (!request_region(ioaddr + 0x400, 8, DRV_NAME)) {
+       retval = -EBUSY;
+       goto out;
+    }
+
+    /* Reset and/or avoid any lurking NE2000 */
+    if (inb(ioaddr + 0x408) == 0xff) {
+       mdelay(1);
+       retval = -ENODEV;
+       goto out1;
+    }
+
+    /* We verify that it's a 3C503 board by checking the first three octets
+       of its ethernet address. */
+    iobase_reg = inb(ioaddr+0x403);
+    membase_reg = inb(ioaddr+0x404);
+    /* ASIC location registers should be 0 or have only a single bit set. */
+    if ((iobase_reg  & (iobase_reg - 1)) ||
+       (membase_reg & (membase_reg - 1))) {
+       retval = -ENODEV;
+       goto out1;
+    }
+    saved_406 = inb_p(ioaddr + 0x406);
+    outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */
+    outb_p(ECNTRL_THIN, ioaddr + 0x406);
+    /* Map the station addr PROM into the lower I/O ports. We now check
+       for both the old and new 3Com prefix */
+    outb(ECNTRL_SAPROM|ECNTRL_THIN, ioaddr + 0x406);
+    vendor_id = inb(ioaddr)*0x10000 + inb(ioaddr + 1)*0x100 + inb(ioaddr + 2);
+    if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID)) {
+       /* Restore the register we frobbed. */
+       outb(saved_406, ioaddr + 0x406);
+       retval = -ENODEV;
+       goto out1;
+    }
+
+    if (ei_debug  &&  version_printed++ == 0)
+       pr_debug("%s", version);
+
+    dev->base_addr = ioaddr;
+
+    pr_info("%s: 3c503 at i/o base %#3x, node ", dev->name, ioaddr);
+
+    /* Retrieve and print the ethernet address. */
+    for (i = 0; i < 6; i++)
+       dev->dev_addr[i] = inb(ioaddr + i);
+    pr_cont("%pM", dev->dev_addr);
+
+    /* Map the 8390 back into the window. */
+    outb(ECNTRL_THIN, ioaddr + 0x406);
+
+    /* Check for EL2/16 as described in tech. man. */
+    outb_p(E8390_PAGE0, ioaddr + E8390_CMD);
+    outb_p(0, ioaddr + EN0_DCFG);
+    outb_p(E8390_PAGE2, ioaddr + E8390_CMD);
+    wordlength = inb_p(ioaddr + EN0_DCFG) & ENDCFG_WTS;
+    outb_p(E8390_PAGE0, ioaddr + E8390_CMD);
+
+    /* Probe for, turn on and clear the board's shared memory. */
+    if (ei_debug > 2)
+       pr_cont(" memory jumpers %2.2x ", membase_reg);
+    outb(EGACFR_NORM, ioaddr + 0x405); /* Enable RAM */
+
+    /* This should be probed for (or set via an ioctl()) at run-time.
+       Right now we use a sleazy hack to pass in the interface number
+       at boot-time via the low bits of the mem_end field.  That value is
+       unused, and the low bits would be discarded even if it was used. */
+#if defined(EI8390_THICK) || defined(EL2_AUI)
+    ei_status.interface_num = 1;
+#else
+    ei_status.interface_num = dev->mem_end & 0xf;
+#endif
+    pr_cont(", using %sternal xcvr.\n", ei_status.interface_num == 0 ? "in" : "ex");
+
+    if ((membase_reg & 0xf0) == 0) {
+       dev->mem_start = 0;
+       ei_status.name = "3c503-PIO";
+       ei_status.mem = NULL;
+    } else {
+       dev->mem_start = ((membase_reg & 0xc0) ? 0xD8000 : 0xC8000) +
+           ((membase_reg & 0xA0) ? 0x4000 : 0);
+#define EL2_MEMSIZE (EL2_MB1_STOP_PG - EL2_MB1_START_PG)*256
+       ei_status.mem = ioremap(dev->mem_start, EL2_MEMSIZE);
+
+#ifdef EL2MEMTEST
+       /* This has never found an error, but someone might care.
+          Note that it only tests the 2nd 8kB on 16kB 3c503/16
+          cards between card addr. 0x2000 and 0x3fff. */
+       {                       /* Check the card's memory. */
+           void __iomem *mem_base = ei_status.mem;
+           unsigned int test_val = 0xbbadf00d;
+           writel(0xba5eba5e, mem_base);
+           for (i = sizeof(test_val); i < EL2_MEMSIZE; i+=sizeof(test_val)) {
+               writel(test_val, mem_base + i);
+               if (readl(mem_base) != 0xba5eba5e ||
+                   readl(mem_base + i) != test_val) {
+                   pr_warning("3c503: memory failure or memory address conflict.\n");
+                   dev->mem_start = 0;
+                   ei_status.name = "3c503-PIO";
+                   iounmap(mem_base);
+                   ei_status.mem = NULL;
+                   break;
+               }
+               test_val += 0x55555555;
+               writel(0, mem_base + i);
+           }
+       }
+#endif  /* EL2MEMTEST */
+
+       if (dev->mem_start)
+               dev->mem_end = dev->mem_start + EL2_MEMSIZE;
+
+       if (wordlength) {       /* No Tx pages to skip over to get to Rx */
+               ei_status.priv = 0;
+               ei_status.name = "3c503/16";
+       } else {
+               ei_status.priv = TX_PAGES * 256;
+               ei_status.name = "3c503";
+       }
+    }
+
+    /*
+       Divide up the memory on the card. This is the same regardless of
+       whether shared-mem or PIO is used. For 16 bit cards (16kB RAM),
+       we use the entire 8k of bank1 for an Rx ring. We only use 3k
+       of the bank0 for 2 full size Tx packet slots. For 8 bit cards,
+       (8kB RAM) we use 3kB of bank1 for two Tx slots, and the remaining
+       5kB for an Rx ring.  */
+
+    if (wordlength) {
+       ei_status.tx_start_page = EL2_MB0_START_PG;
+       ei_status.rx_start_page = EL2_MB1_START_PG;
+    } else {
+       ei_status.tx_start_page = EL2_MB1_START_PG;
+       ei_status.rx_start_page = EL2_MB1_START_PG + TX_PAGES;
+    }
+
+    /* Finish setting the board's parameters. */
+    ei_status.stop_page = EL2_MB1_STOP_PG;
+    ei_status.word16 = wordlength;
+    ei_status.reset_8390 = el2_reset_8390;
+    ei_status.get_8390_hdr = el2_get_8390_hdr;
+    ei_status.block_input = el2_block_input;
+    ei_status.block_output = el2_block_output;
+
+    if (dev->irq == 2)
+       dev->irq = 9;
+    else if (dev->irq > 5 && dev->irq != 9) {
+       pr_warning("3c503: configured interrupt %d invalid, will use autoIRQ.\n",
+              dev->irq);
+       dev->irq = 0;
+    }
+
+    ei_status.saved_irq = dev->irq;
+
+    dev->netdev_ops = &el2_netdev_ops;
+    dev->ethtool_ops = &netdev_ethtool_ops;
+
+    retval = register_netdev(dev);
+    if (retval)
+       goto out1;
+
+    if (dev->mem_start)
+       pr_info("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n",
+               dev->name, ei_status.name, (wordlength+1)<<3,
+               dev->mem_start, dev->mem_end-1);
+
+    else
+    {
+       ei_status.tx_start_page = EL2_MB1_START_PG;
+       ei_status.rx_start_page = EL2_MB1_START_PG + TX_PAGES;
+       pr_info("%s: %s, %dkB RAM, using programmed I/O (REJUMPER for SHARED MEMORY).\n",
+              dev->name, ei_status.name, (wordlength+1)<<3);
+    }
+    release_region(ioaddr + 0x400, 8);
+    return 0;
+out1:
+    release_region(ioaddr + 0x400, 8);
+out:
+    release_region(ioaddr, EL2_IO_EXTENT);
+    return retval;
+}
+
+static irqreturn_t el2_probe_interrupt(int irq, void *seen)
+{
+       *(bool *)seen = true;
+       return IRQ_HANDLED;
+}
+
+static int
+el2_open(struct net_device *dev)
+{
+    int retval;
+
+    if (dev->irq < 2) {
+       static const int irqlist[] = {5, 9, 3, 4, 0};
+       const int *irqp = irqlist;
+
+       outb(EGACFR_NORM, E33G_GACFR);  /* Enable RAM and interrupts. */
+       do {
+               bool seen;
+
+               retval = request_irq(*irqp, el2_probe_interrupt, 0,
+                                    dev->name, &seen);
+               if (retval == -EBUSY)
+                       continue;
+               if (retval < 0)
+                       goto err_disable;
+
+               /* Twinkle the interrupt, and check if it's seen. */
+               seen = false;
+               smp_wmb();
+               outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
+               outb_p(0x00, E33G_IDCFR);
+               msleep(1);
+               free_irq(*irqp, &seen);
+               if (!seen)
+                       continue;
+
+               retval = request_irq(dev->irq = *irqp, eip_interrupt, 0,
+                                    dev->name, dev);
+               if (retval == -EBUSY)
+                       continue;
+               if (retval < 0)
+                       goto err_disable;
+               break;
+       } while (*++irqp);
+
+       if (*irqp == 0) {
+       err_disable:
+           outb(EGACFR_IRQOFF, E33G_GACFR);    /* disable interrupts. */
+           return -EAGAIN;
+       }
+    } else {
+       if ((retval = request_irq(dev->irq, eip_interrupt, 0, dev->name, dev))) {
+           return retval;
+       }
+    }
+
+    el2_init_card(dev);
+    eip_open(dev);
+    return 0;
+}
+
+static int
+el2_close(struct net_device *dev)
+{
+    free_irq(dev->irq, dev);
+    dev->irq = ei_status.saved_irq;
+    outb(EGACFR_IRQOFF, E33G_GACFR);   /* disable interrupts. */
+
+    eip_close(dev);
+    return 0;
+}
+
+/* This is called whenever we have a unrecoverable failure:
+       transmit timeout
+       Bad ring buffer packet header
+ */
+static void
+el2_reset_8390(struct net_device *dev)
+{
+    if (ei_debug > 1) {
+       pr_debug("%s: Resetting the 3c503 board...", dev->name);
+       pr_cont(" %#lx=%#02x %#lx=%#02x %#lx=%#02x...", E33G_IDCFR, inb(E33G_IDCFR),
+              E33G_CNTRL, inb(E33G_CNTRL), E33G_GACFR, inb(E33G_GACFR));
+    }
+    outb_p(ECNTRL_RESET|ECNTRL_THIN, E33G_CNTRL);
+    ei_status.txing = 0;
+    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
+    el2_init_card(dev);
+    if (ei_debug > 1)
+       pr_cont("done\n");
+}
+
+/* Initialize the 3c503 GA registers after a reset. */
+static void
+el2_init_card(struct net_device *dev)
+{
+    /* Unmap the station PROM and select the DIX or BNC connector. */
+    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
+
+    /* Set ASIC copy of rx's first and last+1 buffer pages */
+    /* These must be the same as in the 8390. */
+    outb(ei_status.rx_start_page, E33G_STARTPG);
+    outb(ei_status.stop_page,  E33G_STOPPG);
+
+    /* Point the vector pointer registers somewhere ?harmless?. */
+    outb(0xff, E33G_VP2);      /* Point at the ROM restart location 0xffff0 */
+    outb(0xff, E33G_VP1);
+    outb(0x00, E33G_VP0);
+    /* Turn off all interrupts until we're opened. */
+    outb_p(0x00,  dev->base_addr + EN0_IMR);
+    /* Enable IRQs iff started. */
+    outb(EGACFR_NORM, E33G_GACFR);
+
+    /* Set the interrupt line. */
+    outb_p((0x04 << (dev->irq == 9 ? 2 : dev->irq)), E33G_IDCFR);
+    outb_p((WRD_COUNT << 1), E33G_DRQCNT);     /* Set burst size to 8 */
+    outb_p(0x20, E33G_DMAAH);  /* Put a valid addr in the GA DMA */
+    outb_p(0x00, E33G_DMAAL);
+    return;                    /* We always succeed */
+}
+
+/*
+ * Either use the shared memory (if enabled on the board) or put the packet
+ * out through the ASIC FIFO.
+ */
+static void
+el2_block_output(struct net_device *dev, int count,
+                const unsigned char *buf, int start_page)
+{
+    unsigned short int *wrd;
+    int boguscount;            /* timeout counter */
+    unsigned short word;       /* temporary for better machine code */
+    void __iomem *base = ei_status.mem;
+
+    if (ei_status.word16)      /* Tx packets go into bank 0 on EL2/16 card */
+       outb(EGACFR_RSEL|EGACFR_TCM, E33G_GACFR);
+    else
+       outb(EGACFR_NORM, E33G_GACFR);
+
+    if (base) {        /* Shared memory transfer */
+       memcpy_toio(base + ((start_page - ei_status.tx_start_page) << 8),
+                       buf, count);
+       outb(EGACFR_NORM, E33G_GACFR);  /* Back to bank1 in case on bank0 */
+       return;
+    }
+
+/*
+ *  No shared memory, put the packet out the other way.
+ *  Set up then start the internal memory transfer to Tx Start Page
+ */
+
+    word = (unsigned short)start_page;
+    outb(word&0xFF, E33G_DMAAH);
+    outb(word>>8, E33G_DMAAL);
+
+    outb_p((ei_status.interface_num ? ECNTRL_AUI : ECNTRL_THIN ) | ECNTRL_OUTPUT
+          | ECNTRL_START, E33G_CNTRL);
+
+/*
+ *  Here I am going to write data to the FIFO as quickly as possible.
+ *  Note that E33G_FIFOH is defined incorrectly. It is really
+ *  E33G_FIFOL, the lowest port address for both the byte and
+ *  word write. Variable 'count' is NOT checked. Caller must supply a
+ *  valid count. Note that I may write a harmless extra byte to the
+ *  8390 if the byte-count was not even.
+ */
+    wrd = (unsigned short int *) buf;
+    count  = (count + 1) >> 1;
+    for(;;)
+    {
+        boguscount = 0x1000;
+        while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
+        {
+            if(!boguscount--)
+            {
+                pr_notice("%s: FIFO blocked in el2_block_output.\n", dev->name);
+                el2_reset_8390(dev);
+                goto blocked;
+            }
+        }
+        if(count > WRD_COUNT)
+        {
+            outsw(E33G_FIFOH, wrd, WRD_COUNT);
+            wrd   += WRD_COUNT;
+            count -= WRD_COUNT;
+        }
+        else
+        {
+            outsw(E33G_FIFOH, wrd, count);
+            break;
+        }
+    }
+    blocked:;
+    outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
+}
+
+/* Read the 4 byte, page aligned 8390 specific header. */
+static void
+el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+    int boguscount;
+    void __iomem *base = ei_status.mem;
+    unsigned short word;
+
+    if (base) {       /* Use the shared memory. */
+       void __iomem *hdr_start = base + ((ring_page - EL2_MB1_START_PG)<<8);
+       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+       hdr->count = le16_to_cpu(hdr->count);
+       return;
+    }
+
+/*
+ *  No shared memory, use programmed I/O.
+ */
+
+    word = (unsigned short)ring_page;
+    outb(word&0xFF, E33G_DMAAH);
+    outb(word>>8, E33G_DMAAL);
+
+    outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT
+          | ECNTRL_START, E33G_CNTRL);
+    boguscount = 0x1000;
+    while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
+    {
+        if(!boguscount--)
+        {
+            pr_notice("%s: FIFO blocked in el2_get_8390_hdr.\n", dev->name);
+            memset(hdr, 0x00, sizeof(struct e8390_pkt_hdr));
+            el2_reset_8390(dev);
+            goto blocked;
+        }
+    }
+    insw(E33G_FIFOH, hdr, (sizeof(struct e8390_pkt_hdr))>> 1);
+    blocked:;
+    outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
+}
+
+
+static void
+el2_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+    int boguscount = 0;
+    void __iomem *base = ei_status.mem;
+    unsigned short int *buf;
+    unsigned short word;
+
+    /* Maybe enable shared memory just be to be safe... nahh.*/
+    if (base) {        /* Use the shared memory. */
+       ring_offset -= (EL2_MB1_START_PG<<8);
+       if (ring_offset + count > EL2_MEMSIZE) {
+           /* We must wrap the input move. */
+           int semi_count = EL2_MEMSIZE - ring_offset;
+           memcpy_fromio(skb->data, base + ring_offset, semi_count);
+           count -= semi_count;
+           memcpy_fromio(skb->data + semi_count, base + ei_status.priv, count);
+       } else {
+               memcpy_fromio(skb->data, base + ring_offset, count);
+       }
+       return;
+    }
+
+/*
+ *  No shared memory, use programmed I/O.
+ */
+    word = (unsigned short) ring_offset;
+    outb(word>>8, E33G_DMAAH);
+    outb(word&0xFF, E33G_DMAAL);
+
+    outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT
+          | ECNTRL_START, E33G_CNTRL);
+
+/*
+ *  Here I also try to get data as fast as possible. I am betting that I
+ *  can read one extra byte without clobbering anything in the kernel because
+ *  this would only occur on an odd byte-count and allocation of skb->data
+ *  is word-aligned. Variable 'count' is NOT checked. Caller must check
+ *  for a valid count.
+ *  [This is currently quite safe.... but if one day the 3c503 explodes
+ *   you know where to come looking ;)]
+ */
+
+    buf =  (unsigned short int *) skb->data;
+    count =  (count + 1) >> 1;
+    for(;;)
+    {
+        boguscount = 0x1000;
+        while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
+        {
+            if(!boguscount--)
+            {
+                pr_notice("%s: FIFO blocked in el2_block_input.\n", dev->name);
+                el2_reset_8390(dev);
+                goto blocked;
+            }
+        }
+        if(count > WRD_COUNT)
+        {
+            insw(E33G_FIFOH, buf, WRD_COUNT);
+            buf   += WRD_COUNT;
+            count -= WRD_COUNT;
+        }
+        else
+        {
+            insw(E33G_FIFOH, buf, count);
+            break;
+        }
+    }
+    blocked:;
+    outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
+}
+
+
+static void netdev_get_drvinfo(struct net_device *dev,
+                              struct ethtool_drvinfo *info)
+{
+       strcpy(info->driver, DRV_NAME);
+       strcpy(info->version, DRV_VERSION);
+       sprintf(info->bus_info, "ISA 0x%lx", dev->base_addr);
+}
+
+static const struct ethtool_ops netdev_ethtool_ops = {
+       .get_drvinfo            = netdev_get_drvinfo,
+};
+
+#ifdef MODULE
+#define MAX_EL2_CARDS  4       /* Max number of EL2 cards per module */
+
+static struct net_device *dev_el2[MAX_EL2_CARDS];
+static int io[MAX_EL2_CARDS];
+static int irq[MAX_EL2_CARDS];
+static int xcvr[MAX_EL2_CARDS];        /* choose int. or ext. xcvr */
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(xcvr, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
+MODULE_PARM_DESC(xcvr, "transceiver(s) (0=internal, 1=external)");
+MODULE_DESCRIPTION("3Com ISA EtherLink II, II/16 (3c503, 3c503/16) driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that only a single autoprobe takes place per call.
+ISA device autoprobes on a running machine are not recommended. */
+int __init
+init_module(void)
+{
+       struct net_device *dev;
+       int this_dev, found = 0;
+
+       for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) {
+               if (io[this_dev] == 0)  {
+                       if (this_dev != 0) break; /* only autoprobe 1st one */
+                       pr_notice("3c503.c: Presently autoprobing (not recommended) for a single card.\n");
+               }
+               dev = alloc_eip_netdev();
+               if (!dev)
+                       break;
+               dev->irq = irq[this_dev];
+               dev->base_addr = io[this_dev];
+               dev->mem_end = xcvr[this_dev];  /* low 4bits = xcvr sel. */
+               if (do_el2_probe(dev) == 0) {
+                       dev_el2[found++] = dev;
+                       continue;
+               }
+               free_netdev(dev);
+               pr_warning("3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]);
+               break;
+       }
+       if (found)
+               return 0;
+       return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+       /* NB: el2_close() handles free_irq */
+       release_region(dev->base_addr, EL2_IO_EXTENT);
+       if (ei_status.mem)
+               iounmap(ei_status.mem);
+}
+
+void __exit
+cleanup_module(void)
+{
+       int this_dev;
+
+       for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) {
+               struct net_device *dev = dev_el2[this_dev];
+               if (dev) {
+                       unregister_netdev(dev);
+                       cleanup_card(dev);
+                       free_netdev(dev);
+               }
+       }
+}
+#endif /* MODULE */
diff --git a/drivers/net/ethernet/8390/3c503.h b/drivers/net/ethernet/8390/3c503.h
new file mode 100644 (file)
index 0000000..e2367b8
--- /dev/null
@@ -0,0 +1,91 @@
+/* Definitions for the 3Com 3c503 Etherlink 2. */
+/* This file is distributed under the GPL.
+   Many of these names and comments are directly from the Crynwr packet
+   drivers, which are released under the GPL. */
+
+#define EL2H (dev->base_addr + 0x400)
+#define EL2L (dev->base_addr)
+
+/* Vendor unique hardware addr. prefix. 3Com has 2 because they ran
+   out of available addresses on the first one... */
+
+#define OLD_3COM_ID    0x02608c
+#define NEW_3COM_ID    0x0020af
+
+/* Shared memory management parameters. NB: The 8 bit cards have only
+   one bank (MB1) which serves both Tx and Rx packet space. The 16bit
+   cards have 2 banks, MB0 for Tx packets, and MB1 for Rx packets.
+   You choose which bank appears in the sh. mem window with EGACFR_MBSn */
+
+#define EL2_MB0_START_PG       (0x00)  /* EL2/16 Tx packets go in bank 0 */
+#define EL2_MB1_START_PG       (0x20)  /* First page of bank 1 */
+#define EL2_MB1_STOP_PG                (0x40)  /* Last page +1 of bank 1 */
+
+/* 3Com 3c503 ASIC registers */
+#define E33G_STARTPG   (EL2H+0)        /* Start page, matching EN0_STARTPG */
+#define E33G_STOPPG    (EL2H+1)        /* Stop page, must match EN0_STOPPG */
+#define E33G_DRQCNT    (EL2H+2)        /* DMA burst count */
+#define E33G_IOBASE    (EL2H+3)        /* Read of I/O base jumpers. */
+       /* (non-useful, but it also appears at the end of EPROM space) */
+#define E33G_ROMBASE   (EL2H+4)        /* Read of memory base jumpers. */
+#define E33G_GACFR     (EL2H+5)        /* Config/setup bits for the ASIC GA */
+#define E33G_CNTRL     (EL2H+6)        /* Board's main control register */
+#define E33G_STATUS    (EL2H+7)        /* Status on completions. */
+#define E33G_IDCFR     (EL2H+8)        /* Interrupt/DMA config register */
+                               /* (Which IRQ to assert, DMA chan to use) */
+#define E33G_DMAAH     (EL2H+9)        /* High byte of DMA address reg */
+#define E33G_DMAAL     (EL2H+10)       /* Low byte of DMA address reg */
+/* "Vector pointer" - if this address matches a read, the EPROM (rather than
+   shared RAM) is mapped into memory space. */
+#define E33G_VP2       (EL2H+11)
+#define E33G_VP1       (EL2H+12)
+#define E33G_VP0       (EL2H+13)
+#define E33G_FIFOH     (EL2H+14)       /* FIFO for programmed I/O moves */
+#define E33G_FIFOL     (EL2H+15)       /* ... low byte of above. */
+
+/* Bits in E33G_CNTRL register: */
+
+#define ECNTRL_RESET   (0x01)  /* Software reset of the ASIC and 8390 */
+#define ECNTRL_THIN    (0x02)  /* Onboard xcvr enable, AUI disable */
+#define ECNTRL_AUI     (0x00)  /* Onboard xcvr disable, AUI enable */
+#define ECNTRL_SAPROM  (0x04)  /* Map the station address prom */
+#define ECNTRL_DBLBFR  (0x20)  /* FIFO configuration bit */
+#define ECNTRL_OUTPUT  (0x40)  /* PC-to-3C503 direction if 1 */
+#define ECNTRL_INPUT   (0x00)  /* 3C503-to-PC direction if 0 */
+#define ECNTRL_START   (0x80)  /* Start the DMA logic */
+
+/* Bits in E33G_STATUS register: */
+
+#define ESTAT_DPRDY    (0x80)  /* Data port (of FIFO) ready */
+#define ESTAT_UFLW     (0x40)  /* Tried to read FIFO when it was empty */
+#define ESTAT_OFLW     (0x20)  /* Tried to write FIFO when it was full */
+#define ESTAT_DTC      (0x10)  /* Terminal Count from PC bus DMA logic */
+#define ESTAT_DIP      (0x08)  /* DMA In Progress */
+
+/* Bits in E33G_GACFR register: */
+
+#define EGACFR_NIM     (0x80)  /* NIC interrupt mask */
+#define EGACFR_TCM     (0x40)  /* DMA term. count interrupt mask */
+#define EGACFR_RSEL    (0x08)  /* Map a bank of card mem into system mem */
+#define EGACFR_MBS2    (0x04)  /* Memory bank select, bit 2. */
+#define EGACFR_MBS1    (0x02)  /* Memory bank select, bit 1. */
+#define EGACFR_MBS0    (0x01)  /* Memory bank select, bit 0. */
+
+#define EGACFR_NORM    (0x49)  /* TCM | RSEL | MBS0 */
+#define EGACFR_IRQOFF  (0xc9)  /* TCM | RSEL | MBS0 | NIM */
+
+/*
+       MBS2    MBS1    MBS0    Sh. mem windows card mem at:
+       ----    ----    ----    -----------------------------
+       0       0       0       0x0000 -- bank 0
+       0       0       1       0x2000 -- bank 1 (only choice for 8bit card)
+       0       1       0       0x4000 -- bank 2, not used
+       0       1       1       0x6000 -- bank 3, not used
+
+There was going to be a 32k card that used bank 2 and 3, but it
+never got produced.
+
+*/
+
+
+/* End of 3C503 parameter definitions */
diff --git a/drivers/net/ethernet/8390/8390.c b/drivers/net/ethernet/8390/8390.c
new file mode 100644 (file)
index 0000000..7c7518b
--- /dev/null
@@ -0,0 +1,103 @@
+/* 8390 core for usual drivers */
+
+static const char version[] =
+    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include "lib8390.c"
+
+int ei_open(struct net_device *dev)
+{
+       return __ei_open(dev);
+}
+EXPORT_SYMBOL(ei_open);
+
+int ei_close(struct net_device *dev)
+{
+       return __ei_close(dev);
+}
+EXPORT_SYMBOL(ei_close);
+
+netdev_tx_t ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       return __ei_start_xmit(skb, dev);
+}
+EXPORT_SYMBOL(ei_start_xmit);
+
+struct net_device_stats *ei_get_stats(struct net_device *dev)
+{
+       return __ei_get_stats(dev);
+}
+EXPORT_SYMBOL(ei_get_stats);
+
+void ei_set_multicast_list(struct net_device *dev)
+{
+       __ei_set_multicast_list(dev);
+}
+EXPORT_SYMBOL(ei_set_multicast_list);
+
+void ei_tx_timeout(struct net_device *dev)
+{
+       __ei_tx_timeout(dev);
+}
+EXPORT_SYMBOL(ei_tx_timeout);
+
+irqreturn_t ei_interrupt(int irq, void *dev_id)
+{
+       return __ei_interrupt(irq, dev_id);
+}
+EXPORT_SYMBOL(ei_interrupt);
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+void ei_poll(struct net_device *dev)
+{
+       __ei_poll(dev);
+}
+EXPORT_SYMBOL(ei_poll);
+#endif
+
+const struct net_device_ops ei_netdev_ops = {
+       .ndo_open               = ei_open,
+       .ndo_stop               = ei_close,
+       .ndo_start_xmit         = ei_start_xmit,
+       .ndo_tx_timeout         = ei_tx_timeout,
+       .ndo_get_stats          = ei_get_stats,
+       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = ei_poll,
+#endif
+};
+EXPORT_SYMBOL(ei_netdev_ops);
+
+struct net_device *__alloc_ei_netdev(int size)
+{
+       struct net_device *dev = ____alloc_ei_netdev(size);
+       if (dev)
+               dev->netdev_ops = &ei_netdev_ops;
+       return dev;
+}
+EXPORT_SYMBOL(__alloc_ei_netdev);
+
+void NS8390_init(struct net_device *dev, int startp)
+{
+       __NS8390_init(dev, startp);
+}
+EXPORT_SYMBOL(NS8390_init);
+
+#if defined(MODULE)
+
+static int __init ns8390_module_init(void)
+{
+       return 0;
+}
+
+static void __exit ns8390_module_exit(void)
+{
+}
+
+module_init(ns8390_module_init);
+module_exit(ns8390_module_exit);
+#endif /* MODULE */
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/8390/8390.h b/drivers/net/ethernet/8390/8390.h
new file mode 100644 (file)
index 0000000..58a12e4
--- /dev/null
@@ -0,0 +1,232 @@
+/* Generic NS8390 register definitions. */
+/* This file is part of Donald Becker's 8390 drivers, and is distributed
+   under the same license. Auto-loading of 8390.o only in v2.2 - Paul G.
+   Some of these names and comments originated from the Crynwr
+   packet drivers, which are distributed under the GPL. */
+
+#ifndef _8390_h
+#define _8390_h
+
+#include <linux/if_ether.h>
+#include <linux/ioport.h>
+#include <linux/irqreturn.h>
+#include <linux/skbuff.h>
+
+#define TX_PAGES 12    /* Two Tx slots */
+
+#define ETHER_ADDR_LEN 6
+
+/* The 8390 specific per-packet-header format. */
+struct e8390_pkt_hdr {
+  unsigned char status; /* status */
+  unsigned char next;   /* pointer to next packet. */
+  unsigned short count; /* header + packet length in bytes */
+};
+
+#ifdef notdef
+extern int ei_debug;
+#else
+#define ei_debug 1
+#endif
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+extern void ei_poll(struct net_device *dev);
+extern void eip_poll(struct net_device *dev);
+#endif
+
+
+/* Without I/O delay - non ISA or later chips */
+extern void NS8390_init(struct net_device *dev, int startp);
+extern int ei_open(struct net_device *dev);
+extern int ei_close(struct net_device *dev);
+extern irqreturn_t ei_interrupt(int irq, void *dev_id);
+extern void ei_tx_timeout(struct net_device *dev);
+extern netdev_tx_t ei_start_xmit(struct sk_buff *skb, struct net_device *dev);
+extern void ei_set_multicast_list(struct net_device *dev);
+extern struct net_device_stats *ei_get_stats(struct net_device *dev);
+
+extern const struct net_device_ops ei_netdev_ops;
+
+extern struct net_device *__alloc_ei_netdev(int size);
+static inline struct net_device *alloc_ei_netdev(void)
+{
+       return __alloc_ei_netdev(0);
+}
+
+/* With I/O delay form */
+extern void NS8390p_init(struct net_device *dev, int startp);
+extern int eip_open(struct net_device *dev);
+extern int eip_close(struct net_device *dev);
+extern irqreturn_t eip_interrupt(int irq, void *dev_id);
+extern void eip_tx_timeout(struct net_device *dev);
+extern netdev_tx_t eip_start_xmit(struct sk_buff *skb, struct net_device *dev);
+extern void eip_set_multicast_list(struct net_device *dev);
+extern struct net_device_stats *eip_get_stats(struct net_device *dev);
+
+extern const struct net_device_ops eip_netdev_ops;
+
+extern struct net_device *__alloc_eip_netdev(int size);
+static inline struct net_device *alloc_eip_netdev(void)
+{
+       return __alloc_eip_netdev(0);
+}
+
+/* You have one of these per-board */
+struct ei_device {
+       const char *name;
+       void (*reset_8390)(struct net_device *);
+       void (*get_8390_hdr)(struct net_device *, struct e8390_pkt_hdr *, int);
+       void (*block_output)(struct net_device *, int, const unsigned char *, int);
+       void (*block_input)(struct net_device *, int, struct sk_buff *, int);
+       unsigned long rmem_start;
+       unsigned long rmem_end;
+       void __iomem *mem;
+       unsigned char mcfilter[8];
+       unsigned open:1;
+       unsigned word16:1;              /* We have the 16-bit (vs 8-bit) version of the card. */
+       unsigned bigendian:1;           /* 16-bit big endian mode. Do NOT */
+                                       /* set this on random 8390 clones! */
+       unsigned txing:1;               /* Transmit Active */
+       unsigned irqlock:1;             /* 8390's intrs disabled when '1'. */
+       unsigned dmaing:1;              /* Remote DMA Active */
+       unsigned char tx_start_page, rx_start_page, stop_page;
+       unsigned char current_page;     /* Read pointer in buffer  */
+       unsigned char interface_num;    /* Net port (AUI, 10bT.) to use. */
+       unsigned char txqueue;          /* Tx Packet buffer queue length. */
+       short tx1, tx2;                 /* Packet lengths for ping-pong tx. */
+       short lasttx;                   /* Alpha version consistency check. */
+       unsigned char reg0;             /* Register '0' in a WD8013 */
+       unsigned char reg5;             /* Register '5' in a WD8013 */
+       unsigned char saved_irq;        /* Original dev->irq value. */
+       u32 *reg_offset;                /* Register mapping table */
+       spinlock_t page_lock;           /* Page register locks */
+       unsigned long priv;             /* Private field to store bus IDs etc. */
+#ifdef AX88796_PLATFORM
+       unsigned char rxcr_base;        /* default value for RXCR */
+#endif
+};
+
+/* The maximum number of 8390 interrupt service routines called per IRQ. */
+#define MAX_SERVICE 12
+
+/* The maximum time waited (in jiffies) before assuming a Tx failed. (20ms) */
+#define TX_TIMEOUT (20*HZ/100)
+
+#define ei_status (*(struct ei_device *)netdev_priv(dev))
+
+/* Some generic ethernet register configurations. */
+#define E8390_TX_IRQ_MASK      0xa     /* For register EN0_ISR */
+#define E8390_RX_IRQ_MASK      0x5
+
+#ifdef AX88796_PLATFORM
+#define E8390_RXCONFIG         (ei_status.rxcr_base | 0x04)
+#define E8390_RXOFF            (ei_status.rxcr_base | 0x20)
+#else
+#define E8390_RXCONFIG         0x4     /* EN0_RXCR: broadcasts, no multicast,errors */
+#define E8390_RXOFF            0x20    /* EN0_RXCR: Accept no packets */
+#endif
+
+#define E8390_TXCONFIG         0x00    /* EN0_TXCR: Normal transmit mode */
+#define E8390_TXOFF            0x02    /* EN0_TXCR: Transmitter off */
+
+
+/*  Register accessed at EN_CMD, the 8390 base addr.  */
+#define E8390_STOP     0x01    /* Stop and reset the chip */
+#define E8390_START    0x02    /* Start the chip, clear reset */
+#define E8390_TRANS    0x04    /* Transmit a frame */
+#define E8390_RREAD    0x08    /* Remote read */
+#define E8390_RWRITE   0x10    /* Remote write  */
+#define E8390_NODMA    0x20    /* Remote DMA */
+#define E8390_PAGE0    0x00    /* Select page chip registers */
+#define E8390_PAGE1    0x40    /* using the two high-order bits */
+#define E8390_PAGE2    0x80    /* Page 3 is invalid. */
+
+/*
+ *     Only generate indirect loads given a machine that needs them.
+ *      - removed AMIGA_PCMCIA from this list, handled as ISA io now
+ *     - the _p for generates no delay by default 8390p.c overrides this.
+ */
+
+#ifndef ei_inb
+#define ei_inb(_p)     inb(_p)
+#define ei_outb(_v,_p) outb(_v,_p)
+#define ei_inb_p(_p)   inb(_p)
+#define ei_outb_p(_v,_p) outb(_v,_p)
+#endif
+
+#ifndef EI_SHIFT
+#define EI_SHIFT(x)    (x)
+#endif
+
+#define E8390_CMD      EI_SHIFT(0x00)  /* The command register (for all pages) */
+/* Page 0 register offsets. */
+#define EN0_CLDALO     EI_SHIFT(0x01)  /* Low byte of current local dma addr  RD */
+#define EN0_STARTPG    EI_SHIFT(0x01)  /* Starting page of ring bfr WR */
+#define EN0_CLDAHI     EI_SHIFT(0x02)  /* High byte of current local dma addr  RD */
+#define EN0_STOPPG     EI_SHIFT(0x02)  /* Ending page +1 of ring bfr WR */
+#define EN0_BOUNDARY   EI_SHIFT(0x03)  /* Boundary page of ring bfr RD WR */
+#define EN0_TSR                EI_SHIFT(0x04)  /* Transmit status reg RD */
+#define EN0_TPSR       EI_SHIFT(0x04)  /* Transmit starting page WR */
+#define EN0_NCR                EI_SHIFT(0x05)  /* Number of collision reg RD */
+#define EN0_TCNTLO     EI_SHIFT(0x05)  /* Low  byte of tx byte count WR */
+#define EN0_FIFO       EI_SHIFT(0x06)  /* FIFO RD */
+#define EN0_TCNTHI     EI_SHIFT(0x06)  /* High byte of tx byte count WR */
+#define EN0_ISR                EI_SHIFT(0x07)  /* Interrupt status reg RD WR */
+#define EN0_CRDALO     EI_SHIFT(0x08)  /* low byte of current remote dma address RD */
+#define EN0_RSARLO     EI_SHIFT(0x08)  /* Remote start address reg 0 */
+#define EN0_CRDAHI     EI_SHIFT(0x09)  /* high byte, current remote dma address RD */
+#define EN0_RSARHI     EI_SHIFT(0x09)  /* Remote start address reg 1 */
+#define EN0_RCNTLO     EI_SHIFT(0x0a)  /* Remote byte count reg WR */
+#define EN0_RCNTHI     EI_SHIFT(0x0b)  /* Remote byte count reg WR */
+#define EN0_RSR                EI_SHIFT(0x0c)  /* rx status reg RD */
+#define EN0_RXCR       EI_SHIFT(0x0c)  /* RX configuration reg WR */
+#define EN0_TXCR       EI_SHIFT(0x0d)  /* TX configuration reg WR */
+#define EN0_COUNTER0   EI_SHIFT(0x0d)  /* Rcv alignment error counter RD */
+#define EN0_DCFG       EI_SHIFT(0x0e)  /* Data configuration reg WR */
+#define EN0_COUNTER1   EI_SHIFT(0x0e)  /* Rcv CRC error counter RD */
+#define EN0_IMR                EI_SHIFT(0x0f)  /* Interrupt mask reg WR */
+#define EN0_COUNTER2   EI_SHIFT(0x0f)  /* Rcv missed frame error counter RD */
+
+/* Bits in EN0_ISR - Interrupt status register */
+#define ENISR_RX       0x01    /* Receiver, no error */
+#define ENISR_TX       0x02    /* Transmitter, no error */
+#define ENISR_RX_ERR   0x04    /* Receiver, with error */
+#define ENISR_TX_ERR   0x08    /* Transmitter, with error */
+#define ENISR_OVER     0x10    /* Receiver overwrote the ring */
+#define ENISR_COUNTERS 0x20    /* Counters need emptying */
+#define ENISR_RDC      0x40    /* remote dma complete */
+#define ENISR_RESET    0x80    /* Reset completed */
+#define ENISR_ALL      0x3f    /* Interrupts we will enable */
+
+/* Bits in EN0_DCFG - Data config register */
+#define ENDCFG_WTS     0x01    /* word transfer mode selection */
+#define ENDCFG_BOS     0x02    /* byte order selection */
+
+/* Page 1 register offsets. */
+#define EN1_PHYS   EI_SHIFT(0x01)      /* This board's physical enet addr RD WR */
+#define EN1_PHYS_SHIFT(i)  EI_SHIFT(i+1) /* Get and set mac address */
+#define EN1_CURPAG EI_SHIFT(0x07)      /* Current memory page RD WR */
+#define EN1_MULT   EI_SHIFT(0x08)      /* Multicast filter mask array (8 bytes) RD WR */
+#define EN1_MULT_SHIFT(i)  EI_SHIFT(8+i) /* Get and set multicast filter */
+
+/* Bits in received packet status byte and EN0_RSR*/
+#define ENRSR_RXOK     0x01    /* Received a good packet */
+#define ENRSR_CRC      0x02    /* CRC error */
+#define ENRSR_FAE      0x04    /* frame alignment error */
+#define ENRSR_FO       0x08    /* FIFO overrun */
+#define ENRSR_MPA      0x10    /* missed pkt */
+#define ENRSR_PHY      0x20    /* physical/multicast address */
+#define ENRSR_DIS      0x40    /* receiver disable. set in monitor mode */
+#define ENRSR_DEF      0x80    /* deferring */
+
+/* Transmitted packet status, EN0_TSR. */
+#define ENTSR_PTX 0x01 /* Packet transmitted without error */
+#define ENTSR_ND  0x02 /* The transmit wasn't deferred. */
+#define ENTSR_COL 0x04 /* The transmit collided at least once. */
+#define ENTSR_ABT 0x08  /* The transmit collided 16 times, and was deferred. */
+#define ENTSR_CRS 0x10 /* The carrier sense was lost. */
+#define ENTSR_FU  0x20  /* A "FIFO underrun" occurred during transmit. */
+#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */
+#define ENTSR_OWC 0x80  /* There was an out-of-window collision. */
+
+#endif /* _8390_h */
diff --git a/drivers/net/ethernet/8390/8390p.c b/drivers/net/ethernet/8390/8390p.c
new file mode 100644 (file)
index 0000000..a2a64ea
--- /dev/null
@@ -0,0 +1,105 @@
+/* 8390 core for ISA devices needing bus delays */
+
+static const char version[] =
+    "8390p.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#define ei_inb(_p)     inb(_p)
+#define ei_outb(_v, _p)        outb(_v, _p)
+#define ei_inb_p(_p)   inb_p(_p)
+#define ei_outb_p(_v, _p) outb_p(_v, _p)
+
+#include "lib8390.c"
+
+int eip_open(struct net_device *dev)
+{
+       return __ei_open(dev);
+}
+EXPORT_SYMBOL(eip_open);
+
+int eip_close(struct net_device *dev)
+{
+       return __ei_close(dev);
+}
+EXPORT_SYMBOL(eip_close);
+
+netdev_tx_t eip_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       return __ei_start_xmit(skb, dev);
+}
+EXPORT_SYMBOL(eip_start_xmit);
+
+struct net_device_stats *eip_get_stats(struct net_device *dev)
+{
+       return __ei_get_stats(dev);
+}
+EXPORT_SYMBOL(eip_get_stats);
+
+void eip_set_multicast_list(struct net_device *dev)
+{
+       __ei_set_multicast_list(dev);
+}
+EXPORT_SYMBOL(eip_set_multicast_list);
+
+void eip_tx_timeout(struct net_device *dev)
+{
+       __ei_tx_timeout(dev);
+}
+EXPORT_SYMBOL(eip_tx_timeout);
+
+irqreturn_t eip_interrupt(int irq, void *dev_id)
+{
+       return __ei_interrupt(irq, dev_id);
+}
+EXPORT_SYMBOL(eip_interrupt);
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+void eip_poll(struct net_device *dev)
+{
+       __ei_poll(dev);
+}
+EXPORT_SYMBOL(eip_poll);
+#endif
+
+const struct net_device_ops eip_netdev_ops = {
+       .ndo_open               = eip_open,
+       .ndo_stop               = eip_close,
+       .ndo_start_xmit         = eip_start_xmit,
+       .ndo_tx_timeout         = eip_tx_timeout,
+       .ndo_get_stats          = eip_get_stats,
+       .ndo_set_multicast_list = eip_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = eip_poll,
+#endif
+};
+EXPORT_SYMBOL(eip_netdev_ops);
+
+struct net_device *__alloc_eip_netdev(int size)
+{
+       struct net_device *dev = ____alloc_ei_netdev(size);
+       if (dev)
+               dev->netdev_ops = &eip_netdev_ops;
+       return dev;
+}
+EXPORT_SYMBOL(__alloc_eip_netdev);
+
+void NS8390p_init(struct net_device *dev, int startp)
+{
+       __NS8390_init(dev, startp);
+}
+EXPORT_SYMBOL(NS8390p_init);
+
+static int __init NS8390p_init_module(void)
+{
+       return 0;
+}
+
+static void __exit NS8390p_cleanup_module(void)
+{
+}
+
+module_init(NS8390p_init_module);
+module_exit(NS8390p_cleanup_module);
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/8390/Kconfig b/drivers/net/ethernet/8390/Kconfig
new file mode 100644 (file)
index 0000000..5cd53f1
--- /dev/null
@@ -0,0 +1,348 @@
+#
+# 8390 device configuration
+#
+
+config NET_VENDOR_8390
+       bool "National Semi-conductor 8390 devices"
+       depends on AMIGA_PCMCIA || PCI || SUPERH || ISA || MCA || EISA ||  \
+                  MAC || M32R || MACH_TX49XX || MCA_LEGACY || H8300 ||  \
+                  ARM || MIPS || ZORRO || PCMCIA || EXPERIMENTAL
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Western Digital cards. If you say Y, you will be
+         asked for your specific card in the following questions.
+
+if NET_VENDOR_8390
+
+config EL2
+       tristate "3c503 \"EtherLink II\" support"
+       depends on ISA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called 3c503.
+
+config AC3200
+       tristate "Ansel Communications EISA 3200 support (EXPERIMENTAL)"
+       depends on PCI && (ISA || EISA) && EXPERIMENTAL
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ac3200.
+
+config PCMCIA_AXNET
+       tristate "Asix AX88190 PCMCIA support"
+       depends on PCMCIA
+       ---help---
+         Say Y here if you intend to attach an Asix AX88190-based PCMCIA
+         (PC-card) Fast Ethernet card to your computer.  These cards are
+         nearly NE2000 compatible but need a separate driver due to a few
+         misfeatures.
+
+         To compile this driver as a module, choose M here: the module will be
+         called axnet_cs.  If unsure, say N.
+
+config AX88796
+       tristate "ASIX AX88796 NE2000 clone support"
+       depends on (ARM || MIPS || SUPERH)
+       select PHYLIB
+       select MDIO_BITBANG
+       ---help---
+         AX88796 driver, using platform bus to provide
+         chip detection and resources
+
+config AX88796_93CX6
+       bool "ASIX AX88796 external 93CX6 eeprom support"
+       depends on AX88796
+       select EEPROM_93CX6
+       ---help---
+         Select this if your platform comes with an external 93CX6 eeprom.
+
+config E2100
+       tristate "Cabletron E21xx support"
+       depends on ISA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called e2100.
+
+config ES3210
+       tristate "Racal-Interlan EISA ES3210 support (EXPERIMENTAL)"
+       depends on PCI && EISA && EXPERIMENTAL
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called es3210.
+
+config HPLAN_PLUS
+       tristate "HP PCLAN+ (27247B and 27252A) support"
+       depends on ISA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called hp-plus.
+
+config HPLAN
+       tristate "HP PCLAN (27245 and other 27xxx series) support"
+       depends on ISA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called hp.
+
+config HYDRA
+       tristate "Hydra support"
+       depends on ZORRO
+       select CRC32
+       ---help---
+         If you have a Hydra Ethernet adapter, say Y. Otherwise, say N.
+
+         To compile this driver as a module, choose M here: the module
+         will be called hydra.
+
+config ARM_ETHERH
+       tristate "I-cubed EtherH/ANT EtherM support"
+       depends on ARM && ARCH_ACORN
+       select CRC32
+       ---help---
+         If you have an Acorn system with one of these network cards, you
+         should say Y to this option if you wish to use it with Linux.
+
+config LNE390
+       tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)"
+       depends on PCI && EISA && EXPERIMENTAL
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called lne390.
+
+config MAC8390
+       bool "Macintosh NS 8390 based ethernet cards"
+       depends on MAC
+       select CRC32
+       ---help---
+         If you want to include a driver to support Nubus or LC-PDS
+         Ethernet cards using an NS8390 chipset or its equivalent, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+config NE2000
+       tristate "NE2000/NE1000 support"
+       depends on (ISA || (Q40 && m) || M32R || MACH_TX49XX)
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.  Many Ethernet cards
+         without a specific driver are compatible with NE2000.
+
+         If you have a PCI NE2000 card however, say N here and Y to "PCI
+         NE2000 and clone support" under "EISA, VLB, PCI and on board
+         controllers" below. If you have a NE2000 card and are running on
+         an MCA system (a bus system used on some IBM PS/2 computers and
+         laptops), say N here and Y to "NE/2 (ne2000 MCA version) support",
+         below.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ne.
+
+config NE2_MCA
+       tristate "NE/2 (ne2000 MCA version) support"
+       depends on MCA_LEGACY
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ne2.
+
+config NE2K_PCI
+       tristate "PCI NE2000 and clones support (see help)"
+       depends on PCI
+       select CRC32
+       ---help---
+         This driver is for NE2000 compatible PCI cards. It will not work
+         with ISA NE2000 cards (they have their own driver, "NE2000/NE1000
+         support" below). If you have a PCI NE2000 network (Ethernet) card,
+         say Y and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         This driver also works for the following NE2000 clone cards:
+         RealTek RTL-8029  Winbond 89C940  Compex RL2000  KTI ET32P2
+         NetVin NV5000SC   Via 86C926      SureCom NE34   Winbond
+         Holtek HT80232    Holtek HT80229
+
+         To compile this driver as a module, choose M here. The module
+         will be called ne2k-pci.
+
+config APNE
+       tristate "PCMCIA NE2000 support"
+       depends on AMIGA_PCMCIA
+       select CRC32
+       ---help---
+         If you have a PCMCIA NE2000 compatible adapter, say Y.  Otherwise,
+         say N.
+
+         To compile this driver as a module, choose M here: the module
+         will be called apne.
+
+config NE3210
+       tristate "Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)"
+       depends on PCI && EISA && EXPERIMENTAL
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.  Note that this driver
+         will NOT WORK for NE3200 cards as they are completely different.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ne3210.
+
+config PCMCIA_PCNET
+       tristate "NE2000 compatible PCMCIA support"
+       depends on PCMCIA
+       select CRC32
+       ---help---
+         Say Y here if you intend to attach an NE2000 compatible PCMCIA
+         (PC-card) Ethernet or Fast Ethernet card to your computer.
+
+         To compile this driver as a module, choose M here: the module will be
+         called pcnet_cs.  If unsure, say N.
+
+config NE_H8300
+       tristate "NE2000 compatible support for H8/300"
+       depends on H8300
+       ---help---
+         Say Y here if you want to use the NE2000 compatible
+         controller on the Renesas H8/300 processor.
+
+config STNIC
+       tristate "National DP83902AV  support"
+       depends on SUPERH
+       select CRC32
+       ---help---
+         Support for cards based on the National Semiconductor DP83902AV
+         ST-NIC Serial Network Interface Controller for Twisted Pair.  This
+         is a 10Mbit/sec Ethernet controller.  Product overview and specs at
+         <http://www.national.com/pf/DP/DP83902A.html>.
+
+         If unsure, say N.
+
+config NET_VENDOR_SMC
+       bool "Western Digital/SMC cards"
+       depends on (ISA || MCA || EISA || MAC)
+       ---help---
+         If you have a network (Ethernet) card belonging to this class, say Y
+         and read the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Note that the answer to this question doesn't directly affect the
+         kernel: saying N will just cause the configurator to skip all
+         the questions about Western Digital cards. If you say Y, you will be
+         asked for your specific card in the following questions.
+
+config ULTRAMCA
+       tristate "SMC Ultra MCA support"
+       depends on NET_VENDOR_SMC && MCA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type and are running
+         an MCA based system (PS/2), say Y and read the Ethernet-HOWTO,
+         available from <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called smc-mca.
+
+config ULTRA
+       tristate "SMC Ultra support"
+       depends on NET_VENDOR_SMC && ISA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         Important: There have been many reports that, with some motherboards
+         mixing an SMC Ultra and an Adaptec AHA154x SCSI card (or compatible,
+         such as some BusLogic models) causes corruption problems with many
+         operating systems. The Linux smc-ultra driver has a work-around for
+         this but keep it in mind if you have such a SCSI card and have
+         problems.
+
+         To compile this driver as a module, choose M here. The module
+         will be called smc-ultra.
+
+config ULTRA32
+       tristate "SMC Ultra32 EISA support"
+       depends on NET_VENDOR_SMC && EISA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called smc-ultra32.
+
+config WD80x3
+       tristate "WD80*3 support"
+       depends on NET_VENDOR_SMC && ISA
+       select CRC32
+       ---help---
+         If you have a network (Ethernet) card of this type, say Y and read
+         the Ethernet-HOWTO, available from
+         <http://www.tldp.org/docs.html#howto>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called wd.
+
+config ZORRO8390
+       tristate "Zorro NS8390-based Ethernet support"
+       depends on ZORRO
+       select CRC32
+       ---help---
+         This driver is for Zorro Ethernet cards using an NS8390-compatible
+         chipset, like the Village Tronic Ariadne II and the Individual
+         Computers X-Surf Ethernet cards. If you have such a card, say Y.
+         Otherwise, say N.
+
+         To compile this driver as a module, choose M here: the module
+         will be called zorro8390.
+
+endif # NET_VENDOR_8390
diff --git a/drivers/net/ethernet/8390/Makefile b/drivers/net/ethernet/8390/Makefile
new file mode 100644 (file)
index 0000000..3337d7f
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# Makefile for the 8390 network device drivers.
+#
+
+obj-$(CONFIG_MAC8390) += mac8390.o
+obj-$(CONFIG_AC3200) += ac3200.o 8390.o
+obj-$(CONFIG_APNE) += apne.o 8390.o
+obj-$(CONFIG_ARM_ETHERH) += etherh.o
+obj-$(CONFIG_AX88796) += ax88796.o
+obj-$(CONFIG_E2100) += e2100.o 8390.o
+obj-$(CONFIG_EL2) += 3c503.o 8390p.o
+obj-$(CONFIG_ES3210) += es3210.o 8390.o
+obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390p.o
+obj-$(CONFIG_HPLAN) += hp.o 8390p.o
+obj-$(CONFIG_HYDRA) += hydra.o 8390.o
+obj-$(CONFIG_LNE390) += lne390.o 8390.o
+obj-$(CONFIG_NE2000) += ne.o 8390p.o
+obj-$(CONFIG_NE2_MCA) += ne2.o 8390p.o
+obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
+obj-$(CONFIG_NE3210) += ne3210.o 8390.o
+obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
+obj-$(CONFIG_PCMCIA_AXNET) += axnet_cs.o 8390.o
+obj-$(CONFIG_PCMCIA_PCNET) += pcnet_cs.o 8390.o
+obj-$(CONFIG_STNIC) += stnic.o 8390.o
+obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o
+obj-$(CONFIG_ULTRA32) += smc-ultra32.o 8390.o
+obj-$(CONFIG_ULTRAMCA) += smc-mca.o 8390.o
+obj-$(CONFIG_WD80x3) += wd.o 8390.o
+obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o
diff --git a/drivers/net/ethernet/8390/ac3200.c b/drivers/net/ethernet/8390/ac3200.c
new file mode 100644 (file)
index 0000000..f07b2e9
--- /dev/null
@@ -0,0 +1,432 @@
+/* ac3200.c: A driver for the Ansel Communications EISA ethernet adaptor. */
+/*
+       Written 1993, 1994 by Donald Becker.
+       Copyright 1993 United States Government as represented by the Director,
+       National Security Agency.  This software may only be used and distributed
+       according to the terms of the GNU General Public License as modified by SRC,
+       incorporated herein by reference.
+
+       The author may be reached as becker@scyld.com, or C/O
+       Scyld Computing Corporation
+       410 Severn Ave., Suite 210
+       Annapolis MD 21403
+
+       This is driver for the Ansel Communications Model 3200 EISA Ethernet LAN
+       Adapter.  The programming information is from the users manual, as related
+       by glee@ardnassak.math.clemson.edu.
+
+       Changelog:
+
+       Paul Gortmaker 05/98    : add support for shared mem above 1MB.
+
+  */
+
+static const char version[] =
+       "ac3200.c:v1.01 7/1/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include <linux/module.h>
+#include <linux/eisa.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "8390.h"
+
+#define DRV_NAME       "ac3200"
+
+/* Offsets from the base address. */
+#define AC_NIC_BASE    0x00
+#define AC_SA_PROM     0x16                    /* The station address PROM. */
+#define AC_ADDR0       0x00                    /* Prefix station address values. */
+#define AC_ADDR1       0x40
+#define AC_ADDR2       0x90
+#define AC_ID_PORT     0xC80
+#define AC_EISA_ID     0x0110d305
+#define AC_RESET_PORT  0xC84
+#define AC_RESET       0x00
+#define AC_ENABLE      0x01
+#define AC_CONFIG      0xC90   /* The configuration port. */
+
+#define AC_IO_EXTENT 0x20
+                                /* Actually accessed is:
+                                                                * AC_NIC_BASE (0-15)
+                                                                * AC_SA_PROM (0-5)
+                                                                * AC_ID_PORT (0-3)
+                                                                * AC_RESET_PORT
+                                                                * AC_CONFIG
+                                                                */
+
+/* Decoding of the configuration register. */
+static unsigned char config2irqmap[8] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
+static int addrmap[8] =
+{0xFF0000, 0xFE0000, 0xFD0000, 0xFFF0000, 0xFFE0000, 0xFFC0000,  0xD0000, 0 };
+static const char *port_name[4] = { "10baseT", "invalid", "AUI", "10base2"};
+
+#define config2irq(configval)  config2irqmap[((configval) >> 3) & 7]
+#define config2mem(configval)  addrmap[(configval) & 7]
+#define config2name(configval) port_name[((configval) >> 6) & 3]
+
+/* First and last 8390 pages. */
+#define AC_START_PG            0x00    /* First page of 8390 TX buffer */
+#define AC_STOP_PG             0x80    /* Last page +1 of the 8390 RX ring */
+
+static int ac_probe1(int ioaddr, struct net_device *dev);
+
+static int ac_open(struct net_device *dev);
+static void ac_reset_8390(struct net_device *dev);
+static void ac_block_input(struct net_device *dev, int count,
+                                       struct sk_buff *skb, int ring_offset);
+static void ac_block_output(struct net_device *dev, const int count,
+                                                       const unsigned char *buf, const int start_page);
+static void ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                                       int ring_page);
+
+static int ac_close_card(struct net_device *dev);
+
+
+/*     Probe for the AC3200.
+
+       The AC3200 can be identified by either the EISA configuration registers,
+       or the unique value in the station address PROM.
+       */
+
+static int __init do_ac3200_probe(struct net_device *dev)
+{
+       unsigned short ioaddr = dev->base_addr;
+       int irq = dev->irq;
+       int mem_start = dev->mem_start;
+
+       if (ioaddr > 0x1ff)             /* Check a single specified location. */
+               return ac_probe1(ioaddr, dev);
+       else if (ioaddr > 0)            /* Don't probe at all. */
+               return -ENXIO;
+
+       if ( ! EISA_bus)
+               return -ENXIO;
+
+       for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
+               if (ac_probe1(ioaddr, dev) == 0)
+                       return 0;
+               dev->irq = irq;
+               dev->mem_start = mem_start;
+       }
+
+       return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init ac3200_probe(int unit)
+{
+       struct net_device *dev = alloc_ei_netdev();
+       int err;
+
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       sprintf(dev->name, "eth%d", unit);
+       netdev_boot_setup_check(dev);
+
+       err = do_ac3200_probe(dev);
+       if (err)
+               goto out;
+       return dev;
+out:
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops ac_netdev_ops = {
+       .ndo_open               = ac_open,
+       .ndo_stop               = ac_close_card,
+
+       .ndo_start_xmit         = ei_start_xmit,
+       .ndo_tx_timeout         = ei_tx_timeout,
+       .ndo_get_stats          = ei_get_stats,
+       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = ei_poll,
+#endif
+};
+
+static int __init ac_probe1(int ioaddr, struct net_device *dev)
+{
+       int i, retval;
+
+       if (!request_region(ioaddr, AC_IO_EXTENT, DRV_NAME))
+               return -EBUSY;
+
+       if (inb_p(ioaddr + AC_ID_PORT) == 0xff) {
+               retval = -ENODEV;
+               goto out;
+       }
+
+       if (inl(ioaddr + AC_ID_PORT) != AC_EISA_ID) {
+               retval = -ENODEV;
+               goto out;
+       }
+
+#ifndef final_version
+       printk(KERN_DEBUG "AC3200 ethercard configuration register is %#02x,"
+                  " EISA ID %02x %02x %02x %02x.\n", inb(ioaddr + AC_CONFIG),
+                  inb(ioaddr + AC_ID_PORT + 0), inb(ioaddr + AC_ID_PORT + 1),
+                  inb(ioaddr + AC_ID_PORT + 2), inb(ioaddr + AC_ID_PORT + 3));
+#endif
+
+       for (i = 0; i < 6; i++)
+               dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i);
+
+       printk(KERN_DEBUG "AC3200 in EISA slot %d, node %pM",
+              ioaddr/0x1000, dev->dev_addr);
+#if 0
+       /* Check the vendor ID/prefix. Redundant after checking the EISA ID */
+       if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
+               || inb(ioaddr + AC_SA_PROM + 1) != AC_ADDR1
+               || inb(ioaddr + AC_SA_PROM + 2) != AC_ADDR2 ) {
+               printk(", not found (invalid prefix).\n");
+               retval = -ENODEV;
+               goto out;
+       }
+#endif
+
+       /* Assign and allocate the interrupt now. */
+       if (dev->irq == 0) {
+               dev->irq = config2irq(inb(ioaddr + AC_CONFIG));
+               printk(", using");
+       } else {
+               dev->irq = irq_canonicalize(dev->irq);
+               printk(", assigning");
+       }
+
+       retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
+       if (retval) {
+               printk (" nothing! Unable to get IRQ %d.\n", dev->irq);
+               goto out;
+       }
+
+       printk(" IRQ %d, %s port\n", dev->irq, port_name[dev->if_port]);
+
+       dev->base_addr = ioaddr;
+
+#ifdef notyet
+       if (dev->mem_start)     {               /* Override the value from the board. */
+               for (i = 0; i < 7; i++)
+                       if (addrmap[i] == dev->mem_start)
+                               break;
+               if (i >= 7)
+                       i = 0;
+               outb((inb(ioaddr + AC_CONFIG) & ~7) | i, ioaddr + AC_CONFIG);
+       }
+#endif
+
+       dev->if_port = inb(ioaddr + AC_CONFIG) >> 6;
+       dev->mem_start = config2mem(inb(ioaddr + AC_CONFIG));
+
+       printk("%s: AC3200 at %#3x with %dkB memory at physical address %#lx.\n",
+                       dev->name, ioaddr, AC_STOP_PG/4, dev->mem_start);
+
+       /*
+        *  BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
+        *  the card mem within the region covered by `normal' RAM  !!!
+        *
+        *  ioremap() will fail in that case.
+        */
+       ei_status.mem = ioremap(dev->mem_start, AC_STOP_PG*0x100);
+       if (!ei_status.mem) {
+               printk(KERN_ERR "ac3200.c: Unable to remap card memory above 1MB !!\n");
+               printk(KERN_ERR "ac3200.c: Try using EISA SCU to set memory below 1MB.\n");
+               printk(KERN_ERR "ac3200.c: Driver NOT installed.\n");
+               retval = -EINVAL;
+               goto out1;
+       }
+       printk("ac3200.c: remapped %dkB card memory to virtual address %p\n",
+                       AC_STOP_PG/4, ei_status.mem);
+
+       dev->mem_start = (unsigned long)ei_status.mem;
+       dev->mem_end = dev->mem_start + (AC_STOP_PG - AC_START_PG)*256;
+
+       ei_status.name = "AC3200";
+       ei_status.tx_start_page = AC_START_PG;
+       ei_status.rx_start_page = AC_START_PG + TX_PAGES;
+       ei_status.stop_page = AC_STOP_PG;
+       ei_status.word16 = 1;
+
+       if (ei_debug > 0)
+               printk(version);
+
+       ei_status.reset_8390 = &ac_reset_8390;
+       ei_status.block_input = &ac_block_input;
+       ei_status.block_output = &ac_block_output;
+       ei_status.get_8390_hdr = &ac_get_8390_hdr;
+
+       dev->netdev_ops = &ac_netdev_ops;
+       NS8390_init(dev, 0);
+
+       retval = register_netdev(dev);
+       if (retval)
+               goto out2;
+       return 0;
+out2:
+       if (ei_status.reg0)
+               iounmap(ei_status.mem);
+out1:
+       free_irq(dev->irq, dev);
+out:
+       release_region(ioaddr, AC_IO_EXTENT);
+       return retval;
+}
+
+static int ac_open(struct net_device *dev)
+{
+#ifdef notyet
+       /* Someday we may enable the IRQ and shared memory here. */
+       int ioaddr = dev->base_addr;
+#endif
+
+       ei_open(dev);
+       return 0;
+}
+
+static void ac_reset_8390(struct net_device *dev)
+{
+       ushort ioaddr = dev->base_addr;
+
+       outb(AC_RESET, ioaddr + AC_RESET_PORT);
+       if (ei_debug > 1) printk("resetting AC3200, t=%ld...", jiffies);
+
+       ei_status.txing = 0;
+       outb(AC_ENABLE, ioaddr + AC_RESET_PORT);
+       if (ei_debug > 1) printk("reset done\n");
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void
+ac_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+       void __iomem *hdr_start = ei_status.mem + ((ring_page - AC_START_PG)<<8);
+       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+}
+
+/*  Block input and output are easy on shared memory ethercards, the only
+       complication is when the ring buffer wraps. */
+
+static void ac_block_input(struct net_device *dev, int count, struct sk_buff *skb,
+                                                 int ring_offset)
+{
+       void __iomem *start = ei_status.mem + ring_offset - AC_START_PG*256;
+
+       if (ring_offset + count > AC_STOP_PG*256) {
+               /* We must wrap the input move. */
+               int semi_count = AC_STOP_PG*256 - ring_offset;
+               memcpy_fromio(skb->data, start, semi_count);
+               count -= semi_count;
+               memcpy_fromio(skb->data + semi_count,
+                               ei_status.mem + TX_PAGES*256, count);
+       } else {
+               memcpy_fromio(skb->data, start, count);
+       }
+}
+
+static void ac_block_output(struct net_device *dev, int count,
+                                                       const unsigned char *buf, int start_page)
+{
+       void __iomem *shmem = ei_status.mem + ((start_page - AC_START_PG)<<8);
+
+       memcpy_toio(shmem, buf, count);
+}
+
+static int ac_close_card(struct net_device *dev)
+{
+       if (ei_debug > 1)
+               printk("%s: Shutting down ethercard.\n", dev->name);
+
+#ifdef notyet
+       /* We should someday disable shared memory and interrupts. */
+       outb(0x00, ioaddr + 6); /* Disable interrupts. */
+       free_irq(dev->irq, dev);
+#endif
+
+       ei_close(dev);
+       return 0;
+}
+
+#ifdef MODULE
+#define MAX_AC32_CARDS 4       /* Max number of AC32 cards per module */
+static struct net_device *dev_ac32[MAX_AC32_CARDS];
+static int io[MAX_AC32_CARDS];
+static int irq[MAX_AC32_CARDS];
+static int mem[MAX_AC32_CARDS];
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(mem, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_PARM_DESC(mem, "Memory base address(es)");
+MODULE_DESCRIPTION("Ansel AC3200 EISA ethernet driver");
+MODULE_LICENSE("GPL");
+
+static int __init ac3200_module_init(void)
+{
+       struct net_device *dev;
+       int this_dev, found = 0;
+
+       for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
+               if (io[this_dev] == 0 && this_dev != 0)
+                       break;
+               dev = alloc_ei_netdev();
+               if (!dev)
+                       break;
+               dev->irq = irq[this_dev];
+               dev->base_addr = io[this_dev];
+               dev->mem_start = mem[this_dev];         /* Currently ignored by driver */
+               if (do_ac3200_probe(dev) == 0) {
+                       dev_ac32[found++] = dev;
+                       continue;
+               }
+               free_netdev(dev);
+               printk(KERN_WARNING "ac3200.c: No ac3200 card found (i/o = 0x%x).\n", io[this_dev]);
+               break;
+       }
+       if (found)
+               return 0;
+       return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+       /* Someday free_irq may be in ac_close_card() */
+       free_irq(dev->irq, dev);
+       release_region(dev->base_addr, AC_IO_EXTENT);
+       iounmap(ei_status.mem);
+}
+
+static void __exit ac3200_module_exit(void)
+{
+       int this_dev;
+
+       for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) {
+               struct net_device *dev = dev_ac32[this_dev];
+               if (dev) {
+                       unregister_netdev(dev);
+                       cleanup_card(dev);
+                       free_netdev(dev);
+               }
+       }
+}
+module_init(ac3200_module_init);
+module_exit(ac3200_module_exit);
+#endif /* MODULE */
diff --git a/drivers/net/ethernet/8390/apne.c b/drivers/net/ethernet/8390/apne.c
new file mode 100644 (file)
index 0000000..5477373
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+ * Amiga Linux/68k 8390 based PCMCIA Ethernet Driver for the Amiga 1200
+ *
+ * (C) Copyright 1997 Alain Malek
+ *                    (Alain.Malek@cryogen.com)
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is based on
+ *
+ * ne.c:       A general non-shared-memory NS8390 ethernet driver for linux
+ *             Written 1992-94 by Donald Becker.
+ *
+ * 8390.c:     A general NS8390 ethernet driver core for linux.
+ *             Written 1992-94 by Donald Becker.
+ *
+ * cnetdevice: A Sana-II ethernet driver for AmigaOS
+ *             Written by Bruce Abbott (bhabbott@inhb.co.nz)
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of the Linux
+ * distribution for more details.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/setup.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+#include <asm/amigayle.h>
+#include <asm/amipcmcia.h>
+
+#include "8390.h"
+
+/* ---- No user-serviceable parts below ---- */
+
+#define DRV_NAME "apne"
+
+#define NE_BASE         (dev->base_addr)
+#define NE_CMD                 0x00
+#define NE_DATAPORT            0x10            /* NatSemi-defined port window offset. */
+#define NE_RESET               0x1f            /* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT           0x20
+
+#define NE_EN0_ISR             0x07
+#define NE_EN0_DCFG            0x0e
+
+#define NE_EN0_RSARLO          0x08
+#define NE_EN0_RSARHI          0x09
+#define NE_EN0_RCNTLO          0x0a
+#define NE_EN0_RXCR            0x0c
+#define NE_EN0_TXCR            0x0d
+#define NE_EN0_RCNTHI          0x0b
+#define NE_EN0_IMR             0x0f
+
+#define NE1SM_START_PG 0x20    /* First page of TX buffer */
+#define NE1SM_STOP_PG  0x40    /* Last page +1 of RX ring */
+#define NESM_START_PG  0x40    /* First page of TX buffer */
+#define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
+
+
+struct net_device * __init apne_probe(int unit);
+static int apne_probe1(struct net_device *dev, int ioaddr);
+
+static void apne_reset_8390(struct net_device *dev);
+static void apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                         int ring_page);
+static void apne_block_input(struct net_device *dev, int count,
+                                                               struct sk_buff *skb, int ring_offset);
+static void apne_block_output(struct net_device *dev, const int count,
+                                                       const unsigned char *buf, const int start_page);
+static irqreturn_t apne_interrupt(int irq, void *dev_id);
+
+static int init_pcmcia(void);
+
+/* IO base address used for nic */
+
+#define IOBASE 0x300
+
+/*
+   use MANUAL_CONFIG and MANUAL_OFFSET for enabling IO by hand
+   you can find the values to use by looking at the cnet.device
+   config file example (the default values are for the CNET40BC card)
+*/
+
+/*
+#define MANUAL_CONFIG 0x20
+#define MANUAL_OFFSET 0x3f8
+
+#define MANUAL_HWADDR0 0x00
+#define MANUAL_HWADDR1 0x12
+#define MANUAL_HWADDR2 0x34
+#define MANUAL_HWADDR3 0x56
+#define MANUAL_HWADDR4 0x78
+#define MANUAL_HWADDR5 0x9a
+*/
+
+static const char version[] =
+    "apne.c:v1.1 7/10/98 Alain Malek (Alain.Malek@cryogen.ch)\n";
+
+static int apne_owned; /* signal if card already owned */
+
+struct net_device * __init apne_probe(int unit)
+{
+       struct net_device *dev;
+#ifndef MANUAL_CONFIG
+       char tuple[8];
+#endif
+       int err;
+
+       if (!MACH_IS_AMIGA)
+               return ERR_PTR(-ENODEV);
+
+       if (apne_owned)
+               return ERR_PTR(-ENODEV);
+
+       if ( !(AMIGAHW_PRESENT(PCMCIA)) )
+               return ERR_PTR(-ENODEV);
+
+       printk("Looking for PCMCIA ethernet card : ");
+
+       /* check if a card is inserted */
+       if (!(PCMCIA_INSERTED)) {
+               printk("NO PCMCIA card inserted\n");
+               return ERR_PTR(-ENODEV);
+       }
+
+       dev = alloc_ei_netdev();
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+       if (unit >= 0) {
+               sprintf(dev->name, "eth%d", unit);
+               netdev_boot_setup_check(dev);
+       }
+
+       /* disable pcmcia irq for readtuple */
+       pcmcia_disable_irq();
+
+#ifndef MANUAL_CONFIG
+       if ((pcmcia_copy_tuple(CISTPL_FUNCID, tuple, 8) < 3) ||
+               (tuple[2] != CISTPL_FUNCID_NETWORK)) {
+               printk("not an ethernet card\n");
+               /* XXX: shouldn't we re-enable irq here? */
+               free_netdev(dev);
+               return ERR_PTR(-ENODEV);
+       }
+#endif
+
+       printk("ethernet PCMCIA card inserted\n");
+
+       if (!init_pcmcia()) {
+               /* XXX: shouldn't we re-enable irq here? */
+               free_netdev(dev);
+               return ERR_PTR(-ENODEV);
+       }
+
+       if (!request_region(IOBASE, 0x20, DRV_NAME)) {
+               free_netdev(dev);
+               return ERR_PTR(-EBUSY);
+       }
+
+       err = apne_probe1(dev, IOBASE);
+       if (err) {
+               release_region(IOBASE, 0x20);
+               free_netdev(dev);
+               return ERR_PTR(err);
+       }
+       err = register_netdev(dev);
+       if (!err)
+               return dev;
+
+       pcmcia_disable_irq();
+       free_irq(IRQ_AMIGA_PORTS, dev);
+       pcmcia_reset();
+       release_region(IOBASE, 0x20);
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+
+static int __init apne_probe1(struct net_device *dev, int ioaddr)
+{
+    int i;
+    unsigned char SA_prom[32];
+    int wordlength = 2;
+    const char *name = NULL;
+    int start_page, stop_page;
+#ifndef MANUAL_HWADDR0
+    int neX000, ctron;
+#endif
+    static unsigned version_printed;
+
+    if (ei_debug  &&  version_printed++ == 0)
+       printk(version);
+
+    printk("PCMCIA NE*000 ethercard probe");
+
+    /* Reset card. Who knows what dain-bramaged state it was left in. */
+    {  unsigned long reset_start_time = jiffies;
+
+       outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+
+       while ((inb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
+               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
+                       printk(" not found (no reset ack).\n");
+                       return -ENODEV;
+               }
+
+       outb(0xff, ioaddr + NE_EN0_ISR);                /* Ack all intr. */
+    }
+
+#ifndef MANUAL_HWADDR0
+
+    /* Read the 16 bytes of station address PROM.
+       We must first initialize registers, similar to NS8390_init(eifdev, 0).
+       We can't reliably read the SAPROM address without this.
+       (I learned the hard way!). */
+    {
+       struct {unsigned long value, offset; } program_seq[] = {
+           {E8390_NODMA+E8390_PAGE0+E8390_STOP, NE_CMD}, /* Select page 0*/
+           {0x48,      NE_EN0_DCFG},   /* Set byte-wide (0x48) access. */
+           {0x00,      NE_EN0_RCNTLO}, /* Clear the count regs. */
+           {0x00,      NE_EN0_RCNTHI},
+           {0x00,      NE_EN0_IMR},    /* Mask completion irq. */
+           {0xFF,      NE_EN0_ISR},
+           {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20  Set to monitor */
+           {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02  and loopback mode. */
+           {32,        NE_EN0_RCNTLO},
+           {0x00,      NE_EN0_RCNTHI},
+           {0x00,      NE_EN0_RSARLO}, /* DMA starting at 0x0000. */
+           {0x00,      NE_EN0_RSARHI},
+           {E8390_RREAD+E8390_START, NE_CMD},
+       };
+       for (i = 0; i < ARRAY_SIZE(program_seq); i++) {
+           outb(program_seq[i].value, ioaddr + program_seq[i].offset);
+       }
+
+    }
+    for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
+       SA_prom[i] = inb(ioaddr + NE_DATAPORT);
+       SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
+       if (SA_prom[i] != SA_prom[i+1])
+           wordlength = 1;
+    }
+
+    /* At this point, wordlength *only* tells us if the SA_prom is doubled
+       up or not because some broken PCI cards don't respect the byte-wide
+       request in program_seq above, and hence don't have doubled up values.
+       These broken cards would otherwise be detected as an ne1000.  */
+
+    if (wordlength == 2)
+       for (i = 0; i < 16; i++)
+               SA_prom[i] = SA_prom[i+i];
+
+    if (wordlength == 2) {
+       /* We must set the 8390 for word mode. */
+       outb(0x49, ioaddr + NE_EN0_DCFG);
+       start_page = NESM_START_PG;
+       stop_page = NESM_STOP_PG;
+    } else {
+       start_page = NE1SM_START_PG;
+       stop_page = NE1SM_STOP_PG;
+    }
+
+    neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
+    ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
+
+    /* Set up the rest of the parameters. */
+    if (neX000) {
+       name = (wordlength == 2) ? "NE2000" : "NE1000";
+    } else if (ctron) {
+       name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
+       start_page = 0x01;
+       stop_page = (wordlength == 2) ? 0x40 : 0x20;
+    } else {
+       printk(" not found.\n");
+       return -ENXIO;
+
+    }
+
+#else
+    wordlength = 2;
+    /* We must set the 8390 for word mode. */
+    outb(0x49, ioaddr + NE_EN0_DCFG);
+    start_page = NESM_START_PG;
+    stop_page = NESM_STOP_PG;
+
+    SA_prom[0] = MANUAL_HWADDR0;
+    SA_prom[1] = MANUAL_HWADDR1;
+    SA_prom[2] = MANUAL_HWADDR2;
+    SA_prom[3] = MANUAL_HWADDR3;
+    SA_prom[4] = MANUAL_HWADDR4;
+    SA_prom[5] = MANUAL_HWADDR5;
+    name = "NE2000";
+#endif
+
+    dev->base_addr = ioaddr;
+    dev->irq = IRQ_AMIGA_PORTS;
+    dev->netdev_ops = &ei_netdev_ops;
+
+    /* Install the Interrupt handler */
+    i = request_irq(dev->irq, apne_interrupt, IRQF_SHARED, DRV_NAME, dev);
+    if (i) return i;
+
+    for(i = 0; i < ETHER_ADDR_LEN; i++)
+       dev->dev_addr[i] = SA_prom[i];
+
+    printk(" %pM\n", dev->dev_addr);
+
+    printk("%s: %s found.\n", dev->name, name);
+
+    ei_status.name = name;
+    ei_status.tx_start_page = start_page;
+    ei_status.stop_page = stop_page;
+    ei_status.word16 = (wordlength == 2);
+
+    ei_status.rx_start_page = start_page + TX_PAGES;
+
+    ei_status.reset_8390 = &apne_reset_8390;
+    ei_status.block_input = &apne_block_input;
+    ei_status.block_output = &apne_block_output;
+    ei_status.get_8390_hdr = &apne_get_8390_hdr;
+
+    NS8390_init(dev, 0);
+
+    pcmcia_ack_int(pcmcia_get_intreq());               /* ack PCMCIA int req */
+    pcmcia_enable_irq();
+
+    apne_owned = 1;
+
+    return 0;
+}
+
+/* Hard reset the card.  This used to pause for the same period that a
+   8390 reset command required, but that shouldn't be necessary. */
+static void
+apne_reset_8390(struct net_device *dev)
+{
+    unsigned long reset_start_time = jiffies;
+
+    init_pcmcia();
+
+    if (ei_debug > 1) printk("resetting the 8390 t=%ld...", jiffies);
+
+    outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+    ei_status.txing = 0;
+    ei_status.dmaing = 0;
+
+    /* This check _should_not_ be necessary, omit eventually. */
+    while ((inb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
+       if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
+           printk("%s: ne_reset_8390() did not complete.\n", dev->name);
+           break;
+       }
+    outb(ENISR_RESET, NE_BASE + NE_EN0_ISR);   /* Ack intr. */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void
+apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+
+    int nic_base = dev->base_addr;
+    int cnt;
+    char *ptrc;
+    short *ptrs;
+
+    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+    if (ei_status.dmaing) {
+       printk("%s: DMAing conflict in ne_get_8390_hdr "
+          "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+          dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
+       return;
+    }
+
+    ei_status.dmaing |= 0x01;
+    outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+    outb(ENISR_RDC, nic_base + NE_EN0_ISR);
+    outb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
+    outb(0, nic_base + NE_EN0_RCNTHI);
+    outb(0, nic_base + NE_EN0_RSARLO);         /* On page boundary */
+    outb(ring_page, nic_base + NE_EN0_RSARHI);
+    outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+    if (ei_status.word16) {
+        ptrs = (short*)hdr;
+        for(cnt = 0; cnt < (sizeof(struct e8390_pkt_hdr)>>1); cnt++)
+            *ptrs++ = inw(NE_BASE + NE_DATAPORT);
+    } else {
+        ptrc = (char*)hdr;
+        for(cnt = 0; cnt < sizeof(struct e8390_pkt_hdr); cnt++)
+            *ptrc++ = inb(NE_BASE + NE_DATAPORT);
+    }
+
+    outb(ENISR_RDC, nic_base + NE_EN0_ISR);    /* Ack intr. */
+    ei_status.dmaing &= ~0x01;
+
+    le16_to_cpus(&hdr->count);
+}
+
+/* Block input and output, similar to the Crynwr packet driver.  If you
+   are porting to a new ethercard, look at the packet driver source for hints.
+   The NEx000 doesn't share the on-board packet memory -- you have to put
+   the packet out through the "remote DMA" dataport using outb. */
+
+static void
+apne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+    int nic_base = dev->base_addr;
+    char *buf = skb->data;
+    char *ptrc;
+    short *ptrs;
+    int cnt;
+
+    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+    if (ei_status.dmaing) {
+       printk("%s: DMAing conflict in ne_block_input "
+          "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+          dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
+       return;
+    }
+    ei_status.dmaing |= 0x01;
+    outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+    outb(ENISR_RDC, nic_base + NE_EN0_ISR);
+    outb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+    outb(count >> 8, nic_base + NE_EN0_RCNTHI);
+    outb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
+    outb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
+    outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+    if (ei_status.word16) {
+      ptrs = (short*)buf;
+      for (cnt = 0; cnt < (count>>1); cnt++)
+        *ptrs++ = inw(NE_BASE + NE_DATAPORT);
+      if (count & 0x01) {
+       buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+      }
+    } else {
+      ptrc = (char*)buf;
+      for (cnt = 0; cnt < count; cnt++)
+        *ptrc++ = inb(NE_BASE + NE_DATAPORT);
+    }
+
+    outb(ENISR_RDC, nic_base + NE_EN0_ISR);    /* Ack intr. */
+    ei_status.dmaing &= ~0x01;
+}
+
+static void
+apne_block_output(struct net_device *dev, int count,
+               const unsigned char *buf, const int start_page)
+{
+    int nic_base = NE_BASE;
+    unsigned long dma_start;
+    char *ptrc;
+    short *ptrs;
+    int cnt;
+
+    /* Round the count up for word writes.  Do we need to do this?
+       What effect will an odd byte count have on the 8390?
+       I should check someday. */
+    if (ei_status.word16 && (count & 0x01))
+      count++;
+
+    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+    if (ei_status.dmaing) {
+       printk("%s: DMAing conflict in ne_block_output."
+          "[DMAstat:%d][irqlock:%d][intr:%d]\n",
+          dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq);
+       return;
+    }
+    ei_status.dmaing |= 0x01;
+    /* We should already be in page 0, but to be safe... */
+    outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+    outb(ENISR_RDC, nic_base + NE_EN0_ISR);
+
+   /* Now the normal output. */
+    outb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+    outb(count >> 8,   nic_base + NE_EN0_RCNTHI);
+    outb(0x00, nic_base + NE_EN0_RSARLO);
+    outb(start_page, nic_base + NE_EN0_RSARHI);
+
+    outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+    if (ei_status.word16) {
+        ptrs = (short*)buf;
+        for (cnt = 0; cnt < count>>1; cnt++)
+            outw(*ptrs++, NE_BASE+NE_DATAPORT);
+    } else {
+        ptrc = (char*)buf;
+        for (cnt = 0; cnt < count; cnt++)
+           outb(*ptrc++, NE_BASE + NE_DATAPORT);
+    }
+
+    dma_start = jiffies;
+
+    while ((inb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
+       if (time_after(jiffies, dma_start + 2*HZ/100)) {        /* 20ms */
+               printk("%s: timeout waiting for Tx RDC.\n", dev->name);
+               apne_reset_8390(dev);
+               NS8390_init(dev,1);
+               break;
+       }
+
+    outb(ENISR_RDC, nic_base + NE_EN0_ISR);    /* Ack intr. */
+    ei_status.dmaing &= ~0x01;
+}
+
+static irqreturn_t apne_interrupt(int irq, void *dev_id)
+{
+    unsigned char pcmcia_intreq;
+
+    if (!(gayle.inten & GAYLE_IRQ_IRQ))
+        return IRQ_NONE;
+
+    pcmcia_intreq = pcmcia_get_intreq();
+
+    if (!(pcmcia_intreq & GAYLE_IRQ_IRQ)) {
+        pcmcia_ack_int(pcmcia_intreq);
+        return IRQ_NONE;
+    }
+    if (ei_debug > 3)
+        printk("pcmcia intreq = %x\n", pcmcia_intreq);
+    pcmcia_disable_irq();                      /* to get rid of the sti() within ei_interrupt */
+    ei_interrupt(irq, dev_id);
+    pcmcia_ack_int(pcmcia_get_intreq());
+    pcmcia_enable_irq();
+    return IRQ_HANDLED;
+}
+
+#ifdef MODULE
+static struct net_device *apne_dev;
+
+static int __init apne_module_init(void)
+{
+       apne_dev = apne_probe(-1);
+       if (IS_ERR(apne_dev))
+               return PTR_ERR(apne_dev);
+       return 0;
+}
+
+static void __exit apne_module_exit(void)
+{
+       unregister_netdev(apne_dev);
+
+       pcmcia_disable_irq();
+
+       free_irq(IRQ_AMIGA_PORTS, apne_dev);
+
+       pcmcia_reset();
+
+       release_region(IOBASE, 0x20);
+
+       free_netdev(apne_dev);
+}
+module_init(apne_module_init);
+module_exit(apne_module_exit);
+#endif
+
+static int init_pcmcia(void)
+{
+       u_char config;
+#ifndef MANUAL_CONFIG
+       u_char tuple[32];
+       int offset_len;
+#endif
+       u_long offset;
+
+       pcmcia_reset();
+       pcmcia_program_voltage(PCMCIA_0V);
+       pcmcia_access_speed(PCMCIA_SPEED_250NS);
+       pcmcia_write_enable();
+
+#ifdef MANUAL_CONFIG
+       config = MANUAL_CONFIG;
+#else
+       /* get and write config byte to enable IO port */
+
+       if (pcmcia_copy_tuple(CISTPL_CFTABLE_ENTRY, tuple, 32) < 3)
+               return 0;
+
+       config = tuple[2] & 0x3f;
+#endif
+#ifdef MANUAL_OFFSET
+       offset = MANUAL_OFFSET;
+#else
+       if (pcmcia_copy_tuple(CISTPL_CONFIG, tuple, 32) < 6)
+               return 0;
+
+       offset_len = (tuple[2] & 0x3) + 1;
+       offset = 0;
+       while(offset_len--) {
+               offset = (offset << 8) | tuple[4+offset_len];
+       }
+#endif
+
+       out_8(GAYLE_ATTRIBUTE+offset, config);
+
+       return 1;
+}
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/8390/ax88796.c b/drivers/net/ethernet/8390/ax88796.c
new file mode 100644 (file)
index 0000000..e7cb8c8
--- /dev/null
@@ -0,0 +1,1010 @@
+/* drivers/net/ax88796.c
+ *
+ * Copyright 2005,2007 Simtec Electronics
+ *     Ben Dooks <ben@simtec.co.uk>
+ *
+ * Asix AX88796 10/100 Ethernet controller support
+ *     Based on ne.c, by Donald Becker, et-al.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/isapnp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mdio-bitbang.h>
+#include <linux/phy.h>
+#include <linux/eeprom_93cx6.h>
+#include <linux/slab.h>
+
+#include <net/ax88796.h>
+
+#include <asm/system.h>
+
+/* Rename the lib8390.c functions to show that they are in this driver */
+#define __ei_open ax_ei_open
+#define __ei_close ax_ei_close
+#define __ei_poll ax_ei_poll
+#define __ei_start_xmit ax_ei_start_xmit
+#define __ei_tx_timeout ax_ei_tx_timeout
+#define __ei_get_stats ax_ei_get_stats
+#define __ei_set_multicast_list ax_ei_set_multicast_list
+#define __ei_interrupt ax_ei_interrupt
+#define ____alloc_ei_netdev ax__alloc_ei_netdev
+#define __NS8390_init ax_NS8390_init
+
+/* force unsigned long back to 'void __iomem *' */
+#define ax_convert_addr(_a) ((void __force __iomem *)(_a))
+
+#define ei_inb(_a) readb(ax_convert_addr(_a))
+#define ei_outb(_v, _a) writeb(_v, ax_convert_addr(_a))
+
+#define ei_inb_p(_a) ei_inb(_a)
+#define ei_outb_p(_v, _a) ei_outb(_v, _a)
+
+/* define EI_SHIFT() to take into account our register offsets */
+#define EI_SHIFT(x) (ei_local->reg_offset[(x)])
+
+/* Ensure we have our RCR base value */
+#define AX88796_PLATFORM
+
+static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electronics\n";
+
+#include "lib8390.c"
+
+#define DRV_NAME "ax88796"
+#define DRV_VERSION "1.00"
+
+/* from ne.c */
+#define NE_CMD         EI_SHIFT(0x00)
+#define NE_RESET       EI_SHIFT(0x1f)
+#define NE_DATAPORT    EI_SHIFT(0x10)
+
+#define NE1SM_START_PG 0x20    /* First page of TX buffer */
+#define NE1SM_STOP_PG  0x40    /* Last page +1 of RX ring */
+#define NESM_START_PG  0x40    /* First page of TX buffer */
+#define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
+
+#define AX_GPOC_PPDSET BIT(6)
+
+/* device private data */
+
+struct ax_device {
+       struct mii_bus *mii_bus;
+       struct mdiobb_ctrl bb_ctrl;
+       struct phy_device *phy_dev;
+       void __iomem *addr_memr;
+       u8 reg_memr;
+       int link;
+       int speed;
+       int duplex;
+
+       void __iomem *map2;
+       const struct ax_plat_data *plat;
+
+       unsigned char running;
+       unsigned char resume_open;
+       unsigned int irqflags;
+
+       u32 reg_offsets[0x20];
+};
+
+static inline struct ax_device *to_ax_dev(struct net_device *dev)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       return (struct ax_device *)(ei_local + 1);
+}
+
+/*
+ * ax_initial_check
+ *
+ * do an initial probe for the card to check wether it exists
+ * and is functional
+ */
+static int ax_initial_check(struct net_device *dev)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       void __iomem *ioaddr = ei_local->mem;
+       int reg0;
+       int regd;
+
+       reg0 = ei_inb(ioaddr);
+       if (reg0 == 0xFF)
+               return -ENODEV;
+
+       ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP, ioaddr + E8390_CMD);
+       regd = ei_inb(ioaddr + 0x0d);
+       ei_outb(0xff, ioaddr + 0x0d);
+       ei_outb(E8390_NODMA + E8390_PAGE0, ioaddr + E8390_CMD);
+       ei_inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
+       if (ei_inb(ioaddr + EN0_COUNTER0) != 0) {
+               ei_outb(reg0, ioaddr);
+               ei_outb(regd, ioaddr + 0x0d);   /* Restore the old values. */
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+/*
+ * Hard reset the card. This used to pause for the same period that a
+ * 8390 reset command required, but that shouldn't be necessary.
+ */
+static void ax_reset_8390(struct net_device *dev)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       unsigned long reset_start_time = jiffies;
+       void __iomem *addr = (void __iomem *)dev->base_addr;
+
+       if (ei_debug > 1)
+               netdev_dbg(dev, "resetting the 8390 t=%ld\n", jiffies);
+
+       ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
+
+       ei_local->txing = 0;
+       ei_local->dmaing = 0;
+
+       /* This check _should_not_ be necessary, omit eventually. */
+       while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) {
+               if (jiffies - reset_start_time > 2 * HZ / 100) {
+                       netdev_warn(dev, "%s: did not complete.\n", __func__);
+                       break;
+               }
+       }
+
+       ei_outb(ENISR_RESET, addr + EN0_ISR);   /* Ack intr. */
+}
+
+
+static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                           int ring_page)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       void __iomem *nic_base = ei_local->mem;
+
+       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+       if (ei_local->dmaing) {
+               netdev_err(dev, "DMAing conflict in %s "
+                       "[DMAstat:%d][irqlock:%d].\n",
+                       __func__,
+                       ei_local->dmaing, ei_local->irqlock);
+               return;
+       }
+
+       ei_local->dmaing |= 0x01;
+       ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
+       ei_outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+       ei_outb(0, nic_base + EN0_RCNTHI);
+       ei_outb(0, nic_base + EN0_RSARLO);              /* On page boundary */
+       ei_outb(ring_page, nic_base + EN0_RSARHI);
+       ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+       if (ei_local->word16)
+               readsw(nic_base + NE_DATAPORT, hdr,
+                      sizeof(struct e8390_pkt_hdr) >> 1);
+       else
+               readsb(nic_base + NE_DATAPORT, hdr,
+                      sizeof(struct e8390_pkt_hdr));
+
+       ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
+       ei_local->dmaing &= ~0x01;
+
+       le16_to_cpus(&hdr->count);
+}
+
+
+/*
+ * Block input and output, similar to the Crynwr packet driver. If
+ * you are porting to a new ethercard, look at the packet driver
+ * source for hints. The NEx000 doesn't share the on-board packet
+ * memory -- you have to put the packet out through the "remote DMA"
+ * dataport using ei_outb.
+ */
+static void ax_block_input(struct net_device *dev, int count,
+                          struct sk_buff *skb, int ring_offset)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       void __iomem *nic_base = ei_local->mem;
+       char *buf = skb->data;
+
+       if (ei_local->dmaing) {
+               netdev_err(dev,
+                       "DMAing conflict in %s "
+                       "[DMAstat:%d][irqlock:%d].\n",
+                       __func__,
+                       ei_local->dmaing, ei_local->irqlock);
+               return;
+       }
+
+       ei_local->dmaing |= 0x01;
+
+       ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + NE_CMD);
+       ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
+       ei_outb(count >> 8, nic_base + EN0_RCNTHI);
+       ei_outb(ring_offset & 0xff, nic_base + EN0_RSARLO);
+       ei_outb(ring_offset >> 8, nic_base + EN0_RSARHI);
+       ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+       if (ei_local->word16) {
+               readsw(nic_base + NE_DATAPORT, buf, count >> 1);
+               if (count & 0x01)
+                       buf[count-1] = ei_inb(nic_base + NE_DATAPORT);
+
+       } else {
+               readsb(nic_base + NE_DATAPORT, buf, count);
+       }
+
+       ei_local->dmaing &= ~1;
+}
+
+static void ax_block_output(struct net_device *dev, int count,
+                           const unsigned char *buf, const int start_page)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       void __iomem *nic_base = ei_local->mem;
+       unsigned long dma_start;
+
+       /*
+        * Round the count up for word writes. Do we need to do this?
+        * What effect will an odd byte count have on the 8390?  I
+        * should check someday.
+        */
+       if (ei_local->word16 && (count & 0x01))
+               count++;
+
+       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+       if (ei_local->dmaing) {
+               netdev_err(dev, "DMAing conflict in %s."
+                       "[DMAstat:%d][irqlock:%d]\n",
+                       __func__,
+                      ei_local->dmaing, ei_local->irqlock);
+               return;
+       }
+
+       ei_local->dmaing |= 0x01;
+       /* We should already be in page 0, but to be safe... */
+       ei_outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+       ei_outb(ENISR_RDC, nic_base + EN0_ISR);
+
+       /* Now the normal output. */
+       ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
+       ei_outb(count >> 8, nic_base + EN0_RCNTHI);
+       ei_outb(0x00, nic_base + EN0_RSARLO);
+       ei_outb(start_page, nic_base + EN0_RSARHI);
+
+       ei_outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+       if (ei_local->word16)
+               writesw(nic_base + NE_DATAPORT, buf, count >> 1);
+       else
+               writesb(nic_base + NE_DATAPORT, buf, count);
+
+       dma_start = jiffies;
+
+       while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) {
+               if (jiffies - dma_start > 2 * HZ / 100) {               /* 20ms */
+                       netdev_warn(dev, "timeout waiting for Tx RDC.\n");
+                       ax_reset_8390(dev);
+                       ax_NS8390_init(dev, 1);
+                       break;
+               }
+       }
+
+       ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
+       ei_local->dmaing &= ~0x01;
+}
+
+/* definitions for accessing MII/EEPROM interface */
+
+#define AX_MEMR                        EI_SHIFT(0x14)
+#define AX_MEMR_MDC            BIT(0)
+#define AX_MEMR_MDIR           BIT(1)
+#define AX_MEMR_MDI            BIT(2)
+#define AX_MEMR_MDO            BIT(3)
+#define AX_MEMR_EECS           BIT(4)
+#define AX_MEMR_EEI            BIT(5)
+#define AX_MEMR_EEO            BIT(6)
+#define AX_MEMR_EECLK          BIT(7)
+
+static void ax_handle_link_change(struct net_device *dev)
+{
+       struct ax_device  *ax = to_ax_dev(dev);
+       struct phy_device *phy_dev = ax->phy_dev;
+       int status_change = 0;
+
+       if (phy_dev->link && ((ax->speed != phy_dev->speed) ||
+                            (ax->duplex != phy_dev->duplex))) {
+
+               ax->speed = phy_dev->speed;
+               ax->duplex = phy_dev->duplex;
+               status_change = 1;
+       }
+
+       if (phy_dev->link != ax->link) {
+               if (!phy_dev->link) {
+                       ax->speed = 0;
+                       ax->duplex = -1;
+               }
+               ax->link = phy_dev->link;
+
+               status_change = 1;
+       }
+
+       if (status_change)
+               phy_print_status(phy_dev);
+}
+
+static int ax_mii_probe(struct net_device *dev)
+{
+       struct ax_device  *ax = to_ax_dev(dev);
+       struct phy_device *phy_dev = NULL;
+       int ret;
+
+       /* find the first phy */
+       phy_dev = phy_find_first(ax->mii_bus);
+       if (!phy_dev) {
+               netdev_err(dev, "no PHY found\n");
+               return -ENODEV;
+       }
+
+       ret = phy_connect_direct(dev, phy_dev, ax_handle_link_change, 0,
+                                PHY_INTERFACE_MODE_MII);
+       if (ret) {
+               netdev_err(dev, "Could not attach to PHY\n");
+               return ret;
+       }
+
+       /* mask with MAC supported features */
+       phy_dev->supported &= PHY_BASIC_FEATURES;
+       phy_dev->advertising = phy_dev->supported;
+
+       ax->phy_dev = phy_dev;
+
+       netdev_info(dev, "PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+                   phy_dev->drv->name, dev_name(&phy_dev->dev), phy_dev->irq);
+
+       return 0;
+}
+
+static void ax_phy_switch(struct net_device *dev, int on)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       struct ax_device *ax = to_ax_dev(dev);
+
+       u8 reg_gpoc =  ax->plat->gpoc_val;
+
+       if (!!on)
+               reg_gpoc &= ~AX_GPOC_PPDSET;
+       else
+               reg_gpoc |= AX_GPOC_PPDSET;
+
+       ei_outb(reg_gpoc, ei_local->mem + EI_SHIFT(0x17));
+}
+
+static int ax_open(struct net_device *dev)
+{
+       struct ax_device *ax = to_ax_dev(dev);
+       int ret;
+
+       netdev_dbg(dev, "open\n");
+
+       ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags,
+                         dev->name, dev);
+       if (ret)
+               goto failed_request_irq;
+
+       /* turn the phy on (if turned off) */
+       ax_phy_switch(dev, 1);
+
+       ret = ax_mii_probe(dev);
+       if (ret)
+               goto failed_mii_probe;
+       phy_start(ax->phy_dev);
+
+       ret = ax_ei_open(dev);
+       if (ret)
+               goto failed_ax_ei_open;
+
+       ax->running = 1;
+
+       return 0;
+
+ failed_ax_ei_open:
+       phy_disconnect(ax->phy_dev);
+ failed_mii_probe:
+       ax_phy_switch(dev, 0);
+       free_irq(dev->irq, dev);
+ failed_request_irq:
+       return ret;
+}
+
+static int ax_close(struct net_device *dev)
+{
+       struct ax_device *ax = to_ax_dev(dev);
+
+       netdev_dbg(dev, "close\n");
+
+       ax->running = 0;
+       wmb();
+
+       ax_ei_close(dev);
+
+       /* turn the phy off */
+       ax_phy_switch(dev, 0);
+       phy_disconnect(ax->phy_dev);
+
+       free_irq(dev->irq, dev);
+       return 0;
+}
+
+static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+       struct ax_device *ax = to_ax_dev(dev);
+       struct phy_device *phy_dev = ax->phy_dev;
+
+       if (!netif_running(dev))
+               return -EINVAL;
+
+       if (!phy_dev)
+               return -ENODEV;
+
+       return phy_mii_ioctl(phy_dev, req, cmd);
+}
+
+/* ethtool ops */
+
+static void ax_get_drvinfo(struct net_device *dev,
+                          struct ethtool_drvinfo *info)
+{
+       struct platform_device *pdev = to_platform_device(dev->dev.parent);
+
+       strcpy(info->driver, DRV_NAME);
+       strcpy(info->version, DRV_VERSION);
+       strcpy(info->bus_info, pdev->name);
+}
+
+static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct ax_device *ax = to_ax_dev(dev);
+       struct phy_device *phy_dev = ax->phy_dev;
+
+       if (!phy_dev)
+               return -ENODEV;
+
+       return phy_ethtool_gset(phy_dev, cmd);
+}
+
+static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       struct ax_device *ax = to_ax_dev(dev);
+       struct phy_device *phy_dev = ax->phy_dev;
+
+       if (!phy_dev)
+               return -ENODEV;
+
+       return phy_ethtool_sset(phy_dev, cmd);
+}
+
+static const struct ethtool_ops ax_ethtool_ops = {
+       .get_drvinfo            = ax_get_drvinfo,
+       .get_settings           = ax_get_settings,
+       .set_settings           = ax_set_settings,
+       .get_link               = ethtool_op_get_link,
+};
+
+#ifdef CONFIG_AX88796_93CX6
+static void ax_eeprom_register_read(struct eeprom_93cx6 *eeprom)
+{
+       struct ei_device *ei_local = eeprom->data;
+       u8 reg = ei_inb(ei_local->mem + AX_MEMR);
+
+       eeprom->reg_data_in = reg & AX_MEMR_EEI;
+       eeprom->reg_data_out = reg & AX_MEMR_EEO; /* Input pin */
+       eeprom->reg_data_clock = reg & AX_MEMR_EECLK;
+       eeprom->reg_chip_select = reg & AX_MEMR_EECS;
+}
+
+static void ax_eeprom_register_write(struct eeprom_93cx6 *eeprom)
+{
+       struct ei_device *ei_local = eeprom->data;
+       u8 reg = ei_inb(ei_local->mem + AX_MEMR);
+
+       reg &= ~(AX_MEMR_EEI | AX_MEMR_EECLK | AX_MEMR_EECS);
+
+       if (eeprom->reg_data_in)
+               reg |= AX_MEMR_EEI;
+       if (eeprom->reg_data_clock)
+               reg |= AX_MEMR_EECLK;
+       if (eeprom->reg_chip_select)
+               reg |= AX_MEMR_EECS;
+
+       ei_outb(reg, ei_local->mem + AX_MEMR);
+       udelay(10);
+}
+#endif
+
+static const struct net_device_ops ax_netdev_ops = {
+       .ndo_open               = ax_open,
+       .ndo_stop               = ax_close,
+       .ndo_do_ioctl           = ax_ioctl,
+
+       .ndo_start_xmit         = ax_ei_start_xmit,
+       .ndo_tx_timeout         = ax_ei_tx_timeout,
+       .ndo_get_stats          = ax_ei_get_stats,
+       .ndo_set_multicast_list = ax_ei_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = ax_ei_poll,
+#endif
+};
+
+static void ax_bb_mdc(struct mdiobb_ctrl *ctrl, int level)
+{
+       struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
+
+       if (level)
+               ax->reg_memr |= AX_MEMR_MDC;
+       else
+               ax->reg_memr &= ~AX_MEMR_MDC;
+
+       ei_outb(ax->reg_memr, ax->addr_memr);
+}
+
+static void ax_bb_dir(struct mdiobb_ctrl *ctrl, int output)
+{
+       struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
+
+       if (output)
+               ax->reg_memr &= ~AX_MEMR_MDIR;
+       else
+               ax->reg_memr |= AX_MEMR_MDIR;
+
+       ei_outb(ax->reg_memr, ax->addr_memr);
+}
+
+static void ax_bb_set_data(struct mdiobb_ctrl *ctrl, int value)
+{
+       struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
+
+       if (value)
+               ax->reg_memr |= AX_MEMR_MDO;
+       else
+               ax->reg_memr &= ~AX_MEMR_MDO;
+
+       ei_outb(ax->reg_memr, ax->addr_memr);
+}
+
+static int ax_bb_get_data(struct mdiobb_ctrl *ctrl)
+{
+       struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
+       int reg_memr = ei_inb(ax->addr_memr);
+
+       return reg_memr & AX_MEMR_MDI ? 1 : 0;
+}
+
+static struct mdiobb_ops bb_ops = {
+       .owner = THIS_MODULE,
+       .set_mdc = ax_bb_mdc,
+       .set_mdio_dir = ax_bb_dir,
+       .set_mdio_data = ax_bb_set_data,
+       .get_mdio_data = ax_bb_get_data,
+};
+
+/* setup code */
+
+static int ax_mii_init(struct net_device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev->dev.parent);
+       struct ei_device *ei_local = netdev_priv(dev);
+       struct ax_device *ax = to_ax_dev(dev);
+       int err, i;
+
+       ax->bb_ctrl.ops = &bb_ops;
+       ax->addr_memr = ei_local->mem + AX_MEMR;
+       ax->mii_bus = alloc_mdio_bitbang(&ax->bb_ctrl);
+       if (!ax->mii_bus) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       ax->mii_bus->name = "ax88796_mii_bus";
+       ax->mii_bus->parent = dev->dev.parent;
+       snprintf(ax->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+
+       ax->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+       if (!ax->mii_bus->irq) {
+               err = -ENOMEM;
+               goto out_free_mdio_bitbang;
+       }
+
+       for (i = 0; i < PHY_MAX_ADDR; i++)
+               ax->mii_bus->irq[i] = PHY_POLL;
+
+       err = mdiobus_register(ax->mii_bus);
+       if (err)
+               goto out_free_irq;
+
+       return 0;
+
+ out_free_irq:
+       kfree(ax->mii_bus->irq);
+ out_free_mdio_bitbang:
+       free_mdio_bitbang(ax->mii_bus);
+ out:
+       return err;
+}
+
+static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local)
+{
+       void __iomem *ioaddr = ei_local->mem;
+       struct ax_device *ax = to_ax_dev(dev);
+
+       /* Select page 0 */
+       ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_STOP, ioaddr + E8390_CMD);
+
+       /* set to byte access */
+       ei_outb(ax->plat->dcr_val & ~1, ioaddr + EN0_DCFG);
+       ei_outb(ax->plat->gpoc_val, ioaddr + EI_SHIFT(0x17));
+}
+
+/*
+ * ax_init_dev
+ *
+ * initialise the specified device, taking care to note the MAC
+ * address it may already have (if configured), ensure
+ * the device is ready to be used by lib8390.c and registerd with
+ * the network layer.
+ */
+static int ax_init_dev(struct net_device *dev)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       struct ax_device *ax = to_ax_dev(dev);
+       void __iomem *ioaddr = ei_local->mem;
+       unsigned int start_page;
+       unsigned int stop_page;
+       int ret;
+       int i;
+
+       ret = ax_initial_check(dev);
+       if (ret)
+               goto err_out;
+
+       /* setup goes here */
+
+       ax_initial_setup(dev, ei_local);
+
+       /* read the mac from the card prom if we need it */
+
+       if (ax->plat->flags & AXFLG_HAS_EEPROM) {
+               unsigned char SA_prom[32];
+
+               for (i = 0; i < sizeof(SA_prom); i += 2) {
+                       SA_prom[i] = ei_inb(ioaddr + NE_DATAPORT);
+                       SA_prom[i + 1] = ei_inb(ioaddr + NE_DATAPORT);
+               }
+
+               if (ax->plat->wordlength == 2)
+                       for (i = 0; i < 16; i++)
+                               SA_prom[i] = SA_prom[i+i];
+
+               memcpy(dev->dev_addr, SA_prom, 6);
+       }
+
+#ifdef CONFIG_AX88796_93CX6
+       if (ax->plat->flags & AXFLG_HAS_93CX6) {
+               unsigned char mac_addr[6];
+               struct eeprom_93cx6 eeprom;
+
+               eeprom.data = ei_local;
+               eeprom.register_read = ax_eeprom_register_read;
+               eeprom.register_write = ax_eeprom_register_write;
+               eeprom.width = PCI_EEPROM_WIDTH_93C56;
+
+               eeprom_93cx6_multiread(&eeprom, 0,
+                                      (__le16 __force *)mac_addr,
+                                      sizeof(mac_addr) >> 1);
+
+               memcpy(dev->dev_addr, mac_addr, 6);
+       }
+#endif
+       if (ax->plat->wordlength == 2) {
+               /* We must set the 8390 for word mode. */
+               ei_outb(ax->plat->dcr_val, ei_local->mem + EN0_DCFG);
+               start_page = NESM_START_PG;
+               stop_page = NESM_STOP_PG;
+       } else {
+               start_page = NE1SM_START_PG;
+               stop_page = NE1SM_STOP_PG;
+       }
+
+       /* load the mac-address from the device */
+       if (ax->plat->flags & AXFLG_MAC_FROMDEV) {
+               ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
+                       ei_local->mem + E8390_CMD); /* 0x61 */
+               for (i = 0; i < ETHER_ADDR_LEN; i++)
+                       dev->dev_addr[i] =
+                               ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
+       }
+
+       if ((ax->plat->flags & AXFLG_MAC_FROMPLATFORM) &&
+           ax->plat->mac_addr)
+               memcpy(dev->dev_addr, ax->plat->mac_addr,
+                      ETHER_ADDR_LEN);
+
+       ax_reset_8390(dev);
+
+       ei_local->name = "AX88796";
+       ei_local->tx_start_page = start_page;
+       ei_local->stop_page = stop_page;
+       ei_local->word16 = (ax->plat->wordlength == 2);
+       ei_local->rx_start_page = start_page + TX_PAGES;
+
+#ifdef PACKETBUF_MEMSIZE
+       /* Allow the packet buffer size to be overridden by know-it-alls. */
+       ei_local->stop_page = ei_local->tx_start_page + PACKETBUF_MEMSIZE;
+#endif
+
+       ei_local->reset_8390 = &ax_reset_8390;
+       ei_local->block_input = &ax_block_input;
+       ei_local->block_output = &ax_block_output;
+       ei_local->get_8390_hdr = &ax_get_8390_hdr;
+       ei_local->priv = 0;
+
+       dev->netdev_ops = &ax_netdev_ops;
+       dev->ethtool_ops = &ax_ethtool_ops;
+
+       ret = ax_mii_init(dev);
+       if (ret)
+               goto out_irq;
+
+       ax_NS8390_init(dev, 0);
+
+       ret = register_netdev(dev);
+       if (ret)
+               goto out_irq;
+
+       netdev_info(dev, "%dbit, irq %d, %lx, MAC: %pM\n",
+                   ei_local->word16 ? 16 : 8, dev->irq, dev->base_addr,
+                   dev->dev_addr);
+
+       return 0;
+
+ out_irq:
+       /* cleanup irq */
+       free_irq(dev->irq, dev);
+ err_out:
+       return ret;
+}
+
+static int ax_remove(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+       struct ei_device *ei_local = netdev_priv(dev);
+       struct ax_device *ax = to_ax_dev(dev);
+       struct resource *mem;
+
+       unregister_netdev(dev);
+       free_irq(dev->irq, dev);
+
+       iounmap(ei_local->mem);
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(mem->start, resource_size(mem));
+
+       if (ax->map2) {
+               iounmap(ax->map2);
+               mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+               release_mem_region(mem->start, resource_size(mem));
+       }
+
+       free_netdev(dev);
+
+       return 0;
+}
+
+/*
+ * ax_probe
+ *
+ * This is the entry point when the platform device system uses to
+ * notify us of a new device to attach to. Allocate memory, find the
+ * resources and information passed, and map the necessary registers.
+ */
+static int ax_probe(struct platform_device *pdev)
+{
+       struct net_device *dev;
+       struct ei_device *ei_local;
+       struct ax_device *ax;
+       struct resource *irq, *mem, *mem2;
+       resource_size_t mem_size, mem2_size = 0;
+       int ret = 0;
+
+       dev = ax__alloc_ei_netdev(sizeof(struct ax_device));
+       if (dev == NULL)
+               return -ENOMEM;
+
+       /* ok, let's setup our device */
+       SET_NETDEV_DEV(dev, &pdev->dev);
+       ei_local = netdev_priv(dev);
+       ax = to_ax_dev(dev);
+
+       ax->plat = pdev->dev.platform_data;
+       platform_set_drvdata(pdev, dev);
+
+       ei_local->rxcr_base = ax->plat->rcr_val;
+
+       /* find the platform resources */
+       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!irq) {
+               dev_err(&pdev->dev, "no IRQ specified\n");
+               ret = -ENXIO;
+               goto exit_mem;
+       }
+
+       dev->irq = irq->start;
+       ax->irqflags = irq->flags & IRQF_TRIGGER_MASK;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               dev_err(&pdev->dev, "no MEM specified\n");
+               ret = -ENXIO;
+               goto exit_mem;
+       }
+
+       mem_size = resource_size(mem);
+
+       /*
+        * setup the register offsets from either the platform data or
+        * by using the size of the resource provided
+        */
+       if (ax->plat->reg_offsets)
+               ei_local->reg_offset = ax->plat->reg_offsets;
+       else {
+               ei_local->reg_offset = ax->reg_offsets;
+               for (ret = 0; ret < 0x18; ret++)
+                       ax->reg_offsets[ret] = (mem_size / 0x18) * ret;
+       }
+
+       if (!request_mem_region(mem->start, mem_size, pdev->name)) {
+               dev_err(&pdev->dev, "cannot reserve registers\n");
+               ret = -ENXIO;
+               goto exit_mem;
+       }
+
+       ei_local->mem = ioremap(mem->start, mem_size);
+       dev->base_addr = (unsigned long)ei_local->mem;
+
+       if (ei_local->mem == NULL) {
+               dev_err(&pdev->dev, "Cannot ioremap area %pR\n", mem);
+
+               ret = -ENXIO;
+               goto exit_req;
+       }
+
+       /* look for reset area */
+       mem2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (!mem2) {
+               if (!ax->plat->reg_offsets) {
+                       for (ret = 0; ret < 0x20; ret++)
+                               ax->reg_offsets[ret] = (mem_size / 0x20) * ret;
+               }
+       } else {
+               mem2_size = resource_size(mem2);
+
+               if (!request_mem_region(mem2->start, mem2_size, pdev->name)) {
+                       dev_err(&pdev->dev, "cannot reserve registers\n");
+                       ret = -ENXIO;
+                       goto exit_mem1;
+               }
+
+               ax->map2 = ioremap(mem2->start, mem2_size);
+               if (!ax->map2) {
+                       dev_err(&pdev->dev, "cannot map reset register\n");
+                       ret = -ENXIO;
+                       goto exit_mem2;
+               }
+
+               ei_local->reg_offset[0x1f] = ax->map2 - ei_local->mem;
+       }
+
+       /* got resources, now initialise and register device */
+       ret = ax_init_dev(dev);
+       if (!ret)
+               return 0;
+
+       if (!ax->map2)
+               goto exit_mem1;
+
+       iounmap(ax->map2);
+
+ exit_mem2:
+       release_mem_region(mem2->start, mem2_size);
+
+ exit_mem1:
+       iounmap(ei_local->mem);
+
+ exit_req:
+       release_mem_region(mem->start, mem_size);
+
+ exit_mem:
+       free_netdev(dev);
+
+       return ret;
+}
+
+/* suspend and resume */
+
+#ifdef CONFIG_PM
+static int ax_suspend(struct platform_device *dev, pm_message_t state)
+{
+       struct net_device *ndev = platform_get_drvdata(dev);
+       struct ax_device *ax = to_ax_dev(ndev);
+
+       ax->resume_open = ax->running;
+
+       netif_device_detach(ndev);
+       ax_close(ndev);
+
+       return 0;
+}
+
+static int ax_resume(struct platform_device *pdev)
+{
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       struct ax_device *ax = to_ax_dev(ndev);
+
+       ax_initial_setup(ndev, netdev_priv(ndev));
+       ax_NS8390_init(ndev, ax->resume_open);
+       netif_device_attach(ndev);
+
+       if (ax->resume_open)
+               ax_open(ndev);
+
+       return 0;
+}
+
+#else
+#define ax_suspend NULL
+#define ax_resume NULL
+#endif
+
+static struct platform_driver axdrv = {
+       .driver = {
+               .name           = "ax88796",
+               .owner          = THIS_MODULE,
+       },
+       .probe          = ax_probe,
+       .remove         = ax_remove,
+       .suspend        = ax_suspend,
+       .resume         = ax_resume,
+};
+
+static int __init axdrv_init(void)
+{
+       return platform_driver_register(&axdrv);
+}
+
+static void __exit axdrv_exit(void)
+{
+       platform_driver_unregister(&axdrv);
+}
+
+module_init(axdrv_init);
+module_exit(axdrv_exit);
+
+MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
+MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:ax88796");
diff --git a/drivers/net/ethernet/8390/axnet_cs.c b/drivers/net/ethernet/8390/axnet_cs.c
new file mode 100644 (file)
index 0000000..3e4b926
--- /dev/null
@@ -0,0 +1,1725 @@
+/*======================================================================
+
+    A PCMCIA ethernet driver for Asix AX88190-based cards
+
+    The Asix AX88190 is a NS8390-derived chipset with a few nasty
+    idiosyncracies that make it very inconvenient to support with a
+    standard 8390 driver.  This driver is based on pcnet_cs, with the
+    tweaked 8390 code grafted on the end.  Much of what I did was to
+    clean up and update a similar driver supplied by Asix, which was
+    adapted by William Lee, william@asix.com.tw.
+
+    Copyright (C) 2001 David A. Hinds -- dahinds@users.sourceforge.net
+
+    axnet_cs.c 1.28 2002/06/29 06:27:37
+
+    The network driver code is based on Donald Becker's NE2000 code:
+
+    Written 1992,1993 by Donald Becker.
+    Copyright 1993 United States Government as represented by the
+    Director, National Security Agency.  This software may be used and
+    distributed according to the terms of the GNU General Public License,
+    incorporated herein by reference.
+    Donald Becker may be reached at becker@scyld.com
+
+======================================================================*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include "8390.h"
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ciscode.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#define AXNET_CMD      0x00
+#define AXNET_DATAPORT 0x10    /* NatSemi-defined port window offset. */
+#define AXNET_RESET    0x1f    /* Issue a read to reset, a write to clear. */
+#define AXNET_MII_EEP  0x14    /* Offset of MII access port */
+#define AXNET_TEST     0x15    /* Offset of TEST Register port */
+#define AXNET_GPIO     0x17    /* Offset of General Purpose Register Port */
+
+#define AXNET_START_PG 0x40    /* First page of TX buffer */
+#define AXNET_STOP_PG  0x80    /* Last page +1 of RX ring */
+
+#define AXNET_RDC_TIMEOUT 0x02 /* Max wait in jiffies for Tx RDC */
+
+#define IS_AX88190     0x0001
+#define IS_AX88790     0x0002
+
+/*====================================================================*/
+
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("Asix AX88190 PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");
+
+
+/*====================================================================*/
+
+static int axnet_config(struct pcmcia_device *link);
+static void axnet_release(struct pcmcia_device *link);
+static int axnet_open(struct net_device *dev);
+static int axnet_close(struct net_device *dev);
+static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static netdev_tx_t axnet_start_xmit(struct sk_buff *skb,
+                                         struct net_device *dev);
+static struct net_device_stats *get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static void axnet_tx_timeout(struct net_device *dev);
+static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
+static void ei_watchdog(u_long arg);
+static void axnet_reset_8390(struct net_device *dev);
+
+static int mdio_read(unsigned int addr, int phy_id, int loc);
+static void mdio_write(unsigned int addr, int phy_id, int loc, int value);
+
+static void get_8390_hdr(struct net_device *,
+                        struct e8390_pkt_hdr *, int);
+static void block_input(struct net_device *dev, int count,
+                       struct sk_buff *skb, int ring_offset);
+static void block_output(struct net_device *dev, int count,
+                        const u_char *buf, const int start_page);
+
+static void axnet_detach(struct pcmcia_device *p_dev);
+
+static void AX88190_init(struct net_device *dev, int startp);
+static int ax_open(struct net_device *dev);
+static int ax_close(struct net_device *dev);
+static irqreturn_t ax_interrupt(int irq, void *dev_id);
+
+/*====================================================================*/
+
+typedef struct axnet_dev_t {
+       struct pcmcia_device    *p_dev;
+       caddr_t base;
+       struct timer_list       watchdog;
+       int     stale, fast_poll;
+       u_short link_status;
+       u_char  duplex_flag;
+       int     phy_id;
+       int     flags;
+       int     active_low;
+} axnet_dev_t;
+
+static inline axnet_dev_t *PRIV(struct net_device *dev)
+{
+       void *p = (char *)netdev_priv(dev) + sizeof(struct ei_device);
+       return p;
+}
+
+static const struct net_device_ops axnet_netdev_ops = {
+       .ndo_open               = axnet_open,
+       .ndo_stop               = axnet_close,
+       .ndo_do_ioctl           = axnet_ioctl,
+       .ndo_start_xmit         = axnet_start_xmit,
+       .ndo_tx_timeout         = axnet_tx_timeout,
+       .ndo_get_stats          = get_stats,
+       .ndo_set_multicast_list = set_multicast_list,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
+static int axnet_probe(struct pcmcia_device *link)
+{
+    axnet_dev_t *info;
+    struct net_device *dev;
+    struct ei_device *ei_local;
+
+    dev_dbg(&link->dev, "axnet_attach()\n");
+
+    dev = alloc_etherdev(sizeof(struct ei_device) + sizeof(axnet_dev_t));
+    if (!dev)
+       return -ENOMEM;
+
+    ei_local = netdev_priv(dev);
+    spin_lock_init(&ei_local->page_lock);
+
+    info = PRIV(dev);
+    info->p_dev = link;
+    link->priv = dev;
+    link->config_flags |= CONF_ENABLE_IRQ;
+
+    dev->netdev_ops = &axnet_netdev_ops;
+
+    dev->watchdog_timeo = TX_TIMEOUT;
+
+    return axnet_config(link);
+} /* axnet_attach */
+
+static void axnet_detach(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+
+    dev_dbg(&link->dev, "axnet_detach(0x%p)\n", link);
+
+    unregister_netdev(dev);
+
+    axnet_release(link);
+
+    free_netdev(dev);
+} /* axnet_detach */
+
+/*======================================================================
+
+    This probes for a card's hardware address by reading the PROM.
+
+======================================================================*/
+
+static int get_prom(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    unsigned int ioaddr = dev->base_addr;
+    int i, j;
+
+    /* This is based on drivers/net/ne.c */
+    struct {
+       u_char value, offset;
+    } program_seq[] = {
+       {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+       {0x01,  EN0_DCFG},      /* Set word-wide access. */
+       {0x00,  EN0_RCNTLO},    /* Clear the count regs. */
+       {0x00,  EN0_RCNTHI},
+       {0x00,  EN0_IMR},       /* Mask completion irq. */
+       {0xFF,  EN0_ISR},
+       {E8390_RXOFF|0x40, EN0_RXCR},   /* 0x60  Set to monitor */
+       {E8390_TXOFF, EN0_TXCR},        /* 0x02  and loopback mode. */
+       {0x10,  EN0_RCNTLO},
+       {0x00,  EN0_RCNTHI},
+       {0x00,  EN0_RSARLO},    /* DMA starting at 0x0400. */
+       {0x04,  EN0_RSARHI},
+       {E8390_RREAD+E8390_START, E8390_CMD},
+    };
+
+    /* Not much of a test, but the alternatives are messy */
+    if (link->config_base != 0x03c0)
+       return 0;
+
+    axnet_reset_8390(dev);
+    mdelay(10);
+
+    for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+       outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
+
+    for (i = 0; i < 6; i += 2) {
+       j = inw(ioaddr + AXNET_DATAPORT);
+       dev->dev_addr[i] = j & 0xff;
+       dev->dev_addr[i+1] = j >> 8;
+    }
+    return 1;
+} /* get_prom */
+
+static int try_io_port(struct pcmcia_device *link)
+{
+    int j, ret;
+    link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+    link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+    if (link->resource[0]->end == 32) {
+       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+       /* for master/slave multifunction cards */
+       if (link->resource[1]->end > 0)
+           link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+    } else {
+       /* This should be two 16-port windows */
+       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+       link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
+    }
+    if (link->resource[0]->start == 0) {
+       for (j = 0; j < 0x400; j += 0x20) {
+           link->resource[0]->start = j ^ 0x300;
+           link->resource[1]->start = (j ^ 0x300) + 0x10;
+           link->io_lines = 16;
+           ret = pcmcia_request_io(link);
+           if (ret == 0)
+                   return ret;
+       }
+       return ret;
+    } else {
+       return pcmcia_request_io(link);
+    }
+}
+
+static int axnet_configcheck(struct pcmcia_device *p_dev, void *priv_data)
+{
+       if (p_dev->config_index == 0)
+               return -EINVAL;
+
+       p_dev->config_index = 0x05;
+       if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
+               return -ENODEV;
+
+       return try_io_port(p_dev);
+}
+
+static int axnet_config(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    axnet_dev_t *info = PRIV(dev);
+    int i, j, j2, ret;
+
+    dev_dbg(&link->dev, "axnet_config(0x%p)\n", link);
+
+    /* don't trust the CIS on this; Linksys got it wrong */
+    link->config_regs = 0x63;
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+    ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
+    if (ret != 0)
+       goto failed;
+
+    if (!link->irq)
+           goto failed;
+
+    if (resource_size(link->resource[1]) == 8)
+       link->config_flags |= CONF_ENABLE_SPKR;
+    
+    ret = pcmcia_enable_device(link);
+    if (ret)
+           goto failed;
+
+    dev->irq = link->irq;
+    dev->base_addr = link->resource[0]->start;
+
+    if (!get_prom(link)) {
+       pr_notice("this is not an AX88190 card!\n");
+       pr_notice("use pcnet_cs instead.\n");
+       goto failed;
+    }
+
+    ei_status.name = "AX88190";
+    ei_status.word16 = 1;
+    ei_status.tx_start_page = AXNET_START_PG;
+    ei_status.rx_start_page = AXNET_START_PG + TX_PAGES;
+    ei_status.stop_page = AXNET_STOP_PG;
+    ei_status.reset_8390 = axnet_reset_8390;
+    ei_status.get_8390_hdr = get_8390_hdr;
+    ei_status.block_input = block_input;
+    ei_status.block_output = block_output;
+
+    if (inb(dev->base_addr + AXNET_TEST) != 0)
+       info->flags |= IS_AX88790;
+    else
+       info->flags |= IS_AX88190;
+
+    if (info->flags & IS_AX88790)
+       outb(0x10, dev->base_addr + AXNET_GPIO);  /* select Internal PHY */
+
+    info->active_low = 0;
+
+    for (i = 0; i < 32; i++) {
+       j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
+       j2 = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 2);
+       if (j == j2) continue;
+       if ((j != 0) && (j != 0xffff)) break;
+    }
+
+    if (i == 32) {
+       /* Maybe PHY is in power down mode. (PPD_SET = 1)
+          Bit 2 of CCSR is active low. */
+       pcmcia_write_config_byte(link, CISREG_CCSR, 0x04);
+       for (i = 0; i < 32; i++) {
+           j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
+           j2 = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 2);
+           if (j == j2) continue;
+           if ((j != 0) && (j != 0xffff)) {
+               info->active_low = 1;
+               break;
+           }
+       }
+    }
+
+    info->phy_id = (i < 32) ? i : -1;
+    SET_NETDEV_DEV(dev, &link->dev);
+
+    if (register_netdev(dev) != 0) {
+       pr_notice("register_netdev() failed\n");
+       goto failed;
+    }
+
+    netdev_info(dev, "Asix AX88%d90: io %#3lx, irq %d, hw_addr %pM\n",
+               ((info->flags & IS_AX88790) ? 7 : 1),
+               dev->base_addr, dev->irq, dev->dev_addr);
+    if (info->phy_id != -1) {
+       netdev_dbg(dev, "  MII transceiver at index %d, status %x\n",
+                  info->phy_id, j);
+    } else {
+       netdev_notice(dev, "  No MII transceivers found!\n");
+    }
+    return 0;
+
+failed:
+    axnet_release(link);
+    return -ENODEV;
+} /* axnet_config */
+
+static void axnet_release(struct pcmcia_device *link)
+{
+       pcmcia_disable_device(link);
+}
+
+static int axnet_suspend(struct pcmcia_device *link)
+{
+       struct net_device *dev = link->priv;
+
+       if (link->open)
+               netif_device_detach(dev);
+
+       return 0;
+}
+
+static int axnet_resume(struct pcmcia_device *link)
+{
+       struct net_device *dev = link->priv;
+       axnet_dev_t *info = PRIV(dev);
+
+       if (link->open) {
+               if (info->active_low == 1)
+                       pcmcia_write_config_byte(link, CISREG_CCSR, 0x04);
+
+               axnet_reset_8390(dev);
+               AX88190_init(dev, 1);
+               netif_device_attach(dev);
+       }
+
+       return 0;
+}
+
+
+/*======================================================================
+
+    MII interface support
+
+======================================================================*/
+
+#define MDIO_SHIFT_CLK         0x01
+#define MDIO_DATA_WRITE0       0x00
+#define MDIO_DATA_WRITE1       0x08
+#define MDIO_DATA_READ         0x04
+#define MDIO_MASK              0x0f
+#define MDIO_ENB_IN            0x02
+
+static void mdio_sync(unsigned int addr)
+{
+    int bits;
+    for (bits = 0; bits < 32; bits++) {
+       outb_p(MDIO_DATA_WRITE1, addr);
+       outb_p(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
+    }
+}
+
+static int mdio_read(unsigned int addr, int phy_id, int loc)
+{
+    u_int cmd = (0xf6<<10)|(phy_id<<5)|loc;
+    int i, retval = 0;
+
+    mdio_sync(addr);
+    for (i = 14; i >= 0; i--) {
+       int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+       outb_p(dat, addr);
+       outb_p(dat | MDIO_SHIFT_CLK, addr);
+    }
+    for (i = 19; i > 0; i--) {
+       outb_p(MDIO_ENB_IN, addr);
+       retval = (retval << 1) | ((inb_p(addr) & MDIO_DATA_READ) != 0);
+       outb_p(MDIO_ENB_IN | MDIO_SHIFT_CLK, addr);
+    }
+    return (retval>>1) & 0xffff;
+}
+
+static void mdio_write(unsigned int addr, int phy_id, int loc, int value)
+{
+    u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
+    int i;
+
+    mdio_sync(addr);
+    for (i = 31; i >= 0; i--) {
+       int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+       outb_p(dat, addr);
+       outb_p(dat | MDIO_SHIFT_CLK, addr);
+    }
+    for (i = 1; i >= 0; i--) {
+       outb_p(MDIO_ENB_IN, addr);
+       outb_p(MDIO_ENB_IN | MDIO_SHIFT_CLK, addr);
+    }
+}
+
+/*====================================================================*/
+
+static int axnet_open(struct net_device *dev)
+{
+    int ret;
+    axnet_dev_t *info = PRIV(dev);
+    struct pcmcia_device *link = info->p_dev;
+    unsigned int nic_base = dev->base_addr;
+    
+    dev_dbg(&link->dev, "axnet_open('%s')\n", dev->name);
+
+    if (!pcmcia_dev_present(link))
+       return -ENODEV;
+
+    outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */
+    ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
+    if (ret)
+           return ret;
+
+    link->open++;
+
+    info->link_status = 0x00;
+    init_timer(&info->watchdog);
+    info->watchdog.function = ei_watchdog;
+    info->watchdog.data = (u_long)dev;
+    info->watchdog.expires = jiffies + HZ;
+    add_timer(&info->watchdog);
+
+    return ax_open(dev);
+} /* axnet_open */
+
+/*====================================================================*/
+
+static int axnet_close(struct net_device *dev)
+{
+    axnet_dev_t *info = PRIV(dev);
+    struct pcmcia_device *link = info->p_dev;
+
+    dev_dbg(&link->dev, "axnet_close('%s')\n", dev->name);
+
+    ax_close(dev);
+    free_irq(dev->irq, dev);
+    
+    link->open--;
+    netif_stop_queue(dev);
+    del_timer_sync(&info->watchdog);
+
+    return 0;
+} /* axnet_close */
+
+/*======================================================================
+
+    Hard reset the card.  This used to pause for the same period that
+    a 8390 reset command required, but that shouldn't be necessary.
+
+======================================================================*/
+
+static void axnet_reset_8390(struct net_device *dev)
+{
+    unsigned int nic_base = dev->base_addr;
+    int i;
+
+    ei_status.txing = ei_status.dmaing = 0;
+
+    outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, nic_base + E8390_CMD);
+
+    outb(inb(nic_base + AXNET_RESET), nic_base + AXNET_RESET);
+
+    for (i = 0; i < 100; i++) {
+       if ((inb_p(nic_base+EN0_ISR) & ENISR_RESET) != 0)
+           break;
+       udelay(100);
+    }
+    outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
+    
+    if (i == 100)
+       netdev_err(dev, "axnet_reset_8390() did not complete\n");
+    
+} /* axnet_reset_8390 */
+
+/*====================================================================*/
+
+static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
+{
+    struct net_device *dev = dev_id;
+    PRIV(dev)->stale = 0;
+    return ax_interrupt(irq, dev_id);
+}
+
+static void ei_watchdog(u_long arg)
+{
+    struct net_device *dev = (struct net_device *)(arg);
+    axnet_dev_t *info = PRIV(dev);
+    unsigned int nic_base = dev->base_addr;
+    unsigned int mii_addr = nic_base + AXNET_MII_EEP;
+    u_short link;
+
+    if (!netif_device_present(dev)) goto reschedule;
+
+    /* Check for pending interrupt with expired latency timer: with
+       this, we can limp along even if the interrupt is blocked */
+    if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
+       if (!info->fast_poll)
+           netdev_info(dev, "interrupt(s) dropped!\n");
+       ei_irq_wrapper(dev->irq, dev);
+       info->fast_poll = HZ;
+    }
+    if (info->fast_poll) {
+       info->fast_poll--;
+       info->watchdog.expires = jiffies + 1;
+       add_timer(&info->watchdog);
+       return;
+    }
+
+    if (info->phy_id < 0)
+       goto reschedule;
+    link = mdio_read(mii_addr, info->phy_id, 1);
+    if (!link || (link == 0xffff)) {
+       netdev_info(dev, "MII is missing!\n");
+       info->phy_id = -1;
+       goto reschedule;
+    }
+
+    link &= 0x0004;
+    if (link != info->link_status) {
+       u_short p = mdio_read(mii_addr, info->phy_id, 5);
+       netdev_info(dev, "%s link beat\n", link ? "found" : "lost");
+       if (link) {
+           info->duplex_flag = (p & 0x0140) ? 0x80 : 0x00;
+           if (p)
+               netdev_info(dev, "autonegotiation complete: %dbaseT-%cD selected\n",
+                           (p & 0x0180) ? 100 : 10, (p & 0x0140) ? 'F' : 'H');
+           else
+               netdev_info(dev, "link partner did not autonegotiate\n");
+           AX88190_init(dev, 1);
+       }
+       info->link_status = link;
+    }
+
+reschedule:
+    info->watchdog.expires = jiffies + HZ;
+    add_timer(&info->watchdog);
+}
+
+/*====================================================================*/
+
+static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+    axnet_dev_t *info = PRIV(dev);
+    struct mii_ioctl_data *data = if_mii(rq);
+    unsigned int mii_addr = dev->base_addr + AXNET_MII_EEP;
+    switch (cmd) {
+    case SIOCGMIIPHY:
+       data->phy_id = info->phy_id;
+    case SIOCGMIIREG:          /* Read MII PHY register. */
+       data->val_out = mdio_read(mii_addr, data->phy_id, data->reg_num & 0x1f);
+       return 0;
+    case SIOCSMIIREG:          /* Write MII PHY register. */
+       mdio_write(mii_addr, data->phy_id, data->reg_num & 0x1f, data->val_in);
+       return 0;
+    }
+    return -EOPNOTSUPP;
+}
+
+/*====================================================================*/
+
+static void get_8390_hdr(struct net_device *dev,
+                        struct e8390_pkt_hdr *hdr,
+                        int ring_page)
+{
+    unsigned int nic_base = dev->base_addr;
+
+    outb_p(0, nic_base + EN0_RSARLO);          /* On page boundary */
+    outb_p(ring_page, nic_base + EN0_RSARHI);
+    outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD);
+
+    insw(nic_base + AXNET_DATAPORT, hdr,
+           sizeof(struct e8390_pkt_hdr)>>1);
+    /* Fix for big endian systems */
+    hdr->count = le16_to_cpu(hdr->count);
+
+}
+
+/*====================================================================*/
+
+static void block_input(struct net_device *dev, int count,
+                       struct sk_buff *skb, int ring_offset)
+{
+    unsigned int nic_base = dev->base_addr;
+    int xfer_count = count;
+    char *buf = skb->data;
+
+    if ((ei_debug > 4) && (count != 4))
+           pr_debug("%s: [bi=%d]\n", dev->name, count+4);
+    outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+    outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+    outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD);
+
+    insw(nic_base + AXNET_DATAPORT,buf,count>>1);
+    if (count & 0x01)
+       buf[count-1] = inb(nic_base + AXNET_DATAPORT), xfer_count++;
+
+}
+
+/*====================================================================*/
+
+static void block_output(struct net_device *dev, int count,
+                        const u_char *buf, const int start_page)
+{
+    unsigned int nic_base = dev->base_addr;
+
+    pr_debug("%s: [bo=%d]\n", dev->name, count);
+
+    /* Round the count up for word writes.  Do we need to do this?
+       What effect will an odd byte count have on the 8390?
+       I should check someday. */
+    if (count & 0x01)
+       count++;
+
+    outb_p(0x00, nic_base + EN0_RSARLO);
+    outb_p(start_page, nic_base + EN0_RSARHI);
+    outb_p(E8390_RWRITE+E8390_START, nic_base + AXNET_CMD);
+    outsw(nic_base + AXNET_DATAPORT, buf, count>>1);
+}
+
+static const struct pcmcia_device_id axnet_ids[] = {
+       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x016c, 0x0081),
+       PCMCIA_DEVICE_MANF_CARD(0x018a, 0x0301),
+       PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328),
+       PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0301),
+       PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0303),
+       PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0309),
+       PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1106),
+       PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab),
+       PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), 
+       PCMCIA_DEVICE_MANF_CARD(0xffff, 0x1090),
+       PCMCIA_DEVICE_PROD_ID12("AmbiCom,Inc.", "Fast Ethernet PC Card(AMB8110)", 0x49b020a7, 0x119cc9fc),
+       PCMCIA_DEVICE_PROD_ID124("Fast Ethernet", "16-bit PC Card", "AX88190", 0xb4be14e3, 0x9a12eb6a, 0xab9be5ef),
+       PCMCIA_DEVICE_PROD_ID12("ASIX", "AX88190", 0x0959823b, 0xab9be5ef),
+       PCMCIA_DEVICE_PROD_ID12("Billionton", "LNA-100B", 0x552ab682, 0xbc3b87e1),
+       PCMCIA_DEVICE_PROD_ID12("CHEETAH ETHERCARD", "EN2228", 0x00fa7bc8, 0x00e990cc),
+       PCMCIA_DEVICE_PROD_ID12("CNet", "CNF301", 0xbc477dde, 0x78c5f40b),
+       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXD", 0x5261440f, 0x436768c5),
+       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEtherII PCC-TXD", 0x5261440f, 0x730df72e),
+       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXM", 0x5261440f, 0x3abbd061),
+       PCMCIA_DEVICE_PROD_ID12("Dynalink", "L100C16", 0x55632fd5, 0x66bc2a90),
+       PCMCIA_DEVICE_PROD_ID12("IO DATA", "ETXPCM", 0x547e66dc, 0x233adac2),
+       PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V3)", 0x0733cc81, 0x232019a8),
+       PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC3-TX", 0x481e0094, 0xf91af609),
+       PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA411", 0x9aa79dc3, 0x40fad875),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "100BASE", 0x281f1c5d, 0x7c2add04),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEtherCard", 0x281f1c5d, 0x7ef26116),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FEP501", 0x281f1c5d, 0x2e272058),
+       PCMCIA_DEVICE_PROD_ID14("Network Everywhere", "AX88190", 0x820a67b6,  0xab9be5ef),
+       PCMCIA_DEVICE_NULL,
+};
+MODULE_DEVICE_TABLE(pcmcia, axnet_ids);
+
+static struct pcmcia_driver axnet_cs_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "axnet_cs",
+       .probe          = axnet_probe,
+       .remove         = axnet_detach,
+       .id_table       = axnet_ids,
+       .suspend        = axnet_suspend,
+       .resume         = axnet_resume,
+};
+
+static int __init init_axnet_cs(void)
+{
+       return pcmcia_register_driver(&axnet_cs_driver);
+}
+
+static void __exit exit_axnet_cs(void)
+{
+       pcmcia_unregister_driver(&axnet_cs_driver);
+}
+
+module_init(init_axnet_cs);
+module_exit(exit_axnet_cs);
+
+/*====================================================================*/
+
+/* 8390.c: A general NS8390 ethernet driver core for linux. */
+/*
+       Written 1992-94 by Donald Becker.
+  
+       Copyright 1993 United States Government as represented by the
+       Director, National Security Agency.
+
+       This software may be used and distributed according to the terms
+       of the GNU General Public License, incorporated herein by reference.
+
+       The author may be reached as becker@scyld.com, or C/O
+       Scyld Computing Corporation
+       410 Severn Ave., Suite 210
+       Annapolis MD 21403
+
+  This is the chip-specific code for many 8390-based ethernet adaptors.
+  This is not a complete driver, it must be combined with board-specific
+  code such as ne.c, wd.c, 3c503.c, etc.
+
+  Seeing how at least eight drivers use this code, (not counting the
+  PCMCIA ones either) it is easy to break some card by what seems like
+  a simple innocent change. Please contact me or Donald if you think
+  you have found something that needs changing. -- PG
+
+  Changelog:
+
+  Paul Gortmaker       : remove set_bit lock, other cleanups.
+  Paul Gortmaker       : add ei_get_8390_hdr() so we can pass skb's to 
+                         ei_block_input() for eth_io_copy_and_sum().
+  Paul Gortmaker       : exchange static int ei_pingpong for a #define,
+                         also add better Tx error handling.
+  Paul Gortmaker       : rewrite Rx overrun handling as per NS specs.
+  Alexey Kuznetsov     : use the 8390's six bit hash multicast filter.
+  Paul Gortmaker       : tweak ANK's above multicast changes a bit.
+  Paul Gortmaker       : update packet statistics for v2.1.x
+  Alan Cox             : support arbitrary stupid port mappings on the
+                         68K Macintosh. Support >16bit I/O spaces
+  Paul Gortmaker       : add kmod support for auto-loading of the 8390
+                         module by all drivers that require it.
+  Alan Cox             : Spinlocking work, added 'BUG_83C690'
+  Paul Gortmaker       : Separate out Tx timeout code from Tx path.
+
+  Sources:
+  The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
+
+  */
+
+#include <linux/bitops.h>
+#include <asm/irq.h>
+#include <linux/fcntl.h>
+#include <linux/in.h>
+#include <linux/interrupt.h>
+
+#define BUG_83C690
+
+/* These are the operational function interfaces to board-specific
+   routines.
+       void reset_8390(struct net_device *dev)
+               Resets the board associated with DEV, including a hardware reset of
+               the 8390.  This is only called when there is a transmit timeout, and
+               it is always followed by 8390_init().
+       void block_output(struct net_device *dev, int count, const unsigned char *buf,
+                                         int start_page)
+               Write the COUNT bytes of BUF to the packet buffer at START_PAGE.  The
+               "page" value uses the 8390's 256-byte pages.
+       void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page)
+               Read the 4 byte, page aligned 8390 header. *If* there is a
+               subsequent read, it will be of the rest of the packet.
+       void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+               Read COUNT bytes from the packet buffer into the skb data area. Start 
+               reading from RING_OFFSET, the address as the 8390 sees it.  This will always
+               follow the read of the 8390 header. 
+*/
+#define ei_reset_8390 (ei_local->reset_8390)
+#define ei_block_output (ei_local->block_output)
+#define ei_block_input (ei_local->block_input)
+#define ei_get_8390_hdr (ei_local->get_8390_hdr)
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifndef ei_debug
+int ei_debug = 1;
+#endif
+
+/* Index to functions. */
+static void ei_tx_intr(struct net_device *dev);
+static void ei_tx_err(struct net_device *dev);
+static void ei_receive(struct net_device *dev);
+static void ei_rx_overrun(struct net_device *dev);
+
+/* Routines generic to NS8390-based boards. */
+static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
+                                                               int start_page);
+static void do_set_multicast_list(struct net_device *dev);
+
+/*
+ *     SMP and the 8390 setup.
+ *
+ *     The 8390 isn't exactly designed to be multithreaded on RX/TX. There is
+ *     a page register that controls bank and packet buffer access. We guard
+ *     this with ei_local->page_lock. Nobody should assume or set the page other
+ *     than zero when the lock is not held. Lock holders must restore page 0
+ *     before unlocking. Even pure readers must take the lock to protect in 
+ *     page 0.
+ *
+ *     To make life difficult the chip can also be very slow. We therefore can't
+ *     just use spinlocks. For the longer lockups we disable the irq the device
+ *     sits on and hold the lock. We must hold the lock because there is a dual
+ *     processor case other than interrupts (get stats/set multicast list in
+ *     parallel with each other and transmit).
+ *
+ *     Note: in theory we can just disable the irq on the card _but_ there is
+ *     a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs"
+ *     enter lock, take the queued irq. So we waddle instead of flying.
+ *
+ *     Finally by special arrangement for the purpose of being generally 
+ *     annoying the transmit function is called bh atomic. That places
+ *     restrictions on the user context callers as disable_irq won't save
+ *     them.
+ */
+/**
+ * ax_open - Open/initialize the board.
+ * @dev: network device to initialize
+ *
+ * This routine goes all-out, setting everything
+ * up anew at each open, even though many of these registers should only
+ * need to be set once at boot.
+ */
+static int ax_open(struct net_device *dev)
+{
+       unsigned long flags;
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       /*
+        *      Grab the page lock so we own the register set, then call
+        *      the init function.
+        */
+      
+       spin_lock_irqsave(&ei_local->page_lock, flags);
+       AX88190_init(dev, 1);
+       /* Set the flag before we drop the lock, That way the IRQ arrives
+          after its set and we get no silly warnings */
+       netif_start_queue(dev);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
+       ei_local->irqlock = 0;
+       return 0;
+}
+
+#define dev_lock(dev) (((struct ei_device *)netdev_priv(dev))->page_lock)
+
+/**
+ * ax_close - shut down network device
+ * @dev: network device to close
+ *
+ * Opposite of ax_open(). Only used when "ifconfig <devname> down" is done.
+ */
+static int ax_close(struct net_device *dev)
+{
+       unsigned long flags;
+
+       /*
+        *      Hold the page lock during close
+        */
+
+       spin_lock_irqsave(&dev_lock(dev), flags);
+       AX88190_init(dev, 0);
+       spin_unlock_irqrestore(&dev_lock(dev), flags);
+       netif_stop_queue(dev);
+       return 0;
+}
+
+/**
+ * axnet_tx_timeout - handle transmit time out condition
+ * @dev: network device which has apparently fallen asleep
+ *
+ * Called by kernel when device never acknowledges a transmit has
+ * completed (or failed) - i.e. never posted a Tx related interrupt.
+ */
+
+static void axnet_tx_timeout(struct net_device *dev)
+{
+       long e8390_base = dev->base_addr;
+       struct ei_device *ei_local = netdev_priv(dev);
+       int txsr, isr, tickssofar = jiffies - dev_trans_start(dev);
+       unsigned long flags;
+
+       dev->stats.tx_errors++;
+
+       spin_lock_irqsave(&ei_local->page_lock, flags);
+       txsr = inb(e8390_base+EN0_TSR);
+       isr = inb(e8390_base+EN0_ISR);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+       netdev_printk(KERN_DEBUG, dev,
+                     "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
+                     (txsr & ENTSR_ABT) ? "excess collisions." :
+                     (isr) ? "lost interrupt?" : "cable problem?",
+                     txsr, isr, tickssofar);
+
+       if (!isr && !dev->stats.tx_packets) 
+       {
+               /* The 8390 probably hasn't gotten on the cable yet. */
+               ei_local->interface_num ^= 1;   /* Try a different xcvr.  */
+       }
+
+       /* Ugly but a reset can be slow, yet must be protected */
+               
+       spin_lock_irqsave(&ei_local->page_lock, flags);
+               
+       /* Try to restart the card.  Perhaps the user has fixed something. */
+       ei_reset_8390(dev);
+       AX88190_init(dev, 1);
+               
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
+       netif_wake_queue(dev);
+}
+    
+/**
+ * axnet_start_xmit - begin packet transmission
+ * @skb: packet to be sent
+ * @dev: network device to which packet is sent
+ *
+ * Sends a packet to an 8390 network device.
+ */
+static netdev_tx_t axnet_start_xmit(struct sk_buff *skb,
+                                         struct net_device *dev)
+{
+       long e8390_base = dev->base_addr;
+       struct ei_device *ei_local = netdev_priv(dev);
+       int length, send_length, output_page;
+       unsigned long flags;
+       u8 packet[ETH_ZLEN];
+       
+       netif_stop_queue(dev);
+
+       length = skb->len;
+
+       /* Mask interrupts from the ethercard. 
+          SMP: We have to grab the lock here otherwise the IRQ handler
+          on another CPU can flip window and race the IRQ mask set. We end
+          up trashing the mcast filter not disabling irqs if we don't lock */
+          
+       spin_lock_irqsave(&ei_local->page_lock, flags);
+       outb_p(0x00, e8390_base + EN0_IMR);
+       
+       /*
+        *      Slow phase with lock held.
+        */
+        
+       ei_local->irqlock = 1;
+
+       send_length = max(length, ETH_ZLEN);
+
+       /*
+        * We have two Tx slots available for use. Find the first free
+        * slot, and then perform some sanity checks. With two Tx bufs,
+        * you get very close to transmitting back-to-back packets. With
+        * only one Tx buf, the transmitter sits idle while you reload the
+        * card, leaving a substantial gap between each transmitted packet.
+        */
+
+       if (ei_local->tx1 == 0) 
+       {
+               output_page = ei_local->tx_start_page;
+               ei_local->tx1 = send_length;
+               if (ei_debug  &&  ei_local->tx2 > 0)
+                       netdev_printk(KERN_DEBUG, dev,
+                                     "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
+                                     ei_local->tx2, ei_local->lasttx,
+                                     ei_local->txing);
+       }
+       else if (ei_local->tx2 == 0) 
+       {
+               output_page = ei_local->tx_start_page + TX_PAGES/2;
+               ei_local->tx2 = send_length;
+               if (ei_debug  &&  ei_local->tx1 > 0)
+                       netdev_printk(KERN_DEBUG, dev,
+                                     "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
+                                     ei_local->tx1, ei_local->lasttx,
+                                     ei_local->txing);
+       }
+       else
+       {       /* We should never get here. */
+               if (ei_debug)
+                       netdev_printk(KERN_DEBUG, dev,
+                                     "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
+                                     ei_local->tx1, ei_local->tx2,
+                                     ei_local->lasttx);
+               ei_local->irqlock = 0;
+               netif_stop_queue(dev);
+               outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+               spin_unlock_irqrestore(&ei_local->page_lock, flags);
+               dev->stats.tx_errors++;
+               return NETDEV_TX_BUSY;
+       }
+
+       /*
+        * Okay, now upload the packet and trigger a send if the transmitter
+        * isn't already sending. If it is busy, the interrupt handler will
+        * trigger the send later, upon receiving a Tx done interrupt.
+        */
+
+       if (length == skb->len)
+               ei_block_output(dev, length, skb->data, output_page);
+       else {
+               memset(packet, 0, ETH_ZLEN);
+               skb_copy_from_linear_data(skb, packet, skb->len);
+               ei_block_output(dev, length, packet, output_page);
+       }
+       
+       if (! ei_local->txing) 
+       {
+               ei_local->txing = 1;
+               NS8390_trigger_send(dev, send_length, output_page);
+               dev->trans_start = jiffies;
+               if (output_page == ei_local->tx_start_page) 
+               {
+                       ei_local->tx1 = -1;
+                       ei_local->lasttx = -1;
+               }
+               else 
+               {
+                       ei_local->tx2 = -1;
+                       ei_local->lasttx = -2;
+               }
+       }
+       else ei_local->txqueue++;
+
+       if (ei_local->tx1  &&  ei_local->tx2)
+               netif_stop_queue(dev);
+       else
+               netif_start_queue(dev);
+
+       /* Turn 8390 interrupts back on. */
+       ei_local->irqlock = 0;
+       outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+       
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+       dev_kfree_skb (skb);
+       dev->stats.tx_bytes += send_length;
+    
+       return NETDEV_TX_OK;
+}
+
+/**
+ * ax_interrupt - handle the interrupts from an 8390
+ * @irq: interrupt number
+ * @dev_id: a pointer to the net_device
+ *
+ * Handle the ether interface interrupts. We pull packets from
+ * the 8390 via the card specific functions and fire them at the networking
+ * stack. We also handle transmit completions and wake the transmit path if
+ * necessary. We also update the counters and do other housekeeping as
+ * needed.
+ */
+
+static irqreturn_t ax_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev = dev_id;
+       long e8390_base;
+       int interrupts, nr_serviced = 0, i;
+       struct ei_device *ei_local;
+       int handled = 0;
+       unsigned long flags;
+
+       e8390_base = dev->base_addr;
+       ei_local = netdev_priv(dev);
+
+       /*
+        *      Protect the irq test too.
+        */
+        
+       spin_lock_irqsave(&ei_local->page_lock, flags);
+
+       if (ei_local->irqlock) {
+#if 1 /* This might just be an interrupt for a PCI device sharing this line */
+               const char *msg;
+               /* The "irqlock" check is only for testing. */
+               if (ei_local->irqlock)
+                       msg = "Interrupted while interrupts are masked!";
+               else
+                       msg = "Reentering the interrupt handler!";
+               netdev_info(dev, "%s, isr=%#2x imr=%#2x\n",
+                           msg,
+                           inb_p(e8390_base + EN0_ISR),
+                           inb_p(e8390_base + EN0_IMR));
+#endif
+               spin_unlock_irqrestore(&ei_local->page_lock, flags);
+               return IRQ_NONE;
+       }
+    
+       if (ei_debug > 3)
+               netdev_printk(KERN_DEBUG, dev, "interrupt(isr=%#2.2x)\n",
+                             inb_p(e8390_base + EN0_ISR));
+
+       outb_p(0x00, e8390_base + EN0_ISR);
+       ei_local->irqlock = 1;
+   
+       /* !!Assumption!! -- we stay in page 0.  Don't break this. */
+       while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0 &&
+              ++nr_serviced < MAX_SERVICE)
+       {
+               if (!netif_running(dev) || (interrupts == 0xff)) {
+                       if (ei_debug > 1)
+                               netdev_warn(dev,
+                                           "interrupt from stopped card\n");
+                       outb_p(interrupts, e8390_base + EN0_ISR);
+                       interrupts = 0;
+                       break;
+               }
+               handled = 1;
+
+               /* AX88190 bug fix. */
+               outb_p(interrupts, e8390_base + EN0_ISR);
+               for (i = 0; i < 10; i++) {
+                       if (!(inb(e8390_base + EN0_ISR) & interrupts))
+                               break;
+                       outb_p(0, e8390_base + EN0_ISR);
+                       outb_p(interrupts, e8390_base + EN0_ISR);
+               }
+               if (interrupts & ENISR_OVER) 
+                       ei_rx_overrun(dev);
+               else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) 
+               {
+                       /* Got a good (?) packet. */
+                       ei_receive(dev);
+               }
+               /* Push the next to-transmit packet through. */
+               if (interrupts & ENISR_TX)
+                       ei_tx_intr(dev);
+               else if (interrupts & ENISR_TX_ERR)
+                       ei_tx_err(dev);
+
+               if (interrupts & ENISR_COUNTERS) 
+               {
+                       dev->stats.rx_frame_errors += inb_p(e8390_base + EN0_COUNTER0);
+                       dev->stats.rx_crc_errors   += inb_p(e8390_base + EN0_COUNTER1);
+                       dev->stats.rx_missed_errors+= inb_p(e8390_base + EN0_COUNTER2);
+               }
+       }
+    
+       if (interrupts && ei_debug > 3) 
+       {
+               handled = 1;
+               if (nr_serviced >= MAX_SERVICE) 
+               {
+                       /* 0xFF is valid for a card removal */
+                       if(interrupts!=0xFF)
+                               netdev_warn(dev, "Too much work at interrupt, status %#2.2x\n",
+                                           interrupts);
+                       outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
+               } else {
+                       netdev_warn(dev, "unknown interrupt %#2x\n",
+                                   interrupts);
+                       outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
+               }
+       }
+
+       /* Turn 8390 interrupts back on. */
+       ei_local->irqlock = 0;
+       outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
+       return IRQ_RETVAL(handled);
+}
+
+/**
+ * ei_tx_err - handle transmitter error
+ * @dev: network device which threw the exception
+ *
+ * A transmitter error has happened. Most likely excess collisions (which
+ * is a fairly normal condition). If the error is one where the Tx will
+ * have been aborted, we try and send another one right away, instead of
+ * letting the failed packet sit and collect dust in the Tx buffer. This
+ * is a much better solution as it avoids kernel based Tx timeouts, and
+ * an unnecessary card reset.
+ *
+ * Called with lock held.
+ */
+
+static void ei_tx_err(struct net_device *dev)
+{
+       long e8390_base = dev->base_addr;
+       unsigned char txsr = inb_p(e8390_base+EN0_TSR);
+       unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
+
+#ifdef VERBOSE_ERROR_DUMP
+       netdev_printk(KERN_DEBUG, dev,
+                     "transmitter error (%#2x):", txsr);
+       if (txsr & ENTSR_ABT)
+               pr_cont(" excess-collisions");
+       if (txsr & ENTSR_ND)
+               pr_cont(" non-deferral");
+       if (txsr & ENTSR_CRS)
+               pr_cont(" lost-carrier");
+       if (txsr & ENTSR_FU)
+               pr_cont(" FIFO-underrun");
+       if (txsr & ENTSR_CDH)
+               pr_cont(" lost-heartbeat");
+       pr_cont("\n");
+#endif
+
+       if (tx_was_aborted)
+               ei_tx_intr(dev);
+       else 
+       {
+               dev->stats.tx_errors++;
+               if (txsr & ENTSR_CRS) dev->stats.tx_carrier_errors++;
+               if (txsr & ENTSR_CDH) dev->stats.tx_heartbeat_errors++;
+               if (txsr & ENTSR_OWC) dev->stats.tx_window_errors++;
+       }
+}
+
+/**
+ * ei_tx_intr - transmit interrupt handler
+ * @dev: network device for which tx intr is handled
+ *
+ * We have finished a transmit: check for errors and then trigger the next
+ * packet to be sent. Called with lock held.
+ */
+
+static void ei_tx_intr(struct net_device *dev)
+{
+       long e8390_base = dev->base_addr;
+       struct ei_device *ei_local = netdev_priv(dev);
+       int status = inb(e8390_base + EN0_TSR);
+    
+       /*
+        * There are two Tx buffers, see which one finished, and trigger
+        * the send of another one if it exists.
+        */
+       ei_local->txqueue--;
+
+       if (ei_local->tx1 < 0) 
+       {
+               if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
+                       netdev_err(dev, "%s: bogus last_tx_buffer %d, tx1=%d\n",
+                                  ei_local->name, ei_local->lasttx,
+                                  ei_local->tx1);
+               ei_local->tx1 = 0;
+               if (ei_local->tx2 > 0) 
+               {
+                       ei_local->txing = 1;
+                       NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
+                       dev->trans_start = jiffies;
+                       ei_local->tx2 = -1,
+                       ei_local->lasttx = 2;
+               }
+               else ei_local->lasttx = 20, ei_local->txing = 0;        
+       }
+       else if (ei_local->tx2 < 0) 
+       {
+               if (ei_local->lasttx != 2  &&  ei_local->lasttx != -2)
+                       netdev_info(dev, "%s: bogus last_tx_buffer %d, tx2=%d\n",
+                                   ei_local->name, ei_local->lasttx,
+                                   ei_local->tx2);
+               ei_local->tx2 = 0;
+               if (ei_local->tx1 > 0) 
+               {
+                       ei_local->txing = 1;
+                       NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
+                       dev->trans_start = jiffies;
+                       ei_local->tx1 = -1;
+                       ei_local->lasttx = 1;
+               }
+               else
+                       ei_local->lasttx = 10, ei_local->txing = 0;
+       }
+//     else
+//             netdev_warn(dev, "unexpected TX-done interrupt, lasttx=%d\n",
+//                         ei_local->lasttx);
+
+       /* Minimize Tx latency: update the statistics after we restart TXing. */
+       if (status & ENTSR_COL)
+               dev->stats.collisions++;
+       if (status & ENTSR_PTX)
+               dev->stats.tx_packets++;
+       else 
+       {
+               dev->stats.tx_errors++;
+               if (status & ENTSR_ABT) 
+               {
+                       dev->stats.tx_aborted_errors++;
+                       dev->stats.collisions += 16;
+               }
+               if (status & ENTSR_CRS) 
+                       dev->stats.tx_carrier_errors++;
+               if (status & ENTSR_FU) 
+                       dev->stats.tx_fifo_errors++;
+               if (status & ENTSR_CDH)
+                       dev->stats.tx_heartbeat_errors++;
+               if (status & ENTSR_OWC)
+                       dev->stats.tx_window_errors++;
+       }
+       netif_wake_queue(dev);
+}
+
+/**
+ * ei_receive - receive some packets
+ * @dev: network device with which receive will be run
+ *
+ * We have a good packet(s), get it/them out of the buffers. 
+ * Called with lock held.
+ */
+
+static void ei_receive(struct net_device *dev)
+{
+       long e8390_base = dev->base_addr;
+       struct ei_device *ei_local = netdev_priv(dev);
+       unsigned char rxing_page, this_frame, next_frame;
+       unsigned short current_offset;
+       int rx_pkt_count = 0;
+       struct e8390_pkt_hdr rx_frame;
+    
+       while (++rx_pkt_count < 10) 
+       {
+               int pkt_len, pkt_stat;
+               
+               /* Get the rx page (incoming packet pointer). */
+               rxing_page = inb_p(e8390_base + EN1_CURPAG -1);
+               
+               /* Remove one frame from the ring.  Boundary is always a page behind. */
+               this_frame = inb_p(e8390_base + EN0_BOUNDARY) + 1;
+               if (this_frame >= ei_local->stop_page)
+                       this_frame = ei_local->rx_start_page;
+               
+               /* Someday we'll omit the previous, iff we never get this message.
+                  (There is at least one clone claimed to have a problem.)  
+                  
+                  Keep quiet if it looks like a card removal. One problem here
+                  is that some clones crash in roughly the same way.
+                */
+               if (ei_debug > 0  &&  this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF))
+                   netdev_err(dev, "mismatched read page pointers %2x vs %2x\n",
+                              this_frame, ei_local->current_page);
+               
+               if (this_frame == rxing_page)   /* Read all the frames? */
+                       break;                          /* Done for now */
+               
+               current_offset = this_frame << 8;
+               ei_get_8390_hdr(dev, &rx_frame, this_frame);
+               
+               pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr);
+               pkt_stat = rx_frame.status;
+               
+               next_frame = this_frame + 1 + ((pkt_len+4)>>8);
+               
+               if (pkt_len < 60  ||  pkt_len > 1518) 
+               {
+                       if (ei_debug)
+                               netdev_printk(KERN_DEBUG, dev,
+                                             "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
+                                             rx_frame.count, rx_frame.status,
+                                             rx_frame.next);
+                       dev->stats.rx_errors++;
+                       dev->stats.rx_length_errors++;
+               }
+                else if ((pkt_stat & 0x0F) == ENRSR_RXOK) 
+               {
+                       struct sk_buff *skb;
+                       
+                       skb = dev_alloc_skb(pkt_len+2);
+                       if (skb == NULL) 
+                       {
+                               if (ei_debug > 1)
+                                       netdev_printk(KERN_DEBUG, dev,
+                                                     "Couldn't allocate a sk_buff of size %d\n",
+                                                     pkt_len);
+                               dev->stats.rx_dropped++;
+                               break;
+                       }
+                       else
+                       {
+                               skb_reserve(skb,2);     /* IP headers on 16 byte boundaries */
+                               skb_put(skb, pkt_len);  /* Make room */
+                               ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
+                               skb->protocol=eth_type_trans(skb,dev);
+                               netif_rx(skb);
+                               dev->stats.rx_packets++;
+                               dev->stats.rx_bytes += pkt_len;
+                               if (pkt_stat & ENRSR_PHY)
+                                       dev->stats.multicast++;
+                       }
+               } 
+               else 
+               {
+                       if (ei_debug)
+                               netdev_printk(KERN_DEBUG, dev,
+                                             "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
+                                             rx_frame.status, rx_frame.next,
+                                             rx_frame.count);
+                       dev->stats.rx_errors++;
+                       /* NB: The NIC counts CRC, frame and missed errors. */
+                       if (pkt_stat & ENRSR_FO)
+                               dev->stats.rx_fifo_errors++;
+               }
+               next_frame = rx_frame.next;
+               
+               /* This _should_ never happen: it's here for avoiding bad clones. */
+               if (next_frame >= ei_local->stop_page) {
+                       netdev_info(dev, "next frame inconsistency, %#2x\n",
+                                   next_frame);
+                       next_frame = ei_local->rx_start_page;
+               }
+               ei_local->current_page = next_frame;
+               outb_p(next_frame-1, e8390_base+EN0_BOUNDARY);
+       }
+}
+
+/**
+ * ei_rx_overrun - handle receiver overrun
+ * @dev: network device which threw exception
+ *
+ * We have a receiver overrun: we have to kick the 8390 to get it started
+ * again. Problem is that you have to kick it exactly as NS prescribes in
+ * the updated datasheets, or "the NIC may act in an unpredictable manner."
+ * This includes causing "the NIC to defer indefinitely when it is stopped
+ * on a busy network."  Ugh.
+ * Called with lock held. Don't call this with the interrupts off or your
+ * computer will hate you - it takes 10ms or so. 
+ */
+
+static void ei_rx_overrun(struct net_device *dev)
+{
+       axnet_dev_t *info = PRIV(dev);
+       long e8390_base = dev->base_addr;
+       unsigned char was_txing, must_resend = 0;
+    
+       /*
+        * Record whether a Tx was in progress and then issue the
+        * stop command.
+        */
+       was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
+       outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
+    
+       if (ei_debug > 1)
+               netdev_printk(KERN_DEBUG, dev, "Receiver overrun\n");
+       dev->stats.rx_over_errors++;
+    
+       /* 
+        * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
+        * We wait at least 2ms.
+        */
+
+       mdelay(2);
+
+       /*
+        * Reset RBCR[01] back to zero as per magic incantation.
+        */
+       outb_p(0x00, e8390_base+EN0_RCNTLO);
+       outb_p(0x00, e8390_base+EN0_RCNTHI);
+
+       /*
+        * See if any Tx was interrupted or not. According to NS, this
+        * step is vital, and skipping it will cause no end of havoc.
+        */
+
+       if (was_txing)
+       { 
+               unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
+               if (!tx_completed)
+                       must_resend = 1;
+       }
+
+       /*
+        * Have to enter loopback mode and then restart the NIC before
+        * you are allowed to slurp packets up off the ring.
+        */
+       outb_p(E8390_TXOFF, e8390_base + EN0_TXCR);
+       outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
+
+       /*
+        * Clear the Rx ring of all the debris, and ack the interrupt.
+        */
+       ei_receive(dev);
+
+       /*
+        * Leave loopback mode, and resend any packet that got stopped.
+        */
+       outb_p(E8390_TXCONFIG | info->duplex_flag, e8390_base + EN0_TXCR); 
+       if (must_resend)
+               outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
+}
+
+/*
+ *     Collect the stats. This is called unlocked and from several contexts.
+ */
+static struct net_device_stats *get_stats(struct net_device *dev)
+{
+       long ioaddr = dev->base_addr;
+       struct ei_device *ei_local = netdev_priv(dev);
+       unsigned long flags;
+    
+       /* If the card is stopped, just return the present stats. */
+       if (!netif_running(dev))
+               return &dev->stats;
+
+       spin_lock_irqsave(&ei_local->page_lock,flags);
+       /* Read the counter registers, assuming we are in page 0. */
+       dev->stats.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0);
+       dev->stats.rx_crc_errors   += inb_p(ioaddr + EN0_COUNTER1);
+       dev->stats.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
+    
+       return &dev->stats;
+}
+
+/*
+ * Form the 64 bit 8390 multicast table from the linked list of addresses
+ * associated with this dev structure.
+ */
+static inline void make_mc_bits(u8 *bits, struct net_device *dev)
+{
+       struct netdev_hw_addr *ha;
+       u32 crc;
+
+       netdev_for_each_mc_addr(ha, dev) {
+               crc = ether_crc(ETH_ALEN, ha->addr);
+               /* 
+                * The 8390 uses the 6 most significant bits of the
+                * CRC to index the multicast table.
+                */
+               bits[crc>>29] |= (1<<((crc>>26)&7));
+       }
+}
+
+/**
+ * do_set_multicast_list - set/clear multicast filter
+ * @dev: net device for which multicast filter is adjusted
+ *
+ *     Set or clear the multicast filter for this adaptor.
+ *     Must be called with lock held. 
+ */
+static void do_set_multicast_list(struct net_device *dev)
+{
+       long e8390_base = dev->base_addr;
+       int i;
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
+               memset(ei_local->mcfilter, 0, 8);
+               if (!netdev_mc_empty(dev))
+                       make_mc_bits(ei_local->mcfilter, dev);
+       } else {
+               /* set to accept-all */
+               memset(ei_local->mcfilter, 0xFF, 8);
+       }
+
+       outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
+       for(i = 0; i < 8; i++) 
+       {
+               outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
+       }
+       outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
+
+       if(dev->flags&IFF_PROMISC)
+               outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR);
+       else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev))
+               outb_p(E8390_RXCONFIG | 0x48, e8390_base + EN0_RXCR);
+       else
+               outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR);
+
+       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
+}
+
+/*
+ *     Called without lock held. This is invoked from user context and may
+ *     be parallel to just about everything else. Its also fairly quick and
+ *     not called too often. Must protect against both bh and irq users
+ */
+
+static void set_multicast_list(struct net_device *dev)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev_lock(dev), flags);
+       do_set_multicast_list(dev);
+       spin_unlock_irqrestore(&dev_lock(dev), flags);
+}      
+
+/* This page of functions should be 8390 generic */
+/* Follow National Semi's recommendations for initializing the "NIC". */
+
+/**
+ * AX88190_init - initialize 8390 hardware
+ * @dev: network device to initialize
+ * @startp: boolean.  non-zero value to initiate chip processing
+ *
+ *     Must be called with lock held.
+ */
+
+static void AX88190_init(struct net_device *dev, int startp)
+{
+       axnet_dev_t *info = PRIV(dev);
+       long e8390_base = dev->base_addr;
+       struct ei_device *ei_local = netdev_priv(dev);
+       int i;
+       int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48;
+    
+       if(sizeof(struct e8390_pkt_hdr)!=4)
+               panic("8390.c: header struct mispacked\n");    
+       /* Follow National Semi's recommendations for initing the DP83902. */
+       outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */
+       outb_p(endcfg, e8390_base + EN0_DCFG);  /* 0x48 or 0x49 */
+       /* Clear the remote byte count registers. */
+       outb_p(0x00,  e8390_base + EN0_RCNTLO);
+       outb_p(0x00,  e8390_base + EN0_RCNTHI);
+       /* Set to monitor and loopback mode -- this is vital!. */
+       outb_p(E8390_RXOFF|0x40, e8390_base + EN0_RXCR); /* 0x60 */
+       outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
+       /* Set the transmit page and receive ring. */
+       outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
+       ei_local->tx1 = ei_local->tx2 = 0;
+       outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG);
+       outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY);       /* 3c503 says 0x3f,NS0x26*/
+       ei_local->current_page = ei_local->rx_start_page;               /* assert boundary+1 */
+       outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG);
+       /* Clear the pending interrupts and mask. */
+       outb_p(0xFF, e8390_base + EN0_ISR);
+       outb_p(0x00,  e8390_base + EN0_IMR);
+    
+       /* Copy the station address into the DS8390 registers. */
+
+       outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
+       for(i = 0; i < 6; i++) 
+       {
+               outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
+               if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
+                       netdev_err(dev, "Hw. address read/write mismap %d\n", i);
+       }
+
+       outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
+       outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
+
+       netif_start_queue(dev);
+       ei_local->tx1 = ei_local->tx2 = 0;
+       ei_local->txing = 0;
+
+       if (info->flags & IS_AX88790)   /* select Internal PHY */
+               outb(0x10, e8390_base + AXNET_GPIO);
+
+       if (startp) 
+       {
+               outb_p(0xff,  e8390_base + EN0_ISR);
+               outb_p(ENISR_ALL,  e8390_base + EN0_IMR);
+               outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
+               outb_p(E8390_TXCONFIG | info->duplex_flag,
+                      e8390_base + EN0_TXCR); /* xmit on. */
+               /* 3c503 TechMan says rxconfig only after the NIC is started. */
+               outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR); /* rx on, */
+               do_set_multicast_list(dev);     /* (re)load the mcast table */
+       }
+}
+
+/* Trigger a transmit start, assuming the length is valid. 
+   Always called with the page lock held */
+   
+static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
+                                                               int start_page)
+{
+       long e8390_base = dev->base_addr;
+       struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev);
+    
+       if (inb_p(e8390_base) & E8390_TRANS) 
+       {
+               netdev_warn(dev, "trigger_send() called with the transmitter busy\n");
+               return;
+       }
+       outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
+       outb_p(length >> 8, e8390_base + EN0_TCNTHI);
+       outb_p(start_page, e8390_base + EN0_TPSR);
+       outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD);
+}
diff --git a/drivers/net/ethernet/8390/e2100.c b/drivers/net/ethernet/8390/e2100.c
new file mode 100644 (file)
index 0000000..d50a999
--- /dev/null
@@ -0,0 +1,490 @@
+/* e2100.c: A Cabletron E2100 series ethernet driver for linux. */
+/*
+       Written 1993-1994 by Donald Becker.
+
+       Copyright 1994 by Donald Becker.
+       Copyright 1993 United States Government as represented by the
+       Director, National Security Agency.  This software may be used and
+       distributed according to the terms of the GNU General Public License,
+       incorporated herein by reference.
+
+       This is a driver for the Cabletron E2100 series ethercards.
+
+       The Author may be reached as becker@scyld.com, or C/O
+       Scyld Computing Corporation
+       410 Severn Ave., Suite 210
+       Annapolis MD 21403
+
+       The E2100 series ethercard is a fairly generic shared memory 8390
+       implementation.  The only unusual aspect is the way the shared memory
+       registers are set: first you do an inb() in what is normally the
+       station address region, and the low three bits of next outb() *address*
+       is used as the write value for that register.  Either someone wasn't
+       too used to dem bit en bites, or they were trying to obfuscate the
+       programming interface.
+
+       There is an additional complication when setting the window on the packet
+       buffer.  You must first do a read into the packet buffer region with the
+       low 8 address bits the address setting the page for the start of the packet
+       buffer window, and then do the above operation.  See mem_on() for details.
+
+       One bug on the chip is that even a hard reset won't disable the memory
+       window, usually resulting in a hung machine if mem_off() isn't called.
+       If this happens, you must power down the machine for about 30 seconds.
+*/
+
+static const char version[] =
+       "e2100.c:v1.01 7/21/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+#define DRV_NAME "e2100"
+
+static int e21_probe_list[] = {0x300, 0x280, 0x380, 0x220, 0};
+
+/* Offsets from the base_addr.
+   Read from the ASIC register, and the low three bits of the next outb()
+   address is used to set the corresponding register. */
+#define E21_NIC_OFFSET  0              /* Offset to the 8390 NIC. */
+#define E21_ASIC               0x10
+#define E21_MEM_ENABLE 0x10
+#define  E21_MEM_ON            0x05    /* Enable memory in 16 bit mode. */
+#define  E21_MEM_ON_8  0x07    /* Enable memory in  8 bit mode. */
+#define E21_MEM_BASE   0x11
+#define E21_IRQ_LOW            0x12    /* The low three bits of the IRQ number. */
+#define E21_IRQ_HIGH   0x14    /* The high IRQ bit and media select ...  */
+#define E21_MEDIA              0x14    /* (alias). */
+#define  E21_ALT_IFPORT 0x02   /* Set to use the other (BNC,AUI) port. */
+#define  E21_BIG_MEM   0x04    /* Use a bigger (64K) buffer (we don't) */
+#define E21_SAPROM             0x10    /* Offset to station address data. */
+#define E21_IO_EXTENT   0x20
+
+static inline void mem_on(short port, volatile char __iomem *mem_base,
+                                                 unsigned char start_page )
+{
+       /* This is a little weird: set the shared memory window by doing a
+          read.  The low address bits specify the starting page. */
+       readb(mem_base+start_page);
+       inb(port + E21_MEM_ENABLE);
+       outb(E21_MEM_ON, port + E21_MEM_ENABLE + E21_MEM_ON);
+}
+
+static inline void mem_off(short port)
+{
+       inb(port + E21_MEM_ENABLE);
+       outb(0x00, port + E21_MEM_ENABLE);
+}
+
+/* In other drivers I put the TX pages first, but the E2100 window circuitry
+   is designed to have a 4K Tx region last. The windowing circuitry wraps the
+   window at 0x2fff->0x0000 so that the packets at e.g. 0x2f00 in the RX ring
+   appear contiguously in the window. */
+#define E21_RX_START_PG                0x00    /* First page of RX buffer */
+#define E21_RX_STOP_PG         0x30    /* Last page +1 of RX ring */
+#define E21_BIG_RX_STOP_PG     0xF0    /* Last page +1 of RX ring */
+#define E21_TX_START_PG                E21_RX_STOP_PG  /* First page of TX buffer */
+
+static int e21_probe1(struct net_device *dev, int ioaddr);
+
+static int e21_open(struct net_device *dev);
+static void e21_reset_8390(struct net_device *dev);
+static void e21_block_input(struct net_device *dev, int count,
+                                                  struct sk_buff *skb, int ring_offset);
+static void e21_block_output(struct net_device *dev, int count,
+                                                        const unsigned char *buf, int start_page);
+static void e21_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                                                       int ring_page);
+static int e21_open(struct net_device *dev);
+static int e21_close(struct net_device *dev);
+
+
+/*  Probe for the E2100 series ethercards.  These cards have an 8390 at the
+       base address and the station address at both offset 0x10 and 0x18.  I read
+       the station address from offset 0x18 to avoid the dataport of NE2000
+       ethercards, and look for Ctron's unique ID (first three octets of the
+       station address).
+ */
+
+static int  __init do_e2100_probe(struct net_device *dev)
+{
+       int *port;
+       int base_addr = dev->base_addr;
+       int irq = dev->irq;
+
+       if (base_addr > 0x1ff)          /* Check a single specified location. */
+               return e21_probe1(dev, base_addr);
+       else if (base_addr != 0)        /* Don't probe at all. */
+               return -ENXIO;
+
+       for (port = e21_probe_list; *port; port++) {
+               dev->irq = irq;
+               if (e21_probe1(dev, *port) == 0)
+                       return 0;
+       }
+
+       return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init e2100_probe(int unit)
+{
+       struct net_device *dev = alloc_ei_netdev();
+       int err;
+
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       sprintf(dev->name, "eth%d", unit);
+       netdev_boot_setup_check(dev);
+
+       err = do_e2100_probe(dev);
+       if (err)
+               goto out;
+       return dev;
+out:
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops e21_netdev_ops = {
+       .ndo_open               = e21_open,
+       .ndo_stop               = e21_close,
+
+       .ndo_start_xmit         = ei_start_xmit,
+       .ndo_tx_timeout         = ei_tx_timeout,
+       .ndo_get_stats          = ei_get_stats,
+       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = ei_poll,
+#endif
+};
+
+static int __init e21_probe1(struct net_device *dev, int ioaddr)
+{
+       int i, status, retval;
+       unsigned char *station_addr = dev->dev_addr;
+       static unsigned version_printed;
+
+       if (!request_region(ioaddr, E21_IO_EXTENT, DRV_NAME))
+               return -EBUSY;
+
+       /* First check the station address for the Ctron prefix. */
+       if (inb(ioaddr + E21_SAPROM + 0) != 0x00 ||
+           inb(ioaddr + E21_SAPROM + 1) != 0x00 ||
+           inb(ioaddr + E21_SAPROM + 2) != 0x1d) {
+               retval = -ENODEV;
+               goto out;
+       }
+
+       /* Verify by making certain that there is a 8390 at there. */
+       outb(E8390_NODMA + E8390_STOP, ioaddr);
+       udelay(1);      /* we want to delay one I/O cycle - which is 2MHz */
+       status = inb(ioaddr);
+       if (status != 0x21 && status != 0x23) {
+               retval = -ENODEV;
+               goto out;
+       }
+
+       /* Read the station address PROM.  */
+       for (i = 0; i < 6; i++)
+               station_addr[i] = inb(ioaddr + E21_SAPROM + i);
+
+       inb(ioaddr + E21_MEDIA);                /* Point to media selection. */
+       outb(0, ioaddr + E21_ASIC);     /* and disable the secondary interface. */
+
+       if (ei_debug  &&  version_printed++ == 0)
+               printk(version);
+
+       for (i = 0; i < 6; i++)
+               printk(" %02X", station_addr[i]);
+
+       if (dev->irq < 2) {
+               static const int irqlist[] = {15, 11, 10, 12, 5, 9, 3, 4};
+               for (i = 0; i < ARRAY_SIZE(irqlist); i++)
+                       if (request_irq (irqlist[i], NULL, 0, "bogus", NULL) != -EBUSY) {
+                               dev->irq = irqlist[i];
+                               break;
+                       }
+               if (i >= ARRAY_SIZE(irqlist)) {
+                       printk(" unable to get IRQ %d.\n", dev->irq);
+                       retval = -EAGAIN;
+                       goto out;
+               }
+       } else if (dev->irq == 2)       /* Fixup luser bogosity: IRQ2 is really IRQ9 */
+               dev->irq = 9;
+
+       /* The 8390 is at the base address. */
+       dev->base_addr = ioaddr;
+
+       ei_status.name = "E2100";
+       ei_status.word16 = 1;
+       ei_status.tx_start_page = E21_TX_START_PG;
+       ei_status.rx_start_page = E21_RX_START_PG;
+       ei_status.stop_page = E21_RX_STOP_PG;
+       ei_status.saved_irq = dev->irq;
+
+       /* Check the media port used.  The port can be passed in on the
+          low mem_end bits. */
+       if (dev->mem_end & 15)
+               dev->if_port = dev->mem_end & 7;
+       else {
+               dev->if_port = 0;
+               inb(ioaddr + E21_MEDIA);        /* Turn automatic media detection on. */
+               for(i = 0; i < 6; i++)
+                       if (station_addr[i] != inb(ioaddr + E21_SAPROM + 8 + i)) {
+                               dev->if_port = 1;
+                               break;
+                       }
+       }
+
+       /* Never map in the E21 shared memory unless you are actively using it.
+          Also, the shared memory has effective only one setting -- spread all
+          over the 128K region! */
+       if (dev->mem_start == 0)
+               dev->mem_start = 0xd0000;
+
+       ei_status.mem = ioremap(dev->mem_start, 2*1024);
+       if (!ei_status.mem) {
+               printk("unable to remap memory\n");
+               retval = -EAGAIN;
+               goto out;
+       }
+
+#ifdef notdef
+       /* These values are unused.  The E2100 has a 2K window into the packet
+          buffer.  The window can be set to start on any page boundary. */
+       ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
+       dev->mem_end = ei_status.rmem_end = dev->mem_start + 2*1024;
+#endif
+
+       printk(", IRQ %d, %s media, memory @ %#lx.\n", dev->irq,
+                  dev->if_port ? "secondary" : "primary", dev->mem_start);
+
+       ei_status.reset_8390 = &e21_reset_8390;
+       ei_status.block_input = &e21_block_input;
+       ei_status.block_output = &e21_block_output;
+       ei_status.get_8390_hdr = &e21_get_8390_hdr;
+
+       dev->netdev_ops = &e21_netdev_ops;
+       NS8390_init(dev, 0);
+
+       retval = register_netdev(dev);
+       if (retval)
+               goto out;
+       return 0;
+out:
+       release_region(ioaddr, E21_IO_EXTENT);
+       return retval;
+}
+
+static int
+e21_open(struct net_device *dev)
+{
+       short ioaddr = dev->base_addr;
+       int retval;
+
+       if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev)))
+               return retval;
+
+       /* Set the interrupt line and memory base on the hardware. */
+       inb(ioaddr + E21_IRQ_LOW);
+       outb(0, ioaddr + E21_ASIC + (dev->irq & 7));
+       inb(ioaddr + E21_IRQ_HIGH);                     /* High IRQ bit, and if_port. */
+       outb(0, ioaddr + E21_ASIC + (dev->irq > 7 ? 1:0)
+                  + (dev->if_port ? E21_ALT_IFPORT : 0));
+       inb(ioaddr + E21_MEM_BASE);
+       outb(0, ioaddr + E21_ASIC + ((dev->mem_start >> 17) & 7));
+
+       ei_open(dev);
+       return 0;
+}
+
+static void
+e21_reset_8390(struct net_device *dev)
+{
+       short ioaddr = dev->base_addr;
+
+       outb(0x01, ioaddr);
+       if (ei_debug > 1) printk("resetting the E2180x3 t=%ld...", jiffies);
+       ei_status.txing = 0;
+
+       /* Set up the ASIC registers, just in case something changed them. */
+
+       if (ei_debug > 1) printk("reset done\n");
+}
+
+/* Grab the 8390 specific header. We put the 2k window so the header page
+   appears at the start of the shared memory. */
+
+static void
+e21_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+
+       short ioaddr = dev->base_addr;
+       char __iomem *shared_mem = ei_status.mem;
+
+       mem_on(ioaddr, shared_mem, ring_page);
+
+#ifdef notdef
+       /* Officially this is what we are doing, but the readl() is faster */
+       memcpy_fromio(hdr, shared_mem, sizeof(struct e8390_pkt_hdr));
+#else
+       ((unsigned int*)hdr)[0] = readl(shared_mem);
+#endif
+
+       /* Turn off memory access: we would need to reprogram the window anyway. */
+       mem_off(ioaddr);
+
+}
+
+/*  Block input and output are easy on shared memory ethercards.
+       The E21xx makes block_input() especially easy by wrapping the top
+       ring buffer to the bottom automatically. */
+static void
+e21_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+       short ioaddr = dev->base_addr;
+       char __iomem *shared_mem = ei_status.mem;
+
+       mem_on(ioaddr, shared_mem, (ring_offset>>8));
+
+       memcpy_fromio(skb->data, ei_status.mem + (ring_offset & 0xff), count);
+
+       mem_off(ioaddr);
+}
+
+static void
+e21_block_output(struct net_device *dev, int count, const unsigned char *buf,
+                                int start_page)
+{
+       short ioaddr = dev->base_addr;
+       volatile char __iomem *shared_mem = ei_status.mem;
+
+       /* Set the shared memory window start by doing a read, with the low address
+          bits specifying the starting page. */
+       readb(shared_mem + start_page);
+       mem_on(ioaddr, shared_mem, start_page);
+
+       memcpy_toio(shared_mem, buf, count);
+       mem_off(ioaddr);
+}
+
+static int
+e21_close(struct net_device *dev)
+{
+       short ioaddr = dev->base_addr;
+
+       if (ei_debug > 1)
+               printk("%s: Shutting down ethercard.\n", dev->name);
+
+       free_irq(dev->irq, dev);
+       dev->irq = ei_status.saved_irq;
+
+       /* Shut off the interrupt line and secondary interface. */
+       inb(ioaddr + E21_IRQ_LOW);
+       outb(0, ioaddr + E21_ASIC);
+       inb(ioaddr + E21_IRQ_HIGH);                     /* High IRQ bit, and if_port. */
+       outb(0, ioaddr + E21_ASIC);
+
+       ei_close(dev);
+
+       /* Double-check that the memory has been turned off, because really
+          really bad things happen if it isn't. */
+       mem_off(ioaddr);
+
+       return 0;
+}
+
+
+#ifdef MODULE
+#define MAX_E21_CARDS  4       /* Max number of E21 cards per module */
+static struct net_device *dev_e21[MAX_E21_CARDS];
+static int io[MAX_E21_CARDS];
+static int irq[MAX_E21_CARDS];
+static int mem[MAX_E21_CARDS];
+static int xcvr[MAX_E21_CARDS];                /* choose int. or ext. xcvr */
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(mem, int, NULL, 0);
+module_param_array(xcvr, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_PARM_DESC(mem, " memory base address(es)");
+MODULE_PARM_DESC(xcvr, "transceiver(s) (0=internal, 1=external)");
+MODULE_DESCRIPTION("Cabletron E2100 ISA ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that only a single autoprobe takes place per call.
+ISA device autoprobes on a running machine are not recommended. */
+
+int __init init_module(void)
+{
+       struct net_device *dev;
+       int this_dev, found = 0;
+
+       for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
+               if (io[this_dev] == 0)  {
+                       if (this_dev != 0) break; /* only autoprobe 1st one */
+                       printk(KERN_NOTICE "e2100.c: Presently autoprobing (not recommended) for a single card.\n");
+               }
+               dev = alloc_ei_netdev();
+               if (!dev)
+                       break;
+               dev->irq = irq[this_dev];
+               dev->base_addr = io[this_dev];
+               dev->mem_start = mem[this_dev];
+               dev->mem_end = xcvr[this_dev];  /* low 4bits = xcvr sel. */
+               if (do_e2100_probe(dev) == 0) {
+                       dev_e21[found++] = dev;
+                       continue;
+               }
+               free_netdev(dev);
+               printk(KERN_WARNING "e2100.c: No E2100 card found (i/o = 0x%x).\n", io[this_dev]);
+               break;
+       }
+       if (found)
+               return 0;
+       return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+       /* NB: e21_close() handles free_irq */
+       iounmap(ei_status.mem);
+       release_region(dev->base_addr, E21_IO_EXTENT);
+}
+
+void __exit
+cleanup_module(void)
+{
+       int this_dev;
+
+       for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
+               struct net_device *dev = dev_e21[this_dev];
+               if (dev) {
+                       unregister_netdev(dev);
+                       cleanup_card(dev);
+                       free_netdev(dev);
+               }
+       }
+}
+#endif /* MODULE */
diff --git a/drivers/net/ethernet/8390/es3210.c b/drivers/net/ethernet/8390/es3210.c
new file mode 100644 (file)
index 0000000..7a09575
--- /dev/null
@@ -0,0 +1,446 @@
+/*
+       es3210.c
+
+       Linux driver for Racal-Interlan ES3210 EISA Network Adapter
+
+       Copyright (C) 1996, Paul Gortmaker.
+
+       This software may be used and distributed according to the terms
+       of the GNU General Public License, incorporated herein by reference.
+
+       Information and Code Sources:
+
+       1) The existing myriad of Linux 8390 drivers written by Donald Becker.
+
+       2) Once again Russ Nelson's asm packet driver provided additional info.
+
+       3) Info for getting IRQ and sh-mem gleaned from the EISA cfg files.
+          Too bad it doesn't work -- see below.
+
+       The ES3210 is an EISA shared memory NS8390 implementation. Note
+       that all memory copies to/from the board must be 32bit transfers.
+       Which rules out using eth_io_copy_and_sum() in this driver.
+
+       Apparently there are two slightly different revisions of the
+       card, since there are two distinct EISA cfg files (!rii0101.cfg
+       and !rii0102.cfg) One has media select in the cfg file and the
+       other doesn't. Hopefully this will work with either.
+
+       That is about all I can tell you about it, having never actually
+       even seen one of these cards. :)  Try http://www.interlan.com
+       if you want more info.
+
+       Thanks go to Mark Salazar for testing v0.02 of this driver.
+
+       Bugs, to-fix, etc:
+
+       1) The EISA cfg ports that are *supposed* to have the IRQ and shared
+          mem values just read 0xff all the time. Hrrmpf. Apparently the
+          same happens with the packet driver as the code for reading
+          these registers is disabled there. In the meantime, boot with:
+          ether=<IRQ>,0,0x<shared_mem_addr>,eth0 to override the IRQ and
+          shared memory detection. (The i/o port detection is okay.)
+
+       2) Module support currently untested. Probably works though.
+
+*/
+
+static const char version[] =
+       "es3210.c: Driver revision v0.03, 14/09/96\n";
+
+#include <linux/module.h>
+#include <linux/eisa.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+static int es_probe1(struct net_device *dev, int ioaddr);
+
+static void es_reset_8390(struct net_device *dev);
+
+static void es_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
+static void es_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset);
+static void es_block_output(struct net_device *dev, int count, const unsigned char *buf, int start_page);
+
+#define ES_START_PG    0x00    /* First page of TX buffer              */
+#define ES_STOP_PG     0x40    /* Last page +1 of RX ring              */
+
+#define ES_IO_EXTENT   0x37    /* The cfg file says 0xc90 -> 0xcc7     */
+#define ES_ID_PORT     0xc80   /* Same for all EISA cards              */
+#define ES_SA_PROM     0xc90   /* Start of e'net addr.                 */
+#define ES_RESET_PORT  0xc84   /* From the packet driver source        */
+#define ES_NIC_OFFSET  0xca0   /* Hello, the 8390 is *here*            */
+
+#define ES_ADDR0       0x02    /* 3 byte vendor prefix                 */
+#define ES_ADDR1       0x07
+#define ES_ADDR2       0x01
+
+/*
+ * Two card revisions. EISA ID's are always rev. minor, rev. major,, and
+ * then the three vendor letters stored in 5 bits each, with an "a" = 1.
+ * For eg: "rii" = 10010 01001 01001 = 0x4929, which is how the EISA
+ * config utility determines automagically what config file(s) to use.
+ */
+#define ES_EISA_ID1    0x01012949      /* !rii0101.cfg                 */
+#define ES_EISA_ID2    0x02012949      /* !rii0102.cfg                 */
+
+#define ES_CFG1                0xcc0   /* IOPORT(1) --> IOPORT(6) in cfg file  */
+#define ES_CFG2                0xcc1
+#define ES_CFG3                0xcc2
+#define ES_CFG4                0xcc3
+#define ES_CFG5                0xcc4
+#define ES_CFG6                0xc84   /* NB: 0xc84 is also "reset" port.      */
+
+/*
+ *     You can OR any of the following bits together and assign it
+ *     to ES_DEBUG to get verbose driver info during operation.
+ *     Some of these don't do anything yet.
+ */
+
+#define ES_D_PROBE     0x01
+#define ES_D_RX_PKT    0x02
+#define ES_D_TX_PKT    0x04
+#define ED_D_IRQ       0x08
+
+#define ES_DEBUG       0
+
+static unsigned char lo_irq_map[] __initdata = {3, 4, 5, 6, 7, 9, 10};
+static unsigned char hi_irq_map[] __initdata = {11, 12, 0, 14, 0, 0, 0, 15};
+
+/*
+ *     Probe for the card. The best way is to read the EISA ID if it
+ *     is known. Then we check the prefix of the station address
+ *     PROM for a match against the Racal-Interlan assigned value.
+ */
+
+static int __init do_es_probe(struct net_device *dev)
+{
+       unsigned short ioaddr = dev->base_addr;
+       int irq = dev->irq;
+       int mem_start = dev->mem_start;
+
+       if (ioaddr > 0x1ff)             /* Check a single specified location. */
+               return es_probe1(dev, ioaddr);
+       else if (ioaddr > 0)            /* Don't probe at all. */
+               return -ENXIO;
+
+       if (!EISA_bus) {
+#if ES_DEBUG & ES_D_PROBE
+               printk("es3210.c: Not EISA bus. Not probing high ports.\n");
+#endif
+               return -ENXIO;
+       }
+
+       /* EISA spec allows for up to 16 slots, but 8 is typical. */
+       for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
+               if (es_probe1(dev, ioaddr) == 0)
+                       return 0;
+               dev->irq = irq;
+               dev->mem_start = mem_start;
+       }
+
+       return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init es_probe(int unit)
+{
+       struct net_device *dev = alloc_ei_netdev();
+       int err;
+
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       sprintf(dev->name, "eth%d", unit);
+       netdev_boot_setup_check(dev);
+
+       err = do_es_probe(dev);
+       if (err)
+               goto out;
+       return dev;
+out:
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+#endif
+
+static int __init es_probe1(struct net_device *dev, int ioaddr)
+{
+       int i, retval;
+       unsigned long eisa_id;
+
+       if (!request_region(ioaddr + ES_SA_PROM, ES_IO_EXTENT, "es3210"))
+               return -ENODEV;
+
+#if ES_DEBUG & ES_D_PROBE
+       printk("es3210.c: probe at %#x, ID %#8x\n", ioaddr, inl(ioaddr + ES_ID_PORT));
+       printk("es3210.c: config regs: %#x %#x %#x %#x %#x %#x\n",
+               inb(ioaddr + ES_CFG1), inb(ioaddr + ES_CFG2), inb(ioaddr + ES_CFG3),
+               inb(ioaddr + ES_CFG4), inb(ioaddr + ES_CFG5), inb(ioaddr + ES_CFG6));
+#endif
+
+/*     Check the EISA ID of the card. */
+       eisa_id = inl(ioaddr + ES_ID_PORT);
+       if ((eisa_id != ES_EISA_ID1) && (eisa_id != ES_EISA_ID2)) {
+               retval = -ENODEV;
+               goto out;
+       }
+
+       for (i = 0; i < ETHER_ADDR_LEN ; i++)
+               dev->dev_addr[i] = inb(ioaddr + ES_SA_PROM + i);
+
+/*     Check the Racal vendor ID as well. */
+       if (dev->dev_addr[0] != ES_ADDR0 ||
+           dev->dev_addr[1] != ES_ADDR1 ||
+           dev->dev_addr[2] != ES_ADDR2) {
+               printk("es3210.c: card not found %pM (invalid_prefix).\n",
+                      dev->dev_addr);
+               retval = -ENODEV;
+               goto out;
+       }
+
+       printk("es3210.c: ES3210 rev. %ld at %#x, node %pM",
+              eisa_id>>24, ioaddr, dev->dev_addr);
+
+       /* Snarf the interrupt now. */
+       if (dev->irq == 0) {
+               unsigned char hi_irq = inb(ioaddr + ES_CFG2) & 0x07;
+               unsigned char lo_irq = inb(ioaddr + ES_CFG1) & 0xfe;
+
+               if (hi_irq != 0) {
+                       dev->irq = hi_irq_map[hi_irq - 1];
+               } else {
+                       int i = 0;
+                       while (lo_irq > (1<<i)) i++;
+                       dev->irq = lo_irq_map[i];
+               }
+               printk(" using IRQ %d", dev->irq);
+#if ES_DEBUG & ES_D_PROBE
+               printk("es3210.c: hi_irq %#x, lo_irq %#x, dev->irq = %d\n",
+                                       hi_irq, lo_irq, dev->irq);
+#endif
+       } else {
+               if (dev->irq == 2)
+                       dev->irq = 9;                   /* Doh! */
+               printk(" assigning IRQ %d", dev->irq);
+       }
+
+       if (request_irq(dev->irq, ei_interrupt, 0, "es3210", dev)) {
+               printk (" unable to get IRQ %d.\n", dev->irq);
+               retval = -EAGAIN;
+               goto out;
+       }
+
+       if (dev->mem_start == 0) {
+               unsigned char mem_enabled = inb(ioaddr + ES_CFG2) & 0xc0;
+               unsigned char mem_bits = inb(ioaddr + ES_CFG3) & 0x07;
+
+               if (mem_enabled != 0x80) {
+                       printk(" shared mem disabled - giving up\n");
+                       retval = -ENXIO;
+                       goto out1;
+               }
+               dev->mem_start = 0xC0000 + mem_bits*0x4000;
+               printk(" using ");
+       } else {
+               printk(" assigning ");
+       }
+
+       ei_status.mem = ioremap(dev->mem_start, (ES_STOP_PG - ES_START_PG)*256);
+       if (!ei_status.mem) {
+               printk("ioremap failed - giving up\n");
+               retval = -ENXIO;
+               goto out1;
+       }
+
+       dev->mem_end = dev->mem_start + (ES_STOP_PG - ES_START_PG)*256;
+
+       printk("mem %#lx-%#lx\n", dev->mem_start, dev->mem_end-1);
+
+#if ES_DEBUG & ES_D_PROBE
+       if (inb(ioaddr + ES_CFG5))
+               printk("es3210: Warning - DMA channel enabled, but not used here.\n");
+#endif
+       /* Note, point at the 8390, and not the card... */
+       dev->base_addr = ioaddr + ES_NIC_OFFSET;
+
+       ei_status.name = "ES3210";
+       ei_status.tx_start_page = ES_START_PG;
+       ei_status.rx_start_page = ES_START_PG + TX_PAGES;
+       ei_status.stop_page = ES_STOP_PG;
+       ei_status.word16 = 1;
+
+       if (ei_debug > 0)
+               printk(version);
+
+       ei_status.reset_8390 = &es_reset_8390;
+       ei_status.block_input = &es_block_input;
+       ei_status.block_output = &es_block_output;
+       ei_status.get_8390_hdr = &es_get_8390_hdr;
+
+       dev->netdev_ops = &ei_netdev_ops;
+       NS8390_init(dev, 0);
+
+       retval = register_netdev(dev);
+       if (retval)
+               goto out1;
+       return 0;
+out1:
+       free_irq(dev->irq, dev);
+out:
+       release_region(ioaddr + ES_SA_PROM, ES_IO_EXTENT);
+       return retval;
+}
+
+/*
+ *     Reset as per the packet driver method. Judging by the EISA cfg
+ *     file, this just toggles the "Board Enable" bits (bit 2 and 0).
+ */
+
+static void es_reset_8390(struct net_device *dev)
+{
+       unsigned short ioaddr = dev->base_addr;
+       unsigned long end;
+
+       outb(0x04, ioaddr + ES_RESET_PORT);
+       if (ei_debug > 1) printk("%s: resetting the ES3210...", dev->name);
+
+       end = jiffies + 2*HZ/100;
+        while ((signed)(end - jiffies) > 0) continue;
+
+       ei_status.txing = 0;
+       outb(0x01, ioaddr + ES_RESET_PORT);
+       if (ei_debug > 1) printk("reset done\n");
+}
+
+/*
+ *     Note: In the following three functions is the implicit assumption
+ *     that the associated memcpy will only use "rep; movsl" as long as
+ *     we keep the counts as some multiple of doublewords. This is a
+ *     requirement of the hardware, and also prevents us from using
+ *     eth_io_copy_and_sum() since we can't guarantee it will limit
+ *     itself to doubleword access.
+ */
+
+/*
+ *     Grab the 8390 specific header. Similar to the block_input routine, but
+ *     we don't need to be concerned with ring wrap as the header will be at
+ *     the start of a page, so we optimize accordingly. (A single doubleword.)
+ */
+
+static void
+es_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+       void __iomem *hdr_start = ei_status.mem + ((ring_page - ES_START_PG)<<8);
+       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+       hdr->count = (hdr->count + 3) & ~3;     /* Round up allocation. */
+}
+
+/*
+ *     Block input and output are easy on shared memory ethercards, the only
+ *     complication is when the ring buffer wraps. The count will already
+ *     be rounded up to a doubleword value via es_get_8390_hdr() above.
+ */
+
+static void es_block_input(struct net_device *dev, int count, struct sk_buff *skb,
+                                                 int ring_offset)
+{
+       void __iomem *xfer_start = ei_status.mem + ring_offset - ES_START_PG*256;
+
+       if (ring_offset + count > ES_STOP_PG*256) {
+               /* Packet wraps over end of ring buffer. */
+               int semi_count = ES_STOP_PG*256 - ring_offset;
+               memcpy_fromio(skb->data, xfer_start, semi_count);
+               count -= semi_count;
+               memcpy_fromio(skb->data + semi_count, ei_status.mem, count);
+       } else {
+               /* Packet is in one chunk. */
+               memcpy_fromio(skb->data, xfer_start, count);
+       }
+}
+
+static void es_block_output(struct net_device *dev, int count,
+                               const unsigned char *buf, int start_page)
+{
+       void __iomem *shmem = ei_status.mem + ((start_page - ES_START_PG)<<8);
+
+       count = (count + 3) & ~3;     /* Round up to doubleword */
+       memcpy_toio(shmem, buf, count);
+}
+
+#ifdef MODULE
+#define MAX_ES_CARDS   4       /* Max number of ES3210 cards per module */
+#define NAMELEN                8       /* # of chars for storing dev->name */
+static struct net_device *dev_es3210[MAX_ES_CARDS];
+static int io[MAX_ES_CARDS];
+static int irq[MAX_ES_CARDS];
+static int mem[MAX_ES_CARDS];
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(mem, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_PARM_DESC(mem, "memory base address(es)");
+MODULE_DESCRIPTION("Racal-Interlan ES3210 EISA ethernet driver");
+MODULE_LICENSE("GPL");
+
+int __init init_module(void)
+{
+       struct net_device *dev;
+       int this_dev, found = 0;
+
+       for (this_dev = 0; this_dev < MAX_ES_CARDS; this_dev++) {
+               if (io[this_dev] == 0 && this_dev != 0)
+                       break;
+               dev = alloc_ei_netdev();
+               if (!dev)
+                       break;
+               dev->irq = irq[this_dev];
+               dev->base_addr = io[this_dev];
+               dev->mem_start = mem[this_dev];
+               if (do_es_probe(dev) == 0) {
+                       dev_es3210[found++] = dev;
+                       continue;
+               }
+               free_netdev(dev);
+               printk(KERN_WARNING "es3210.c: No es3210 card found (i/o = 0x%x).\n", io[this_dev]);
+               break;
+       }
+       if (found)
+               return 0;
+       return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+       free_irq(dev->irq, dev);
+       release_region(dev->base_addr, ES_IO_EXTENT);
+       iounmap(ei_status.mem);
+}
+
+void __exit
+cleanup_module(void)
+{
+       int this_dev;
+
+       for (this_dev = 0; this_dev < MAX_ES_CARDS; this_dev++) {
+               struct net_device *dev = dev_es3210[this_dev];
+               if (dev) {
+                       unregister_netdev(dev);
+                       cleanup_card(dev);
+                       free_netdev(dev);
+               }
+       }
+}
+#endif /* MODULE */
+
diff --git a/drivers/net/ethernet/8390/etherh.c b/drivers/net/ethernet/8390/etherh.c
new file mode 100644 (file)
index 0000000..cf851fa
--- /dev/null
@@ -0,0 +1,866 @@
+/*
+ *  linux/drivers/acorn/net/etherh.c
+ *
+ *  Copyright (C) 2000-2002 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * NS8390 I-cubed EtherH and ANT EtherM specific driver
+ * Thanks to I-Cubed for information on their cards.
+ * EtherM conversion (C) 1999 Chris Kemp and Tim Watterton
+ * EtherM integration (C) 2000 Aleph One Ltd (Tak-Shing Chan)
+ * EtherM integration re-engineered by Russell King.
+ *
+ * Changelog:
+ *  08-12-1996 RMK     1.00    Created
+ *             RMK     1.03    Added support for EtherLan500 cards
+ *  23-11-1997 RMK     1.04    Added media autodetection
+ *  16-04-1998 RMK     1.05    Improved media autodetection
+ *  10-02-2000 RMK     1.06    Updated for 2.3.43
+ *  13-05-2000 RMK     1.07    Updated for 2.3.99-pre8
+ *  12-10-1999  CK/TEW         EtherM driver first release
+ *  21-12-2000 TTC             EtherH/EtherM integration
+ *  25-12-2000 RMK     1.08    Clean integration of EtherM into this driver.
+ *  03-01-2002 RMK     1.09    Always enable IRQs if we're in the nic slot.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/jiffies.h>
+
+#include <asm/system.h>
+#include <asm/ecard.h>
+#include <asm/io.h>
+
+#define EI_SHIFT(x)    (ei_local->reg_offset[x])
+
+#define ei_inb(_p)      readb((void __iomem *)_p)
+#define ei_outb(_v,_p)  writeb(_v,(void __iomem *)_p)
+#define ei_inb_p(_p)    readb((void __iomem *)_p)
+#define ei_outb_p(_v,_p) writeb(_v,(void __iomem *)_p)
+
+#define NET_DEBUG  0
+#define DEBUG_INIT 2
+
+#define DRV_NAME       "etherh"
+#define DRV_VERSION    "1.11"
+
+static char version[] __initdata =
+       "EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n";
+
+#include "lib8390.c"
+
+static unsigned int net_debug = NET_DEBUG;
+
+struct etherh_priv {
+       void __iomem    *ioc_fast;
+       void __iomem    *memc;
+       void __iomem    *dma_base;
+       unsigned int    id;
+       void __iomem    *ctrl_port;
+       unsigned char   ctrl;
+       u32             supported;
+};
+
+struct etherh_data {
+       unsigned long   ns8390_offset;
+       unsigned long   dataport_offset;
+       unsigned long   ctrlport_offset;
+       int             ctrl_ioc;
+       const char      name[16];
+       u32             supported;
+       unsigned char   tx_start_page;
+       unsigned char   stop_page;
+};
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("EtherH/EtherM driver");
+MODULE_LICENSE("GPL");
+
+#define ETHERH500_DATAPORT     0x800   /* MEMC */
+#define ETHERH500_NS8390       0x000   /* MEMC */
+#define ETHERH500_CTRLPORT     0x800   /* IOC  */
+
+#define ETHERH600_DATAPORT     0x040   /* MEMC */
+#define ETHERH600_NS8390       0x800   /* MEMC */
+#define ETHERH600_CTRLPORT     0x200   /* MEMC */
+
+#define ETHERH_CP_IE           1
+#define ETHERH_CP_IF           2
+#define ETHERH_CP_HEARTBEAT    2
+
+#define ETHERH_TX_START_PAGE   1
+#define ETHERH_STOP_PAGE       127
+
+/*
+ * These came from CK/TEW
+ */
+#define ETHERM_DATAPORT                0x200   /* MEMC */
+#define ETHERM_NS8390          0x800   /* MEMC */
+#define ETHERM_CTRLPORT                0x23c   /* MEMC */
+
+#define ETHERM_TX_START_PAGE   64
+#define ETHERM_STOP_PAGE       127
+
+/* ------------------------------------------------------------------------ */
+
+#define etherh_priv(dev) \
+ ((struct etherh_priv *)(((char *)netdev_priv(dev)) + sizeof(struct ei_device)))
+
+static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned char mask)
+{
+       unsigned char ctrl = eh->ctrl | mask;
+       eh->ctrl = ctrl;
+       writeb(ctrl, eh->ctrl_port);
+}
+
+static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned char mask)
+{
+       unsigned char ctrl = eh->ctrl & ~mask;
+       eh->ctrl = ctrl;
+       writeb(ctrl, eh->ctrl_port);
+}
+
+static inline unsigned int etherh_get_stat(struct etherh_priv *eh)
+{
+       return readb(eh->ctrl_port);
+}
+
+
+
+
+static void etherh_irq_enable(ecard_t *ec, int irqnr)
+{
+       struct etherh_priv *eh = ec->irq_data;
+
+       etherh_set_ctrl(eh, ETHERH_CP_IE);
+}
+
+static void etherh_irq_disable(ecard_t *ec, int irqnr)
+{
+       struct etherh_priv *eh = ec->irq_data;
+
+       etherh_clr_ctrl(eh, ETHERH_CP_IE);
+}
+
+static expansioncard_ops_t etherh_ops = {
+       .irqenable      = etherh_irq_enable,
+       .irqdisable     = etherh_irq_disable,
+};
+
+
+
+
+static void
+etherh_setif(struct net_device *dev)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       unsigned long flags;
+       void __iomem *addr;
+
+       local_irq_save(flags);
+
+       /* set the interface type */
+       switch (etherh_priv(dev)->id) {
+       case PROD_I3_ETHERLAN600:
+       case PROD_I3_ETHERLAN600A:
+               addr = (void __iomem *)dev->base_addr + EN0_RCNTHI;
+
+               switch (dev->if_port) {
+               case IF_PORT_10BASE2:
+                       writeb((readb(addr) & 0xf8) | 1, addr);
+                       break;
+               case IF_PORT_10BASET:
+                       writeb((readb(addr) & 0xf8), addr);
+                       break;
+               }
+               break;
+
+       case PROD_I3_ETHERLAN500:
+               switch (dev->if_port) {
+               case IF_PORT_10BASE2:
+                       etherh_clr_ctrl(etherh_priv(dev), ETHERH_CP_IF);
+                       break;
+
+               case IF_PORT_10BASET:
+                       etherh_set_ctrl(etherh_priv(dev), ETHERH_CP_IF);
+                       break;
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       local_irq_restore(flags);
+}
+
+static int
+etherh_getifstat(struct net_device *dev)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       void __iomem *addr;
+       int stat = 0;
+
+       switch (etherh_priv(dev)->id) {
+       case PROD_I3_ETHERLAN600:
+       case PROD_I3_ETHERLAN600A:
+               addr = (void __iomem *)dev->base_addr + EN0_RCNTHI;
+               switch (dev->if_port) {
+               case IF_PORT_10BASE2:
+                       stat = 1;
+                       break;
+               case IF_PORT_10BASET:
+                       stat = readb(addr) & 4;
+                       break;
+               }
+               break;
+
+       case PROD_I3_ETHERLAN500:
+               switch (dev->if_port) {
+               case IF_PORT_10BASE2:
+                       stat = 1;
+                       break;
+               case IF_PORT_10BASET:
+                       stat = etherh_get_stat(etherh_priv(dev)) & ETHERH_CP_HEARTBEAT;
+                       break;
+               }
+               break;
+
+       default:
+               stat = 0;
+               break;
+       }
+
+       return stat != 0;
+}
+
+/*
+ * Configure the interface.  Note that we ignore the other
+ * parts of ifmap, since its mostly meaningless for this driver.
+ */
+static int etherh_set_config(struct net_device *dev, struct ifmap *map)
+{
+       switch (map->port) {
+       case IF_PORT_10BASE2:
+       case IF_PORT_10BASET:
+               /*
+                * If the user explicitly sets the interface
+                * media type, turn off automedia detection.
+                */
+               dev->flags &= ~IFF_AUTOMEDIA;
+               dev->if_port = map->port;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       etherh_setif(dev);
+
+       return 0;
+}
+
+/*
+ * Reset the 8390 (hard reset).  Note that we can't actually do this.
+ */
+static void
+etherh_reset(struct net_device *dev)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       void __iomem *addr = (void __iomem *)dev->base_addr;
+
+       writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr);
+
+       /*
+        * See if we need to change the interface type.
+        * Note that we use 'interface_num' as a flag
+        * to indicate that we need to change the media.
+        */
+       if (dev->flags & IFF_AUTOMEDIA && ei_local->interface_num) {
+               ei_local->interface_num = 0;
+
+               if (dev->if_port == IF_PORT_10BASET)
+                       dev->if_port = IF_PORT_10BASE2;
+               else
+                       dev->if_port = IF_PORT_10BASET;
+
+               etherh_setif(dev);
+       }
+}
+
+/*
+ * Write a block of data out to the 8390
+ */
+static void
+etherh_block_output (struct net_device *dev, int count, const unsigned char *buf, int start_page)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       unsigned long dma_start;
+       void __iomem *dma_base, *addr;
+
+       if (ei_local->dmaing) {
+               printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: "
+                       " DMAstat %d irqlock %d\n", dev->name,
+                       ei_local->dmaing, ei_local->irqlock);
+               return;
+       }
+
+       /*
+        * Make sure we have a round number of bytes if we're in word mode.
+        */
+       if (count & 1 && ei_local->word16)
+               count++;
+
+       ei_local->dmaing = 1;
+
+       addr = (void __iomem *)dev->base_addr;
+       dma_base = etherh_priv(dev)->dma_base;
+
+       count = (count + 1) & ~1;
+       writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
+
+       writeb (0x42, addr + EN0_RCNTLO);
+       writeb (0x00, addr + EN0_RCNTHI);
+       writeb (0x42, addr + EN0_RSARLO);
+       writeb (0x00, addr + EN0_RSARHI);
+       writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
+
+       udelay (1);
+
+       writeb (ENISR_RDC, addr + EN0_ISR);
+       writeb (count, addr + EN0_RCNTLO);
+       writeb (count >> 8, addr + EN0_RCNTHI);
+       writeb (0, addr + EN0_RSARLO);
+       writeb (start_page, addr + EN0_RSARHI);
+       writeb (E8390_RWRITE | E8390_START, addr + E8390_CMD);
+
+       if (ei_local->word16)
+               writesw (dma_base, buf, count >> 1);
+       else
+               writesb (dma_base, buf, count);
+
+       dma_start = jiffies;
+
+       while ((readb (addr + EN0_ISR) & ENISR_RDC) == 0)
+               if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */
+                       printk(KERN_ERR "%s: timeout waiting for TX RDC\n",
+                               dev->name);
+                       etherh_reset (dev);
+                       __NS8390_init (dev, 1);
+                       break;
+               }
+
+       writeb (ENISR_RDC, addr + EN0_ISR);
+       ei_local->dmaing = 0;
+}
+
+/*
+ * Read a block of data from the 8390
+ */
+static void
+etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       unsigned char *buf;
+       void __iomem *dma_base, *addr;
+
+       if (ei_local->dmaing) {
+               printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: "
+                       " DMAstat %d irqlock %d\n", dev->name,
+                       ei_local->dmaing, ei_local->irqlock);
+               return;
+       }
+
+       ei_local->dmaing = 1;
+
+       addr = (void __iomem *)dev->base_addr;
+       dma_base = etherh_priv(dev)->dma_base;
+
+       buf = skb->data;
+       writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
+       writeb (count, addr + EN0_RCNTLO);
+       writeb (count >> 8, addr + EN0_RCNTHI);
+       writeb (ring_offset, addr + EN0_RSARLO);
+       writeb (ring_offset >> 8, addr + EN0_RSARHI);
+       writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
+
+       if (ei_local->word16) {
+               readsw (dma_base, buf, count >> 1);
+               if (count & 1)
+                       buf[count - 1] = readb (dma_base);
+       } else
+               readsb (dma_base, buf, count);
+
+       writeb (ENISR_RDC, addr + EN0_ISR);
+       ei_local->dmaing = 0;
+}
+
+/*
+ * Read a header from the 8390
+ */
+static void
+etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       void __iomem *dma_base, *addr;
+
+       if (ei_local->dmaing) {
+               printk(KERN_ERR "%s: DMAing conflict in etherh_get_header: "
+                       " DMAstat %d irqlock %d\n", dev->name,
+                       ei_local->dmaing, ei_local->irqlock);
+               return;
+       }
+
+       ei_local->dmaing = 1;
+
+       addr = (void __iomem *)dev->base_addr;
+       dma_base = etherh_priv(dev)->dma_base;
+
+       writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
+       writeb (sizeof (*hdr), addr + EN0_RCNTLO);
+       writeb (0, addr + EN0_RCNTHI);
+       writeb (0, addr + EN0_RSARLO);
+       writeb (ring_page, addr + EN0_RSARHI);
+       writeb (E8390_RREAD | E8390_START, addr + E8390_CMD);
+
+       if (ei_local->word16)
+               readsw (dma_base, hdr, sizeof (*hdr) >> 1);
+       else
+               readsb (dma_base, hdr, sizeof (*hdr));
+
+       writeb (ENISR_RDC, addr + EN0_ISR);
+       ei_local->dmaing = 0;
+}
+
+/*
+ * Open/initialize the board.  This is called (in the current kernel)
+ * sometime after booting when the 'ifconfig' program is run.
+ *
+ * This routine should set everything up anew at each open, even
+ * registers that "should" only need to be set once at boot, so that
+ * there is non-reboot way to recover if something goes wrong.
+ */
+static int
+etherh_open(struct net_device *dev)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       if (!is_valid_ether_addr(dev->dev_addr)) {
+               printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
+                       dev->name);
+               return -EINVAL;
+       }
+
+       if (request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev))
+               return -EAGAIN;
+
+       /*
+        * Make sure that we aren't going to change the
+        * media type on the next reset - we are about to
+        * do automedia manually now.
+        */
+       ei_local->interface_num = 0;
+
+       /*
+        * If we are doing automedia detection, do it now.
+        * This is more reliable than the 8390's detection.
+        */
+       if (dev->flags & IFF_AUTOMEDIA) {
+               dev->if_port = IF_PORT_10BASET;
+               etherh_setif(dev);
+               mdelay(1);
+               if (!etherh_getifstat(dev)) {
+                       dev->if_port = IF_PORT_10BASE2;
+                       etherh_setif(dev);
+               }
+       } else
+               etherh_setif(dev);
+
+       etherh_reset(dev);
+       __ei_open(dev);
+
+       return 0;
+}
+
+/*
+ * The inverse routine to etherh_open().
+ */
+static int
+etherh_close(struct net_device *dev)
+{
+       __ei_close (dev);
+       free_irq (dev->irq, dev);
+       return 0;
+}
+
+/*
+ * Initialisation
+ */
+
+static void __init etherh_banner(void)
+{
+       static int version_printed;
+
+       if (net_debug && version_printed++ == 0)
+               printk(KERN_INFO "%s", version);
+}
+
+/*
+ * Read the ethernet address string from the on board rom.
+ * This is an ascii string...
+ */
+static int __devinit etherh_addr(char *addr, struct expansion_card *ec)
+{
+       struct in_chunk_dir cd;
+       char *s;
+       
+       if (!ecard_readchunk(&cd, ec, 0xf5, 0)) {
+               printk(KERN_ERR "%s: unable to read podule description string\n",
+                      dev_name(&ec->dev));
+               goto no_addr;
+       }
+
+       s = strchr(cd.d.string, '(');
+       if (s) {
+               int i;
+
+               for (i = 0; i < 6; i++) {
+                       addr[i] = simple_strtoul(s + 1, &s, 0x10);
+                       if (*s != (i == 5? ')' : ':'))
+                               break;
+               }
+
+               if (i == 6)
+                       return 0;
+       }
+
+       printk(KERN_ERR "%s: unable to parse MAC address: %s\n",
+              dev_name(&ec->dev), cd.d.string);
+
+ no_addr:
+       return -ENODEV;
+}
+
+/*
+ * Create an ethernet address from the system serial number.
+ */
+static int __init etherm_addr(char *addr)
+{
+       unsigned int serial;
+
+       if (system_serial_low == 0 && system_serial_high == 0)
+               return -ENODEV;
+
+       serial = system_serial_low | system_serial_high;
+
+       addr[0] = 0;
+       addr[1] = 0;
+       addr[2] = 0xa4;
+       addr[3] = 0x10 + (serial >> 24);
+       addr[4] = serial >> 16;
+       addr[5] = serial >> 8;
+       return 0;
+}
+
+static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+       strlcpy(info->bus_info, dev_name(dev->dev.parent),
+               sizeof(info->bus_info));
+}
+
+static int etherh_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       cmd->supported  = etherh_priv(dev)->supported;
+       ethtool_cmd_speed_set(cmd, SPEED_10);
+       cmd->duplex     = DUPLEX_HALF;
+       cmd->port       = dev->if_port == IF_PORT_10BASET ? PORT_TP : PORT_BNC;
+       cmd->autoneg    = (dev->flags & IFF_AUTOMEDIA ?
+                          AUTONEG_ENABLE : AUTONEG_DISABLE);
+       return 0;
+}
+
+static int etherh_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+       switch (cmd->autoneg) {
+       case AUTONEG_ENABLE:
+               dev->flags |= IFF_AUTOMEDIA;
+               break;
+
+       case AUTONEG_DISABLE:
+               switch (cmd->port) {
+               case PORT_TP:
+                       dev->if_port = IF_PORT_10BASET;
+                       break;
+
+               case PORT_BNC:
+                       dev->if_port = IF_PORT_10BASE2;
+                       break;
+
+               default:
+                       return -EINVAL;
+               }
+               dev->flags &= ~IFF_AUTOMEDIA;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       etherh_setif(dev);
+
+       return 0;
+}
+
+static const struct ethtool_ops etherh_ethtool_ops = {
+       .get_settings   = etherh_get_settings,
+       .set_settings   = etherh_set_settings,
+       .get_drvinfo    = etherh_get_drvinfo,
+};
+
+static const struct net_device_ops etherh_netdev_ops = {
+       .ndo_open               = etherh_open,
+       .ndo_stop               = etherh_close,
+       .ndo_set_config         = etherh_set_config,
+       .ndo_start_xmit         = __ei_start_xmit,
+       .ndo_tx_timeout         = __ei_tx_timeout,
+       .ndo_get_stats          = __ei_get_stats,
+       .ndo_set_multicast_list = __ei_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = __ei_poll,
+#endif
+};
+
+static u32 etherh_regoffsets[16];
+static u32 etherm_regoffsets[16];
+
+static int __devinit
+etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
+{
+       const struct etherh_data *data = id->data;
+       struct ei_device *ei_local;
+       struct net_device *dev;
+       struct etherh_priv *eh;
+       int ret;
+
+       etherh_banner();
+
+       ret = ecard_request_resources(ec);
+       if (ret)
+               goto out;
+
+       dev = ____alloc_ei_netdev(sizeof(struct etherh_priv));
+       if (!dev) {
+               ret = -ENOMEM;
+               goto release;
+       }
+
+       SET_NETDEV_DEV(dev, &ec->dev);
+
+       dev->netdev_ops         = &etherh_netdev_ops;
+       dev->irq                = ec->irq;
+       dev->ethtool_ops        = &etherh_ethtool_ops;
+
+       if (data->supported & SUPPORTED_Autoneg)
+               dev->flags |= IFF_AUTOMEDIA;
+       if (data->supported & SUPPORTED_TP) {
+               dev->flags |= IFF_PORTSEL;
+               dev->if_port = IF_PORT_10BASET;
+       } else if (data->supported & SUPPORTED_BNC) {
+               dev->flags |= IFF_PORTSEL;
+               dev->if_port = IF_PORT_10BASE2;
+       } else
+               dev->if_port = IF_PORT_UNKNOWN;
+
+       eh = etherh_priv(dev);
+       eh->supported           = data->supported;
+       eh->ctrl                = 0;
+       eh->id                  = ec->cid.product;
+       eh->memc                = ecardm_iomap(ec, ECARD_RES_MEMC, 0, PAGE_SIZE);
+       if (!eh->memc) {
+               ret = -ENOMEM;
+               goto free;
+       }
+
+       eh->ctrl_port = eh->memc;
+       if (data->ctrl_ioc) {
+               eh->ioc_fast = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, PAGE_SIZE);
+               if (!eh->ioc_fast) {
+                       ret = -ENOMEM;
+                       goto free;
+               }
+               eh->ctrl_port = eh->ioc_fast;
+       }
+
+       dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset;
+       eh->dma_base = eh->memc + data->dataport_offset;
+       eh->ctrl_port += data->ctrlport_offset;
+
+       /*
+        * IRQ and control port handling - only for non-NIC slot cards.
+        */
+       if (ec->slot_no != 8) {
+               ecard_setirq(ec, &etherh_ops, eh);
+       } else {
+               /*
+                * If we're in the NIC slot, make sure the IRQ is enabled
+                */
+               etherh_set_ctrl(eh, ETHERH_CP_IE);
+       }
+
+       ei_local = netdev_priv(dev);
+       spin_lock_init(&ei_local->page_lock);
+
+       if (ec->cid.product == PROD_ANT_ETHERM) {
+               etherm_addr(dev->dev_addr);
+               ei_local->reg_offset = etherm_regoffsets;
+       } else {
+               etherh_addr(dev->dev_addr, ec);
+               ei_local->reg_offset = etherh_regoffsets;
+       }
+
+       ei_local->name          = dev->name;
+       ei_local->word16        = 1;
+       ei_local->tx_start_page = data->tx_start_page;
+       ei_local->rx_start_page = ei_local->tx_start_page + TX_PAGES;
+       ei_local->stop_page     = data->stop_page;
+       ei_local->reset_8390    = etherh_reset;
+       ei_local->block_input   = etherh_block_input;
+       ei_local->block_output  = etherh_block_output;
+       ei_local->get_8390_hdr  = etherh_get_header;
+       ei_local->interface_num = 0;
+
+       etherh_reset(dev);
+       __NS8390_init(dev, 0);
+
+       ret = register_netdev(dev);
+       if (ret)
+               goto free;
+
+       printk(KERN_INFO "%s: %s in slot %d, %pM\n",
+               dev->name, data->name, ec->slot_no, dev->dev_addr);
+
+       ecard_set_drvdata(ec, dev);
+
+       return 0;
+
+ free:
+       free_netdev(dev);
+ release:
+       ecard_release_resources(ec);
+ out:
+       return ret;
+}
+
+static void __devexit etherh_remove(struct expansion_card *ec)
+{
+       struct net_device *dev = ecard_get_drvdata(ec);
+
+       ecard_set_drvdata(ec, NULL);
+
+       unregister_netdev(dev);
+
+       free_netdev(dev);
+
+       ecard_release_resources(ec);
+}
+
+static struct etherh_data etherm_data = {
+       .ns8390_offset          = ETHERM_NS8390,
+       .dataport_offset        = ETHERM_NS8390 + ETHERM_DATAPORT,
+       .ctrlport_offset        = ETHERM_NS8390 + ETHERM_CTRLPORT,
+       .name                   = "ANT EtherM",
+       .supported              = SUPPORTED_10baseT_Half,
+       .tx_start_page          = ETHERM_TX_START_PAGE,
+       .stop_page              = ETHERM_STOP_PAGE,
+};
+
+static struct etherh_data etherlan500_data = {
+       .ns8390_offset          = ETHERH500_NS8390,
+       .dataport_offset        = ETHERH500_NS8390 + ETHERH500_DATAPORT,
+       .ctrlport_offset        = ETHERH500_CTRLPORT,
+       .ctrl_ioc               = 1,
+       .name                   = "i3 EtherH 500",
+       .supported              = SUPPORTED_10baseT_Half,
+       .tx_start_page          = ETHERH_TX_START_PAGE,
+       .stop_page              = ETHERH_STOP_PAGE,
+};
+
+static struct etherh_data etherlan600_data = {
+       .ns8390_offset          = ETHERH600_NS8390,
+       .dataport_offset        = ETHERH600_NS8390 + ETHERH600_DATAPORT,
+       .ctrlport_offset        = ETHERH600_NS8390 + ETHERH600_CTRLPORT,
+       .name                   = "i3 EtherH 600",
+       .supported              = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg,
+       .tx_start_page          = ETHERH_TX_START_PAGE,
+       .stop_page              = ETHERH_STOP_PAGE,
+};
+
+static struct etherh_data etherlan600a_data = {
+       .ns8390_offset          = ETHERH600_NS8390,
+       .dataport_offset        = ETHERH600_NS8390 + ETHERH600_DATAPORT,
+       .ctrlport_offset        = ETHERH600_NS8390 + ETHERH600_CTRLPORT,
+       .name                   = "i3 EtherH 600A",
+       .supported              = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg,
+       .tx_start_page          = ETHERH_TX_START_PAGE,
+       .stop_page              = ETHERH_STOP_PAGE,
+};
+
+static const struct ecard_id etherh_ids[] = {
+       { MANU_ANT, PROD_ANT_ETHERM,      &etherm_data       },
+       { MANU_I3,  PROD_I3_ETHERLAN500,  &etherlan500_data  },
+       { MANU_I3,  PROD_I3_ETHERLAN600,  &etherlan600_data  },
+       { MANU_I3,  PROD_I3_ETHERLAN600A, &etherlan600a_data },
+       { 0xffff,   0xffff }
+};
+
+static struct ecard_driver etherh_driver = {
+       .probe          = etherh_probe,
+       .remove         = __devexit_p(etherh_remove),
+       .id_table       = etherh_ids,
+       .drv = {
+               .name   = DRV_NAME,
+       },
+};
+
+static int __init etherh_init(void)
+{
+       int i;
+
+       for (i = 0; i < 16; i++) {
+               etherh_regoffsets[i] = i << 2;
+               etherm_regoffsets[i] = i << 5;
+       }
+
+       return ecard_register_driver(&etherh_driver);
+}
+
+static void __exit etherh_exit(void)
+{
+       ecard_remove_driver(&etherh_driver);
+}
+
+module_init(etherh_init);
+module_exit(etherh_exit);
diff --git a/drivers/net/ethernet/8390/hp-plus.c b/drivers/net/ethernet/8390/hp-plus.c
new file mode 100644 (file)
index 0000000..2991736
--- /dev/null
@@ -0,0 +1,506 @@
+/* hp-plus.c: A HP PCLAN/plus ethernet driver for linux. */
+/*
+       Written 1994 by Donald Becker.
+
+       This driver is for the Hewlett Packard PC LAN (27***) plus ethercards.
+       These cards are sold under several model numbers, usually 2724*.
+
+       This software may be used and distributed according to the terms
+       of the GNU General Public License, incorporated herein by reference.
+
+       The author may be reached as becker@scyld.com, or C/O
+       Scyld Computing Corporation
+       410 Severn Ave., Suite 210
+       Annapolis MD 21403
+
+       As is often the case, a great deal of credit is owed to Russ Nelson.
+       The Crynwr packet driver was my primary source of HP-specific
+       programming information.
+*/
+
+static const char version[] =
+"hp-plus.c:v1.10 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include <linux/module.h>
+
+#include <linux/string.h>              /* Important -- this inlines word moves. */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include "8390.h"
+
+#define DRV_NAME "hp-plus"
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int hpplus_portlist[] __initdata =
+{0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0};
+
+/*
+   The HP EtherTwist chip implementation is a fairly routine DP8390
+   implementation.  It allows both shared memory and programmed-I/O buffer
+   access, using a custom interface for both.  The programmed-I/O mode is
+   entirely implemented in the HP EtherTwist chip, bypassing the problem
+   ridden built-in 8390 facilities used on NE2000 designs.  The shared
+   memory mode is likewise special, with an offset register used to make
+   packets appear at the shared memory base.  Both modes use a base and bounds
+   page register to hide the Rx ring buffer wrap -- a packet that spans the
+   end of physical buffer memory appears continuous to the driver. (c.f. the
+   3c503 and Cabletron E2100)
+
+   A special note: the internal buffer of the board is only 8 bits wide.
+   This lays several nasty traps for the unaware:
+   - the 8390 must be programmed for byte-wide operations
+   - all I/O and memory operations must work on whole words (the access
+     latches are serially preloaded and have no byte-swapping ability).
+
+   This board is laid out in I/O space much like the earlier HP boards:
+   the first 16 locations are for the board registers, and the second 16 are
+   for the 8390.  The board is easy to identify, with both a dedicated 16 bit
+   ID register and a constant 0x530* value in the upper bits of the paging
+   register.
+*/
+
+#define HP_ID                  0x00    /* ID register, always 0x4850. */
+#define HP_PAGING              0x02    /* Registers visible @ 8-f, see PageName. */
+#define HPP_OPTION             0x04    /* Bitmapped options, see HP_Option.    */
+#define HPP_OUT_ADDR   0x08    /* I/O output location in Perf_Page.    */
+#define HPP_IN_ADDR            0x0A    /* I/O input location in Perf_Page.             */
+#define HP_DATAPORT            0x0c    /* I/O data transfer in Perf_Page.              */
+#define NIC_OFFSET             0x10    /* Offset to the 8390 registers.                */
+#define HP_IO_EXTENT   32
+
+#define HP_START_PG            0x00    /* First page of TX buffer */
+#define HP_STOP_PG             0x80    /* Last page +1 of RX ring */
+
+/* The register set selected in HP_PAGING. */
+enum PageName {
+       Perf_Page = 0,                          /* Normal operation. */
+       MAC_Page = 1,                           /* The ethernet address (+checksum). */
+       HW_Page = 2,                            /* EEPROM-loaded hardware parameters. */
+       LAN_Page = 4,                           /* Transceiver selection, testing, etc. */
+       ID_Page = 6 };
+
+/* The bit definitions for the HPP_OPTION register. */
+enum HP_Option {
+       NICReset = 1, ChipReset = 2,    /* Active low, really UNreset. */
+       EnableIRQ = 4, FakeIntr = 8, BootROMEnb = 0x10, IOEnb = 0x20,
+       MemEnable = 0x40, ZeroWait = 0x80, MemDisable = 0x1000, };
+
+static int hpp_probe1(struct net_device *dev, int ioaddr);
+
+static void hpp_reset_8390(struct net_device *dev);
+static int hpp_open(struct net_device *dev);
+static int hpp_close(struct net_device *dev);
+static void hpp_mem_block_input(struct net_device *dev, int count,
+                                                 struct sk_buff *skb, int ring_offset);
+static void hpp_mem_block_output(struct net_device *dev, int count,
+                                                       const unsigned char *buf, int start_page);
+static void hpp_mem_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                                                 int ring_page);
+static void hpp_io_block_input(struct net_device *dev, int count,
+                                                 struct sk_buff *skb, int ring_offset);
+static void hpp_io_block_output(struct net_device *dev, int count,
+                                                       const unsigned char *buf, int start_page);
+static void hpp_io_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                                                 int ring_page);
+
+
+/*     Probe a list of addresses for an HP LAN+ adaptor.
+       This routine is almost boilerplate. */
+
+static int __init do_hpp_probe(struct net_device *dev)
+{
+       int i;
+       int base_addr = dev->base_addr;
+       int irq = dev->irq;
+
+       if (base_addr > 0x1ff)          /* Check a single specified location. */
+               return hpp_probe1(dev, base_addr);
+       else if (base_addr != 0)        /* Don't probe at all. */
+               return -ENXIO;
+
+       for (i = 0; hpplus_portlist[i]; i++) {
+               if (hpp_probe1(dev, hpplus_portlist[i]) == 0)
+                       return 0;
+               dev->irq = irq;
+       }
+
+       return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init hp_plus_probe(int unit)
+{
+       struct net_device *dev = alloc_eip_netdev();
+       int err;
+
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       sprintf(dev->name, "eth%d", unit);
+       netdev_boot_setup_check(dev);
+
+       err = do_hpp_probe(dev);
+       if (err)
+               goto out;
+       return dev;
+out:
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops hpp_netdev_ops = {
+       .ndo_open               = hpp_open,
+       .ndo_stop               = hpp_close,
+       .ndo_start_xmit         = eip_start_xmit,
+       .ndo_tx_timeout         = eip_tx_timeout,
+       .ndo_get_stats          = eip_get_stats,
+       .ndo_set_multicast_list = eip_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = eip_poll,
+#endif
+};
+
+
+/* Do the interesting part of the probe at a single address. */
+static int __init hpp_probe1(struct net_device *dev, int ioaddr)
+{
+       int i, retval;
+       unsigned char checksum = 0;
+       const char name[] = "HP-PC-LAN+";
+       int mem_start;
+       static unsigned version_printed;
+
+       if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME))
+               return -EBUSY;
+
+       /* Check for the HP+ signature, 50 48 0x 53. */
+       if (inw(ioaddr + HP_ID) != 0x4850 ||
+           (inw(ioaddr + HP_PAGING) & 0xfff0) != 0x5300) {
+               retval = -ENODEV;
+               goto out;
+       }
+
+       if (ei_debug  &&  version_printed++ == 0)
+               printk(version);
+
+       printk("%s: %s at %#3x, ", dev->name, name, ioaddr);
+
+       /* Retrieve and checksum the station address. */
+       outw(MAC_Page, ioaddr + HP_PAGING);
+
+       for(i = 0; i < ETHER_ADDR_LEN; i++) {
+               unsigned char inval = inb(ioaddr + 8 + i);
+               dev->dev_addr[i] = inval;
+               checksum += inval;
+       }
+       checksum += inb(ioaddr + 14);
+
+       printk("%pM", dev->dev_addr);
+
+       if (checksum != 0xff) {
+               printk(" bad checksum %2.2x.\n", checksum);
+               retval = -ENODEV;
+               goto out;
+       } else {
+               /* Point at the Software Configuration Flags. */
+               outw(ID_Page, ioaddr + HP_PAGING);
+               printk(" ID %4.4x", inw(ioaddr + 12));
+       }
+
+       /* Read the IRQ line. */
+       outw(HW_Page, ioaddr + HP_PAGING);
+       {
+               int irq = inb(ioaddr + 13) & 0x0f;
+               int option = inw(ioaddr + HPP_OPTION);
+
+               dev->irq = irq;
+               if (option & MemEnable) {
+                       mem_start = inw(ioaddr + 9) << 8;
+                       printk(", IRQ %d, memory address %#x.\n", irq, mem_start);
+               } else {
+                       mem_start = 0;
+                       printk(", IRQ %d, programmed-I/O mode.\n", irq);
+               }
+       }
+
+       /* Set the wrap registers for string I/O reads.   */
+       outw((HP_START_PG + TX_PAGES/2) | ((HP_STOP_PG - 1) << 8), ioaddr + 14);
+
+       /* Set the base address to point to the NIC, not the "real" base! */
+       dev->base_addr = ioaddr + NIC_OFFSET;
+
+       dev->netdev_ops = &hpp_netdev_ops;
+
+       ei_status.name = name;
+       ei_status.word16 = 0;           /* Agggghhhhh! Debug time: 2 days! */
+       ei_status.tx_start_page = HP_START_PG;
+       ei_status.rx_start_page = HP_START_PG + TX_PAGES/2;
+       ei_status.stop_page = HP_STOP_PG;
+
+       ei_status.reset_8390 = &hpp_reset_8390;
+       ei_status.block_input = &hpp_io_block_input;
+       ei_status.block_output = &hpp_io_block_output;
+       ei_status.get_8390_hdr = &hpp_io_get_8390_hdr;
+
+       /* Check if the memory_enable flag is set in the option register. */
+       if (mem_start) {
+               ei_status.block_input = &hpp_mem_block_input;
+               ei_status.block_output = &hpp_mem_block_output;
+               ei_status.get_8390_hdr = &hpp_mem_get_8390_hdr;
+               dev->mem_start = mem_start;
+               ei_status.mem = ioremap(mem_start,
+                                       (HP_STOP_PG - HP_START_PG)*256);
+               if (!ei_status.mem) {
+                       retval = -ENOMEM;
+                       goto out;
+               }
+               ei_status.rmem_start = dev->mem_start + TX_PAGES/2*256;
+               dev->mem_end = ei_status.rmem_end
+                       = dev->mem_start + (HP_STOP_PG - HP_START_PG)*256;
+       }
+
+       outw(Perf_Page, ioaddr + HP_PAGING);
+       NS8390p_init(dev, 0);
+       /* Leave the 8390 and HP chip reset. */
+       outw(inw(ioaddr + HPP_OPTION) & ~EnableIRQ, ioaddr + HPP_OPTION);
+
+       retval = register_netdev(dev);
+       if (retval)
+               goto out1;
+       return 0;
+out1:
+       iounmap(ei_status.mem);
+out:
+       release_region(ioaddr, HP_IO_EXTENT);
+       return retval;
+}
+
+static int
+hpp_open(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr - NIC_OFFSET;
+       int option_reg;
+       int retval;
+
+       if ((retval = request_irq(dev->irq, eip_interrupt, 0, dev->name, dev))) {
+           return retval;
+       }
+
+       /* Reset the 8390 and HP chip. */
+       option_reg = inw(ioaddr + HPP_OPTION);
+       outw(option_reg & ~(NICReset + ChipReset), ioaddr + HPP_OPTION);
+       udelay(5);
+       /* Unreset the board and enable interrupts. */
+       outw(option_reg | (EnableIRQ + NICReset + ChipReset), ioaddr + HPP_OPTION);
+
+       /* Set the wrap registers for programmed-I/O operation.   */
+       outw(HW_Page, ioaddr + HP_PAGING);
+       outw((HP_START_PG + TX_PAGES/2) | ((HP_STOP_PG - 1) << 8), ioaddr + 14);
+
+       /* Select the operational page. */
+       outw(Perf_Page, ioaddr + HP_PAGING);
+
+       return eip_open(dev);
+}
+
+static int
+hpp_close(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr - NIC_OFFSET;
+       int option_reg = inw(ioaddr + HPP_OPTION);
+
+       free_irq(dev->irq, dev);
+       eip_close(dev);
+       outw((option_reg & ~EnableIRQ) | MemDisable | NICReset | ChipReset,
+                ioaddr + HPP_OPTION);
+
+       return 0;
+}
+
+static void
+hpp_reset_8390(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr - NIC_OFFSET;
+       int option_reg = inw(ioaddr + HPP_OPTION);
+
+       if (ei_debug > 1) printk("resetting the 8390 time=%ld...", jiffies);
+
+       outw(option_reg & ~(NICReset + ChipReset), ioaddr + HPP_OPTION);
+       /* Pause a few cycles for the hardware reset to take place. */
+       udelay(5);
+       ei_status.txing = 0;
+       outw(option_reg | (EnableIRQ + NICReset + ChipReset), ioaddr + HPP_OPTION);
+
+       udelay(5);
+
+
+       if ((inb_p(ioaddr+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0)
+               printk("%s: hp_reset_8390() did not complete.\n", dev->name);
+
+       if (ei_debug > 1) printk("8390 reset done (%ld).", jiffies);
+}
+
+/* The programmed-I/O version of reading the 4 byte 8390 specific header.
+   Note that transfer with the EtherTwist+ must be on word boundaries. */
+
+static void
+hpp_io_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+       int ioaddr = dev->base_addr - NIC_OFFSET;
+
+       outw((ring_page<<8), ioaddr + HPP_IN_ADDR);
+       insw(ioaddr + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+}
+
+/* Block input and output, similar to the Crynwr packet driver. */
+
+static void
+hpp_io_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+       int ioaddr = dev->base_addr - NIC_OFFSET;
+       char *buf = skb->data;
+
+       outw(ring_offset, ioaddr + HPP_IN_ADDR);
+       insw(ioaddr + HP_DATAPORT, buf, count>>1);
+       if (count & 0x01)
+        buf[count-1] = inw(ioaddr + HP_DATAPORT);
+}
+
+/* The corresponding shared memory versions of the above 2 functions. */
+
+static void
+hpp_mem_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+       int ioaddr = dev->base_addr - NIC_OFFSET;
+       int option_reg = inw(ioaddr + HPP_OPTION);
+
+       outw((ring_page<<8), ioaddr + HPP_IN_ADDR);
+       outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
+       memcpy_fromio(hdr, ei_status.mem, sizeof(struct e8390_pkt_hdr));
+       outw(option_reg, ioaddr + HPP_OPTION);
+       hdr->count = (le16_to_cpu(hdr->count) + 3) & ~3;        /* Round up allocation. */
+}
+
+static void
+hpp_mem_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+       int ioaddr = dev->base_addr - NIC_OFFSET;
+       int option_reg = inw(ioaddr + HPP_OPTION);
+
+       outw(ring_offset, ioaddr + HPP_IN_ADDR);
+
+       outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
+
+       /* Caution: this relies on get_8390_hdr() rounding up count!
+          Also note that we *can't* use eth_io_copy_and_sum() because
+          it will not always copy "count" bytes (e.g. padded IP).  */
+
+       memcpy_fromio(skb->data, ei_status.mem, count);
+       outw(option_reg, ioaddr + HPP_OPTION);
+}
+
+/* A special note: we *must* always transfer >=16 bit words.
+   It's always safe to round up, so we do. */
+static void
+hpp_io_block_output(struct net_device *dev, int count,
+                                       const unsigned char *buf, int start_page)
+{
+       int ioaddr = dev->base_addr - NIC_OFFSET;
+       outw(start_page << 8, ioaddr + HPP_OUT_ADDR);
+       outsl(ioaddr + HP_DATAPORT, buf, (count+3)>>2);
+}
+
+static void
+hpp_mem_block_output(struct net_device *dev, int count,
+                               const unsigned char *buf, int start_page)
+{
+       int ioaddr = dev->base_addr - NIC_OFFSET;
+       int option_reg = inw(ioaddr + HPP_OPTION);
+
+       outw(start_page << 8, ioaddr + HPP_OUT_ADDR);
+       outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
+       memcpy_toio(ei_status.mem, buf, (count + 3) & ~3);
+       outw(option_reg, ioaddr + HPP_OPTION);
+}
+
+
+#ifdef MODULE
+#define MAX_HPP_CARDS  4       /* Max number of HPP cards per module */
+static struct net_device *dev_hpp[MAX_HPP_CARDS];
+static int io[MAX_HPP_CARDS];
+static int irq[MAX_HPP_CARDS];
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O port address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s); ignored if properly detected");
+MODULE_DESCRIPTION("HP PC-LAN+ ISA ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that only a single autoprobe takes place per call.
+ISA device autoprobes on a running machine are not recommended. */
+int __init
+init_module(void)
+{
+       struct net_device *dev;
+       int this_dev, found = 0;
+
+       for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) {
+               if (io[this_dev] == 0)  {
+                       if (this_dev != 0) break; /* only autoprobe 1st one */
+                       printk(KERN_NOTICE "hp-plus.c: Presently autoprobing (not recommended) for a single card.\n");
+               }
+               dev = alloc_eip_netdev();
+               if (!dev)
+                       break;
+               dev->irq = irq[this_dev];
+               dev->base_addr = io[this_dev];
+               if (do_hpp_probe(dev) == 0) {
+                       dev_hpp[found++] = dev;
+                       continue;
+               }
+               free_netdev(dev);
+               printk(KERN_WARNING "hp-plus.c: No HP-Plus card found (i/o = 0x%x).\n", io[this_dev]);
+               break;
+       }
+       if (found)
+               return 0;
+       return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+       /* NB: hpp_close() handles free_irq */
+       iounmap(ei_status.mem);
+       release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
+}
+
+void __exit
+cleanup_module(void)
+{
+       int this_dev;
+
+       for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) {
+               struct net_device *dev = dev_hpp[this_dev];
+               if (dev) {
+                       unregister_netdev(dev);
+                       cleanup_card(dev);
+                       free_netdev(dev);
+               }
+       }
+}
+#endif /* MODULE */
diff --git a/drivers/net/ethernet/8390/hp.c b/drivers/net/ethernet/8390/hp.c
new file mode 100644 (file)
index 0000000..18564d4
--- /dev/null
@@ -0,0 +1,439 @@
+/* hp.c: A HP LAN ethernet driver for linux. */
+/*
+       Written 1993-94 by Donald Becker.
+
+       Copyright 1993 United States Government as represented by the
+       Director, National Security Agency.
+
+       This software may be used and distributed according to the terms
+       of the GNU General Public License, incorporated herein by reference.
+
+       The author may be reached as becker@scyld.com, or C/O
+       Scyld Computing Corporation
+       410 Severn Ave., Suite 210
+       Annapolis MD 21403
+
+       This is a driver for the HP PC-LAN adaptors.
+
+       Sources:
+         The Crynwr packet driver.
+*/
+
+static const char version[] =
+       "hp.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include "8390.h"
+
+#define DRV_NAME "hp"
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int hppclan_portlist[] __initdata =
+{ 0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0};
+
+#define HP_IO_EXTENT   32
+
+#define HP_DATAPORT            0x0c    /* "Remote DMA" data port. */
+#define HP_ID                  0x07
+#define HP_CONFIGURE   0x08    /* Configuration register. */
+#define         HP_RUN                 0x01    /* 1 == Run, 0 == reset. */
+#define         HP_IRQ                 0x0E    /* Mask for software-configured IRQ line. */
+#define         HP_DATAON              0x10    /* Turn on dataport */
+#define NIC_OFFSET             0x10    /* Offset the 8390 registers. */
+
+#define HP_START_PG            0x00    /* First page of TX buffer */
+#define HP_8BSTOP_PG   0x80    /* Last page +1 of RX ring */
+#define HP_16BSTOP_PG  0xFF    /* Same, for 16 bit cards. */
+
+static int hp_probe1(struct net_device *dev, int ioaddr);
+
+static void hp_reset_8390(struct net_device *dev);
+static void hp_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                                       int ring_page);
+static void hp_block_input(struct net_device *dev, int count,
+                                       struct sk_buff *skb , int ring_offset);
+static void hp_block_output(struct net_device *dev, int count,
+                                                       const unsigned char *buf, int start_page);
+
+static void hp_init_card(struct net_device *dev);
+
+/* The map from IRQ number to HP_CONFIGURE register setting. */
+/* My default is IRQ5               0  1  2  3  4  5  6  7  8  9 10 11 */
+static char irqmap[16] __initdata= { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0};
+
+
+/*     Probe for an HP LAN adaptor.
+       Also initialize the card and fill in STATION_ADDR with the station
+       address. */
+
+static int __init do_hp_probe(struct net_device *dev)
+{
+       int i;
+       int base_addr = dev->base_addr;
+       int irq = dev->irq;
+
+       if (base_addr > 0x1ff)          /* Check a single specified location. */
+               return hp_probe1(dev, base_addr);
+       else if (base_addr != 0)        /* Don't probe at all. */
+               return -ENXIO;
+
+       for (i = 0; hppclan_portlist[i]; i++) {
+               if (hp_probe1(dev, hppclan_portlist[i]) == 0)
+                       return 0;
+               dev->irq = irq;
+       }
+
+       return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init hp_probe(int unit)
+{
+       struct net_device *dev = alloc_eip_netdev();
+       int err;
+
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       sprintf(dev->name, "eth%d", unit);
+       netdev_boot_setup_check(dev);
+
+       err = do_hp_probe(dev);
+       if (err)
+               goto out;
+       return dev;
+out:
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+#endif
+
+static int __init hp_probe1(struct net_device *dev, int ioaddr)
+{
+       int i, retval, board_id, wordmode;
+       const char *name;
+       static unsigned version_printed;
+
+       if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME))
+               return -EBUSY;
+
+       /* Check for the HP physical address, 08 00 09 xx xx xx. */
+       /* This really isn't good enough: we may pick up HP LANCE boards
+          also!  Avoid the lance 0x5757 signature. */
+       if (inb(ioaddr) != 0x08
+               || inb(ioaddr+1) != 0x00
+               || inb(ioaddr+2) != 0x09
+               || inb(ioaddr+14) == 0x57) {
+               retval = -ENODEV;
+               goto out;
+       }
+
+       /* Set up the parameters based on the board ID.
+          If you have additional mappings, please mail them to me -djb. */
+       if ((board_id = inb(ioaddr + HP_ID)) & 0x80) {
+               name = "HP27247";
+               wordmode = 1;
+       } else {
+               name = "HP27250";
+               wordmode = 0;
+       }
+
+       if (ei_debug  &&  version_printed++ == 0)
+               printk(version);
+
+       printk("%s: %s (ID %02x) at %#3x,", dev->name, name, board_id, ioaddr);
+
+       for(i = 0; i < ETHER_ADDR_LEN; i++)
+               dev->dev_addr[i] = inb(ioaddr + i);
+
+       printk(" %pM", dev->dev_addr);
+
+       /* Snarf the interrupt now.  Someday this could be moved to open(). */
+       if (dev->irq < 2) {
+               static const int irq_16list[] = { 11, 10, 5, 3, 4, 7, 9, 0};
+               static const int irq_8list[] = { 7, 5, 3, 4, 9, 0};
+               const int *irqp = wordmode ? irq_16list : irq_8list;
+               do {
+                       int irq = *irqp;
+                       if (request_irq (irq, NULL, 0, "bogus", NULL) != -EBUSY) {
+                               unsigned long cookie = probe_irq_on();
+                               /* Twinkle the interrupt, and check if it's seen. */
+                               outb_p(irqmap[irq] | HP_RUN, ioaddr + HP_CONFIGURE);
+                               outb_p( 0x00 | HP_RUN, ioaddr + HP_CONFIGURE);
+                               if (irq == probe_irq_off(cookie)                 /* It's a good IRQ line! */
+                                       && request_irq (irq, eip_interrupt, 0, DRV_NAME, dev) == 0) {
+                                       printk(" selecting IRQ %d.\n", irq);
+                                       dev->irq = *irqp;
+                                       break;
+                               }
+                       }
+               } while (*++irqp);
+               if (*irqp == 0) {
+                       printk(" no free IRQ lines.\n");
+                       retval = -EBUSY;
+                       goto out;
+               }
+       } else {
+               if (dev->irq == 2)
+                       dev->irq = 9;
+               if ((retval = request_irq(dev->irq, eip_interrupt, 0, DRV_NAME, dev))) {
+                       printk (" unable to get IRQ %d.\n", dev->irq);
+                       goto out;
+               }
+       }
+
+       /* Set the base address to point to the NIC, not the "real" base! */
+       dev->base_addr = ioaddr + NIC_OFFSET;
+       dev->netdev_ops = &eip_netdev_ops;
+
+       ei_status.name = name;
+       ei_status.word16 = wordmode;
+       ei_status.tx_start_page = HP_START_PG;
+       ei_status.rx_start_page = HP_START_PG + TX_PAGES;
+       ei_status.stop_page = wordmode ? HP_16BSTOP_PG : HP_8BSTOP_PG;
+
+       ei_status.reset_8390 = hp_reset_8390;
+       ei_status.get_8390_hdr = hp_get_8390_hdr;
+       ei_status.block_input = hp_block_input;
+       ei_status.block_output = hp_block_output;
+       hp_init_card(dev);
+
+       retval = register_netdev(dev);
+       if (retval)
+               goto out1;
+       return 0;
+out1:
+       free_irq(dev->irq, dev);
+out:
+       release_region(ioaddr, HP_IO_EXTENT);
+       return retval;
+}
+
+static void
+hp_reset_8390(struct net_device *dev)
+{
+       int hp_base = dev->base_addr - NIC_OFFSET;
+       int saved_config = inb_p(hp_base + HP_CONFIGURE);
+
+       if (ei_debug > 1) printk("resetting the 8390 time=%ld...", jiffies);
+       outb_p(0x00, hp_base + HP_CONFIGURE);
+       ei_status.txing = 0;
+       /* Pause just a few cycles for the hardware reset to take place. */
+       udelay(5);
+
+       outb_p(saved_config, hp_base + HP_CONFIGURE);
+       udelay(5);
+
+       if ((inb_p(hp_base+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0)
+               printk("%s: hp_reset_8390() did not complete.\n", dev->name);
+
+       if (ei_debug > 1) printk("8390 reset done (%ld).", jiffies);
+}
+
+static void
+hp_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+       int nic_base = dev->base_addr;
+       int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
+
+       outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
+       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base);
+       outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+       outb_p(0, nic_base + EN0_RCNTHI);
+       outb_p(0, nic_base + EN0_RSARLO);       /* On page boundary */
+       outb_p(ring_page, nic_base + EN0_RSARHI);
+       outb_p(E8390_RREAD+E8390_START, nic_base);
+
+       if (ei_status.word16)
+         insw(nic_base - NIC_OFFSET + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+       else
+         insb(nic_base - NIC_OFFSET + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+
+       outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
+}
+
+/* Block input and output, similar to the Crynwr packet driver. If you are
+   porting to a new ethercard look at the packet driver source for hints.
+   The HP LAN doesn't use shared memory -- we put the packet
+   out through the "remote DMA" dataport. */
+
+static void
+hp_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+       int nic_base = dev->base_addr;
+       int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
+       int xfer_count = count;
+       char *buf = skb->data;
+
+       outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
+       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base);
+       outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+       outb_p(count >> 8, nic_base + EN0_RCNTHI);
+       outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+       outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+       outb_p(E8390_RREAD+E8390_START, nic_base);
+       if (ei_status.word16) {
+         insw(nic_base - NIC_OFFSET + HP_DATAPORT,buf,count>>1);
+         if (count & 0x01)
+               buf[count-1] = inb(nic_base - NIC_OFFSET + HP_DATAPORT), xfer_count++;
+       } else {
+               insb(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count);
+       }
+       /* This is for the ALPHA version only, remove for later releases. */
+       if (ei_debug > 0) {                     /* DMA termination address check... */
+         int high = inb_p(nic_base + EN0_RSARHI);
+         int low = inb_p(nic_base + EN0_RSARLO);
+         int addr = (high << 8) + low;
+         /* Check only the lower 8 bits so we can ignore ring wrap. */
+         if (((ring_offset + xfer_count) & 0xff) != (addr & 0xff))
+               printk("%s: RX transfer address mismatch, %#4.4x vs. %#4.4x (actual).\n",
+                          dev->name, ring_offset + xfer_count, addr);
+       }
+       outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
+}
+
+static void
+hp_block_output(struct net_device *dev, int count,
+                               const unsigned char *buf, int start_page)
+{
+       int nic_base = dev->base_addr;
+       int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
+
+       outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
+       /* Round the count up for word writes.  Do we need to do this?
+          What effect will an odd byte count have on the 8390?
+          I should check someday. */
+       if (ei_status.word16 && (count & 0x01))
+         count++;
+       /* We should already be in page 0, but to be safe... */
+       outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base);
+
+#ifdef NE8390_RW_BUGFIX
+       /* Handle the read-before-write bug the same way as the
+          Crynwr packet driver -- the NatSemi method doesn't work. */
+       outb_p(0x42, nic_base + EN0_RCNTLO);
+       outb_p(0,       nic_base + EN0_RCNTHI);
+       outb_p(0xff, nic_base + EN0_RSARLO);
+       outb_p(0x00, nic_base + EN0_RSARHI);
+#define NE_CMD         0x00
+       outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+       /* Make certain that the dummy read has occurred. */
+       inb_p(0x61);
+       inb_p(0x61);
+#endif
+
+       outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+       outb_p(count >> 8,       nic_base + EN0_RCNTHI);
+       outb_p(0x00, nic_base + EN0_RSARLO);
+       outb_p(start_page, nic_base + EN0_RSARHI);
+
+       outb_p(E8390_RWRITE+E8390_START, nic_base);
+       if (ei_status.word16) {
+               /* Use the 'rep' sequence for 16 bit boards. */
+               outsw(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count>>1);
+       } else {
+               outsb(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count);
+       }
+
+       /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here -- it's broken! */
+
+       /* This is for the ALPHA version only, remove for later releases. */
+       if (ei_debug > 0) {                     /* DMA termination address check... */
+         int high = inb_p(nic_base + EN0_RSARHI);
+         int low  = inb_p(nic_base + EN0_RSARLO);
+         int addr = (high << 8) + low;
+         if ((start_page << 8) + count != addr)
+               printk("%s: TX Transfer address mismatch, %#4.4x vs. %#4.4x.\n",
+                          dev->name, (start_page << 8) + count, addr);
+       }
+       outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
+}
+
+/* This function resets the ethercard if something screws up. */
+static void __init
+hp_init_card(struct net_device *dev)
+{
+       int irq = dev->irq;
+       NS8390p_init(dev, 0);
+       outb_p(irqmap[irq&0x0f] | HP_RUN,
+                  dev->base_addr - NIC_OFFSET + HP_CONFIGURE);
+}
+
+#ifdef MODULE
+#define MAX_HP_CARDS   4       /* Max number of HP cards per module */
+static struct net_device *dev_hp[MAX_HP_CARDS];
+static int io[MAX_HP_CARDS];
+static int irq[MAX_HP_CARDS];
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
+MODULE_DESCRIPTION("HP PC-LAN ISA ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that only a single autoprobe takes place per call.
+ISA device autoprobes on a running machine are not recommended. */
+int __init
+init_module(void)
+{
+       struct net_device *dev;
+       int this_dev, found = 0;
+
+       for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) {
+               if (io[this_dev] == 0)  {
+                       if (this_dev != 0) break; /* only autoprobe 1st one */
+                       printk(KERN_NOTICE "hp.c: Presently autoprobing (not recommended) for a single card.\n");
+               }
+               dev = alloc_eip_netdev();
+               if (!dev)
+                       break;
+               dev->irq = irq[this_dev];
+               dev->base_addr = io[this_dev];
+               if (do_hp_probe(dev) == 0) {
+                       dev_hp[found++] = dev;
+                       continue;
+               }
+               free_netdev(dev);
+               printk(KERN_WARNING "hp.c: No HP card found (i/o = 0x%x).\n", io[this_dev]);
+               break;
+       }
+       if (found)
+               return 0;
+       return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+       free_irq(dev->irq, dev);
+       release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
+}
+
+void __exit
+cleanup_module(void)
+{
+       int this_dev;
+
+       for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) {
+               struct net_device *dev = dev_hp[this_dev];
+               if (dev) {
+                       unregister_netdev(dev);
+                       cleanup_card(dev);
+                       free_netdev(dev);
+               }
+       }
+}
+#endif /* MODULE */
diff --git a/drivers/net/ethernet/8390/hydra.c b/drivers/net/ethernet/8390/hydra.c
new file mode 100644 (file)
index 0000000..1cd481c
--- /dev/null
@@ -0,0 +1,273 @@
+/* New Hydra driver using generic 8390 core */
+/* Based on old hydra driver by Topi Kanerva (topi@susanna.oulu.fi) */
+
+/* This file is subject to the terms and conditions of the GNU General      */
+/* Public License.  See the file COPYING in the main directory of the       */
+/* Linux distribution for more details.                                     */
+
+/* Peter De Schrijver (p2@mind.be) */
+/* Oldenburg 2000 */
+
+/* The Amiganet is a Zorro-II board made by Hydra Systems. It contains a    */
+/* NS8390 NIC (network interface controller) clone, 16 or 64K on-board RAM  */
+/* and 10BASE-2 (thin coax) and AUI connectors.                             */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+#include <linux/zorro.h>
+
+#define EI_SHIFT(x)    (ei_local->reg_offset[x])
+#define ei_inb(port)   in_8(port)
+#define ei_outb(val,port)  out_8(port,val)
+#define ei_inb_p(port)   in_8(port)
+#define ei_outb_p(val,port)  out_8(port,val)
+
+static const char version[] =
+    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include "lib8390.c"
+
+#define NE_EN0_DCFG     (0x0e*2)
+
+#define NESM_START_PG   0x0    /* First page of TX buffer */
+#define NESM_STOP_PG    0x40    /* Last page +1 of RX ring */
+
+#define HYDRA_NIC_BASE 0xffe1
+#define HYDRA_ADDRPROM 0xffc0
+#define HYDRA_VERSION "v3.0alpha"
+
+#define WORDSWAP(a)     ((((a)>>8)&0xff) | ((a)<<8))
+
+
+static int __devinit hydra_init_one(struct zorro_dev *z,
+                                   const struct zorro_device_id *ent);
+static int __devinit hydra_init(struct zorro_dev *z);
+static int hydra_open(struct net_device *dev);
+static int hydra_close(struct net_device *dev);
+static void hydra_reset_8390(struct net_device *dev);
+static void hydra_get_8390_hdr(struct net_device *dev,
+                              struct e8390_pkt_hdr *hdr, int ring_page);
+static void hydra_block_input(struct net_device *dev, int count,
+                             struct sk_buff *skb, int ring_offset);
+static void hydra_block_output(struct net_device *dev, int count,
+                              const unsigned char *buf, int start_page);
+static void __devexit hydra_remove_one(struct zorro_dev *z);
+
+static struct zorro_device_id hydra_zorro_tbl[] __devinitdata = {
+    { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET },
+    { 0 }
+};
+MODULE_DEVICE_TABLE(zorro, hydra_zorro_tbl);
+
+static struct zorro_driver hydra_driver = {
+    .name      = "hydra",
+    .id_table  = hydra_zorro_tbl,
+    .probe     = hydra_init_one,
+    .remove    = __devexit_p(hydra_remove_one),
+};
+
+static int __devinit hydra_init_one(struct zorro_dev *z,
+                                   const struct zorro_device_id *ent)
+{
+    int err;
+
+    if (!request_mem_region(z->resource.start, 0x10000, "Hydra"))
+       return -EBUSY;
+    if ((err = hydra_init(z))) {
+       release_mem_region(z->resource.start, 0x10000);
+       return -EBUSY;
+    }
+    return 0;
+}
+
+static const struct net_device_ops hydra_netdev_ops = {
+       .ndo_open               = hydra_open,
+       .ndo_stop               = hydra_close,
+
+       .ndo_start_xmit         = __ei_start_xmit,
+       .ndo_tx_timeout         = __ei_tx_timeout,
+       .ndo_get_stats          = __ei_get_stats,
+       .ndo_set_multicast_list = __ei_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = __ei_poll,
+#endif
+};
+
+static int __devinit hydra_init(struct zorro_dev *z)
+{
+    struct net_device *dev;
+    unsigned long board = ZTWO_VADDR(z->resource.start);
+    unsigned long ioaddr = board+HYDRA_NIC_BASE;
+    const char name[] = "NE2000";
+    int start_page, stop_page;
+    int j;
+    int err;
+
+    static u32 hydra_offsets[16] = {
+       0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+       0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
+    };
+
+    dev = ____alloc_ei_netdev(0);
+    if (!dev)
+       return -ENOMEM;
+
+    for(j = 0; j < ETHER_ADDR_LEN; j++)
+       dev->dev_addr[j] = *((u8 *)(board + HYDRA_ADDRPROM + 2*j));
+
+    /* We must set the 8390 for word mode. */
+    z_writeb(0x4b, ioaddr + NE_EN0_DCFG);
+    start_page = NESM_START_PG;
+    stop_page = NESM_STOP_PG;
+
+    dev->base_addr = ioaddr;
+    dev->irq = IRQ_AMIGA_PORTS;
+
+    /* Install the Interrupt handler */
+    if (request_irq(IRQ_AMIGA_PORTS, __ei_interrupt, IRQF_SHARED, "Hydra Ethernet",
+                   dev)) {
+       free_netdev(dev);
+       return -EAGAIN;
+    }
+
+    ei_status.name = name;
+    ei_status.tx_start_page = start_page;
+    ei_status.stop_page = stop_page;
+    ei_status.word16 = 1;
+    ei_status.bigendian = 1;
+
+    ei_status.rx_start_page = start_page + TX_PAGES;
+
+    ei_status.reset_8390 = hydra_reset_8390;
+    ei_status.block_input = hydra_block_input;
+    ei_status.block_output = hydra_block_output;
+    ei_status.get_8390_hdr = hydra_get_8390_hdr;
+    ei_status.reg_offset = hydra_offsets;
+
+    dev->netdev_ops = &hydra_netdev_ops;
+    __NS8390_init(dev, 0);
+
+    err = register_netdev(dev);
+    if (err) {
+       free_irq(IRQ_AMIGA_PORTS, dev);
+       free_netdev(dev);
+       return err;
+    }
+
+    zorro_set_drvdata(z, dev);
+
+    pr_info("%s: Hydra at %pR, address %pM (hydra.c " HYDRA_VERSION ")\n",
+           dev->name, &z->resource, dev->dev_addr);
+
+    return 0;
+}
+
+static int hydra_open(struct net_device *dev)
+{
+    __ei_open(dev);
+    return 0;
+}
+
+static int hydra_close(struct net_device *dev)
+{
+    if (ei_debug > 1)
+       printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
+    __ei_close(dev);
+    return 0;
+}
+
+static void hydra_reset_8390(struct net_device *dev)
+{
+    printk(KERN_INFO "Hydra hw reset not there\n");
+}
+
+static void hydra_get_8390_hdr(struct net_device *dev,
+                              struct e8390_pkt_hdr *hdr, int ring_page)
+{
+    int nic_base = dev->base_addr;
+    short *ptrs;
+    unsigned long hdr_start= (nic_base-HYDRA_NIC_BASE) +
+                            ((ring_page - NESM_START_PG)<<8);
+    ptrs = (short *)hdr;
+
+    *(ptrs++) = z_readw(hdr_start);
+    *((short *)hdr) = WORDSWAP(*((short *)hdr));
+    hdr_start += 2;
+    *(ptrs++) = z_readw(hdr_start);
+    *((short *)hdr+1) = WORDSWAP(*((short *)hdr+1));
+}
+
+static void hydra_block_input(struct net_device *dev, int count,
+                             struct sk_buff *skb, int ring_offset)
+{
+    unsigned long nic_base = dev->base_addr;
+    unsigned long mem_base = nic_base - HYDRA_NIC_BASE;
+    unsigned long xfer_start = mem_base + ring_offset - (NESM_START_PG<<8);
+
+    if (count&1)
+       count++;
+
+    if (xfer_start+count >  mem_base + (NESM_STOP_PG<<8)) {
+       int semi_count = (mem_base + (NESM_STOP_PG<<8)) - xfer_start;
+
+       z_memcpy_fromio(skb->data,xfer_start,semi_count);
+       count -= semi_count;
+       z_memcpy_fromio(skb->data+semi_count, mem_base, count);
+    } else
+       z_memcpy_fromio(skb->data, xfer_start,count);
+
+}
+
+static void hydra_block_output(struct net_device *dev, int count,
+                              const unsigned char *buf, int start_page)
+{
+    unsigned long nic_base = dev->base_addr;
+    unsigned long mem_base = nic_base - HYDRA_NIC_BASE;
+
+    if (count&1)
+       count++;
+
+    z_memcpy_toio(mem_base+((start_page - NESM_START_PG)<<8), buf, count);
+}
+
+static void __devexit hydra_remove_one(struct zorro_dev *z)
+{
+    struct net_device *dev = zorro_get_drvdata(z);
+
+    unregister_netdev(dev);
+    free_irq(IRQ_AMIGA_PORTS, dev);
+    release_mem_region(ZTWO_PADDR(dev->base_addr)-HYDRA_NIC_BASE, 0x10000);
+    free_netdev(dev);
+}
+
+static int __init hydra_init_module(void)
+{
+    return zorro_register_driver(&hydra_driver);
+}
+
+static void __exit hydra_cleanup_module(void)
+{
+    zorro_unregister_driver(&hydra_driver);
+}
+
+module_init(hydra_init_module);
+module_exit(hydra_cleanup_module);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/8390/lib8390.c b/drivers/net/ethernet/8390/lib8390.c
new file mode 100644 (file)
index 0000000..05ae214
--- /dev/null
@@ -0,0 +1,1080 @@
+/* 8390.c: A general NS8390 ethernet driver core for linux. */
+/*
+       Written 1992-94 by Donald Becker.
+
+       Copyright 1993 United States Government as represented by the
+       Director, National Security Agency.
+
+       This software may be used and distributed according to the terms
+       of the GNU General Public License, incorporated herein by reference.
+
+       The author may be reached as becker@scyld.com, or C/O
+       Scyld Computing Corporation
+       410 Severn Ave., Suite 210
+       Annapolis MD 21403
+
+
+  This is the chip-specific code for many 8390-based ethernet adaptors.
+  This is not a complete driver, it must be combined with board-specific
+  code such as ne.c, wd.c, 3c503.c, etc.
+
+  Seeing how at least eight drivers use this code, (not counting the
+  PCMCIA ones either) it is easy to break some card by what seems like
+  a simple innocent change. Please contact me or Donald if you think
+  you have found something that needs changing. -- PG
+
+
+  Changelog:
+
+  Paul Gortmaker       : remove set_bit lock, other cleanups.
+  Paul Gortmaker       : add ei_get_8390_hdr() so we can pass skb's to
+                         ei_block_input() for eth_io_copy_and_sum().
+  Paul Gortmaker       : exchange static int ei_pingpong for a #define,
+                         also add better Tx error handling.
+  Paul Gortmaker       : rewrite Rx overrun handling as per NS specs.
+  Alexey Kuznetsov     : use the 8390's six bit hash multicast filter.
+  Paul Gortmaker       : tweak ANK's above multicast changes a bit.
+  Paul Gortmaker       : update packet statistics for v2.1.x
+  Alan Cox             : support arbitrary stupid port mappings on the
+                         68K Macintosh. Support >16bit I/O spaces
+  Paul Gortmaker       : add kmod support for auto-loading of the 8390
+                         module by all drivers that require it.
+  Alan Cox             : Spinlocking work, added 'BUG_83C690'
+  Paul Gortmaker       : Separate out Tx timeout code from Tx path.
+  Paul Gortmaker       : Remove old unused single Tx buffer code.
+  Hayato Fujiwara      : Add m32r support.
+  Paul Gortmaker       : use skb_padto() instead of stack scratch area
+
+  Sources:
+  The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
+
+  */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/bitops.h>
+#include <asm/system.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fcntl.h>
+#include <linux/in.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#define NS8390_CORE
+#include "8390.h"
+
+#define BUG_83C690
+
+/* These are the operational function interfaces to board-specific
+   routines.
+       void reset_8390(struct net_device *dev)
+               Resets the board associated with DEV, including a hardware reset of
+               the 8390.  This is only called when there is a transmit timeout, and
+               it is always followed by 8390_init().
+       void block_output(struct net_device *dev, int count, const unsigned char *buf,
+                                         int start_page)
+               Write the COUNT bytes of BUF to the packet buffer at START_PAGE.  The
+               "page" value uses the 8390's 256-byte pages.
+       void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page)
+               Read the 4 byte, page aligned 8390 header. *If* there is a
+               subsequent read, it will be of the rest of the packet.
+       void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+               Read COUNT bytes from the packet buffer into the skb data area. Start
+               reading from RING_OFFSET, the address as the 8390 sees it.  This will always
+               follow the read of the 8390 header.
+*/
+#define ei_reset_8390 (ei_local->reset_8390)
+#define ei_block_output (ei_local->block_output)
+#define ei_block_input (ei_local->block_input)
+#define ei_get_8390_hdr (ei_local->get_8390_hdr)
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifndef ei_debug
+int ei_debug = 1;
+#endif
+
+/* Index to functions. */
+static void ei_tx_intr(struct net_device *dev);
+static void ei_tx_err(struct net_device *dev);
+static void ei_receive(struct net_device *dev);
+static void ei_rx_overrun(struct net_device *dev);
+
+/* Routines generic to NS8390-based boards. */
+static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
+                                                               int start_page);
+static void do_set_multicast_list(struct net_device *dev);
+static void __NS8390_init(struct net_device *dev, int startp);
+
+/*
+ *     SMP and the 8390 setup.
+ *
+ *     The 8390 isn't exactly designed to be multithreaded on RX/TX. There is
+ *     a page register that controls bank and packet buffer access. We guard
+ *     this with ei_local->page_lock. Nobody should assume or set the page other
+ *     than zero when the lock is not held. Lock holders must restore page 0
+ *     before unlocking. Even pure readers must take the lock to protect in
+ *     page 0.
+ *
+ *     To make life difficult the chip can also be very slow. We therefore can't
+ *     just use spinlocks. For the longer lockups we disable the irq the device
+ *     sits on and hold the lock. We must hold the lock because there is a dual
+ *     processor case other than interrupts (get stats/set multicast list in
+ *     parallel with each other and transmit).
+ *
+ *     Note: in theory we can just disable the irq on the card _but_ there is
+ *     a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs"
+ *     enter lock, take the queued irq. So we waddle instead of flying.
+ *
+ *     Finally by special arrangement for the purpose of being generally
+ *     annoying the transmit function is called bh atomic. That places
+ *     restrictions on the user context callers as disable_irq won't save
+ *     them.
+ *
+ *     Additional explanation of problems with locking by Alan Cox:
+ *
+ *     "The author (me) didn't use spin_lock_irqsave because the slowness of the
+ *     card means that approach caused horrible problems like losing serial data
+ *     at 38400 baud on some chips. Remember many 8390 nics on PCI were ISA
+ *     chips with FPGA front ends.
+ *
+ *     Ok the logic behind the 8390 is very simple:
+ *
+ *     Things to know
+ *             - IRQ delivery is asynchronous to the PCI bus
+ *             - Blocking the local CPU IRQ via spin locks was too slow
+ *             - The chip has register windows needing locking work
+ *
+ *     So the path was once (I say once as people appear to have changed it
+ *     in the mean time and it now looks rather bogus if the changes to use
+ *     disable_irq_nosync_irqsave are disabling the local IRQ)
+ *
+ *
+ *             Take the page lock
+ *             Mask the IRQ on chip
+ *             Disable the IRQ (but not mask locally- someone seems to have
+ *                     broken this with the lock validator stuff)
+ *                     [This must be _nosync as the page lock may otherwise
+ *                             deadlock us]
+ *             Drop the page lock and turn IRQs back on
+ *
+ *             At this point an existing IRQ may still be running but we can't
+ *             get a new one
+ *
+ *             Take the lock (so we know the IRQ has terminated) but don't mask
+ *     the IRQs on the processor
+ *             Set irqlock [for debug]
+ *
+ *             Transmit (slow as ****)
+ *
+ *             re-enable the IRQ
+ *
+ *
+ *     We have to use disable_irq because otherwise you will get delayed
+ *     interrupts on the APIC bus deadlocking the transmit path.
+ *
+ *     Quite hairy but the chip simply wasn't designed for SMP and you can't
+ *     even ACK an interrupt without risking corrupting other parallel
+ *     activities on the chip." [lkml, 25 Jul 2007]
+ */
+
+
+
+/**
+ * ei_open - Open/initialize the board.
+ * @dev: network device to initialize
+ *
+ * This routine goes all-out, setting everything
+ * up anew at each open, even though many of these registers should only
+ * need to be set once at boot.
+ */
+static int __ei_open(struct net_device *dev)
+{
+       unsigned long flags;
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       if (dev->watchdog_timeo <= 0)
+               dev->watchdog_timeo = TX_TIMEOUT;
+
+       /*
+        *      Grab the page lock so we own the register set, then call
+        *      the init function.
+        */
+
+       spin_lock_irqsave(&ei_local->page_lock, flags);
+       __NS8390_init(dev, 1);
+       /* Set the flag before we drop the lock, That way the IRQ arrives
+          after its set and we get no silly warnings */
+       netif_start_queue(dev);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
+       ei_local->irqlock = 0;
+       return 0;
+}
+
+/**
+ * ei_close - shut down network device
+ * @dev: network device to close
+ *
+ * Opposite of ei_open(). Only used when "ifconfig <devname> down" is done.
+ */
+static int __ei_close(struct net_device *dev)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       unsigned long flags;
+
+       /*
+        *      Hold the page lock during close
+        */
+
+       spin_lock_irqsave(&ei_local->page_lock, flags);
+       __NS8390_init(dev, 0);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
+       netif_stop_queue(dev);
+       return 0;
+}
+
+/**
+ * ei_tx_timeout - handle transmit time out condition
+ * @dev: network device which has apparently fallen asleep
+ *
+ * Called by kernel when device never acknowledges a transmit has
+ * completed (or failed) - i.e. never posted a Tx related interrupt.
+ */
+
+static void __ei_tx_timeout(struct net_device *dev)
+{
+       unsigned long e8390_base = dev->base_addr;
+       struct ei_device *ei_local = netdev_priv(dev);
+       int txsr, isr, tickssofar = jiffies - dev_trans_start(dev);
+       unsigned long flags;
+
+       dev->stats.tx_errors++;
+
+       spin_lock_irqsave(&ei_local->page_lock, flags);
+       txsr = ei_inb(e8390_base+EN0_TSR);
+       isr = ei_inb(e8390_base+EN0_ISR);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+       netdev_dbg(dev, "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d\n",
+                  (txsr & ENTSR_ABT) ? "excess collisions." :
+                  (isr) ? "lost interrupt?" : "cable problem?",
+                  txsr, isr, tickssofar);
+
+       if (!isr && !dev->stats.tx_packets) {
+               /* The 8390 probably hasn't gotten on the cable yet. */
+               ei_local->interface_num ^= 1;   /* Try a different xcvr.  */
+       }
+
+       /* Ugly but a reset can be slow, yet must be protected */
+
+       disable_irq_nosync_lockdep(dev->irq);
+       spin_lock(&ei_local->page_lock);
+
+       /* Try to restart the card.  Perhaps the user has fixed something. */
+       ei_reset_8390(dev);
+       __NS8390_init(dev, 1);
+
+       spin_unlock(&ei_local->page_lock);
+       enable_irq_lockdep(dev->irq);
+       netif_wake_queue(dev);
+}
+
+/**
+ * ei_start_xmit - begin packet transmission
+ * @skb: packet to be sent
+ * @dev: network device to which packet is sent
+ *
+ * Sends a packet to an 8390 network device.
+ */
+
+static netdev_tx_t __ei_start_xmit(struct sk_buff *skb,
+                                  struct net_device *dev)
+{
+       unsigned long e8390_base = dev->base_addr;
+       struct ei_device *ei_local = netdev_priv(dev);
+       int send_length = skb->len, output_page;
+       unsigned long flags;
+       char buf[ETH_ZLEN];
+       char *data = skb->data;
+
+       if (skb->len < ETH_ZLEN) {
+               memset(buf, 0, ETH_ZLEN);       /* more efficient than doing just the needed bits */
+               memcpy(buf, data, skb->len);
+               send_length = ETH_ZLEN;
+               data = buf;
+       }
+
+       /* Mask interrupts from the ethercard.
+          SMP: We have to grab the lock here otherwise the IRQ handler
+          on another CPU can flip window and race the IRQ mask set. We end
+          up trashing the mcast filter not disabling irqs if we don't lock */
+
+       spin_lock_irqsave(&ei_local->page_lock, flags);
+       ei_outb_p(0x00, e8390_base + EN0_IMR);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+
+       /*
+        *      Slow phase with lock held.
+        */
+
+       disable_irq_nosync_lockdep_irqsave(dev->irq, &flags);
+
+       spin_lock(&ei_local->page_lock);
+
+       ei_local->irqlock = 1;
+
+       /*
+        * We have two Tx slots available for use. Find the first free
+        * slot, and then perform some sanity checks. With two Tx bufs,
+        * you get very close to transmitting back-to-back packets. With
+        * only one Tx buf, the transmitter sits idle while you reload the
+        * card, leaving a substantial gap between each transmitted packet.
+        */
+
+       if (ei_local->tx1 == 0) {
+               output_page = ei_local->tx_start_page;
+               ei_local->tx1 = send_length;
+               if (ei_debug  &&  ei_local->tx2 > 0)
+                       netdev_dbg(dev, "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
+                                  ei_local->tx2, ei_local->lasttx, ei_local->txing);
+       } else if (ei_local->tx2 == 0) {
+               output_page = ei_local->tx_start_page + TX_PAGES/2;
+               ei_local->tx2 = send_length;
+               if (ei_debug  &&  ei_local->tx1 > 0)
+                       netdev_dbg(dev, "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
+                                  ei_local->tx1, ei_local->lasttx, ei_local->txing);
+       } else {                        /* We should never get here. */
+               if (ei_debug)
+                       netdev_dbg(dev, "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
+                                  ei_local->tx1, ei_local->tx2, ei_local->lasttx);
+               ei_local->irqlock = 0;
+               netif_stop_queue(dev);
+               ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+               spin_unlock(&ei_local->page_lock);
+               enable_irq_lockdep_irqrestore(dev->irq, &flags);
+               dev->stats.tx_errors++;
+               return NETDEV_TX_BUSY;
+       }
+
+       /*
+        * Okay, now upload the packet and trigger a send if the transmitter
+        * isn't already sending. If it is busy, the interrupt handler will
+        * trigger the send later, upon receiving a Tx done interrupt.
+        */
+
+       ei_block_output(dev, send_length, data, output_page);
+
+       if (!ei_local->txing) {
+               ei_local->txing = 1;
+               NS8390_trigger_send(dev, send_length, output_page);
+               if (output_page == ei_local->tx_start_page) {
+                       ei_local->tx1 = -1;
+                       ei_local->lasttx = -1;
+               } else {
+                       ei_local->tx2 = -1;
+                       ei_local->lasttx = -2;
+               }
+       } else
+               ei_local->txqueue++;
+
+       if (ei_local->tx1  &&  ei_local->tx2)
+               netif_stop_queue(dev);
+       else
+               netif_start_queue(dev);
+
+       /* Turn 8390 interrupts back on. */
+       ei_local->irqlock = 0;
+       ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+
+       spin_unlock(&ei_local->page_lock);
+       enable_irq_lockdep_irqrestore(dev->irq, &flags);
+       skb_tx_timestamp(skb);
+       dev_kfree_skb(skb);
+       dev->stats.tx_bytes += send_length;
+
+       return NETDEV_TX_OK;
+}
+
+/**
+ * ei_interrupt - handle the interrupts from an 8390
+ * @irq: interrupt number
+ * @dev_id: a pointer to the net_device
+ *
+ * Handle the ether interface interrupts. We pull packets from
+ * the 8390 via the card specific functions and fire them at the networking
+ * stack. We also handle transmit completions and wake the transmit path if
+ * necessary. We also update the counters and do other housekeeping as
+ * needed.
+ */
+
+static irqreturn_t __ei_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev = dev_id;
+       unsigned long e8390_base = dev->base_addr;
+       int interrupts, nr_serviced = 0;
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       /*
+        *      Protect the irq test too.
+        */
+
+       spin_lock(&ei_local->page_lock);
+
+       if (ei_local->irqlock) {
+               /*
+                * This might just be an interrupt for a PCI device sharing
+                * this line
+                */
+               netdev_err(dev, "Interrupted while interrupts are masked! isr=%#2x imr=%#2x\n",
+                          ei_inb_p(e8390_base + EN0_ISR),
+                          ei_inb_p(e8390_base + EN0_IMR));
+               spin_unlock(&ei_local->page_lock);
+               return IRQ_NONE;
+       }
+
+       /* Change to page 0 and read the intr status reg. */
+       ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
+       if (ei_debug > 3)
+               netdev_dbg(dev, "interrupt(isr=%#2.2x)\n",
+                          ei_inb_p(e8390_base + EN0_ISR));
+
+       /* !!Assumption!! -- we stay in page 0.  Don't break this. */
+       while ((interrupts = ei_inb_p(e8390_base + EN0_ISR)) != 0 &&
+              ++nr_serviced < MAX_SERVICE) {
+               if (!netif_running(dev)) {
+                       netdev_warn(dev, "interrupt from stopped card\n");
+                       /* rmk - acknowledge the interrupts */
+                       ei_outb_p(interrupts, e8390_base + EN0_ISR);
+                       interrupts = 0;
+                       break;
+               }
+               if (interrupts & ENISR_OVER)
+                       ei_rx_overrun(dev);
+               else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) {
+                       /* Got a good (?) packet. */
+                       ei_receive(dev);
+               }
+               /* Push the next to-transmit packet through. */
+               if (interrupts & ENISR_TX)
+                       ei_tx_intr(dev);
+               else if (interrupts & ENISR_TX_ERR)
+                       ei_tx_err(dev);
+
+               if (interrupts & ENISR_COUNTERS) {
+                       dev->stats.rx_frame_errors += ei_inb_p(e8390_base + EN0_COUNTER0);
+                       dev->stats.rx_crc_errors   += ei_inb_p(e8390_base + EN0_COUNTER1);
+                       dev->stats.rx_missed_errors += ei_inb_p(e8390_base + EN0_COUNTER2);
+                       ei_outb_p(ENISR_COUNTERS, e8390_base + EN0_ISR); /* Ack intr. */
+               }
+
+               /* Ignore any RDC interrupts that make it back to here. */
+               if (interrupts & ENISR_RDC)
+                       ei_outb_p(ENISR_RDC, e8390_base + EN0_ISR);
+
+               ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
+       }
+
+       if (interrupts && ei_debug) {
+               ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
+               if (nr_serviced >= MAX_SERVICE) {
+                       /* 0xFF is valid for a card removal */
+                       if (interrupts != 0xFF)
+                               netdev_warn(dev, "Too much work at interrupt, status %#2.2x\n",
+                                           interrupts);
+                       ei_outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
+               } else {
+                       netdev_warn(dev, "unknown interrupt %#2x\n", interrupts);
+                       ei_outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
+               }
+       }
+       spin_unlock(&ei_local->page_lock);
+       return IRQ_RETVAL(nr_serviced > 0);
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void __ei_poll(struct net_device *dev)
+{
+       disable_irq(dev->irq);
+       __ei_interrupt(dev->irq, dev);
+       enable_irq(dev->irq);
+}
+#endif
+
+/**
+ * ei_tx_err - handle transmitter error
+ * @dev: network device which threw the exception
+ *
+ * A transmitter error has happened. Most likely excess collisions (which
+ * is a fairly normal condition). If the error is one where the Tx will
+ * have been aborted, we try and send another one right away, instead of
+ * letting the failed packet sit and collect dust in the Tx buffer. This
+ * is a much better solution as it avoids kernel based Tx timeouts, and
+ * an unnecessary card reset.
+ *
+ * Called with lock held.
+ */
+
+static void ei_tx_err(struct net_device *dev)
+{
+       unsigned long e8390_base = dev->base_addr;
+       /* ei_local is used on some platforms via the EI_SHIFT macro */
+       struct ei_device *ei_local __maybe_unused = netdev_priv(dev);
+       unsigned char txsr = ei_inb_p(e8390_base+EN0_TSR);
+       unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
+
+#ifdef VERBOSE_ERROR_DUMP
+       netdev_dbg(dev, "transmitter error (%#2x):", txsr);
+       if (txsr & ENTSR_ABT)
+               pr_cont(" excess-collisions ");
+       if (txsr & ENTSR_ND)
+               pr_cont(" non-deferral ");
+       if (txsr & ENTSR_CRS)
+               pr_cont(" lost-carrier ");
+       if (txsr & ENTSR_FU)
+               pr_cont(" FIFO-underrun ");
+       if (txsr & ENTSR_CDH)
+               pr_cont(" lost-heartbeat ");
+       pr_cont("\n");
+#endif
+
+       ei_outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */
+
+       if (tx_was_aborted)
+               ei_tx_intr(dev);
+       else {
+               dev->stats.tx_errors++;
+               if (txsr & ENTSR_CRS)
+                       dev->stats.tx_carrier_errors++;
+               if (txsr & ENTSR_CDH)
+                       dev->stats.tx_heartbeat_errors++;
+               if (txsr & ENTSR_OWC)
+                       dev->stats.tx_window_errors++;
+       }
+}
+
+/**
+ * ei_tx_intr - transmit interrupt handler
+ * @dev: network device for which tx intr is handled
+ *
+ * We have finished a transmit: check for errors and then trigger the next
+ * packet to be sent. Called with lock held.
+ */
+
+static void ei_tx_intr(struct net_device *dev)
+{
+       unsigned long e8390_base = dev->base_addr;
+       struct ei_device *ei_local = netdev_priv(dev);
+       int status = ei_inb(e8390_base + EN0_TSR);
+
+       ei_outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */
+
+       /*
+        * There are two Tx buffers, see which one finished, and trigger
+        * the send of another one if it exists.
+        */
+       ei_local->txqueue--;
+
+       if (ei_local->tx1 < 0) {
+               if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
+                       pr_err("%s: bogus last_tx_buffer %d, tx1=%d\n",
+                              ei_local->name, ei_local->lasttx, ei_local->tx1);
+               ei_local->tx1 = 0;
+               if (ei_local->tx2 > 0) {
+                       ei_local->txing = 1;
+                       NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
+                       dev->trans_start = jiffies;
+                       ei_local->tx2 = -1,
+                       ei_local->lasttx = 2;
+               } else
+                       ei_local->lasttx = 20, ei_local->txing = 0;
+       } else if (ei_local->tx2 < 0) {
+               if (ei_local->lasttx != 2  &&  ei_local->lasttx != -2)
+                       pr_err("%s: bogus last_tx_buffer %d, tx2=%d\n",
+                              ei_local->name, ei_local->lasttx, ei_local->tx2);
+               ei_local->tx2 = 0;
+               if (ei_local->tx1 > 0) {
+                       ei_local->txing = 1;
+                       NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
+                       dev->trans_start = jiffies;
+                       ei_local->tx1 = -1;
+                       ei_local->lasttx = 1;
+               } else
+                       ei_local->lasttx = 10, ei_local->txing = 0;
+       } /* else
+               netdev_warn(dev, "unexpected TX-done interrupt, lasttx=%d\n",
+                           ei_local->lasttx);
+*/
+
+       /* Minimize Tx latency: update the statistics after we restart TXing. */
+       if (status & ENTSR_COL)
+               dev->stats.collisions++;
+       if (status & ENTSR_PTX)
+               dev->stats.tx_packets++;
+       else {
+               dev->stats.tx_errors++;
+               if (status & ENTSR_ABT) {
+                       dev->stats.tx_aborted_errors++;
+                       dev->stats.collisions += 16;
+               }
+               if (status & ENTSR_CRS)
+                       dev->stats.tx_carrier_errors++;
+               if (status & ENTSR_FU)
+                       dev->stats.tx_fifo_errors++;
+               if (status & ENTSR_CDH)
+                       dev->stats.tx_heartbeat_errors++;
+               if (status & ENTSR_OWC)
+                       dev->stats.tx_window_errors++;
+       }
+       netif_wake_queue(dev);
+}
+
+/**
+ * ei_receive - receive some packets
+ * @dev: network device with which receive will be run
+ *
+ * We have a good packet(s), get it/them out of the buffers.
+ * Called with lock held.
+ */
+
+static void ei_receive(struct net_device *dev)
+{
+       unsigned long e8390_base = dev->base_addr;
+       struct ei_device *ei_local = netdev_priv(dev);
+       unsigned char rxing_page, this_frame, next_frame;
+       unsigned short current_offset;
+       int rx_pkt_count = 0;
+       struct e8390_pkt_hdr rx_frame;
+       int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page;
+
+       while (++rx_pkt_count < 10) {
+               int pkt_len, pkt_stat;
+
+               /* Get the rx page (incoming packet pointer). */
+               ei_outb_p(E8390_NODMA+E8390_PAGE1, e8390_base + E8390_CMD);
+               rxing_page = ei_inb_p(e8390_base + EN1_CURPAG);
+               ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
+
+               /* Remove one frame from the ring.  Boundary is always a page behind. */
+               this_frame = ei_inb_p(e8390_base + EN0_BOUNDARY) + 1;
+               if (this_frame >= ei_local->stop_page)
+                       this_frame = ei_local->rx_start_page;
+
+               /* Someday we'll omit the previous, iff we never get this message.
+                  (There is at least one clone claimed to have a problem.)
+
+                  Keep quiet if it looks like a card removal. One problem here
+                  is that some clones crash in roughly the same way.
+                */
+               if (ei_debug > 0 &&
+                   this_frame != ei_local->current_page &&
+                   (this_frame != 0x0 || rxing_page != 0xFF))
+                       netdev_err(dev, "mismatched read page pointers %2x vs %2x\n",
+                                  this_frame, ei_local->current_page);
+
+               if (this_frame == rxing_page)   /* Read all the frames? */
+                       break;                          /* Done for now */
+
+               current_offset = this_frame << 8;
+               ei_get_8390_hdr(dev, &rx_frame, this_frame);
+
+               pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr);
+               pkt_stat = rx_frame.status;
+
+               next_frame = this_frame + 1 + ((pkt_len+4)>>8);
+
+               /* Check for bogosity warned by 3c503 book: the status byte is never
+                  written.  This happened a lot during testing! This code should be
+                  cleaned up someday. */
+               if (rx_frame.next != next_frame &&
+                   rx_frame.next != next_frame + 1 &&
+                   rx_frame.next != next_frame - num_rx_pages &&
+                   rx_frame.next != next_frame + 1 - num_rx_pages) {
+                       ei_local->current_page = rxing_page;
+                       ei_outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY);
+                       dev->stats.rx_errors++;
+                       continue;
+               }
+
+               if (pkt_len < 60  ||  pkt_len > 1518) {
+                       if (ei_debug)
+                               netdev_dbg(dev, "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
+                                          rx_frame.count, rx_frame.status,
+                                          rx_frame.next);
+                       dev->stats.rx_errors++;
+                       dev->stats.rx_length_errors++;
+               } else if ((pkt_stat & 0x0F) == ENRSR_RXOK) {
+                       struct sk_buff *skb;
+
+                       skb = dev_alloc_skb(pkt_len+2);
+                       if (skb == NULL) {
+                               if (ei_debug > 1)
+                                       netdev_dbg(dev, "Couldn't allocate a sk_buff of size %d\n",
+                                                  pkt_len);
+                               dev->stats.rx_dropped++;
+                               break;
+                       } else {
+                               skb_reserve(skb, 2);    /* IP headers on 16 byte boundaries */
+                               skb_put(skb, pkt_len);  /* Make room */
+                               ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
+                               skb->protocol = eth_type_trans(skb, dev);
+                               if (!skb_defer_rx_timestamp(skb))
+                                       netif_rx(skb);
+                               dev->stats.rx_packets++;
+                               dev->stats.rx_bytes += pkt_len;
+                               if (pkt_stat & ENRSR_PHY)
+                                       dev->stats.multicast++;
+                       }
+               } else {
+                       if (ei_debug)
+                               netdev_dbg(dev, "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
+                                          rx_frame.status, rx_frame.next,
+                                          rx_frame.count);
+                       dev->stats.rx_errors++;
+                       /* NB: The NIC counts CRC, frame and missed errors. */
+                       if (pkt_stat & ENRSR_FO)
+                               dev->stats.rx_fifo_errors++;
+               }
+               next_frame = rx_frame.next;
+
+               /* This _should_ never happen: it's here for avoiding bad clones. */
+               if (next_frame >= ei_local->stop_page) {
+                       netdev_notice(dev, "next frame inconsistency, %#2x\n",
+                                     next_frame);
+                       next_frame = ei_local->rx_start_page;
+               }
+               ei_local->current_page = next_frame;
+               ei_outb_p(next_frame-1, e8390_base+EN0_BOUNDARY);
+       }
+
+       /* We used to also ack ENISR_OVER here, but that would sometimes mask
+          a real overrun, leaving the 8390 in a stopped state with rec'vr off. */
+       ei_outb_p(ENISR_RX+ENISR_RX_ERR, e8390_base+EN0_ISR);
+}
+
+/**
+ * ei_rx_overrun - handle receiver overrun
+ * @dev: network device which threw exception
+ *
+ * We have a receiver overrun: we have to kick the 8390 to get it started
+ * again. Problem is that you have to kick it exactly as NS prescribes in
+ * the updated datasheets, or "the NIC may act in an unpredictable manner."
+ * This includes causing "the NIC to defer indefinitely when it is stopped
+ * on a busy network."  Ugh.
+ * Called with lock held. Don't call this with the interrupts off or your
+ * computer will hate you - it takes 10ms or so.
+ */
+
+static void ei_rx_overrun(struct net_device *dev)
+{
+       unsigned long e8390_base = dev->base_addr;
+       unsigned char was_txing, must_resend = 0;
+       /* ei_local is used on some platforms via the EI_SHIFT macro */
+       struct ei_device *ei_local __maybe_unused = netdev_priv(dev);
+
+       /*
+        * Record whether a Tx was in progress and then issue the
+        * stop command.
+        */
+       was_txing = ei_inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
+       ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
+
+       if (ei_debug > 1)
+               netdev_dbg(dev, "Receiver overrun\n");
+       dev->stats.rx_over_errors++;
+
+       /*
+        * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
+        * Early datasheets said to poll the reset bit, but now they say that
+        * it "is not a reliable indicator and subsequently should be ignored."
+        * We wait at least 10ms.
+        */
+
+       mdelay(10);
+
+       /*
+        * Reset RBCR[01] back to zero as per magic incantation.
+        */
+       ei_outb_p(0x00, e8390_base+EN0_RCNTLO);
+       ei_outb_p(0x00, e8390_base+EN0_RCNTHI);
+
+       /*
+        * See if any Tx was interrupted or not. According to NS, this
+        * step is vital, and skipping it will cause no end of havoc.
+        */
+
+       if (was_txing) {
+               unsigned char tx_completed = ei_inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
+               if (!tx_completed)
+                       must_resend = 1;
+       }
+
+       /*
+        * Have to enter loopback mode and then restart the NIC before
+        * you are allowed to slurp packets up off the ring.
+        */
+       ei_outb_p(E8390_TXOFF, e8390_base + EN0_TXCR);
+       ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
+
+       /*
+        * Clear the Rx ring of all the debris, and ack the interrupt.
+        */
+       ei_receive(dev);
+       ei_outb_p(ENISR_OVER, e8390_base+EN0_ISR);
+
+       /*
+        * Leave loopback mode, and resend any packet that got stopped.
+        */
+       ei_outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR);
+       if (must_resend)
+               ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
+}
+
+/*
+ *     Collect the stats. This is called unlocked and from several contexts.
+ */
+
+static struct net_device_stats *__ei_get_stats(struct net_device *dev)
+{
+       unsigned long ioaddr = dev->base_addr;
+       struct ei_device *ei_local = netdev_priv(dev);
+       unsigned long flags;
+
+       /* If the card is stopped, just return the present stats. */
+       if (!netif_running(dev))
+               return &dev->stats;
+
+       spin_lock_irqsave(&ei_local->page_lock, flags);
+       /* Read the counter registers, assuming we are in page 0. */
+       dev->stats.rx_frame_errors  += ei_inb_p(ioaddr + EN0_COUNTER0);
+       dev->stats.rx_crc_errors    += ei_inb_p(ioaddr + EN0_COUNTER1);
+       dev->stats.rx_missed_errors += ei_inb_p(ioaddr + EN0_COUNTER2);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+       return &dev->stats;
+}
+
+/*
+ * Form the 64 bit 8390 multicast table from the linked list of addresses
+ * associated with this dev structure.
+ */
+
+static inline void make_mc_bits(u8 *bits, struct net_device *dev)
+{
+       struct netdev_hw_addr *ha;
+
+       netdev_for_each_mc_addr(ha, dev) {
+               u32 crc = ether_crc(ETH_ALEN, ha->addr);
+               /*
+                * The 8390 uses the 6 most significant bits of the
+                * CRC to index the multicast table.
+                */
+               bits[crc>>29] |= (1<<((crc>>26)&7));
+       }
+}
+
+/**
+ * do_set_multicast_list - set/clear multicast filter
+ * @dev: net device for which multicast filter is adjusted
+ *
+ *     Set or clear the multicast filter for this adaptor. May be called
+ *     from a BH in 2.1.x. Must be called with lock held.
+ */
+
+static void do_set_multicast_list(struct net_device *dev)
+{
+       unsigned long e8390_base = dev->base_addr;
+       int i;
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
+               memset(ei_local->mcfilter, 0, 8);
+               if (!netdev_mc_empty(dev))
+                       make_mc_bits(ei_local->mcfilter, dev);
+       } else
+               memset(ei_local->mcfilter, 0xFF, 8);    /* mcast set to accept-all */
+
+       /*
+        * DP8390 manuals don't specify any magic sequence for altering
+        * the multicast regs on an already running card. To be safe, we
+        * ensure multicast mode is off prior to loading up the new hash
+        * table. If this proves to be not enough, we can always resort
+        * to stopping the NIC, loading the table and then restarting.
+        *
+        * Bug Alert!  The MC regs on the SMC 83C690 (SMC Elite and SMC
+        * Elite16) appear to be write-only. The NS 8390 data sheet lists
+        * them as r/w so this is a bug.  The SMC 83C790 (SMC Ultra and
+        * Ultra32 EISA) appears to have this bug fixed.
+        */
+
+       if (netif_running(dev))
+               ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
+       ei_outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
+       for (i = 0; i < 8; i++) {
+               ei_outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
+#ifndef BUG_83C690
+               if (ei_inb_p(e8390_base + EN1_MULT_SHIFT(i)) != ei_local->mcfilter[i])
+                       netdev_err(dev, "Multicast filter read/write mismap %d\n",
+                                  i);
+#endif
+       }
+       ei_outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
+
+       if (dev->flags&IFF_PROMISC)
+               ei_outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
+       else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev))
+               ei_outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
+       else
+               ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
+}
+
+/*
+ *     Called without lock held. This is invoked from user context and may
+ *     be parallel to just about everything else. Its also fairly quick and
+ *     not called too often. Must protect against both bh and irq users
+ */
+
+static void __ei_set_multicast_list(struct net_device *dev)
+{
+       unsigned long flags;
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       spin_lock_irqsave(&ei_local->page_lock, flags);
+       do_set_multicast_list(dev);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
+}
+
+/**
+ * ethdev_setup - init rest of 8390 device struct
+ * @dev: network device structure to init
+ *
+ * Initialize the rest of the 8390 device structure.  Do NOT __init
+ * this, as it is used by 8390 based modular drivers too.
+ */
+
+static void ethdev_setup(struct net_device *dev)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       if (ei_debug > 1)
+               printk(version);
+
+       ether_setup(dev);
+
+       spin_lock_init(&ei_local->page_lock);
+}
+
+/**
+ * alloc_ei_netdev - alloc_etherdev counterpart for 8390
+ * @size: extra bytes to allocate
+ *
+ * Allocate 8390-specific net_device.
+ */
+static struct net_device *____alloc_ei_netdev(int size)
+{
+       return alloc_netdev(sizeof(struct ei_device) + size, "eth%d",
+                               ethdev_setup);
+}
+
+
+
+
+/* This page of functions should be 8390 generic */
+/* Follow National Semi's recommendations for initializing the "NIC". */
+
+/**
+ * NS8390_init - initialize 8390 hardware
+ * @dev: network device to initialize
+ * @startp: boolean.  non-zero value to initiate chip processing
+ *
+ *     Must be called with lock held.
+ */
+
+static void __NS8390_init(struct net_device *dev, int startp)
+{
+       unsigned long e8390_base = dev->base_addr;
+       struct ei_device *ei_local = netdev_priv(dev);
+       int i;
+       int endcfg = ei_local->word16
+           ? (0x48 | ENDCFG_WTS | (ei_local->bigendian ? ENDCFG_BOS : 0))
+           : 0x48;
+
+       if (sizeof(struct e8390_pkt_hdr) != 4)
+               panic("8390.c: header struct mispacked\n");
+       /* Follow National Semi's recommendations for initing the DP83902. */
+       ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */
+       ei_outb_p(endcfg, e8390_base + EN0_DCFG);       /* 0x48 or 0x49 */
+       /* Clear the remote byte count registers. */
+       ei_outb_p(0x00,  e8390_base + EN0_RCNTLO);
+       ei_outb_p(0x00,  e8390_base + EN0_RCNTHI);
+       /* Set to monitor and loopback mode -- this is vital!. */
+       ei_outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */
+       ei_outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
+       /* Set the transmit page and receive ring. */
+       ei_outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
+       ei_local->tx1 = ei_local->tx2 = 0;
+       ei_outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG);
+       ei_outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY);    /* 3c503 says 0x3f,NS0x26*/
+       ei_local->current_page = ei_local->rx_start_page;               /* assert boundary+1 */
+       ei_outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG);
+       /* Clear the pending interrupts and mask. */
+       ei_outb_p(0xFF, e8390_base + EN0_ISR);
+       ei_outb_p(0x00,  e8390_base + EN0_IMR);
+
+       /* Copy the station address into the DS8390 registers. */
+
+       ei_outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
+       for (i = 0; i < 6; i++) {
+               ei_outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
+               if (ei_debug > 1 &&
+                   ei_inb_p(e8390_base + EN1_PHYS_SHIFT(i)) != dev->dev_addr[i])
+                       netdev_err(dev, "Hw. address read/write mismap %d\n", i);
+       }
+
+       ei_outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
+       ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
+
+       ei_local->tx1 = ei_local->tx2 = 0;
+       ei_local->txing = 0;
+
+       if (startp) {
+               ei_outb_p(0xff,  e8390_base + EN0_ISR);
+               ei_outb_p(ENISR_ALL,  e8390_base + EN0_IMR);
+               ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
+               ei_outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */
+               /* 3c503 TechMan says rxconfig only after the NIC is started. */
+               ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on,  */
+               do_set_multicast_list(dev);     /* (re)load the mcast table */
+       }
+}
+
+/* Trigger a transmit start, assuming the length is valid.
+   Always called with the page lock held */
+
+static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
+                                                               int start_page)
+{
+       unsigned long e8390_base = dev->base_addr;
+       struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev);
+
+       ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
+
+       if (ei_inb_p(e8390_base + E8390_CMD) & E8390_TRANS) {
+               netdev_warn(dev, "trigger_send() called with the transmitter busy\n");
+               return;
+       }
+       ei_outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
+       ei_outb_p(length >> 8, e8390_base + EN0_TCNTHI);
+       ei_outb_p(start_page, e8390_base + EN0_TPSR);
+       ei_outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD);
+}
diff --git a/drivers/net/ethernet/8390/lne390.c b/drivers/net/ethernet/8390/lne390.c
new file mode 100644 (file)
index 0000000..f9888d2
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+       lne390.c
+
+       Linux driver for Mylex LNE390 EISA Network Adapter
+
+       Copyright (C) 1996-1998, Paul Gortmaker.
+
+       This software may be used and distributed according to the terms
+       of the GNU General Public License, incorporated herein by reference.
+
+       Information and Code Sources:
+
+       1) Based upon framework of es3210 driver.
+       2) The existing myriad of other Linux 8390 drivers by Donald Becker.
+       3) Russ Nelson's asm packet driver provided additional info.
+       4) Info for getting IRQ and sh-mem gleaned from the EISA cfg files.
+
+       The LNE390 is an EISA shared memory NS8390 implementation. Note
+       that all memory copies to/from the board must be 32bit transfers.
+       There are two versions of the card: the lne390a and the lne390b.
+       Going by the EISA cfg files, the "a" has jumpers to select between
+       BNC/AUI, but the "b" also has RJ-45 and selection is via the SCU.
+       The shared memory address selection is also slightly different.
+       Note that shared memory address > 1MB are supported with this driver.
+
+       You can try <http://www.mylex.com> if you want more info, as I've
+       never even seen one of these cards.  :)
+
+       Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/09/01
+       - get rid of check_region
+       - no need to check if dev == NULL in lne390_probe1
+*/
+
+static const char *version =
+       "lne390.c: Driver revision v0.99.1, 01/09/2000\n";
+
+#include <linux/module.h>
+#include <linux/eisa.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+#define DRV_NAME "lne390"
+
+static int lne390_probe1(struct net_device *dev, int ioaddr);
+
+static void lne390_reset_8390(struct net_device *dev);
+
+static void lne390_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
+static void lne390_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset);
+static void lne390_block_output(struct net_device *dev, int count, const unsigned char *buf, const int start_page);
+
+#define LNE390_START_PG                0x00    /* First page of TX buffer      */
+#define LNE390_STOP_PG         0x80    /* Last page +1 of RX ring      */
+
+#define LNE390_ID_PORT         0xc80   /* Same for all EISA cards      */
+#define LNE390_IO_EXTENT       0x20
+#define LNE390_SA_PROM         0x16    /* Start of e'net addr.         */
+#define LNE390_RESET_PORT      0xc84   /* From the pkt driver source   */
+#define LNE390_NIC_OFFSET      0x00    /* Hello, the 8390 is *here*    */
+
+#define LNE390_ADDR0           0x00    /* 3 byte vendor prefix         */
+#define LNE390_ADDR1           0x80
+#define LNE390_ADDR2           0xe5
+
+#define LNE390_ID0     0x10009835      /* 0x3598 = 01101 01100 11000 = mlx */
+#define LNE390_ID1     0x11009835      /* above is the 390A, this is 390B  */
+
+#define LNE390_CFG1            0xc84   /* NB: 0xc84 is also "reset" port. */
+#define LNE390_CFG2            0xc90
+
+/*
+ *     You can OR any of the following bits together and assign it
+ *     to LNE390_DEBUG to get verbose driver info during operation.
+ *     Currently only the probe one is implemented.
+ */
+
+#define LNE390_D_PROBE 0x01
+#define LNE390_D_RX_PKT        0x02
+#define LNE390_D_TX_PKT        0x04
+#define LNE390_D_IRQ   0x08
+
+#define LNE390_DEBUG   0
+
+static unsigned char irq_map[] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
+static unsigned int shmem_mapA[] __initdata = {0xff, 0xfe, 0xfd, 0xfff, 0xffe, 0xffc, 0x0d, 0x0};
+static unsigned int shmem_mapB[] __initdata = {0xff, 0xfe, 0x0e, 0xfff, 0xffe, 0xffc, 0x0d, 0x0};
+
+/*
+ *     Probe for the card. The best way is to read the EISA ID if it
+ *     is known. Then we can check the prefix of the station address
+ *     PROM for a match against the value assigned to Mylex.
+ */
+
+static int __init do_lne390_probe(struct net_device *dev)
+{
+       unsigned short ioaddr = dev->base_addr;
+       int irq = dev->irq;
+       int mem_start = dev->mem_start;
+       int ret;
+
+       if (ioaddr > 0x1ff) {           /* Check a single specified location. */
+               if (!request_region(ioaddr, LNE390_IO_EXTENT, DRV_NAME))
+                       return -EBUSY;
+               ret = lne390_probe1(dev, ioaddr);
+               if (ret)
+                       release_region(ioaddr, LNE390_IO_EXTENT);
+               return ret;
+       }
+       else if (ioaddr > 0)            /* Don't probe at all. */
+               return -ENXIO;
+
+       if (!EISA_bus) {
+#if LNE390_DEBUG & LNE390_D_PROBE
+               printk("lne390-debug: Not an EISA bus. Not probing high ports.\n");
+#endif
+               return -ENXIO;
+       }
+
+       /* EISA spec allows for up to 16 slots, but 8 is typical. */
+       for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
+               if (!request_region(ioaddr, LNE390_IO_EXTENT, DRV_NAME))
+                       continue;
+               if (lne390_probe1(dev, ioaddr) == 0)
+                       return 0;
+               release_region(ioaddr, LNE390_IO_EXTENT);
+               dev->irq = irq;
+               dev->mem_start = mem_start;
+       }
+
+       return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init lne390_probe(int unit)
+{
+       struct net_device *dev = alloc_ei_netdev();
+       int err;
+
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       sprintf(dev->name, "eth%d", unit);
+       netdev_boot_setup_check(dev);
+
+       err = do_lne390_probe(dev);
+       if (err)
+               goto out;
+       return dev;
+out:
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+#endif
+
+static int __init lne390_probe1(struct net_device *dev, int ioaddr)
+{
+       int i, revision, ret;
+       unsigned long eisa_id;
+
+       if (inb_p(ioaddr + LNE390_ID_PORT) == 0xff) return -ENODEV;
+
+#if LNE390_DEBUG & LNE390_D_PROBE
+       printk("lne390-debug: probe at %#x, ID %#8x\n", ioaddr, inl(ioaddr + LNE390_ID_PORT));
+       printk("lne390-debug: config regs: %#x %#x\n",
+               inb(ioaddr + LNE390_CFG1), inb(ioaddr + LNE390_CFG2));
+#endif
+
+
+/*     Check the EISA ID of the card. */
+       eisa_id = inl(ioaddr + LNE390_ID_PORT);
+       if ((eisa_id != LNE390_ID0) && (eisa_id != LNE390_ID1)) {
+               return -ENODEV;
+       }
+
+       revision = (eisa_id >> 24) & 0x01;      /* 0 = rev A, 1 rev B */
+
+#if 0
+/*     Check the Mylex vendor ID as well. Not really required. */
+       if (inb(ioaddr + LNE390_SA_PROM + 0) != LNE390_ADDR0
+               || inb(ioaddr + LNE390_SA_PROM + 1) != LNE390_ADDR1
+               || inb(ioaddr + LNE390_SA_PROM + 2) != LNE390_ADDR2 ) {
+               printk("lne390.c: card not found");
+               for(i = 0; i < ETHER_ADDR_LEN; i++)
+                       printk(" %02x", inb(ioaddr + LNE390_SA_PROM + i));
+               printk(" (invalid prefix).\n");
+               return -ENODEV;
+       }
+#endif
+
+       for(i = 0; i < ETHER_ADDR_LEN; i++)
+               dev->dev_addr[i] = inb(ioaddr + LNE390_SA_PROM + i);
+       printk("lne390.c: LNE390%X in EISA slot %d, address %pM.\n",
+              0xa+revision, ioaddr/0x1000, dev->dev_addr);
+
+       printk("lne390.c: ");
+
+       /* Snarf the interrupt now. CFG file has them all listed as `edge' with share=NO */
+       if (dev->irq == 0) {
+               unsigned char irq_reg = inb(ioaddr + LNE390_CFG2) >> 3;
+               dev->irq = irq_map[irq_reg & 0x07];
+               printk("using");
+       } else {
+               /* This is useless unless we reprogram the card here too */
+               if (dev->irq == 2) dev->irq = 9;        /* Doh! */
+               printk("assigning");
+       }
+       printk(" IRQ %d,", dev->irq);
+
+       if ((ret = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev))) {
+               printk (" unable to get IRQ %d.\n", dev->irq);
+               return ret;
+       }
+
+       if (dev->mem_start == 0) {
+               unsigned char mem_reg = inb(ioaddr + LNE390_CFG2) & 0x07;
+
+               if (revision)   /* LNE390B */
+                       dev->mem_start = shmem_mapB[mem_reg] * 0x10000;
+               else            /* LNE390A */
+                       dev->mem_start = shmem_mapA[mem_reg] * 0x10000;
+               printk(" using ");
+       } else {
+               /* Should check for value in shmem_map and reprogram the card to use it */
+               dev->mem_start &= 0xfff0000;
+               printk(" assigning ");
+       }
+
+       printk("%dkB memory at physical address %#lx\n",
+                       LNE390_STOP_PG/4, dev->mem_start);
+
+       /*
+          BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
+          the card mem within the region covered by `normal' RAM  !!!
+
+          ioremap() will fail in that case.
+       */
+       ei_status.mem = ioremap(dev->mem_start, LNE390_STOP_PG*0x100);
+       if (!ei_status.mem) {
+               printk(KERN_ERR "lne390.c: Unable to remap card memory above 1MB !!\n");
+               printk(KERN_ERR "lne390.c: Try using EISA SCU to set memory below 1MB.\n");
+               printk(KERN_ERR "lne390.c: Driver NOT installed.\n");
+               ret = -EAGAIN;
+               goto cleanup;
+       }
+       printk("lne390.c: remapped %dkB card memory to virtual address %p\n",
+                       LNE390_STOP_PG/4, ei_status.mem);
+
+       dev->mem_start = (unsigned long)ei_status.mem;
+       dev->mem_end = dev->mem_start + (LNE390_STOP_PG - LNE390_START_PG)*256;
+
+       /* The 8390 offset is zero for the LNE390 */
+       dev->base_addr = ioaddr;
+
+       ei_status.name = "LNE390";
+       ei_status.tx_start_page = LNE390_START_PG;
+       ei_status.rx_start_page = LNE390_START_PG + TX_PAGES;
+       ei_status.stop_page = LNE390_STOP_PG;
+       ei_status.word16 = 1;
+
+       if (ei_debug > 0)
+               printk(version);
+
+       ei_status.reset_8390 = &lne390_reset_8390;
+       ei_status.block_input = &lne390_block_input;
+       ei_status.block_output = &lne390_block_output;
+       ei_status.get_8390_hdr = &lne390_get_8390_hdr;
+
+       dev->netdev_ops = &ei_netdev_ops;
+       NS8390_init(dev, 0);
+
+       ret = register_netdev(dev);
+       if (ret)
+               goto unmap;
+       return 0;
+unmap:
+       if (ei_status.reg0)
+               iounmap(ei_status.mem);
+cleanup:
+       free_irq(dev->irq, dev);
+       return ret;
+}
+
+/*
+ *     Reset as per the packet driver method. Judging by the EISA cfg
+ *     file, this just toggles the "Board Enable" bits (bit 2 and 0).
+ */
+
+static void lne390_reset_8390(struct net_device *dev)
+{
+       unsigned short ioaddr = dev->base_addr;
+
+       outb(0x04, ioaddr + LNE390_RESET_PORT);
+       if (ei_debug > 1) printk("%s: resetting the LNE390...", dev->name);
+
+       mdelay(2);
+
+       ei_status.txing = 0;
+       outb(0x01, ioaddr + LNE390_RESET_PORT);
+       if (ei_debug > 1) printk("reset done\n");
+}
+
+/*
+ *     Note: In the following three functions is the implicit assumption
+ *     that the associated memcpy will only use "rep; movsl" as long as
+ *     we keep the counts as some multiple of doublewords. This is a
+ *     requirement of the hardware, and also prevents us from using
+ *     eth_io_copy_and_sum() since we can't guarantee it will limit
+ *     itself to doubleword access.
+ */
+
+/*
+ *     Grab the 8390 specific header. Similar to the block_input routine, but
+ *     we don't need to be concerned with ring wrap as the header will be at
+ *     the start of a page, so we optimize accordingly. (A single doubleword.)
+ */
+
+static void
+lne390_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+       void __iomem *hdr_start = ei_status.mem + ((ring_page - LNE390_START_PG)<<8);
+       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+       hdr->count = (hdr->count + 3) & ~3;     /* Round up allocation. */
+}
+
+/*
+ *     Block input and output are easy on shared memory ethercards, the only
+ *     complication is when the ring buffer wraps. The count will already
+ *     be rounded up to a doubleword value via lne390_get_8390_hdr() above.
+ */
+
+static void lne390_block_input(struct net_device *dev, int count, struct sk_buff *skb,
+                                                 int ring_offset)
+{
+       void __iomem *xfer_start = ei_status.mem + ring_offset - (LNE390_START_PG<<8);
+
+       if (ring_offset + count > (LNE390_STOP_PG<<8)) {
+               /* Packet wraps over end of ring buffer. */
+               int semi_count = (LNE390_STOP_PG<<8) - ring_offset;
+               memcpy_fromio(skb->data, xfer_start, semi_count);
+               count -= semi_count;
+               memcpy_fromio(skb->data + semi_count,
+                       ei_status.mem + (TX_PAGES<<8), count);
+       } else {
+               /* Packet is in one chunk. */
+               memcpy_fromio(skb->data, xfer_start, count);
+       }
+}
+
+static void lne390_block_output(struct net_device *dev, int count,
+                               const unsigned char *buf, int start_page)
+{
+       void __iomem *shmem = ei_status.mem + ((start_page - LNE390_START_PG)<<8);
+
+       count = (count + 3) & ~3;     /* Round up to doubleword */
+       memcpy_toio(shmem, buf, count);
+}
+
+
+#ifdef MODULE
+#define MAX_LNE_CARDS  4       /* Max number of LNE390 cards per module */
+static struct net_device *dev_lne[MAX_LNE_CARDS];
+static int io[MAX_LNE_CARDS];
+static int irq[MAX_LNE_CARDS];
+static int mem[MAX_LNE_CARDS];
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(mem, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_PARM_DESC(mem, "memory base address(es)");
+MODULE_DESCRIPTION("Mylex LNE390A/B EISA Ethernet driver");
+MODULE_LICENSE("GPL");
+
+int __init init_module(void)
+{
+       struct net_device *dev;
+       int this_dev, found = 0;
+
+       for (this_dev = 0; this_dev < MAX_LNE_CARDS; this_dev++) {
+               if (io[this_dev] == 0 && this_dev != 0)
+                       break;
+               dev = alloc_ei_netdev();
+               if (!dev)
+                       break;
+               dev->irq = irq[this_dev];
+               dev->base_addr = io[this_dev];
+               dev->mem_start = mem[this_dev];
+               if (do_lne390_probe(dev) == 0) {
+                       dev_lne[found++] = dev;
+                       continue;
+               }
+               free_netdev(dev);
+               printk(KERN_WARNING "lne390.c: No LNE390 card found (i/o = 0x%x).\n", io[this_dev]);
+               break;
+       }
+       if (found)
+               return 0;
+       return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+       free_irq(dev->irq, dev);
+       release_region(dev->base_addr, LNE390_IO_EXTENT);
+       iounmap(ei_status.mem);
+}
+
+void __exit cleanup_module(void)
+{
+       int this_dev;
+
+       for (this_dev = 0; this_dev < MAX_LNE_CARDS; this_dev++) {
+               struct net_device *dev = dev_lne[this_dev];
+               if (dev) {
+                       unregister_netdev(dev);
+                       cleanup_card(dev);
+                       free_netdev(dev);
+               }
+       }
+}
+#endif /* MODULE */
+
diff --git a/drivers/net/ethernet/8390/mac8390.c b/drivers/net/ethernet/8390/mac8390.c
new file mode 100644 (file)
index 0000000..f84f5e6
--- /dev/null
@@ -0,0 +1,874 @@
+/* mac8390.c: New driver for 8390-based Nubus (or Nubus-alike)
+   Ethernet cards on Linux */
+/* Based on the former daynaport.c driver, by Alan Cox.  Some code
+   taken from or inspired by skeleton.c by Donald Becker, acenic.c by
+   Jes Sorensen, and ne2k-pci.c by Donald Becker and Paul Gortmaker.
+
+   This software may be used and distributed according to the terms of
+   the GNU Public License, incorporated herein by reference.  */
+
+/* 2000-02-28: support added for Dayna and Kinetics cards by
+   A.G.deWijn@phys.uu.nl */
+/* 2000-04-04: support added for Dayna2 by bart@etpmod.phys.tue.nl */
+/* 2001-04-18: support for DaynaPort E/LC-M by rayk@knightsmanor.org */
+/* 2001-05-15: support for Cabletron ported from old daynaport driver
+ * and fixed access to Sonic Sys card which masquerades as a Farallon
+ * by rayk@knightsmanor.org */
+/* 2002-12-30: Try to support more cards, some clues from NetBSD driver */
+/* 2003-12-26: Make sure Asante cards always work. */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/nubus.h>
+#include <linux/in.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/hwtest.h>
+#include <asm/macints.h>
+
+static char version[] =
+       "v0.4 2001-05-15 David Huggins-Daines <dhd@debian.org> and others\n";
+
+#define EI_SHIFT(x)    (ei_local->reg_offset[x])
+#define ei_inb(port)   in_8(port)
+#define ei_outb(val, port)     out_8(port, val)
+#define ei_inb_p(port) in_8(port)
+#define ei_outb_p(val, port)   out_8(port, val)
+
+#include "lib8390.c"
+
+#define WD_START_PG                    0x00    /* First page of TX buffer */
+#define CABLETRON_RX_START_PG          0x00    /* First page of RX buffer */
+#define CABLETRON_RX_STOP_PG           0x30    /* Last page +1 of RX ring */
+#define CABLETRON_TX_START_PG          CABLETRON_RX_STOP_PG
+                                               /* First page of TX buffer */
+
+/*
+ * Unfortunately it seems we have to hardcode these for the moment
+ * Shouldn't the card know about this?
+ * Does anyone know where to read it off the card?
+ * Do we trust the data provided by the card?
+ */
+
+#define DAYNA_8390_BASE                0x80000
+#define DAYNA_8390_MEM         0x00000
+
+#define CABLETRON_8390_BASE    0x90000
+#define CABLETRON_8390_MEM     0x00000
+
+#define INTERLAN_8390_BASE     0xE0000
+#define INTERLAN_8390_MEM      0xD0000
+
+enum mac8390_type {
+       MAC8390_NONE = -1,
+       MAC8390_APPLE,
+       MAC8390_ASANTE,
+       MAC8390_FARALLON,
+       MAC8390_CABLETRON,
+       MAC8390_DAYNA,
+       MAC8390_INTERLAN,
+       MAC8390_KINETICS,
+};
+
+static const char *cardname[] = {
+       "apple",
+       "asante",
+       "farallon",
+       "cabletron",
+       "dayna",
+       "interlan",
+       "kinetics",
+};
+
+static const int word16[] = {
+       1, /* apple */
+       1, /* asante */
+       1, /* farallon */
+       1, /* cabletron */
+       0, /* dayna */
+       1, /* interlan */
+       0, /* kinetics */
+};
+
+/* on which cards do we use NuBus resources? */
+static const int useresources[] = {
+       1, /* apple */
+       1, /* asante */
+       1, /* farallon */
+       0, /* cabletron */
+       0, /* dayna */
+       0, /* interlan */
+       0, /* kinetics */
+};
+
+enum mac8390_access {
+       ACCESS_UNKNOWN = 0,
+       ACCESS_32,
+       ACCESS_16,
+};
+
+extern int mac8390_memtest(struct net_device *dev);
+static int mac8390_initdev(struct net_device *dev, struct nubus_dev *ndev,
+                          enum mac8390_type type);
+
+static int mac8390_open(struct net_device *dev);
+static int mac8390_close(struct net_device *dev);
+static void mac8390_no_reset(struct net_device *dev);
+static void interlan_reset(struct net_device *dev);
+
+/* Sane (32-bit chunk memory read/write) - Some Farallon and Apple do this*/
+static void sane_get_8390_hdr(struct net_device *dev,
+                             struct e8390_pkt_hdr *hdr, int ring_page);
+static void sane_block_input(struct net_device *dev, int count,
+                            struct sk_buff *skb, int ring_offset);
+static void sane_block_output(struct net_device *dev, int count,
+                             const unsigned char *buf, const int start_page);
+
+/* dayna_memcpy to and from card */
+static void dayna_memcpy_fromcard(struct net_device *dev, void *to,
+                               int from, int count);
+static void dayna_memcpy_tocard(struct net_device *dev, int to,
+                             const void *from, int count);
+
+/* Dayna - Dayna/Kinetics use this */
+static void dayna_get_8390_hdr(struct net_device *dev,
+                              struct e8390_pkt_hdr *hdr, int ring_page);
+static void dayna_block_input(struct net_device *dev, int count,
+                             struct sk_buff *skb, int ring_offset);
+static void dayna_block_output(struct net_device *dev, int count,
+                              const unsigned char *buf, int start_page);
+
+#define memcpy_fromio(a, b, c) memcpy((a), (void *)(b), (c))
+#define memcpy_toio(a, b, c)   memcpy((void *)(a), (b), (c))
+
+#define memcmp_withio(a, b, c) memcmp((a), (void *)(b), (c))
+
+/* Slow Sane (16-bit chunk memory read/write) Cabletron uses this */
+static void slow_sane_get_8390_hdr(struct net_device *dev,
+                                  struct e8390_pkt_hdr *hdr, int ring_page);
+static void slow_sane_block_input(struct net_device *dev, int count,
+                                 struct sk_buff *skb, int ring_offset);
+static void slow_sane_block_output(struct net_device *dev, int count,
+                                  const unsigned char *buf, int start_page);
+static void word_memcpy_tocard(unsigned long tp, const void *fp, int count);
+static void word_memcpy_fromcard(void *tp, unsigned long fp, int count);
+
+static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)
+{
+       switch (dev->dr_sw) {
+       case NUBUS_DRSW_3COM:
+               switch (dev->dr_hw) {
+               case NUBUS_DRHW_APPLE_SONIC_NB:
+               case NUBUS_DRHW_APPLE_SONIC_LC:
+               case NUBUS_DRHW_SONNET:
+                       return MAC8390_NONE;
+                       break;
+               default:
+                       return MAC8390_APPLE;
+                       break;
+               }
+               break;
+
+       case NUBUS_DRSW_APPLE:
+               switch (dev->dr_hw) {
+               case NUBUS_DRHW_ASANTE_LC:
+                       return MAC8390_NONE;
+                       break;
+               case NUBUS_DRHW_CABLETRON:
+                       return MAC8390_CABLETRON;
+                       break;
+               default:
+                       return MAC8390_APPLE;
+                       break;
+               }
+               break;
+
+       case NUBUS_DRSW_ASANTE:
+               return MAC8390_ASANTE;
+               break;
+
+       case NUBUS_DRSW_TECHWORKS:
+       case NUBUS_DRSW_DAYNA2:
+       case NUBUS_DRSW_DAYNA_LC:
+               if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
+                       return MAC8390_CABLETRON;
+               else
+                       return MAC8390_APPLE;
+               break;
+
+       case NUBUS_DRSW_FARALLON:
+               return MAC8390_FARALLON;
+               break;
+
+       case NUBUS_DRSW_KINETICS:
+               switch (dev->dr_hw) {
+               case NUBUS_DRHW_INTERLAN:
+                       return MAC8390_INTERLAN;
+                       break;
+               default:
+                       return MAC8390_KINETICS;
+                       break;
+               }
+               break;
+
+       case NUBUS_DRSW_DAYNA:
+               /*
+                * These correspond to Dayna Sonic cards
+                * which use the macsonic driver
+                */
+               if (dev->dr_hw == NUBUS_DRHW_SMC9194 ||
+                   dev->dr_hw == NUBUS_DRHW_INTERLAN)
+                       return MAC8390_NONE;
+               else
+                       return MAC8390_DAYNA;
+               break;
+       }
+       return MAC8390_NONE;
+}
+
+static enum mac8390_access __init mac8390_testio(volatile unsigned long membase)
+{
+       unsigned long outdata = 0xA5A0B5B0;
+       unsigned long indata =  0x00000000;
+       /* Try writing 32 bits */
+       memcpy_toio(membase, &outdata, 4);
+       /* Now compare them */
+       if (memcmp_withio(&outdata, membase, 4) == 0)
+               return ACCESS_32;
+       /* Write 16 bit output */
+       word_memcpy_tocard(membase, &outdata, 4);
+       /* Now read it back */
+       word_memcpy_fromcard(&indata, membase, 4);
+       if (outdata == indata)
+               return ACCESS_16;
+       return ACCESS_UNKNOWN;
+}
+
+static int __init mac8390_memsize(unsigned long membase)
+{
+       unsigned long flags;
+       int i, j;
+
+       local_irq_save(flags);
+       /* Check up to 32K in 4K increments */
+       for (i = 0; i < 8; i++) {
+               volatile unsigned short *m = (unsigned short *)(membase + (i * 0x1000));
+
+               /* Unwriteable - we have a fully decoded card and the
+                  RAM end located */
+               if (hwreg_present(m) == 0)
+                       break;
+
+               /* write a distinctive byte */
+               *m = 0xA5A0 | i;
+               /* check that we read back what we wrote */
+               if (*m != (0xA5A0 | i))
+                       break;
+
+               /* check for partial decode and wrap */
+               for (j = 0; j < i; j++) {
+                       volatile unsigned short *p = (unsigned short *)(membase + (j * 0x1000));
+                       if (*p != (0xA5A0 | j))
+                               break;
+               }
+       }
+       local_irq_restore(flags);
+       /*
+        * in any case, we stopped once we tried one block too many,
+        * or once we reached 32K
+        */
+       return i * 0x1000;
+}
+
+static bool __init mac8390_init(struct net_device *dev, struct nubus_dev *ndev,
+                               enum mac8390_type cardtype)
+{
+       struct nubus_dir dir;
+       struct nubus_dirent ent;
+       int offset;
+       volatile unsigned short *i;
+
+       printk_once(KERN_INFO pr_fmt("%s"), version);
+
+       dev->irq = SLOT2IRQ(ndev->board->slot);
+       /* This is getting to be a habit */
+       dev->base_addr = (ndev->board->slot_addr |
+                         ((ndev->board->slot & 0xf) << 20));
+
+       /*
+        * Get some Nubus info - we will trust the card's idea
+        * of where its memory and registers are.
+        */
+
+       if (nubus_get_func_dir(ndev, &dir) == -1) {
+               pr_err("%s: Unable to get Nubus functional directory for slot %X!\n",
+                      dev->name, ndev->board->slot);
+               return false;
+       }
+
+       /* Get the MAC address */
+       if (nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent) == -1) {
+               pr_info("%s: Couldn't get MAC address!\n", dev->name);
+               return false;
+       }
+
+       nubus_get_rsrc_mem(dev->dev_addr, &ent, 6);
+
+       if (useresources[cardtype] == 1) {
+               nubus_rewinddir(&dir);
+               if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_BASEOS,
+                                   &ent) == -1) {
+                       pr_err("%s: Memory offset resource for slot %X not found!\n",
+                              dev->name, ndev->board->slot);
+                       return false;
+               }
+               nubus_get_rsrc_mem(&offset, &ent, 4);
+               dev->mem_start = dev->base_addr + offset;
+               /* yes, this is how the Apple driver does it */
+               dev->base_addr = dev->mem_start + 0x10000;
+               nubus_rewinddir(&dir);
+               if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_LENGTH,
+                                   &ent) == -1) {
+                       pr_info("%s: Memory length resource for slot %X not found, probing\n",
+                               dev->name, ndev->board->slot);
+                       offset = mac8390_memsize(dev->mem_start);
+               } else {
+                       nubus_get_rsrc_mem(&offset, &ent, 4);
+               }
+               dev->mem_end = dev->mem_start + offset;
+       } else {
+               switch (cardtype) {
+               case MAC8390_KINETICS:
+               case MAC8390_DAYNA: /* it's the same */
+                       dev->base_addr = (int)(ndev->board->slot_addr +
+                                              DAYNA_8390_BASE);
+                       dev->mem_start = (int)(ndev->board->slot_addr +
+                                              DAYNA_8390_MEM);
+                       dev->mem_end = dev->mem_start +
+                                      mac8390_memsize(dev->mem_start);
+                       break;
+               case MAC8390_INTERLAN:
+                       dev->base_addr = (int)(ndev->board->slot_addr +
+                                              INTERLAN_8390_BASE);
+                       dev->mem_start = (int)(ndev->board->slot_addr +
+                                              INTERLAN_8390_MEM);
+                       dev->mem_end = dev->mem_start +
+                                      mac8390_memsize(dev->mem_start);
+                       break;
+               case MAC8390_CABLETRON:
+                       dev->base_addr = (int)(ndev->board->slot_addr +
+                                              CABLETRON_8390_BASE);
+                       dev->mem_start = (int)(ndev->board->slot_addr +
+                                              CABLETRON_8390_MEM);
+                       /* The base address is unreadable if 0x00
+                        * has been written to the command register
+                        * Reset the chip by writing E8390_NODMA +
+                        *   E8390_PAGE0 + E8390_STOP just to be
+                        *   sure
+                        */
+                       i = (void *)dev->base_addr;
+                       *i = 0x21;
+                       dev->mem_end = dev->mem_start +
+                                      mac8390_memsize(dev->mem_start);
+                       break;
+
+               default:
+                       pr_err("Card type %s is unsupported, sorry\n",
+                              ndev->board->name);
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+struct net_device * __init mac8390_probe(int unit)
+{
+       struct net_device *dev;
+       struct nubus_dev *ndev = NULL;
+       int err = -ENODEV;
+
+       static unsigned int slots;
+
+       enum mac8390_type cardtype;
+
+       /* probably should check for Nubus instead */
+
+       if (!MACH_IS_MAC)
+               return ERR_PTR(-ENODEV);
+
+       dev = ____alloc_ei_netdev(0);
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       if (unit >= 0)
+               sprintf(dev->name, "eth%d", unit);
+
+       while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK, NUBUS_TYPE_ETHERNET,
+                                      ndev))) {
+               /* Have we seen it already? */
+               if (slots & (1 << ndev->board->slot))
+                       continue;
+               slots |= 1 << ndev->board->slot;
+
+               cardtype = mac8390_ident(ndev);
+               if (cardtype == MAC8390_NONE)
+                       continue;
+
+               if (!mac8390_init(dev, ndev, cardtype))
+                       continue;
+
+               /* Do the nasty 8390 stuff */
+               if (!mac8390_initdev(dev, ndev, cardtype))
+                       break;
+       }
+
+       if (!ndev)
+               goto out;
+       err = register_netdev(dev);
+       if (err)
+               goto out;
+       return dev;
+
+out:
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+
+#ifdef MODULE
+MODULE_AUTHOR("David Huggins-Daines <dhd@debian.org> and others");
+MODULE_DESCRIPTION("Macintosh NS8390-based Nubus Ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* overkill, of course */
+static struct net_device *dev_mac8390[15];
+int init_module(void)
+{
+       int i;
+       for (i = 0; i < 15; i++) {
+               struct net_device *dev = mac8390_probe(-1);
+               if (IS_ERR(dev))
+                       break;
+               dev_mac890[i] = dev;
+       }
+       if (!i) {
+               pr_notice("No useable cards found, driver NOT installed.\n");
+               return -ENODEV;
+       }
+       return 0;
+}
+
+void cleanup_module(void)
+{
+       int i;
+       for (i = 0; i < 15; i++) {
+               struct net_device *dev = dev_mac890[i];
+               if (dev) {
+                       unregister_netdev(dev);
+                       free_netdev(dev);
+               }
+       }
+}
+
+#endif /* MODULE */
+
+static const struct net_device_ops mac8390_netdev_ops = {
+       .ndo_open               = mac8390_open,
+       .ndo_stop               = mac8390_close,
+       .ndo_start_xmit         = __ei_start_xmit,
+       .ndo_tx_timeout         = __ei_tx_timeout,
+       .ndo_get_stats          = __ei_get_stats,
+       .ndo_set_multicast_list = __ei_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = __ei_poll,
+#endif
+};
+
+static int __init mac8390_initdev(struct net_device *dev,
+                                 struct nubus_dev *ndev,
+                                 enum mac8390_type type)
+{
+       static u32 fwrd4_offsets[16] = {
+               0,      4,      8,      12,
+               16,     20,     24,     28,
+               32,     36,     40,     44,
+               48,     52,     56,     60
+       };
+       static u32 back4_offsets[16] = {
+               60,     56,     52,     48,
+               44,     40,     36,     32,
+               28,     24,     20,     16,
+               12,     8,      4,      0
+       };
+       static u32 fwrd2_offsets[16] = {
+               0,      2,      4,      6,
+               8,     10,     12,     14,
+               16,    18,     20,     22,
+               24,    26,     28,     30
+       };
+
+       int access_bitmode = 0;
+
+       /* Now fill in our stuff */
+       dev->netdev_ops = &mac8390_netdev_ops;
+
+       /* GAR, ei_status is actually a macro even though it looks global */
+       ei_status.name = cardname[type];
+       ei_status.word16 = word16[type];
+
+       /* Cabletron's TX/RX buffers are backwards */
+       if (type == MAC8390_CABLETRON) {
+               ei_status.tx_start_page = CABLETRON_TX_START_PG;
+               ei_status.rx_start_page = CABLETRON_RX_START_PG;
+               ei_status.stop_page = CABLETRON_RX_STOP_PG;
+               ei_status.rmem_start = dev->mem_start;
+               ei_status.rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256;
+       } else {
+               ei_status.tx_start_page = WD_START_PG;
+               ei_status.rx_start_page = WD_START_PG + TX_PAGES;
+               ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
+               ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
+               ei_status.rmem_end = dev->mem_end;
+       }
+
+       /* Fill in model-specific information and functions */
+       switch (type) {
+       case MAC8390_FARALLON:
+       case MAC8390_APPLE:
+               switch (mac8390_testio(dev->mem_start)) {
+               case ACCESS_UNKNOWN:
+                       pr_err("Don't know how to access card memory!\n");
+                       return -ENODEV;
+                       break;
+
+               case ACCESS_16:
+                       /* 16 bit card, register map is reversed */
+                       ei_status.reset_8390 = mac8390_no_reset;
+                       ei_status.block_input = slow_sane_block_input;
+                       ei_status.block_output = slow_sane_block_output;
+                       ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
+                       ei_status.reg_offset = back4_offsets;
+                       break;
+
+               case ACCESS_32:
+                       /* 32 bit card, register map is reversed */
+                       ei_status.reset_8390 = mac8390_no_reset;
+                       ei_status.block_input = sane_block_input;
+                       ei_status.block_output = sane_block_output;
+                       ei_status.get_8390_hdr = sane_get_8390_hdr;
+                       ei_status.reg_offset = back4_offsets;
+                       access_bitmode = 1;
+                       break;
+               }
+               break;
+
+       case MAC8390_ASANTE:
+               /* Some Asante cards pass the 32 bit test
+                * but overwrite system memory when run at 32 bit.
+                * so we run them all at 16 bit.
+                */
+               ei_status.reset_8390 = mac8390_no_reset;
+               ei_status.block_input = slow_sane_block_input;
+               ei_status.block_output = slow_sane_block_output;
+               ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
+               ei_status.reg_offset = back4_offsets;
+               break;
+
+       case MAC8390_CABLETRON:
+               /* 16 bit card, register map is short forward */
+               ei_status.reset_8390 = mac8390_no_reset;
+               ei_status.block_input = slow_sane_block_input;
+               ei_status.block_output = slow_sane_block_output;
+               ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
+               ei_status.reg_offset = fwrd2_offsets;
+               break;
+
+       case MAC8390_DAYNA:
+       case MAC8390_KINETICS:
+               /* 16 bit memory, register map is forward */
+               /* dayna and similar */
+               ei_status.reset_8390 = mac8390_no_reset;
+               ei_status.block_input = dayna_block_input;
+               ei_status.block_output = dayna_block_output;
+               ei_status.get_8390_hdr = dayna_get_8390_hdr;
+               ei_status.reg_offset = fwrd4_offsets;
+               break;
+
+       case MAC8390_INTERLAN:
+               /* 16 bit memory, register map is forward */
+               ei_status.reset_8390 = interlan_reset;
+               ei_status.block_input = slow_sane_block_input;
+               ei_status.block_output = slow_sane_block_output;
+               ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
+               ei_status.reg_offset = fwrd4_offsets;
+               break;
+
+       default:
+               pr_err("Card type %s is unsupported, sorry\n",
+                      ndev->board->name);
+               return -ENODEV;
+       }
+
+       __NS8390_init(dev, 0);
+
+       /* Good, done, now spit out some messages */
+       pr_info("%s: %s in slot %X (type %s)\n",
+               dev->name, ndev->board->name, ndev->board->slot,
+               cardname[type]);
+       pr_info("MAC %pM IRQ %d, %d KB shared memory at %#lx, %d-bit access.\n",
+               dev->dev_addr, dev->irq,
+               (unsigned int)(dev->mem_end - dev->mem_start) >> 10,
+               dev->mem_start, access_bitmode ? 32 : 16);
+       return 0;
+}
+
+static int mac8390_open(struct net_device *dev)
+{
+       int err;
+
+       __ei_open(dev);
+       err = request_irq(dev->irq, __ei_interrupt, 0, "8390 Ethernet", dev);
+       if (err)
+               pr_err("%s: unable to get IRQ %d\n", dev->name, dev->irq);
+       return err;
+}
+
+static int mac8390_close(struct net_device *dev)
+{
+       free_irq(dev->irq, dev);
+       __ei_close(dev);
+       return 0;
+}
+
+static void mac8390_no_reset(struct net_device *dev)
+{
+       ei_status.txing = 0;
+       if (ei_debug > 1)
+               pr_info("reset not supported\n");
+}
+
+static void interlan_reset(struct net_device *dev)
+{
+       unsigned char *target = nubus_slot_addr(IRQ2SLOT(dev->irq));
+       if (ei_debug > 1)
+               pr_info("Need to reset the NS8390 t=%lu...", jiffies);
+       ei_status.txing = 0;
+       target[0xC0000] = 0;
+       if (ei_debug > 1)
+               pr_cont("reset complete\n");
+}
+
+/* dayna_memcpy_fromio/dayna_memcpy_toio */
+/* directly from daynaport.c by Alan Cox */
+static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from,
+                                 int count)
+{
+       volatile unsigned char *ptr;
+       unsigned char *target = to;
+       from <<= 1;     /* word, skip overhead */
+       ptr = (unsigned char *)(dev->mem_start+from);
+       /* Leading byte? */
+       if (from & 2) {
+               *target++ = ptr[-1];
+               ptr += 2;
+               count--;
+       }
+       while (count >= 2) {
+               *(unsigned short *)target = *(unsigned short volatile *)ptr;
+               ptr += 4;                       /* skip cruft */
+               target += 2;
+               count -= 2;
+       }
+       /* Trailing byte? */
+       if (count)
+               *target = *ptr;
+}
+
+static void dayna_memcpy_tocard(struct net_device *dev, int to,
+                               const void *from, int count)
+{
+       volatile unsigned short *ptr;
+       const unsigned char *src = from;
+       to <<= 1;       /* word, skip overhead */
+       ptr = (unsigned short *)(dev->mem_start+to);
+       /* Leading byte? */
+       if (to & 2) {           /* avoid a byte write (stomps on other data) */
+               ptr[-1] = (ptr[-1]&0xFF00)|*src++;
+               ptr++;
+               count--;
+       }
+       while (count >= 2) {
+               *ptr++ = *(unsigned short *)src;        /* Copy and */
+               ptr++;                  /* skip cruft */
+               src += 2;
+               count -= 2;
+       }
+       /* Trailing byte? */
+       if (count) {
+               /* card doesn't like byte writes */
+               *ptr = (*ptr & 0x00FF) | (*src << 8);
+       }
+}
+
+/* sane block input/output */
+static void sane_get_8390_hdr(struct net_device *dev,
+                             struct e8390_pkt_hdr *hdr, int ring_page)
+{
+       unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
+       memcpy_fromio(hdr, dev->mem_start + hdr_start, 4);
+       /* Fix endianness */
+       hdr->count = swab16(hdr->count);
+}
+
+static void sane_block_input(struct net_device *dev, int count,
+                            struct sk_buff *skb, int ring_offset)
+{
+       unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
+       unsigned long xfer_start = xfer_base + dev->mem_start;
+
+       if (xfer_start + count > ei_status.rmem_end) {
+               /* We must wrap the input move. */
+               int semi_count = ei_status.rmem_end - xfer_start;
+               memcpy_fromio(skb->data, dev->mem_start + xfer_base,
+                             semi_count);
+               count -= semi_count;
+               memcpy_fromio(skb->data + semi_count, ei_status.rmem_start,
+                             count);
+       } else {
+               memcpy_fromio(skb->data, dev->mem_start + xfer_base, count);
+       }
+}
+
+static void sane_block_output(struct net_device *dev, int count,
+                             const unsigned char *buf, int start_page)
+{
+       long shmem = (start_page - WD_START_PG)<<8;
+
+       memcpy_toio(dev->mem_start + shmem, buf, count);
+}
+
+/* dayna block input/output */
+static void dayna_get_8390_hdr(struct net_device *dev,
+                              struct e8390_pkt_hdr *hdr, int ring_page)
+{
+       unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
+
+       dayna_memcpy_fromcard(dev, hdr, hdr_start, 4);
+       /* Fix endianness */
+       hdr->count = (hdr->count & 0xFF) << 8 | (hdr->count >> 8);
+}
+
+static void dayna_block_input(struct net_device *dev, int count,
+                             struct sk_buff *skb, int ring_offset)
+{
+       unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
+       unsigned long xfer_start = xfer_base+dev->mem_start;
+
+       /* Note the offset math is done in card memory space which is word
+          per long onto our space. */
+
+       if (xfer_start + count > ei_status.rmem_end) {
+               /* We must wrap the input move. */
+               int semi_count = ei_status.rmem_end - xfer_start;
+               dayna_memcpy_fromcard(dev, skb->data, xfer_base, semi_count);
+               count -= semi_count;
+               dayna_memcpy_fromcard(dev, skb->data + semi_count,
+                                     ei_status.rmem_start - dev->mem_start,
+                                     count);
+       } else {
+               dayna_memcpy_fromcard(dev, skb->data, xfer_base, count);
+       }
+}
+
+static void dayna_block_output(struct net_device *dev, int count,
+                              const unsigned char *buf,
+                              int start_page)
+{
+       long shmem = (start_page - WD_START_PG)<<8;
+
+       dayna_memcpy_tocard(dev, shmem, buf, count);
+}
+
+/* Cabletron block I/O */
+static void slow_sane_get_8390_hdr(struct net_device *dev,
+                                  struct e8390_pkt_hdr *hdr,
+                                  int ring_page)
+{
+       unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
+       word_memcpy_fromcard(hdr, dev->mem_start + hdr_start, 4);
+       /* Register endianism - fix here rather than 8390.c */
+       hdr->count = (hdr->count&0xFF)<<8|(hdr->count>>8);
+}
+
+static void slow_sane_block_input(struct net_device *dev, int count,
+                                 struct sk_buff *skb, int ring_offset)
+{
+       unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
+       unsigned long xfer_start = xfer_base+dev->mem_start;
+
+       if (xfer_start + count > ei_status.rmem_end) {
+               /* We must wrap the input move. */
+               int semi_count = ei_status.rmem_end - xfer_start;
+               word_memcpy_fromcard(skb->data, dev->mem_start + xfer_base,
+                                    semi_count);
+               count -= semi_count;
+               word_memcpy_fromcard(skb->data + semi_count,
+                                    ei_status.rmem_start, count);
+       } else {
+               word_memcpy_fromcard(skb->data, dev->mem_start + xfer_base,
+                                    count);
+       }
+}
+
+static void slow_sane_block_output(struct net_device *dev, int count,
+                                  const unsigned char *buf, int start_page)
+{
+       long shmem = (start_page - WD_START_PG)<<8;
+
+       word_memcpy_tocard(dev->mem_start + shmem, buf, count);
+}
+
+static void word_memcpy_tocard(unsigned long tp, const void *fp, int count)
+{
+       volatile unsigned short *to = (void *)tp;
+       const unsigned short *from = fp;
+
+       count++;
+       count /= 2;
+
+       while (count--)
+               *to++ = *from++;
+}
+
+static void word_memcpy_fromcard(void *tp, unsigned long fp, int count)
+{
+       unsigned short *to = tp;
+       const volatile unsigned short *from = (const void *)fp;
+
+       count++;
+       count /= 2;
+
+       while (count--)
+               *to++ = *from++;
+}
+
+
diff --git a/drivers/net/ethernet/8390/ne-h8300.c b/drivers/net/ethernet/8390/ne-h8300.c
new file mode 100644 (file)
index 0000000..7298a34
--- /dev/null
@@ -0,0 +1,685 @@
+/* ne-h8300.c: A NE2000 clone on H8/300 driver for linux. */
+/*
+    original ne.c
+    Written 1992-94 by Donald Becker.
+
+    Copyright 1993 United States Government as represented by the
+    Director, National Security Agency.
+
+    This software may be used and distributed according to the terms
+    of the GNU General Public License, incorporated herein by reference.
+
+    The author may be reached as becker@scyld.com, or C/O
+    Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
+
+    H8/300 modified
+    Yoshinori Sato <ysato@users.sourceforge.jp>
+*/
+
+static const char version1[] =
+"ne-h8300.c:v1.00 2004/04/11 ysato\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/jiffies.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#define EI_SHIFT(x)    (ei_local->reg_offset[x])
+
+#include "8390.h"
+
+#define DRV_NAME "ne-h8300"
+
+/* Some defines that people can play with if so inclined. */
+
+/* Do we perform extra sanity checks on stuff ? */
+/* #define NE_SANITY_CHECK */
+
+/* Do we implement the read before write bugfix ? */
+/* #define NE_RW_BUGFIX */
+
+/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
+/* #define PACKETBUF_MEMSIZE   0x40 */
+
+/* A zero-terminated list of I/O addresses to be probed at boot. */
+
+/* ---- No user-serviceable parts below ---- */
+
+static const char version[] =
+    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include "lib8390.c"
+
+#define NE_BASE         (dev->base_addr)
+#define NE_CMD         0x00
+#define NE_DATAPORT    (ei_status.word16?0x20:0x10)    /* NatSemi-defined port window offset. */
+#define NE_RESET       (ei_status.word16?0x3f:0x1f)    /* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT   (ei_status.word16?0x40:0x20)
+
+#define NESM_START_PG  0x40    /* First page of TX buffer */
+#define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
+
+static int ne_probe1(struct net_device *dev, int ioaddr);
+
+static int ne_open(struct net_device *dev);
+static int ne_close(struct net_device *dev);
+
+static void ne_reset_8390(struct net_device *dev);
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                         int ring_page);
+static void ne_block_input(struct net_device *dev, int count,
+                         struct sk_buff *skb, int ring_offset);
+static void ne_block_output(struct net_device *dev, const int count,
+               const unsigned char *buf, const int start_page);
+
+
+static u32 reg_offset[16];
+
+static int __init init_reg_offset(struct net_device *dev,unsigned long base_addr)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       int i;
+       unsigned char bus_width;
+
+       bus_width = *(volatile unsigned char *)ABWCR;
+       bus_width &= 1 << ((base_addr >> 21) & 7);
+
+       for (i = 0; i < ARRAY_SIZE(reg_offset); i++)
+               if (bus_width == 0)
+                       reg_offset[i] = i * 2 + 1;
+               else
+                       reg_offset[i] = i;
+
+       ei_local->reg_offset = reg_offset;
+       return 0;
+}
+
+static int __initdata h8300_ne_count = 0;
+#ifdef CONFIG_H8300H_H8MAX
+static unsigned long __initdata h8300_ne_base[] = { 0x800600 };
+static int h8300_ne_irq[] = {EXT_IRQ4};
+#endif
+#ifdef CONFIG_H8300H_AKI3068NET
+static unsigned long __initdata h8300_ne_base[] = { 0x200000 };
+static int h8300_ne_irq[] = {EXT_IRQ5};
+#endif
+
+static inline int init_dev(struct net_device *dev)
+{
+       if (h8300_ne_count < ARRAY_SIZE(h8300_ne_base)) {
+               dev->base_addr = h8300_ne_base[h8300_ne_count];
+               dev->irq       = h8300_ne_irq[h8300_ne_count];
+               h8300_ne_count++;
+               return 0;
+       } else
+               return -ENODEV;
+}
+
+/*  Probe for various non-shared-memory ethercards.
+
+   NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
+   buffer memory space.  NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
+   the SAPROM, while other supposed NE2000 clones must be detected by their
+   SA prefix.
+
+   Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
+   mode results in doubled values, which can be detected and compensated for.
+
+   The probe is also responsible for initializing the card and filling
+   in the 'dev' and 'ei_status' structures.
+
+   We use the minimum memory size for some ethercard product lines, iff we can't
+   distinguish models.  You can increase the packet buffer size by setting
+   PACKETBUF_MEMSIZE.  Reported Cabletron packet buffer locations are:
+       E1010   starts at 0x100 and ends at 0x2000.
+       E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
+       E2010    starts at 0x100 and ends at 0x4000.
+       E2010-x starts at 0x100 and ends at 0xffff.  */
+
+static int __init do_ne_probe(struct net_device *dev)
+{
+       unsigned int base_addr = dev->base_addr;
+
+       /* First check any supplied i/o locations. User knows best. <cough> */
+       if (base_addr > 0x1ff)  /* Check a single specified location. */
+               return ne_probe1(dev, base_addr);
+       else if (base_addr != 0)        /* Don't probe at all. */
+               return -ENXIO;
+
+       return -ENODEV;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+       free_irq(dev->irq, dev);
+       release_region(dev->base_addr, NE_IO_EXTENT);
+}
+
+#ifndef MODULE
+struct net_device * __init ne_probe(int unit)
+{
+       struct net_device *dev = ____alloc_ei_netdev(0);
+       int err;
+
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       if (init_dev(dev))
+               return ERR_PTR(-ENODEV);
+
+       sprintf(dev->name, "eth%d", unit);
+       netdev_boot_setup_check(dev);
+
+       err = init_reg_offset(dev, dev->base_addr);
+       if (err)
+               goto out;
+
+       err = do_ne_probe(dev);
+       if (err)
+               goto out;
+       return dev;
+out:
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops ne_netdev_ops = {
+       .ndo_open               = ne_open,
+       .ndo_stop               = ne_close,
+
+       .ndo_start_xmit         = __ei_start_xmit,
+       .ndo_tx_timeout         = __ei_tx_timeout,
+       .ndo_get_stats          = __ei_get_stats,
+       .ndo_set_multicast_list = __ei_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = __ei_poll,
+#endif
+};
+
+static int __init ne_probe1(struct net_device *dev, int ioaddr)
+{
+       int i;
+       unsigned char SA_prom[16];
+       int wordlength = 2;
+       const char *name = NULL;
+       int start_page, stop_page;
+       int reg0, ret;
+       static unsigned version_printed;
+       struct ei_device *ei_local = netdev_priv(dev);
+       unsigned char bus_width;
+
+       if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
+               return -EBUSY;
+
+       reg0 = inb_p(ioaddr);
+       if (reg0 == 0xFF) {
+               ret = -ENODEV;
+               goto err_out;
+       }
+
+       /* Do a preliminary verification that we have a 8390. */
+       {
+               int regd;
+               outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
+               regd = inb_p(ioaddr + EI_SHIFT(0x0d));
+               outb_p(0xff, ioaddr + EI_SHIFT(0x0d));
+               outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
+               inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
+               if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
+                       outb_p(reg0, ioaddr + EI_SHIFT(0));
+                       outb_p(regd, ioaddr + EI_SHIFT(0x0d));  /* Restore the old values. */
+                       ret = -ENODEV;
+                       goto err_out;
+               }
+       }
+
+       if (ei_debug  &&  version_printed++ == 0)
+               printk(KERN_INFO "%s", version1);
+
+       printk(KERN_INFO "NE*000 ethercard probe at %08x:", ioaddr);
+
+       /* Read the 16 bytes of station address PROM.
+          We must first initialize registers, similar to NS8390_init(eifdev, 0).
+          We can't reliably read the SAPROM address without this.
+          (I learned the hard way!). */
+       {
+               struct {unsigned char value, offset; } program_seq[] =
+               {
+                       {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+                       {0x48,  EN0_DCFG},      /* Set byte-wide (0x48) access. */
+                       {0x00,  EN0_RCNTLO},    /* Clear the count regs. */
+                       {0x00,  EN0_RCNTHI},
+                       {0x00,  EN0_IMR},       /* Mask completion irq. */
+                       {0xFF,  EN0_ISR},
+                       {E8390_RXOFF, EN0_RXCR},        /* 0x20  Set to monitor */
+                       {E8390_TXOFF, EN0_TXCR},        /* 0x02  and loopback mode. */
+                       {32,    EN0_RCNTLO},
+                       {0x00,  EN0_RCNTHI},
+                       {0x00,  EN0_RSARLO},    /* DMA starting at 0x0000. */
+                       {0x00,  EN0_RSARHI},
+                       {E8390_RREAD+E8390_START, E8390_CMD},
+               };
+
+               for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+                       outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
+
+       }
+       bus_width = *(volatile unsigned char *)ABWCR;
+       bus_width &= 1 << ((ioaddr >> 21) & 7);
+       ei_status.word16 = (bus_width == 0); /* temporary setting */
+       for(i = 0; i < 16 /*sizeof(SA_prom)*/; i++) {
+               SA_prom[i] = inb_p(ioaddr + NE_DATAPORT);
+               inb_p(ioaddr + NE_DATAPORT); /* dummy read */
+       }
+
+       start_page = NESM_START_PG;
+       stop_page = NESM_STOP_PG;
+
+       if (bus_width)
+               wordlength = 1;
+       else
+               outb_p(0x49, ioaddr + EN0_DCFG);
+
+       /* Set up the rest of the parameters. */
+       name = (wordlength == 2) ? "NE2000" : "NE1000";
+
+       if (! dev->irq) {
+               printk(" failed to detect IRQ line.\n");
+               ret = -EAGAIN;
+               goto err_out;
+       }
+
+       /* Snarf the interrupt now.  There's no point in waiting since we cannot
+          share and the board will usually be enabled. */
+       ret = request_irq(dev->irq, __ei_interrupt, 0, name, dev);
+       if (ret) {
+               printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
+               goto err_out;
+       }
+
+       dev->base_addr = ioaddr;
+
+       for(i = 0; i < ETHER_ADDR_LEN; i++)
+               dev->dev_addr[i] = SA_prom[i];
+       printk(" %pM\n", dev->dev_addr);
+
+       printk("%s: %s found at %#x, using IRQ %d.\n",
+               dev->name, name, ioaddr, dev->irq);
+
+       ei_status.name = name;
+       ei_status.tx_start_page = start_page;
+       ei_status.stop_page = stop_page;
+       ei_status.word16 = (wordlength == 2);
+
+       ei_status.rx_start_page = start_page + TX_PAGES;
+#ifdef PACKETBUF_MEMSIZE
+        /* Allow the packet buffer size to be overridden by know-it-alls. */
+       ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
+#endif
+
+       ei_status.reset_8390 = &ne_reset_8390;
+       ei_status.block_input = &ne_block_input;
+       ei_status.block_output = &ne_block_output;
+       ei_status.get_8390_hdr = &ne_get_8390_hdr;
+       ei_status.priv = 0;
+
+       dev->netdev_ops = &ne_netdev_ops;
+
+       __NS8390_init(dev, 0);
+
+       ret = register_netdev(dev);
+       if (ret)
+               goto out_irq;
+       return 0;
+out_irq:
+       free_irq(dev->irq, dev);
+err_out:
+       release_region(ioaddr, NE_IO_EXTENT);
+       return ret;
+}
+
+static int ne_open(struct net_device *dev)
+{
+       __ei_open(dev);
+       return 0;
+}
+
+static int ne_close(struct net_device *dev)
+{
+       if (ei_debug > 1)
+               printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
+       __ei_close(dev);
+       return 0;
+}
+
+/* Hard reset the card.  This used to pause for the same period that a
+   8390 reset command required, but that shouldn't be necessary. */
+
+static void ne_reset_8390(struct net_device *dev)
+{
+       unsigned long reset_start_time = jiffies;
+       struct ei_device *ei_local = netdev_priv(dev);
+
+       if (ei_debug > 1)
+               printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
+
+       /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
+       outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+       ei_status.txing = 0;
+       ei_status.dmaing = 0;
+
+       /* This check _should_not_ be necessary, omit eventually. */
+       while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
+               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
+                       printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
+                       break;
+               }
+       outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+
+       if (ei_status.dmaing)
+       {
+               printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
+                       "[DMAstat:%d][irqlock:%d].\n",
+                       dev->name, ei_status.dmaing, ei_status.irqlock);
+               return;
+       }
+
+       ei_status.dmaing |= 0x01;
+       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, NE_BASE + NE_CMD);
+       outb_p(sizeof(struct e8390_pkt_hdr), NE_BASE + EN0_RCNTLO);
+       outb_p(0, NE_BASE + EN0_RCNTHI);
+       outb_p(0, NE_BASE + EN0_RSARLO);                /* On page boundary */
+       outb_p(ring_page, NE_BASE + EN0_RSARHI);
+       outb_p(E8390_RREAD+E8390_START, NE_BASE + NE_CMD);
+
+       if (ei_status.word16) {
+               int len;
+               unsigned short *p = (unsigned short *)hdr;
+               for (len = sizeof(struct e8390_pkt_hdr)>>1; len > 0; len--)
+                       *p++ = inw(NE_BASE + NE_DATAPORT);
+       } else
+               insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+
+       outb_p(ENISR_RDC, NE_BASE + EN0_ISR);   /* Ack intr. */
+       ei_status.dmaing &= ~0x01;
+
+       le16_to_cpus(&hdr->count);
+}
+
+/* Block input and output, similar to the Crynwr packet driver.  If you
+   are porting to a new ethercard, look at the packet driver source for hints.
+   The NEx000 doesn't share the on-board packet memory -- you have to put
+   the packet out through the "remote DMA" dataport using outb. */
+
+static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+#ifdef NE_SANITY_CHECK
+       int xfer_count = count;
+#endif
+       char *buf = skb->data;
+
+       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+       if (ei_status.dmaing)
+       {
+               printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
+                       "[DMAstat:%d][irqlock:%d].\n",
+                       dev->name, ei_status.dmaing, ei_status.irqlock);
+               return;
+       }
+       ei_status.dmaing |= 0x01;
+       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, NE_BASE + NE_CMD);
+       outb_p(count & 0xff, NE_BASE + EN0_RCNTLO);
+       outb_p(count >> 8, NE_BASE + EN0_RCNTHI);
+       outb_p(ring_offset & 0xff, NE_BASE + EN0_RSARLO);
+       outb_p(ring_offset >> 8, NE_BASE + EN0_RSARHI);
+       outb_p(E8390_RREAD+E8390_START, NE_BASE + NE_CMD);
+       if (ei_status.word16)
+       {
+               int len;
+               unsigned short *p = (unsigned short *)buf;
+               for (len = count>>1; len > 0; len--)
+                       *p++ = inw(NE_BASE + NE_DATAPORT);
+               if (count & 0x01)
+               {
+                       buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+#ifdef NE_SANITY_CHECK
+                       xfer_count++;
+#endif
+               }
+       } else {
+               insb(NE_BASE + NE_DATAPORT, buf, count);
+       }
+
+#ifdef NE_SANITY_CHECK
+       /* This was for the ALPHA version only, but enough people have
+          been encountering problems so it is still here.  If you see
+          this message you either 1) have a slightly incompatible clone
+          or 2) have noise/speed problems with your bus. */
+
+       if (ei_debug > 1)
+       {
+               /* DMA termination address check... */
+               int addr, tries = 20;
+               do {
+                       /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
+                          -- it's broken for Rx on some cards! */
+                       int high = inb_p(NE_BASE + EN0_RSARHI);
+                       int low = inb_p(NE_BASE + EN0_RSARLO);
+                       addr = (high << 8) + low;
+                       if (((ring_offset + xfer_count) & 0xff) == low)
+                               break;
+               } while (--tries > 0);
+               if (tries <= 0)
+                       printk(KERN_WARNING "%s: RX transfer address mismatch,"
+                               "%#4.4x (expected) vs. %#4.4x (actual).\n",
+                               dev->name, ring_offset + xfer_count, addr);
+       }
+#endif
+       outb_p(ENISR_RDC, NE_BASE + EN0_ISR);   /* Ack intr. */
+       ei_status.dmaing &= ~0x01;
+}
+
+static void ne_block_output(struct net_device *dev, int count,
+               const unsigned char *buf, const int start_page)
+{
+       struct ei_device *ei_local = netdev_priv(dev);
+       unsigned long dma_start;
+#ifdef NE_SANITY_CHECK
+       int retries = 0;
+#endif
+
+       /* Round the count up for word writes.  Do we need to do this?
+          What effect will an odd byte count have on the 8390?
+          I should check someday. */
+
+       if (ei_status.word16 && (count & 0x01))
+               count++;
+
+       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+       if (ei_status.dmaing)
+       {
+               printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
+                       "[DMAstat:%d][irqlock:%d]\n",
+                       dev->name, ei_status.dmaing, ei_status.irqlock);
+               return;
+       }
+       ei_status.dmaing |= 0x01;
+       /* We should already be in page 0, but to be safe... */
+       outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, NE_BASE + NE_CMD);
+
+#ifdef NE_SANITY_CHECK
+retry:
+#endif
+
+#ifdef NE8390_RW_BUGFIX
+       /* Handle the read-before-write bug the same way as the
+          Crynwr packet driver -- the NatSemi method doesn't work.
+          Actually this doesn't always work either, but if you have
+          problems with your NEx000 this is better than nothing! */
+
+       outb_p(0x42, NE_BASE + EN0_RCNTLO);
+       outb_p(0x00, NE_BASE + EN0_RCNTHI);
+       outb_p(0x42, NE_BASE + EN0_RSARLO);
+       outb_p(0x00, NE_BASE + EN0_RSARHI);
+       outb_p(E8390_RREAD+E8390_START, NE_BASE + NE_CMD);
+       /* Make certain that the dummy read has occurred. */
+       udelay(6);
+#endif
+
+       outb_p(ENISR_RDC, NE_BASE + EN0_ISR);
+
+       /* Now the normal output. */
+       outb_p(count & 0xff, NE_BASE + EN0_RCNTLO);
+       outb_p(count >> 8,   NE_BASE + EN0_RCNTHI);
+       outb_p(0x00, NE_BASE + EN0_RSARLO);
+       outb_p(start_page, NE_BASE + EN0_RSARHI);
+
+       outb_p(E8390_RWRITE+E8390_START, NE_BASE + NE_CMD);
+       if (ei_status.word16) {
+               int len;
+               unsigned short *p = (unsigned short *)buf;
+               for (len = count>>1; len > 0; len--)
+                       outw(*p++, NE_BASE + NE_DATAPORT);
+       } else {
+               outsb(NE_BASE + NE_DATAPORT, buf, count);
+       }
+
+       dma_start = jiffies;
+
+#ifdef NE_SANITY_CHECK
+       /* This was for the ALPHA version only, but enough people have
+          been encountering problems so it is still here. */
+
+       if (ei_debug > 1)
+       {
+               /* DMA termination address check... */
+               int addr, tries = 20;
+               do {
+                       int high = inb_p(NE_BASE + EN0_RSARHI);
+                       int low = inb_p(NE_BASE + EN0_RSARLO);
+                       addr = (high << 8) + low;
+                       if ((start_page << 8) + count == addr)
+                               break;
+               } while (--tries > 0);
+
+               if (tries <= 0)
+               {
+                       printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
+                               "%#4.4x (expected) vs. %#4.4x (actual).\n",
+                               dev->name, (start_page << 8) + count, addr);
+                       if (retries++ == 0)
+                               goto retry;
+               }
+       }
+#endif
+
+       while ((inb_p(NE_BASE + EN0_ISR) & ENISR_RDC) == 0)
+               if (time_after(jiffies, dma_start + 2*HZ/100)) {                /* 20ms */
+                       printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+                       ne_reset_8390(dev);
+                       __NS8390_init(dev,1);
+                       break;
+               }
+
+       outb_p(ENISR_RDC, NE_BASE + EN0_ISR);   /* Ack intr. */
+       ei_status.dmaing &= ~0x01;
+}
+
+
+#ifdef MODULE
+#define MAX_NE_CARDS   1       /* Max number of NE cards per module */
+static struct net_device *dev_ne[MAX_NE_CARDS];
+static int io[MAX_NE_CARDS];
+static int irq[MAX_NE_CARDS];
+static int bad[MAX_NE_CARDS];  /* 0xbad = bad sig or no reset ack */
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(bad, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_DESCRIPTION("H8/300 NE2000 Ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that no ISA autoprobe takes place. We can't guarantee
+that the ne2k probe is the last 8390 based probe to take place (as it
+is at boot) and so the probe will get confused by any other 8390 cards.
+ISA device autoprobes on a running machine are not recommended anyway. */
+
+int init_module(void)
+{
+       int this_dev, found = 0;
+       int err;
+
+       for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+               struct net_device *dev = ____alloc_ei_netdev(0);
+               if (!dev)
+                       break;
+               if (io[this_dev]) {
+                       dev->irq = irq[this_dev];
+                       dev->mem_end = bad[this_dev];
+                       dev->base_addr = io[this_dev];
+               } else {
+                       dev->base_addr = h8300_ne_base[this_dev];
+                       dev->irq = h8300_ne_irq[this_dev];
+               }
+               err = init_reg_offset(dev, dev->base_addr);
+               if (!err) {
+                       if (do_ne_probe(dev) == 0) {
+                               dev_ne[found++] = dev;
+                               continue;
+                       }
+               }
+               free_netdev(dev);
+               if (found)
+                       break;
+               if (io[this_dev] != 0)
+                       printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", dev->base_addr);
+               else
+                       printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
+               return -ENXIO;
+       }
+       if (found)
+               return 0;
+       return -ENODEV;
+}
+
+void cleanup_module(void)
+{
+       int this_dev;
+
+       for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+               struct net_device *dev = dev_ne[this_dev];
+               if (dev) {
+                       unregister_netdev(dev);
+                       cleanup_card(dev);
+                       free_netdev(dev);
+               }
+       }
+}
+#endif /* MODULE */
diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c
new file mode 100644 (file)
index 0000000..1063093
--- /dev/null
@@ -0,0 +1,1008 @@
+/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
+/*
+    Written 1992-94 by Donald Becker.
+
+    Copyright 1993 United States Government as represented by the
+    Director, National Security Agency.
+
+    This software may be used and distributed according to the terms
+    of the GNU General Public License, incorporated herein by reference.
+
+    The author may be reached as becker@scyld.com, or C/O
+    Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
+
+    This driver should work with many programmed-I/O 8390-based ethernet
+    boards.  Currently it supports the NE1000, NE2000, many clones,
+    and some Cabletron products.
+
+    Changelog:
+
+    Paul Gortmaker     : use ENISR_RDC to monitor Tx PIO uploads, made
+                         sanity checks and bad clone support optional.
+    Paul Gortmaker     : new reset code, reset card after probe at boot.
+    Paul Gortmaker     : multiple card support for module users.
+    Paul Gortmaker     : Support for PCI ne2k clones, similar to lance.c
+    Paul Gortmaker     : Allow users with bad cards to avoid full probe.
+    Paul Gortmaker     : PCI probe changes, more PCI cards supported.
+    rjohnson@analogic.com : Changed init order so an interrupt will only
+    occur after memory is allocated for dev->priv. Deallocated memory
+    last in cleanup_modue()
+    Richard Guenther    : Added support for ISAPnP cards
+    Paul Gortmaker     : Discontinued PCI support - use ne2k-pci.c instead.
+    Hayato Fujiwara    : Add m32r support.
+
+*/
+
+/* Routines for the NatSemi-based designs (NE[12]000). */
+
+static const char version1[] =
+"ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)\n";
+static const char version2[] =
+"Last modified Nov 1, 2000 by Paul Gortmaker\n";
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/isapnp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include "8390.h"
+
+#define DRV_NAME "ne"
+
+/* Some defines that people can play with if so inclined. */
+
+/* Do we support clones that don't adhere to 14,15 of the SAprom ? */
+#define SUPPORT_NE_BAD_CLONES
+/* 0xbad = bad sig or no reset ack */
+#define BAD 0xbad
+
+#define MAX_NE_CARDS   4       /* Max number of NE cards per module */
+static struct platform_device *pdev_ne[MAX_NE_CARDS];
+static int io[MAX_NE_CARDS];
+static int irq[MAX_NE_CARDS];
+static int bad[MAX_NE_CARDS];
+
+#ifdef MODULE
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(bad, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es),required");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
+MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver");
+MODULE_LICENSE("GPL");
+#endif /* MODULE */
+
+/* Do we perform extra sanity checks on stuff ? */
+/* #define NE_SANITY_CHECK */
+
+/* Do we implement the read before write bugfix ? */
+/* #define NE_RW_BUGFIX */
+
+/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
+/* #define PACKETBUF_MEMSIZE   0x40 */
+
+/* This is set up so that no ISA autoprobe takes place. We can't guarantee
+that the ne2k probe is the last 8390 based probe to take place (as it
+is at boot) and so the probe will get confused by any other 8390 cards.
+ISA device autoprobes on a running machine are not recommended anyway. */
+#if !defined(MODULE) && (defined(CONFIG_ISA) || defined(CONFIG_M32R))
+/* Do we need a portlist for the ISA auto-probe ? */
+#define NEEDS_PORTLIST
+#endif
+
+/* A zero-terminated list of I/O addresses to be probed at boot. */
+#ifdef NEEDS_PORTLIST
+static unsigned int netcard_portlist[] __initdata = {
+       0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0
+};
+#endif
+
+static struct isapnp_device_id isapnp_clone_list[] __initdata = {
+       {       ISAPNP_CARD_ID('A','X','E',0x2011),
+               ISAPNP_VENDOR('A','X','E'), ISAPNP_FUNCTION(0x2011),
+               (long) "NetGear EA201" },
+       {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+               ISAPNP_VENDOR('E','D','I'), ISAPNP_FUNCTION(0x0216),
+               (long) "NN NE2000" },
+       {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+               ISAPNP_VENDOR('P','N','P'), ISAPNP_FUNCTION(0x80d6),
+               (long) "Generic PNP" },
+       { }     /* terminate list */
+};
+
+MODULE_DEVICE_TABLE(isapnp, isapnp_clone_list);
+
+#ifdef SUPPORT_NE_BAD_CLONES
+/* A list of bad clones that we none-the-less recognize. */
+static struct { const char *name8, *name16; unsigned char SAprefix[4];}
+bad_clone_list[] __initdata = {
+    {"DE100", "DE200", {0x00, 0xDE, 0x01,}},
+    {"DE120", "DE220", {0x00, 0x80, 0xc8,}},
+    {"DFI1000", "DFI2000", {'D', 'F', 'I',}}, /* Original, eh?  */
+    {"EtherNext UTP8", "EtherNext UTP16", {0x00, 0x00, 0x79}},
+    {"NE1000","NE2000-invalid", {0x00, 0x00, 0xd8}}, /* Ancient real NE1000. */
+    {"NN1000", "NN2000",  {0x08, 0x03, 0x08}}, /* Outlaw no-name clone. */
+    {"4-DIM8","4-DIM16", {0x00,0x00,0x4d,}},  /* Outlaw 4-Dimension cards. */
+    {"Con-Intl_8", "Con-Intl_16", {0x00, 0x00, 0x24}}, /* Connect Int'nl */
+    {"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */
+    {"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */
+    {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
+    {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
+    {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
+#ifdef CONFIG_MACH_TX49XX
+    {"RBHMA4X00-RTL8019", "RBHMA4X00-RTL8019", {0x00, 0x60, 0x0a}},  /* Toshiba built-in */
+#endif
+    {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
+    {NULL,}
+};
+#endif
+
+/* ---- No user-serviceable parts below ---- */
+
+#define NE_BASE         (dev->base_addr)
+#define NE_CMD         0x00
+#define NE_DATAPORT    0x10    /* NatSemi-defined port window offset. */
+#define NE_RESET       0x1f    /* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT   0x20
+
+#define NE1SM_START_PG 0x20    /* First page of TX buffer */
+#define NE1SM_STOP_PG  0x40    /* Last page +1 of RX ring */
+#define NESM_START_PG  0x40    /* First page of TX buffer */
+#define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
+
+#if defined(CONFIG_PLAT_MAPPI)
+#  define DCR_VAL 0x4b
+#elif defined(CONFIG_PLAT_OAKS32R)  || \
+   defined(CONFIG_MACH_TX49XX)
+#  define DCR_VAL 0x48         /* 8-bit mode */
+#else
+#  define DCR_VAL 0x49
+#endif
+
+static int ne_probe1(struct net_device *dev, unsigned long ioaddr);
+static int ne_probe_isapnp(struct net_device *dev);
+
+static void ne_reset_8390(struct net_device *dev);
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                         int ring_page);
+static void ne_block_input(struct net_device *dev, int count,
+                         struct sk_buff *skb, int ring_offset);
+static void ne_block_output(struct net_device *dev, const int count,
+               const unsigned char *buf, const int start_page);
+
+
+/*  Probe for various non-shared-memory ethercards.
+
+   NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
+   buffer memory space.  NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
+   the SAPROM, while other supposed NE2000 clones must be detected by their
+   SA prefix.
+
+   Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
+   mode results in doubled values, which can be detected and compensated for.
+
+   The probe is also responsible for initializing the card and filling
+   in the 'dev' and 'ei_status' structures.
+
+   We use the minimum memory size for some ethercard product lines, iff we can't
+   distinguish models.  You can increase the packet buffer size by setting
+   PACKETBUF_MEMSIZE.  Reported Cabletron packet buffer locations are:
+       E1010   starts at 0x100 and ends at 0x2000.
+       E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
+       E2010    starts at 0x100 and ends at 0x4000.
+       E2010-x starts at 0x100 and ends at 0xffff.  */
+
+static int __init do_ne_probe(struct net_device *dev)
+{
+       unsigned long base_addr = dev->base_addr;
+#ifdef NEEDS_PORTLIST
+       int orig_irq = dev->irq;
+#endif
+
+       /* First check any supplied i/o locations. User knows best. <cough> */
+       if (base_addr > 0x1ff) {        /* Check a single specified location. */
+               int ret = ne_probe1(dev, base_addr);
+               if (ret)
+                       printk(KERN_WARNING "ne.c: No NE*000 card found at "
+                               "i/o = %#lx\n", base_addr);
+               return ret;
+       }
+       else if (base_addr != 0)        /* Don't probe at all. */
+               return -ENXIO;
+
+       /* Then look for any installed ISAPnP clones */
+       if (isapnp_present() && (ne_probe_isapnp(dev) == 0))
+               return 0;
+
+#ifdef NEEDS_PORTLIST
+       /* Last resort. The semi-risky ISA auto-probe. */
+       for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
+               int ioaddr = netcard_portlist[base_addr];
+               dev->irq = orig_irq;
+               if (ne_probe1(dev, ioaddr) == 0)
+                       return 0;
+       }
+#endif
+
+       return -ENODEV;
+}
+
+static int __init ne_probe_isapnp(struct net_device *dev)
+{
+       int i;
+
+       for (i = 0; isapnp_clone_list[i].vendor != 0; i++) {
+               struct pnp_dev *idev = NULL;
+
+               while ((idev = pnp_find_dev(NULL,
+                                           isapnp_clone_list[i].vendor,
+                                           isapnp_clone_list[i].function,
+                                           idev))) {
+                       /* Avoid already found cards from previous calls */
+                       if (pnp_device_attach(idev) < 0)
+                               continue;
+                       if (pnp_activate_dev(idev) < 0) {
+                               pnp_device_detach(idev);
+                               continue;
+                       }
+                       /* if no io and irq, search for next */
+                       if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) {
+                               pnp_device_detach(idev);
+                               continue;
+                       }
+                       /* found it */
+                       dev->base_addr = pnp_port_start(idev, 0);
+                       dev->irq = pnp_irq(idev, 0);
+                       printk(KERN_INFO "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
+                               (char *) isapnp_clone_list[i].driver_data,
+                               dev->base_addr, dev->irq);
+                       if (ne_probe1(dev, dev->base_addr) != 0) {      /* Shouldn't happen. */
+                               printk(KERN_ERR "ne.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr);
+                               pnp_device_detach(idev);
+                               return -ENXIO;
+                       }
+                       ei_status.priv = (unsigned long)idev;
+                       break;
+               }
+               if (!idev)
+                       continue;
+               return 0;
+       }
+
+       return -ENODEV;
+}
+
+static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
+{
+       int i;
+       unsigned char SA_prom[32];
+       int wordlength = 2;
+       const char *name = NULL;
+       int start_page, stop_page;
+       int neX000, ctron, copam, bad_card;
+       int reg0, ret;
+       static unsigned version_printed;
+
+       if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
+               return -EBUSY;
+
+       reg0 = inb_p(ioaddr);
+       if (reg0 == 0xFF) {
+               ret = -ENODEV;
+               goto err_out;
+       }
+
+       /* Do a preliminary verification that we have a 8390. */
+       {
+               int regd;
+               outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
+               regd = inb_p(ioaddr + 0x0d);
+               outb_p(0xff, ioaddr + 0x0d);
+               outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
+               inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
+               if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
+                       outb_p(reg0, ioaddr);
+                       outb_p(regd, ioaddr + 0x0d);    /* Restore the old values. */
+                       ret = -ENODEV;
+                       goto err_out;
+               }
+       }
+
+       if (ei_debug  &&  version_printed++ == 0)
+               printk(KERN_INFO "%s%s", version1, version2);
+
+       printk(KERN_INFO "NE*000 ethercard probe at %#3lx:", ioaddr);
+
+       /* A user with a poor card that fails to ack the reset, or that
+          does not have a valid 0x57,0x57 signature can still use this
+          without having to recompile. Specifying an i/o address along
+          with an otherwise unused dev->mem_end value of "0xBAD" will
+          cause the driver to skip these parts of the probe. */
+
+       bad_card = ((dev->base_addr != 0) && (dev->mem_end == BAD));
+
+       /* Reset card. Who knows what dain-bramaged state it was left in. */
+
+       {
+               unsigned long reset_start_time = jiffies;
+
+               /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
+               outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+
+               while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
+               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
+                       if (bad_card) {
+                               printk(" (warning: no reset ack)");
+                               break;
+                       } else {
+                               printk(" not found (no reset ack).\n");
+                               ret = -ENODEV;
+                               goto err_out;
+                       }
+               }
+
+               outb_p(0xff, ioaddr + EN0_ISR);         /* Ack all intr. */
+       }
+
+       /* Read the 16 bytes of station address PROM.
+          We must first initialize registers, similar to NS8390p_init(eifdev, 0).
+          We can't reliably read the SAPROM address without this.
+          (I learned the hard way!). */
+       {
+               struct {unsigned char value, offset; } program_seq[] =
+               {
+                       {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+                       {0x48,  EN0_DCFG},      /* Set byte-wide (0x48) access. */
+                       {0x00,  EN0_RCNTLO},    /* Clear the count regs. */
+                       {0x00,  EN0_RCNTHI},
+                       {0x00,  EN0_IMR},       /* Mask completion irq. */
+                       {0xFF,  EN0_ISR},
+                       {E8390_RXOFF, EN0_RXCR},        /* 0x20  Set to monitor */
+                       {E8390_TXOFF, EN0_TXCR},        /* 0x02  and loopback mode. */
+                       {32,    EN0_RCNTLO},
+                       {0x00,  EN0_RCNTHI},
+                       {0x00,  EN0_RSARLO},    /* DMA starting at 0x0000. */
+                       {0x00,  EN0_RSARHI},
+                       {E8390_RREAD+E8390_START, E8390_CMD},
+               };
+
+               for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+                       outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
+
+       }
+       for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
+               SA_prom[i] = inb(ioaddr + NE_DATAPORT);
+               SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
+               if (SA_prom[i] != SA_prom[i+1])
+                       wordlength = 1;
+       }
+
+       if (wordlength == 2)
+       {
+               for (i = 0; i < 16; i++)
+                       SA_prom[i] = SA_prom[i+i];
+               /* We must set the 8390 for word mode. */
+               outb_p(DCR_VAL, ioaddr + EN0_DCFG);
+               start_page = NESM_START_PG;
+
+               /*
+                * Realtek RTL8019AS datasheet says that the PSTOP register
+                * shouldn't exceed 0x60 in 8-bit mode.
+                * This chip can be identified by reading the signature from
+                * the  remote byte count registers (otherwise write-only)...
+                */
+               if ((DCR_VAL & 0x01) == 0 &&            /* 8-bit mode */
+                   inb(ioaddr + EN0_RCNTLO) == 0x50 &&
+                   inb(ioaddr + EN0_RCNTHI) == 0x70)
+                       stop_page = 0x60;
+               else
+                       stop_page = NESM_STOP_PG;
+       } else {
+               start_page = NE1SM_START_PG;
+               stop_page  = NE1SM_STOP_PG;
+       }
+
+#if  defined(CONFIG_PLAT_MAPPI) || defined(CONFIG_PLAT_OAKS32R)
+       neX000 = ((SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57)
+               || (SA_prom[14] == 0x42 && SA_prom[15] == 0x42));
+#else
+       neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
+#endif
+       ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
+       copam =  (SA_prom[14] == 0x49 && SA_prom[15] == 0x00);
+
+       /* Set up the rest of the parameters. */
+       if (neX000 || bad_card || copam) {
+               name = (wordlength == 2) ? "NE2000" : "NE1000";
+       }
+       else if (ctron)
+       {
+               name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
+               start_page = 0x01;
+               stop_page = (wordlength == 2) ? 0x40 : 0x20;
+       }
+       else
+       {
+#ifdef SUPPORT_NE_BAD_CLONES
+               /* Ack!  Well, there might be a *bad* NE*000 clone there.
+                  Check for total bogus addresses. */
+               for (i = 0; bad_clone_list[i].name8; i++)
+               {
+                       if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
+                               SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
+                               SA_prom[2] == bad_clone_list[i].SAprefix[2])
+                       {
+                               if (wordlength == 2)
+                               {
+                                       name = bad_clone_list[i].name16;
+                               } else {
+                                       name = bad_clone_list[i].name8;
+                               }
+                               break;
+                       }
+               }
+               if (bad_clone_list[i].name8 == NULL)
+               {
+                       printk(" not found (invalid signature %2.2x %2.2x).\n",
+                               SA_prom[14], SA_prom[15]);
+                       ret = -ENXIO;
+                       goto err_out;
+               }
+#else
+               printk(" not found.\n");
+               ret = -ENXIO;
+               goto err_out;
+#endif
+       }
+
+       if (dev->irq < 2)
+       {
+               unsigned long cookie = probe_irq_on();
+               outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */
+               outb_p(0x00, ioaddr + EN0_RCNTLO);
+               outb_p(0x00, ioaddr + EN0_RCNTHI);
+               outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
+               mdelay(10);             /* wait 10ms for interrupt to propagate */
+               outb_p(0x00, ioaddr + EN0_IMR);                 /* Mask it again. */
+               dev->irq = probe_irq_off(cookie);
+               if (ei_debug > 2)
+                       printk(" autoirq is %d\n", dev->irq);
+       } else if (dev->irq == 2)
+               /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
+                  or don't know which one to set. */
+               dev->irq = 9;
+
+       if (! dev->irq) {
+               printk(" failed to detect IRQ line.\n");
+               ret = -EAGAIN;
+               goto err_out;
+       }
+
+       /* Snarf the interrupt now.  There's no point in waiting since we cannot
+          share and the board will usually be enabled. */
+       ret = request_irq(dev->irq, eip_interrupt, 0, name, dev);
+       if (ret) {
+               printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
+               goto err_out;
+       }
+
+       dev->base_addr = ioaddr;
+
+#ifdef CONFIG_PLAT_MAPPI
+       outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
+               ioaddr + E8390_CMD); /* 0x61 */
+       for (i = 0 ; i < ETHER_ADDR_LEN ; i++) {
+               dev->dev_addr[i] = SA_prom[i]
+                       = inb_p(ioaddr + EN1_PHYS_SHIFT(i));
+       }
+#else
+       for(i = 0; i < ETHER_ADDR_LEN; i++) {
+               dev->dev_addr[i] = SA_prom[i];
+       }
+#endif
+
+       printk("%pM\n", dev->dev_addr);
+
+       ei_status.name = name;
+       ei_status.tx_start_page = start_page;
+       ei_status.stop_page = stop_page;
+
+       /* Use 16-bit mode only if this wasn't overridden by DCR_VAL */
+       ei_status.word16 = (wordlength == 2 && (DCR_VAL & 0x01));
+
+       ei_status.rx_start_page = start_page + TX_PAGES;
+#ifdef PACKETBUF_MEMSIZE
+        /* Allow the packet buffer size to be overridden by know-it-alls. */
+       ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
+#endif
+
+       ei_status.reset_8390 = &ne_reset_8390;
+       ei_status.block_input = &ne_block_input;
+       ei_status.block_output = &ne_block_output;
+       ei_status.get_8390_hdr = &ne_get_8390_hdr;
+       ei_status.priv = 0;
+
+       dev->netdev_ops = &eip_netdev_ops;
+       NS8390p_init(dev, 0);
+
+       ret = register_netdev(dev);
+       if (ret)
+               goto out_irq;
+       printk(KERN_INFO "%s: %s found at %#lx, using IRQ %d.\n",
+              dev->name, name, ioaddr, dev->irq);
+       return 0;
+
+out_irq:
+       free_irq(dev->irq, dev);
+err_out:
+       release_region(ioaddr, NE_IO_EXTENT);
+       return ret;
+}
+
+/* Hard reset the card.  This used to pause for the same period that a
+   8390 reset command required, but that shouldn't be necessary. */
+
+static void ne_reset_8390(struct net_device *dev)
+{
+       unsigned long reset_start_time = jiffies;
+
+       if (ei_debug > 1)
+               printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
+
+       /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
+       outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+       ei_status.txing = 0;
+       ei_status.dmaing = 0;
+
+       /* This check _should_not_ be necessary, omit eventually. */
+       while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
+               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
+                       printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
+                       break;
+               }
+       outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+       int nic_base = dev->base_addr;
+
+       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+
+       if (ei_status.dmaing)
+       {
+               printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
+                       "[DMAstat:%d][irqlock:%d].\n",
+                       dev->name, ei_status.dmaing, ei_status.irqlock);
+               return;
+       }
+
+       ei_status.dmaing |= 0x01;
+       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+       outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+       outb_p(0, nic_base + EN0_RCNTHI);
+       outb_p(0, nic_base + EN0_RSARLO);               /* On page boundary */
+       outb_p(ring_page, nic_base + EN0_RSARHI);
+       outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+       if (ei_status.word16)
+               insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+       else
+               insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+
+       outb_p(ENISR_RDC, nic_base + EN0_ISR);  /* Ack intr. */
+       ei_status.dmaing &= ~0x01;
+
+       le16_to_cpus(&hdr->count);
+}
+
+/* Block input and output, similar to the Crynwr packet driver.  If you
+   are porting to a new ethercard, look at the packet driver source for hints.
+   The NEx000 doesn't share the on-board packet memory -- you have to put
+   the packet out through the "remote DMA" dataport using outb. */
+
+static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+#ifdef NE_SANITY_CHECK
+       int xfer_count = count;
+#endif
+       int nic_base = dev->base_addr;
+       char *buf = skb->data;
+
+       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+       if (ei_status.dmaing)
+       {
+               printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
+                       "[DMAstat:%d][irqlock:%d].\n",
+                       dev->name, ei_status.dmaing, ei_status.irqlock);
+               return;
+       }
+       ei_status.dmaing |= 0x01;
+       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+       outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+       outb_p(count >> 8, nic_base + EN0_RCNTHI);
+       outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+       outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+       outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+       if (ei_status.word16)
+       {
+               insw(NE_BASE + NE_DATAPORT,buf,count>>1);
+               if (count & 0x01)
+               {
+                       buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+#ifdef NE_SANITY_CHECK
+                       xfer_count++;
+#endif
+               }
+       } else {
+               insb(NE_BASE + NE_DATAPORT, buf, count);
+       }
+
+#ifdef NE_SANITY_CHECK
+       /* This was for the ALPHA version only, but enough people have
+          been encountering problems so it is still here.  If you see
+          this message you either 1) have a slightly incompatible clone
+          or 2) have noise/speed problems with your bus. */
+
+       if (ei_debug > 1)
+       {
+               /* DMA termination address check... */
+               int addr, tries = 20;
+               do {
+                       /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
+                          -- it's broken for Rx on some cards! */
+                       int high = inb_p(nic_base + EN0_RSARHI);
+                       int low = inb_p(nic_base + EN0_RSARLO);
+                       addr = (high << 8) + low;
+                       if (((ring_offset + xfer_count) & 0xff) == low)
+                               break;
+               } while (--tries > 0);
+               if (tries <= 0)
+                       printk(KERN_WARNING "%s: RX transfer address mismatch,"
+                               "%#4.4x (expected) vs. %#4.4x (actual).\n",
+                               dev->name, ring_offset + xfer_count, addr);
+       }
+#endif
+       outb_p(ENISR_RDC, nic_base + EN0_ISR);  /* Ack intr. */
+       ei_status.dmaing &= ~0x01;
+}
+
+static void ne_block_output(struct net_device *dev, int count,
+               const unsigned char *buf, const int start_page)
+{
+       int nic_base = NE_BASE;
+       unsigned long dma_start;
+#ifdef NE_SANITY_CHECK
+       int retries = 0;
+#endif
+
+       /* Round the count up for word writes.  Do we need to do this?
+          What effect will an odd byte count have on the 8390?
+          I should check someday. */
+
+       if (ei_status.word16 && (count & 0x01))
+               count++;
+
+       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+       if (ei_status.dmaing)
+       {
+               printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
+                       "[DMAstat:%d][irqlock:%d]\n",
+                       dev->name, ei_status.dmaing, ei_status.irqlock);
+               return;
+       }
+       ei_status.dmaing |= 0x01;
+       /* We should already be in page 0, but to be safe... */
+       outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+#ifdef NE_SANITY_CHECK
+retry:
+#endif
+
+#ifdef NE8390_RW_BUGFIX
+       /* Handle the read-before-write bug the same way as the
+          Crynwr packet driver -- the NatSemi method doesn't work.
+          Actually this doesn't always work either, but if you have
+          problems with your NEx000 this is better than nothing! */
+
+       outb_p(0x42, nic_base + EN0_RCNTLO);
+       outb_p(0x00,   nic_base + EN0_RCNTHI);
+       outb_p(0x42, nic_base + EN0_RSARLO);
+       outb_p(0x00, nic_base + EN0_RSARHI);
+       outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+       /* Make certain that the dummy read has occurred. */
+       udelay(6);
+#endif
+
+       outb_p(ENISR_RDC, nic_base + EN0_ISR);
+
+       /* Now the normal output. */
+       outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+       outb_p(count >> 8,   nic_base + EN0_RCNTHI);
+       outb_p(0x00, nic_base + EN0_RSARLO);
+       outb_p(start_page, nic_base + EN0_RSARHI);
+
+       outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+       if (ei_status.word16) {
+               outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
+       } else {
+               outsb(NE_BASE + NE_DATAPORT, buf, count);
+       }
+
+       dma_start = jiffies;
+
+#ifdef NE_SANITY_CHECK
+       /* This was for the ALPHA version only, but enough people have
+          been encountering problems so it is still here. */
+
+       if (ei_debug > 1)
+       {
+               /* DMA termination address check... */
+               int addr, tries = 20;
+               do {
+                       int high = inb_p(nic_base + EN0_RSARHI);
+                       int low = inb_p(nic_base + EN0_RSARLO);
+                       addr = (high << 8) + low;
+                       if ((start_page << 8) + count == addr)
+                               break;
+               } while (--tries > 0);
+
+               if (tries <= 0)
+               {
+                       printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
+                               "%#4.4x (expected) vs. %#4.4x (actual).\n",
+                               dev->name, (start_page << 8) + count, addr);
+                       if (retries++ == 0)
+                               goto retry;
+               }
+       }
+#endif
+
+       while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
+               if (time_after(jiffies, dma_start + 2*HZ/100)) {                /* 20ms */
+                       printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+                       ne_reset_8390(dev);
+                       NS8390p_init(dev, 1);
+                       break;
+               }
+
+       outb_p(ENISR_RDC, nic_base + EN0_ISR);  /* Ack intr. */
+       ei_status.dmaing &= ~0x01;
+}
+
+static int __init ne_drv_probe(struct platform_device *pdev)
+{
+       struct net_device *dev;
+       int err, this_dev = pdev->id;
+       struct resource *res;
+
+       dev = alloc_eip_netdev();
+       if (!dev)
+               return -ENOMEM;
+
+       /* ne.c doesn't populate resources in platform_device, but
+        * rbtx4927_ne_init and rbtx4938_ne_init do register devices
+        * with resources.
+        */
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (res) {
+               dev->base_addr = res->start;
+               dev->irq = platform_get_irq(pdev, 0);
+       } else {
+               if (this_dev < 0 || this_dev >= MAX_NE_CARDS) {
+                       free_netdev(dev);
+                       return -EINVAL;
+               }
+               dev->base_addr = io[this_dev];
+               dev->irq = irq[this_dev];
+               dev->mem_end = bad[this_dev];
+       }
+       err = do_ne_probe(dev);
+       if (err) {
+               free_netdev(dev);
+               return err;
+       }
+       platform_set_drvdata(pdev, dev);
+
+       /* Update with any values found by probing, don't update if
+        * resources were specified.
+        */
+       if (!res) {
+               io[this_dev] = dev->base_addr;
+               irq[this_dev] = dev->irq;
+       }
+       return 0;
+}
+
+static int ne_drv_remove(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+
+       if (dev) {
+               struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+               netif_device_detach(dev);
+               unregister_netdev(dev);
+               if (idev)
+                       pnp_device_detach(idev);
+               /* Careful ne_drv_remove can be called twice, once from
+                * the platform_driver.remove and again when the
+                * platform_device is being removed.
+                */
+               ei_status.priv = 0;
+               free_irq(dev->irq, dev);
+               release_region(dev->base_addr, NE_IO_EXTENT);
+               free_netdev(dev);
+               platform_set_drvdata(pdev, NULL);
+       }
+       return 0;
+}
+
+/* Remove unused devices or all if true. */
+static void ne_loop_rm_unreg(int all)
+{
+       int this_dev;
+       struct platform_device *pdev;
+       for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+               pdev = pdev_ne[this_dev];
+               /* No network device == unused */
+               if (pdev && (!platform_get_drvdata(pdev) || all)) {
+                       ne_drv_remove(pdev);
+                       platform_device_unregister(pdev);
+                       pdev_ne[this_dev] = NULL;
+               }
+       }
+}
+
+#ifdef CONFIG_PM
+static int ne_drv_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+
+       if (netif_running(dev)) {
+               struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+               netif_device_detach(dev);
+               if (idev)
+                       pnp_stop_dev(idev);
+       }
+       return 0;
+}
+
+static int ne_drv_resume(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+
+       if (netif_running(dev)) {
+               struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+               if (idev)
+                       pnp_start_dev(idev);
+               ne_reset_8390(dev);
+               NS8390p_init(dev, 1);
+               netif_device_attach(dev);
+       }
+       return 0;
+}
+#else
+#define ne_drv_suspend NULL
+#define ne_drv_resume NULL
+#endif
+
+static struct platform_driver ne_driver = {
+       .remove         = ne_drv_remove,
+       .suspend        = ne_drv_suspend,
+       .resume         = ne_drv_resume,
+       .driver         = {
+               .name   = DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static void __init ne_add_devices(void)
+{
+       int this_dev;
+       struct platform_device *pdev;
+
+       for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+               if (pdev_ne[this_dev])
+                       continue;
+               pdev = platform_device_register_simple(
+                       DRV_NAME, this_dev, NULL, 0);
+               if (IS_ERR(pdev))
+                       continue;
+               pdev_ne[this_dev] = pdev;
+       }
+}
+
+#ifdef MODULE
+int __init init_module(void)
+{
+       int retval;
+       ne_add_devices();
+       retval = platform_driver_probe(&ne_driver, ne_drv_probe);
+       if (retval) {
+               if (io[0] == 0)
+                       printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\""
+                               " value(s) for ISA cards.\n");
+               ne_loop_rm_unreg(1);
+               return retval;
+       }
+
+       /* Unregister unused platform_devices. */
+       ne_loop_rm_unreg(0);
+       return retval;
+}
+#else /* MODULE */
+static int __init ne_init(void)
+{
+       int retval = platform_driver_probe(&ne_driver, ne_drv_probe);
+
+       /* Unregister unused platform_devices. */
+       ne_loop_rm_unreg(0);
+       return retval;
+}
+module_init(ne_init);
+
+struct net_device * __init ne_probe(int unit)
+{
+       int this_dev;
+       struct net_device *dev;
+
+       /* Find an empty slot, that is no net_device and zero io port. */
+       this_dev = 0;
+       while ((pdev_ne[this_dev] && platform_get_drvdata(pdev_ne[this_dev])) ||
+               io[this_dev]) {
+               if (++this_dev == MAX_NE_CARDS)
+                       return ERR_PTR(-ENOMEM);
+       }
+
+       /* Get irq, io from kernel command line */
+       dev = alloc_eip_netdev();
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       sprintf(dev->name, "eth%d", unit);
+       netdev_boot_setup_check(dev);
+
+       io[this_dev] = dev->base_addr;
+       irq[this_dev] = dev->irq;
+       bad[this_dev] = dev->mem_end;
+
+       free_netdev(dev);
+
+       ne_add_devices();
+
+       /* return the first device found */
+       for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+               if (pdev_ne[this_dev]) {
+                       dev = platform_get_drvdata(pdev_ne[this_dev]);
+                       if (dev)
+                               return dev;
+               }
+       }
+
+       return ERR_PTR(-ENODEV);
+}
+#endif /* MODULE */
+
+static void __exit ne_exit(void)
+{
+       platform_driver_unregister(&ne_driver);
+       ne_loop_rm_unreg(1);
+}
+module_exit(ne_exit);
diff --git a/drivers/net/ethernet/8390/ne2.c b/drivers/net/ethernet/8390/ne2.c
new file mode 100644 (file)
index 0000000..70cdc69
--- /dev/null
@@ -0,0 +1,799 @@
+/* ne2.c: A NE/2 Ethernet Driver for Linux. */
+/*
+   Based on the NE2000 driver written by Donald Becker (1992-94).
+   modified by Wim Dumon (Apr 1996)
+
+   This software may be used and distributed according to the terms
+   of the GNU General Public License, incorporated herein by reference.
+
+   The author may be reached as wimpie@linux.cc.kuleuven.ac.be
+
+   Currently supported: NE/2
+   This patch was never tested on other MCA-ethernet adapters, but it
+   might work. Just give it a try and let me know if you have problems.
+   Also mail me if it really works, please!
+
+   Changelog:
+   Mon Feb  3 16:26:02 MET 1997
+   - adapted the driver to work with the 2.1.25 kernel
+   - multiple ne2 support (untested)
+   - module support (untested)
+
+   Fri Aug 28 00:18:36 CET 1998 (David Weinehall)
+   - fixed a few minor typos
+   - made the MODULE_PARM conditional (it only works with the v2.1.x kernels)
+   - fixed the module support (Now it's working...)
+
+   Mon Sep  7 19:01:44 CET 1998 (David Weinehall)
+   - added support for Arco Electronics AE/2-card (experimental)
+
+   Mon Sep 14 09:53:42 CET 1998 (David Weinehall)
+   - added support for Compex ENET-16MC/P (experimental)
+
+   Tue Sep 15 16:21:12 CET 1998 (David Weinehall, Magnus Jonsson, Tomas Ogren)
+   - Miscellaneous bugfixes
+
+   Tue Sep 19 16:21:12 CET 1998 (Magnus Jonsson)
+   - Cleanup
+
+   Wed Sep 23 14:33:34 CET 1998 (David Weinehall)
+   - Restructuring and rewriting for v2.1.x compliance
+
+   Wed Oct 14 17:19:21 CET 1998 (David Weinehall)
+   - Added code that unregisters irq and proc-info
+   - Version# bump
+
+   Mon Nov 16 15:28:23 CET 1998 (Wim Dumon)
+   - pass 'dev' as last parameter of request_irq in stead of 'NULL'
+
+   Wed Feb  7 21:24:00 CET 2001 (Alfred Arnold)
+   - added support for the D-Link DE-320CT
+
+   *    WARNING
+       -------
+       This is alpha-test software.  It is not guaranteed to work. As a
+       matter of fact, I'm quite sure there are *LOTS* of bugs in here. I
+       would like to hear from you if you use this driver, even if it works.
+       If it doesn't work, be sure to send me a mail with the problems !
+*/
+
+static const char *version = "ne2.c:v0.91 Nov 16 1998 Wim Dumon <wimpie@kotnet.org>\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/mca-legacy.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/bitops.h>
+#include <linux/jiffies.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+#include "8390.h"
+
+#define DRV_NAME "ne2"
+
+/* Some defines that people can play with if so inclined. */
+
+/* Do we perform extra sanity checks on stuff ? */
+/* #define NE_SANITY_CHECK */
+
+/* Do we implement the read before write bugfix ? */
+/* #define NE_RW_BUGFIX */
+
+/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
+/* #define PACKETBUF_MEMSIZE   0x40 */
+
+
+/* ---- No user-serviceable parts below ---- */
+
+#define NE_BASE         (dev->base_addr)
+#define NE_CMD         0x00
+#define NE_DATAPORT    0x10    /* NatSemi-defined port window offset. */
+#define NE_RESET       0x20    /* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT   0x30
+
+#define NE1SM_START_PG 0x20    /* First page of TX buffer */
+#define NE1SM_STOP_PG  0x40    /* Last page +1 of RX ring */
+#define NESM_START_PG  0x40    /* First page of TX buffer */
+#define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
+
+/* From the .ADF file: */
+static unsigned int addresses[7] __initdata =
+               {0x1000, 0x2020, 0x8020, 0xa0a0, 0xb0b0, 0xc0c0, 0xc3d0};
+static int irqs[4] __initdata = {3, 4, 5, 9};
+
+/* From the D-Link ADF file: */
+static unsigned int dlink_addresses[4] __initdata =
+                {0x300, 0x320, 0x340, 0x360};
+static int dlink_irqs[8] __initdata = {3, 4, 5, 9, 10, 11, 14, 15};
+
+struct ne2_adapters_t {
+       unsigned int    id;
+       char            *name;
+};
+
+static struct ne2_adapters_t ne2_adapters[] __initdata = {
+       { 0x6354, "Arco Ethernet Adapter AE/2" },
+       { 0x70DE, "Compex ENET-16 MC/P" },
+       { 0x7154, "Novell Ethernet Adapter NE/2" },
+        { 0x56ea, "D-Link DE-320CT" },
+       { 0x0000, NULL }
+};
+
+extern int netcard_probe(struct net_device *dev);
+
+static int ne2_probe1(struct net_device *dev, int slot);
+
+static void ne_reset_8390(struct net_device *dev);
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+               int ring_page);
+static void ne_block_input(struct net_device *dev, int count,
+               struct sk_buff *skb, int ring_offset);
+static void ne_block_output(struct net_device *dev, const int count,
+               const unsigned char *buf, const int start_page);
+
+
+/*
+ * special code to read the DE-320's MAC address EEPROM.  In contrast to a
+ * standard NE design, this is a serial EEPROM (93C46) that has to be read
+ * bit by bit.  The EEPROM cotrol port at base + 0x1e has the following
+ * layout:
+ *
+ * Bit 0 = Data out (read from EEPROM)
+ * Bit 1 = Data in  (write to EEPROM)
+ * Bit 2 = Clock
+ * Bit 3 = Chip Select
+ * Bit 7 = ~50 kHz clock for defined delays
+ *
+ */
+
+static void __init dlink_put_eeprom(unsigned char value, unsigned int addr)
+{
+       int z;
+       unsigned char v1, v2;
+
+       /* write the value to the NIC EEPROM register */
+
+       outb(value, addr + 0x1e);
+
+       /* now wait the clock line to toggle twice.  Effectively, we are
+          waiting (at least) for one clock cycle */
+
+       for (z = 0; z < 2; z++) {
+               do {
+                       v1 = inb(addr + 0x1e);
+                       v2 = inb(addr + 0x1e);
+               }
+               while (!((v1 ^ v2) & 0x80));
+       }
+}
+
+static void __init dlink_send_eeprom_bit(unsigned int bit, unsigned int addr)
+{
+       /* shift data bit into correct position */
+
+       bit = bit << 1;
+
+       /* write value, keep clock line high for two cycles */
+
+       dlink_put_eeprom(0x09 | bit, addr);
+       dlink_put_eeprom(0x0d | bit, addr);
+       dlink_put_eeprom(0x0d | bit, addr);
+       dlink_put_eeprom(0x09 | bit, addr);
+}
+
+static void __init dlink_send_eeprom_word(unsigned int value, unsigned int len, unsigned int addr)
+{
+       int z;
+
+       /* adjust bits so that they are left-aligned in a 16-bit-word */
+
+       value = value << (16 - len);
+
+       /* shift bits out to the EEPROM */
+
+       for (z = 0; z < len; z++) {
+               dlink_send_eeprom_bit((value & 0x8000) >> 15, addr);
+               value = value << 1;
+       }
+}
+
+static unsigned int __init dlink_get_eeprom(unsigned int eeaddr, unsigned int addr)
+{
+       int z;
+       unsigned int value = 0;
+
+       /* pull the CS line low for a moment.  This resets the EEPROM-
+          internal logic, and makes it ready for a new command. */
+
+       dlink_put_eeprom(0x01, addr);
+       dlink_put_eeprom(0x09, addr);
+
+       /* send one start bit, read command (1 - 0), plus the address to
+           the EEPROM */
+
+       dlink_send_eeprom_word(0x0180 | (eeaddr & 0x3f), 9, addr);
+
+       /* get the data word.  We clock by sending 0s to the EEPROM, which
+          get ignored during the read process */
+
+       for (z = 0; z < 16; z++) {
+               dlink_send_eeprom_bit(0, addr);
+               value = (value << 1) | (inb(addr + 0x1e) & 0x01);
+       }
+
+       return value;
+}
+
+/*
+ * Note that at boot, this probe only picks up one card at a time.
+ */
+
+static int __init do_ne2_probe(struct net_device *dev)
+{
+       static int current_mca_slot = -1;
+       int i;
+       int adapter_found = 0;
+
+       /* Do not check any supplied i/o locations.
+          POS registers usually don't fail :) */
+
+       /* MCA cards have POS registers.
+          Autodetecting MCA cards is extremely simple.
+          Just search for the card. */
+
+       for(i = 0; (ne2_adapters[i].name != NULL) && !adapter_found; i++) {
+               current_mca_slot =
+                       mca_find_unused_adapter(ne2_adapters[i].id, 0);
+
+               if((current_mca_slot != MCA_NOTFOUND) && !adapter_found) {
+                       int res;
+                       mca_set_adapter_name(current_mca_slot,
+                                       ne2_adapters[i].name);
+                       mca_mark_as_used(current_mca_slot);
+
+                       res = ne2_probe1(dev, current_mca_slot);
+                       if (res)
+                               mca_mark_as_unused(current_mca_slot);
+                       return res;
+               }
+       }
+       return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init ne2_probe(int unit)
+{
+       struct net_device *dev = alloc_eip_netdev();
+       int err;
+
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       sprintf(dev->name, "eth%d", unit);
+       netdev_boot_setup_check(dev);
+
+       err = do_ne2_probe(dev);
+       if (err)
+               goto out;
+       return dev;
+out:
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+#endif
+
+static int ne2_procinfo(char *buf, int slot, struct net_device *dev)
+{
+       int len=0;
+
+       len += sprintf(buf+len, "The NE/2 Ethernet Adapter\n" );
+       len += sprintf(buf+len, "Driver written by Wim Dumon ");
+       len += sprintf(buf+len, "<wimpie@kotnet.org>\n");
+       len += sprintf(buf+len, "Modified by ");
+       len += sprintf(buf+len, "David Weinehall <tao@acc.umu.se>\n");
+       len += sprintf(buf+len, "and by Magnus Jonsson <bigfoot@acc.umu.se>\n");
+       len += sprintf(buf+len, "Based on the original NE2000 drivers\n" );
+       len += sprintf(buf+len, "Base IO: %#x\n", (unsigned int)dev->base_addr);
+       len += sprintf(buf+len, "IRQ    : %d\n", dev->irq);
+       len += sprintf(buf+len, "HW addr : %pM\n", dev->dev_addr);
+
+       return len;
+}
+
+static int __init ne2_probe1(struct net_device *dev, int slot)
+{
+       int i, base_addr, irq, retval;
+       unsigned char POS;
+       unsigned char SA_prom[32];
+       const char *name = "NE/2";
+       int start_page, stop_page;
+       static unsigned version_printed;
+
+       if (ei_debug && version_printed++ == 0)
+               printk(version);
+
+       printk("NE/2 ethercard found in slot %d:", slot);
+
+       /* Read base IO and IRQ from the POS-registers */
+       POS = mca_read_stored_pos(slot, 2);
+       if(!(POS % 2)) {
+               printk(" disabled.\n");
+               return -ENODEV;
+       }
+
+       /* handle different POS register structure for D-Link card */
+
+       if (mca_read_stored_pos(slot, 0) == 0xea) {
+               base_addr = dlink_addresses[(POS >> 5) & 0x03];
+               irq = dlink_irqs[(POS >> 2) & 0x07];
+       }
+        else {
+               i = (POS & 0xE)>>1;
+               /* printk("Halleluja sdog, als er na de pijl een 1 staat is 1 - 1 == 0"
+               " en zou het moeten werken -> %d\n", i);
+               The above line was for remote testing, thanx to sdog ... */
+               base_addr = addresses[i - 1];
+               irq = irqs[(POS & 0x60)>>5];
+       }
+
+       if (!request_region(base_addr, NE_IO_EXTENT, DRV_NAME))
+               return -EBUSY;
+
+#ifdef DEBUG
+       printk("POS info : pos 2 = %#x ; base = %#x ; irq = %ld\n", POS,
+                       base_addr, irq);
+#endif
+
+#ifndef CRYNWR_WAY
+       /* Reset the card the way they do it in the Crynwr packet driver */
+       for (i=0; i<8; i++)
+               outb(0x0, base_addr + NE_RESET);
+       inb(base_addr + NE_RESET);
+       outb(0x21, base_addr + NE_CMD);
+       if (inb(base_addr + NE_CMD) != 0x21) {
+               printk("NE/2 adapter not responding\n");
+               retval = -ENODEV;
+               goto out;
+       }
+
+       /* In the crynwr sources they do a RAM-test here. I skip it. I suppose
+          my RAM is okay.  Suppose your memory is broken.  Then this test
+          should fail and you won't be able to use your card.  But if I do not
+          test, you won't be able to use your card, neither.  So this test
+          won't help you. */
+
+#else  /* _I_ never tested it this way .. Go ahead and try ...*/
+       /* Reset card. Who knows what dain-bramaged state it was left in. */
+       {
+               unsigned long reset_start_time = jiffies;
+
+               /* DON'T change these to inb_p/outb_p or reset will fail on
+                  clones.. */
+               outb(inb(base_addr + NE_RESET), base_addr + NE_RESET);
+
+               while ((inb_p(base_addr + EN0_ISR) & ENISR_RESET) == 0)
+                       if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
+                               printk(" not found (no reset ack).\n");
+                               retval = -ENODEV;
+                               goto out;
+                       }
+
+               outb_p(0xff, base_addr + EN0_ISR);         /* Ack all intr. */
+       }
+#endif
+
+
+       /* Read the 16 bytes of station address PROM.
+          We must first initialize registers, similar to
+          NS8390p_init(eifdev, 0).
+          We can't reliably read the SAPROM address without this.
+          (I learned the hard way!). */
+       {
+               struct {
+                       unsigned char value, offset;
+               } program_seq[] = {
+                                               /* Select page 0 */
+                       {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD},
+                       {0x49,  EN0_DCFG},  /* Set WORD-wide (0x49) access. */
+                       {0x00,  EN0_RCNTLO},  /* Clear the count regs. */
+                       {0x00,  EN0_RCNTHI},
+                       {0x00,  EN0_IMR},  /* Mask completion irq. */
+                       {0xFF,  EN0_ISR},
+                       {E8390_RXOFF, EN0_RXCR},  /* 0x20  Set to monitor */
+                       {E8390_TXOFF, EN0_TXCR},  /* 0x02  and loopback mode. */
+                       {32,    EN0_RCNTLO},
+                       {0x00,  EN0_RCNTHI},
+                       {0x00,  EN0_RSARLO},  /* DMA starting at 0x0000. */
+                       {0x00,  EN0_RSARHI},
+                       {E8390_RREAD+E8390_START, E8390_CMD},
+               };
+
+               for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+                       outb_p(program_seq[i].value, base_addr +
+                               program_seq[i].offset);
+
+       }
+       for(i = 0; i < 6 /*sizeof(SA_prom)*/; i+=1) {
+               SA_prom[i] = inb(base_addr + NE_DATAPORT);
+       }
+
+       /* I don't know whether the previous sequence includes the general
+           board reset procedure, so better don't omit it and just overwrite
+           the garbage read from a DE-320 with correct stuff. */
+
+       if (mca_read_stored_pos(slot, 0) == 0xea) {
+               unsigned int v;
+
+               for (i = 0; i < 3; i++) {
+                       v = dlink_get_eeprom(i, base_addr);
+                       SA_prom[(i << 1)    ] = v & 0xff;
+                       SA_prom[(i << 1) + 1] = (v >> 8) & 0xff;
+               }
+       }
+
+       start_page = NESM_START_PG;
+       stop_page = NESM_STOP_PG;
+
+       dev->irq=irq;
+
+       /* Snarf the interrupt now.  There's no point in waiting since we cannot
+          share and the board will usually be enabled. */
+       retval = request_irq(dev->irq, eip_interrupt, 0, DRV_NAME, dev);
+       if (retval) {
+               printk (" unable to get IRQ %d (irqval=%d).\n",
+                               dev->irq, retval);
+               goto out;
+       }
+
+       dev->base_addr = base_addr;
+
+       for(i = 0; i < ETHER_ADDR_LEN; i++)
+               dev->dev_addr[i] = SA_prom[i];
+
+       printk(" %pM\n", dev->dev_addr);
+
+       printk("%s: %s found at %#x, using IRQ %d.\n",
+                       dev->name, name, base_addr, dev->irq);
+
+       mca_set_adapter_procfn(slot, (MCA_ProcFn) ne2_procinfo, dev);
+
+       ei_status.name = name;
+       ei_status.tx_start_page = start_page;
+       ei_status.stop_page = stop_page;
+       ei_status.word16 = (2 == 2);
+
+       ei_status.rx_start_page = start_page + TX_PAGES;
+#ifdef PACKETBUF_MEMSIZE
+       /* Allow the packet buffer size to be overridden by know-it-alls. */
+       ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
+#endif
+
+       ei_status.reset_8390 = &ne_reset_8390;
+       ei_status.block_input = &ne_block_input;
+       ei_status.block_output = &ne_block_output;
+       ei_status.get_8390_hdr = &ne_get_8390_hdr;
+
+       ei_status.priv = slot;
+
+       dev->netdev_ops = &eip_netdev_ops;
+       NS8390p_init(dev, 0);
+
+       retval = register_netdev(dev);
+       if (retval)
+               goto out1;
+       return 0;
+out1:
+       mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
+       free_irq(dev->irq, dev);
+out:
+       release_region(base_addr, NE_IO_EXTENT);
+       return retval;
+}
+
+/* Hard reset the card.  This used to pause for the same period that a
+   8390 reset command required, but that shouldn't be necessary. */
+static void ne_reset_8390(struct net_device *dev)
+{
+       unsigned long reset_start_time = jiffies;
+
+       if (ei_debug > 1)
+               printk("resetting the 8390 t=%ld...", jiffies);
+
+       /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
+       outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+       ei_status.txing = 0;
+       ei_status.dmaing = 0;
+
+       /* This check _should_not_ be necessary, omit eventually. */
+       while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
+               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
+                       printk("%s: ne_reset_8390() did not complete.\n",
+                                       dev->name);
+                       break;
+               }
+       outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+               int ring_page)
+{
+
+       int nic_base = dev->base_addr;
+
+       /* This *shouldn't* happen.
+          If it does, it's the last thing you'll see */
+       if (ei_status.dmaing) {
+               printk("%s: DMAing conflict in ne_get_8390_hdr "
+                               "[DMAstat:%d][irqlock:%d].\n",
+                               dev->name, ei_status.dmaing, ei_status.irqlock);
+               return;
+       }
+
+       ei_status.dmaing |= 0x01;
+       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+       outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+       outb_p(0, nic_base + EN0_RCNTHI);
+       outb_p(0, nic_base + EN0_RSARLO);               /* On page boundary */
+       outb_p(ring_page, nic_base + EN0_RSARHI);
+       outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+       if (ei_status.word16)
+               insw(NE_BASE + NE_DATAPORT, hdr,
+                               sizeof(struct e8390_pkt_hdr)>>1);
+       else
+               insb(NE_BASE + NE_DATAPORT, hdr,
+                               sizeof(struct e8390_pkt_hdr));
+
+       outb_p(ENISR_RDC, nic_base + EN0_ISR);  /* Ack intr. */
+       ei_status.dmaing &= ~0x01;
+}
+
+/* Block input and output, similar to the Crynwr packet driver.  If you
+   are porting to a new ethercard, look at the packet driver source for
+   hints. The NEx000 doesn't share the on-board packet memory -- you have
+   to put the packet out through the "remote DMA" dataport using outb. */
+
+static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb,
+               int ring_offset)
+{
+#ifdef NE_SANITY_CHECK
+       int xfer_count = count;
+#endif
+       int nic_base = dev->base_addr;
+       char *buf = skb->data;
+
+       /* This *shouldn't* happen.
+          If it does, it's the last thing you'll see */
+       if (ei_status.dmaing) {
+               printk("%s: DMAing conflict in ne_block_input "
+                               "[DMAstat:%d][irqlock:%d].\n",
+                               dev->name, ei_status.dmaing, ei_status.irqlock);
+               return;
+       }
+       ei_status.dmaing |= 0x01;
+       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+       outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+       outb_p(count >> 8, nic_base + EN0_RCNTHI);
+       outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+       outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+       outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+       if (ei_status.word16) {
+               insw(NE_BASE + NE_DATAPORT,buf,count>>1);
+               if (count & 0x01) {
+                       buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+#ifdef NE_SANITY_CHECK
+                       xfer_count++;
+#endif
+               }
+       } else {
+               insb(NE_BASE + NE_DATAPORT, buf, count);
+       }
+
+#ifdef NE_SANITY_CHECK
+       /* This was for the ALPHA version only, but enough people have
+          been encountering problems so it is still here.  If you see
+          this message you either 1) have a slightly incompatible clone
+          or 2) have noise/speed problems with your bus. */
+       if (ei_debug > 1) {     /* DMA termination address check... */
+               int addr, tries = 20;
+               do {
+                       /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
+                          -- it's broken for Rx on some cards! */
+                       int high = inb_p(nic_base + EN0_RSARHI);
+                       int low = inb_p(nic_base + EN0_RSARLO);
+                       addr = (high << 8) + low;
+                       if (((ring_offset + xfer_count) & 0xff) == low)
+                               break;
+               } while (--tries > 0);
+               if (tries <= 0)
+                       printk("%s: RX transfer address mismatch,"
+                               "%#4.4x (expected) vs. %#4.4x (actual).\n",
+                               dev->name, ring_offset + xfer_count, addr);
+       }
+#endif
+       outb_p(ENISR_RDC, nic_base + EN0_ISR);  /* Ack intr. */
+       ei_status.dmaing &= ~0x01;
+}
+
+static void ne_block_output(struct net_device *dev, int count,
+               const unsigned char *buf, const int start_page)
+{
+       int nic_base = NE_BASE;
+       unsigned long dma_start;
+#ifdef NE_SANITY_CHECK
+       int retries = 0;
+#endif
+
+       /* Round the count up for word writes. Do we need to do this?
+          What effect will an odd byte count have on the 8390?
+          I should check someday. */
+       if (ei_status.word16 && (count & 0x01))
+               count++;
+
+       /* This *shouldn't* happen.
+          If it does, it's the last thing you'll see */
+       if (ei_status.dmaing) {
+               printk("%s: DMAing conflict in ne_block_output."
+                               "[DMAstat:%d][irqlock:%d]\n",
+                               dev->name, ei_status.dmaing, ei_status.irqlock);
+               return;
+       }
+       ei_status.dmaing |= 0x01;
+       /* We should already be in page 0, but to be safe... */
+       outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+#ifdef NE_SANITY_CHECK
+retry:
+#endif
+
+#ifdef NE8390_RW_BUGFIX
+       /* Handle the read-before-write bug the same way as the
+          Crynwr packet driver -- the NatSemi method doesn't work.
+          Actually this doesn't always work either, but if you have
+          problems with your NEx000 this is better than nothing! */
+       outb_p(0x42, nic_base + EN0_RCNTLO);
+       outb_p(0x00, nic_base + EN0_RCNTHI);
+       outb_p(0x42, nic_base + EN0_RSARLO);
+       outb_p(0x00, nic_base + EN0_RSARHI);
+       outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+       /* Make certain that the dummy read has occurred. */
+       SLOW_DOWN_IO;
+       SLOW_DOWN_IO;
+       SLOW_DOWN_IO;
+#endif
+
+       outb_p(ENISR_RDC, nic_base + EN0_ISR);
+
+       /* Now the normal output. */
+       outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+       outb_p(count >> 8,   nic_base + EN0_RCNTHI);
+       outb_p(0x00, nic_base + EN0_RSARLO);
+       outb_p(start_page, nic_base + EN0_RSARHI);
+
+       outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+       if (ei_status.word16) {
+               outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
+       } else {
+               outsb(NE_BASE + NE_DATAPORT, buf, count);
+       }
+
+       dma_start = jiffies;
+
+#ifdef NE_SANITY_CHECK
+       /* This was for the ALPHA version only, but enough people have
+          been encountering problems so it is still here. */
+
+       if (ei_debug > 1) {             /* DMA termination address check... */
+               int addr, tries = 20;
+               do {
+                       int high = inb_p(nic_base + EN0_RSARHI);
+                       int low = inb_p(nic_base + EN0_RSARLO);
+                       addr = (high << 8) + low;
+                       if ((start_page << 8) + count == addr)
+                               break;
+               } while (--tries > 0);
+               if (tries <= 0) {
+                       printk("%s: Tx packet transfer address mismatch,"
+                                       "%#4.4x (expected) vs. %#4.4x (actual).\n",
+                                       dev->name, (start_page << 8) + count, addr);
+                       if (retries++ == 0)
+                               goto retry;
+               }
+       }
+#endif
+
+       while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
+               if (time_after(jiffies, dma_start + 2*HZ/100)) {                /* 20ms */
+                       printk("%s: timeout waiting for Tx RDC.\n", dev->name);
+                       ne_reset_8390(dev);
+                       NS8390p_init(dev, 1);
+                       break;
+               }
+
+       outb_p(ENISR_RDC, nic_base + EN0_ISR);  /* Ack intr. */
+       ei_status.dmaing &= ~0x01;
+}
+
+
+#ifdef MODULE
+#define MAX_NE_CARDS   4       /* Max number of NE cards per module */
+static struct net_device *dev_ne[MAX_NE_CARDS];
+static int io[MAX_NE_CARDS];
+static int irq[MAX_NE_CARDS];
+static int bad[MAX_NE_CARDS];  /* 0xbad = bad sig or no reset ack */
+MODULE_LICENSE("GPL");
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(bad, int, NULL, 0);
+MODULE_PARM_DESC(io, "(ignored)");
+MODULE_PARM_DESC(irq, "(ignored)");
+MODULE_PARM_DESC(bad, "(ignored)");
+
+/* Module code fixed by David Weinehall */
+
+int __init init_module(void)
+{
+       struct net_device *dev;
+       int this_dev, found = 0;
+
+       for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+               dev = alloc_eip_netdev();
+               if (!dev)
+                       break;
+               dev->irq = irq[this_dev];
+               dev->mem_end = bad[this_dev];
+               dev->base_addr = io[this_dev];
+               if (do_ne2_probe(dev) == 0) {
+                       dev_ne[found++] = dev;
+                       continue;
+               }
+               free_netdev(dev);
+               break;
+       }
+       if (found)
+               return 0;
+       printk(KERN_WARNING "ne2.c: No NE/2 card found\n");
+       return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+       mca_mark_as_unused(ei_status.priv);
+       mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
+       free_irq(dev->irq, dev);
+       release_region(dev->base_addr, NE_IO_EXTENT);
+}
+
+void __exit cleanup_module(void)
+{
+       int this_dev;
+
+       for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+               struct net_device *dev = dev_ne[this_dev];
+               if (dev) {
+                       unregister_netdev(dev);
+                       cleanup_card(dev);
+                       free_netdev(dev);
+               }
+       }
+}
+#endif /* MODULE */
diff --git a/drivers/net/ethernet/8390/ne2k-pci.c b/drivers/net/ethernet/8390/ne2k-pci.c
new file mode 100644 (file)
index 0000000..3c333cb
--- /dev/null
@@ -0,0 +1,726 @@
+/* ne2k-pci.c: A NE2000 clone on PCI bus driver for Linux. */
+/*
+       A Linux device driver for PCI NE2000 clones.
+
+       Authors and other copyright holders:
+       1992-2000 by Donald Becker, NE2000 core and various modifications.
+       1995-1998 by Paul Gortmaker, core modifications and PCI support.
+       Copyright 1993 assigned to the United States Government as represented
+       by the Director, National Security Agency.
+
+       This software may be used and distributed according to the terms of
+       the GNU General Public License (GPL), incorporated herein by reference.
+       Drivers based on or derived from this code fall under the GPL and must
+       retain the authorship, copyright and license notice.  This file is not
+       a complete program and may only be used when the entire operating
+       system is licensed under the GPL.
+
+       The author may be reached as becker@scyld.com, or C/O
+       Scyld Computing Corporation
+       410 Severn Ave., Suite 210
+       Annapolis MD 21403
+
+       Issues remaining:
+       People are making PCI ne2000 clones! Oh the horror, the horror...
+       Limited full-duplex support.
+*/
+
+#define DRV_NAME       "ne2k-pci"
+#define DRV_VERSION    "1.03"
+#define DRV_RELDATE    "9/22/2003"
+
+
+/* The user-configurable values.
+   These may be modified when a driver module is loaded.*/
+
+static int debug = 1;                  /* 1 normal messages, 0 quiet .. 7 verbose. */
+
+#define MAX_UNITS 8                            /* More are supported, limit only on options */
+/* Used to pass the full-duplex flag, etc. */
+static int full_duplex[MAX_UNITS];
+static int options[MAX_UNITS];
+
+/* Force a non std. amount of memory.  Units are 256 byte pages. */
+/* #define PACKETBUF_MEMSIZE   0x40 */
+
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include "8390.h"
+
+/* These identify the driver base version and may not be removed. */
+static const char version[] __devinitconst =
+       KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE
+       " D. Becker/P. Gortmaker\n";
+
+#if defined(__powerpc__)
+#define inl_le(addr)  le32_to_cpu(inl(addr))
+#define inw_le(addr)  le16_to_cpu(inw(addr))
+#endif
+
+#define PFX DRV_NAME ": "
+
+MODULE_AUTHOR("Donald Becker / Paul Gortmaker");
+MODULE_DESCRIPTION("PCI NE2000 clone driver");
+MODULE_LICENSE("GPL");
+
+module_param(debug, int, 0);
+module_param_array(options, int, NULL, 0);
+module_param_array(full_duplex, int, NULL, 0);
+MODULE_PARM_DESC(debug, "debug level (1-2)");
+MODULE_PARM_DESC(options, "Bit 5: full duplex");
+MODULE_PARM_DESC(full_duplex, "full duplex setting(s) (1)");
+
+/* Some defines that people can play with if so inclined. */
+
+/* Use 32 bit data-movement operations instead of 16 bit. */
+#define USE_LONGIO
+
+/* Do we implement the read before write bugfix ? */
+/* #define NE_RW_BUGFIX */
+
+/* Flags.  We rename an existing ei_status field to store flags! */
+/* Thus only the low 8 bits are usable for non-init-time flags. */
+#define ne2k_flags reg0
+enum {
+       ONLY_16BIT_IO=8, ONLY_32BIT_IO=4,       /* Chip can do only 16/32-bit xfers. */
+       FORCE_FDX=0x20,                                         /* User override. */
+       REALTEK_FDX=0x40, HOLTEK_FDX=0x80,
+       STOP_PG_0x60=0x100,
+};
+
+enum ne2k_pci_chipsets {
+       CH_RealTek_RTL_8029 = 0,
+       CH_Winbond_89C940,
+       CH_Compex_RL2000,
+       CH_KTI_ET32P2,
+       CH_NetVin_NV5000SC,
+       CH_Via_86C926,
+       CH_SureCom_NE34,
+       CH_Winbond_W89C940F,
+       CH_Holtek_HT80232,
+       CH_Holtek_HT80229,
+       CH_Winbond_89C940_8c4a,
+};
+
+
+static struct {
+       char *name;
+       int flags;
+} pci_clone_list[] __devinitdata = {
+       {"RealTek RTL-8029", REALTEK_FDX},
+       {"Winbond 89C940", 0},
+       {"Compex RL2000", 0},
+       {"KTI ET32P2", 0},
+       {"NetVin NV5000SC", 0},
+       {"Via 86C926", ONLY_16BIT_IO},
+       {"SureCom NE34", 0},
+       {"Winbond W89C940F", 0},
+       {"Holtek HT80232", ONLY_16BIT_IO | HOLTEK_FDX},
+       {"Holtek HT80229", ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60 },
+       {"Winbond W89C940(misprogrammed)", 0},
+       {NULL,}
+};
+
+
+static DEFINE_PCI_DEVICE_TABLE(ne2k_pci_tbl) = {
+       { 0x10ec, 0x8029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RealTek_RTL_8029 },
+       { 0x1050, 0x0940, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_89C940 },
+       { 0x11f6, 0x1401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Compex_RL2000 },
+       { 0x8e2e, 0x3000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_KTI_ET32P2 },
+       { 0x4a14, 0x5000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_NetVin_NV5000SC },
+       { 0x1106, 0x0926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Via_86C926 },
+       { 0x10bd, 0x0e34, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_SureCom_NE34 },
+       { 0x1050, 0x5a5a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_W89C940F },
+       { 0x12c3, 0x0058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80232 },
+       { 0x12c3, 0x5598, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80229 },
+       { 0x8c4a, 0x1980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_89C940_8c4a },
+       { 0, }
+};
+MODULE_DEVICE_TABLE(pci, ne2k_pci_tbl);
+
+
+/* ---- No user-serviceable parts below ---- */
+
+#define NE_BASE         (dev->base_addr)
+#define NE_CMD         0x00
+#define NE_DATAPORT    0x10    /* NatSemi-defined port window offset. */
+#define NE_RESET       0x1f    /* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT   0x20
+
+#define NESM_START_PG  0x40    /* First page of TX buffer */
+#define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
+
+
+static int ne2k_pci_open(struct net_device *dev);
+static int ne2k_pci_close(struct net_device *dev);
+
+static void ne2k_pci_reset_8390(struct net_device *dev);
+static void ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                         int ring_page);
+static void ne2k_pci_block_input(struct net_device *dev, int count,
+                         struct sk_buff *skb, int ring_offset);
+static void ne2k_pci_block_output(struct net_device *dev, const int count,
+               const unsigned char *buf, const int start_page);
+static const struct ethtool_ops ne2k_pci_ethtool_ops;
+
+
+
+/* There is no room in the standard 8390 structure for extra info we need,
+   so we build a meta/outer-wrapper structure.. */
+struct ne2k_pci_card {
+       struct net_device *dev;
+       struct pci_dev *pci_dev;
+};
+
+
+
+/*
+  NEx000-clone boards have a Station Address (SA) PROM (SAPROM) in the packet
+  buffer memory space.  By-the-spec NE2000 clones have 0x57,0x57 in bytes
+  0x0e,0x0f of the SAPROM, while other supposed NE2000 clones must be
+  detected by their SA prefix.
+
+  Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
+  mode results in doubled values, which can be detected and compensated for.
+
+  The probe is also responsible for initializing the card and filling
+  in the 'dev' and 'ei_status' structures.
+*/
+
+static const struct net_device_ops ne2k_netdev_ops = {
+       .ndo_open               = ne2k_pci_open,
+       .ndo_stop               = ne2k_pci_close,
+       .ndo_start_xmit         = ei_start_xmit,
+       .ndo_tx_timeout         = ei_tx_timeout,
+       .ndo_get_stats          = ei_get_stats,
+       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller = ei_poll,
+#endif
+};
+
+static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
+                                    const struct pci_device_id *ent)
+{
+       struct net_device *dev;
+       int i;
+       unsigned char SA_prom[32];
+       int start_page, stop_page;
+       int irq, reg0, chip_idx = ent->driver_data;
+       static unsigned int fnd_cnt;
+       long ioaddr;
+       int flags = pci_clone_list[chip_idx].flags;
+
+/* when built into the kernel, we only print version if device is found */
+#ifndef MODULE
+       static int printed_version;
+       if (!printed_version++)
+               printk(version);
+#endif
+
+       fnd_cnt++;
+
+       i = pci_enable_device (pdev);
+       if (i)
+               return i;
+
+       ioaddr = pci_resource_start (pdev, 0);
+       irq = pdev->irq;
+
+       if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_IO) == 0)) {
+               dev_err(&pdev->dev, "no I/O resource at PCI BAR #0\n");
+               return -ENODEV;
+       }
+
+       if (request_region (ioaddr, NE_IO_EXTENT, DRV_NAME) == NULL) {
+               dev_err(&pdev->dev, "I/O resource 0x%x @ 0x%lx busy\n",
+                       NE_IO_EXTENT, ioaddr);
+               return -EBUSY;
+       }
+
+       reg0 = inb(ioaddr);
+       if (reg0 == 0xFF)
+               goto err_out_free_res;
+
+       /* Do a preliminary verification that we have a 8390. */
+       {
+               int regd;
+               outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
+               regd = inb(ioaddr + 0x0d);
+               outb(0xff, ioaddr + 0x0d);
+               outb(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
+               inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
+               if (inb(ioaddr + EN0_COUNTER0) != 0) {
+                       outb(reg0, ioaddr);
+                       outb(regd, ioaddr + 0x0d);      /* Restore the old values. */
+                       goto err_out_free_res;
+               }
+       }
+
+       /* Allocate net_device, dev->priv; fill in 8390 specific dev fields. */
+       dev = alloc_ei_netdev();
+       if (!dev) {
+               dev_err(&pdev->dev, "cannot allocate ethernet device\n");
+               goto err_out_free_res;
+       }
+       dev->netdev_ops = &ne2k_netdev_ops;
+
+       SET_NETDEV_DEV(dev, &pdev->dev);
+
+       /* Reset card. Who knows what dain-bramaged state it was left in. */
+       {
+               unsigned long reset_start_time = jiffies;
+
+               outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+
+               /* This looks like a horrible timing loop, but it should never take
+                  more than a few cycles.
+               */
+               while ((inb(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
+                       /* Limit wait: '2' avoids jiffy roll-over. */
+                       if (jiffies - reset_start_time > 2) {
+                               dev_err(&pdev->dev,
+                                       "Card failure (no reset ack).\n");
+                               goto err_out_free_netdev;
+                       }
+
+               outb(0xff, ioaddr + EN0_ISR);           /* Ack all intr. */
+       }
+
+       /* Read the 16 bytes of station address PROM.
+          We must first initialize registers, similar to NS8390_init(eifdev, 0).
+          We can't reliably read the SAPROM address without this.
+          (I learned the hard way!). */
+       {
+               struct {unsigned char value, offset; } program_seq[] = {
+                       {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+                       {0x49,  EN0_DCFG},      /* Set word-wide access. */
+                       {0x00,  EN0_RCNTLO},    /* Clear the count regs. */
+                       {0x00,  EN0_RCNTHI},
+                       {0x00,  EN0_IMR},       /* Mask completion irq. */
+                       {0xFF,  EN0_ISR},
+                       {E8390_RXOFF, EN0_RXCR},        /* 0x20  Set to monitor */
+                       {E8390_TXOFF, EN0_TXCR},        /* 0x02  and loopback mode. */
+                       {32,    EN0_RCNTLO},
+                       {0x00,  EN0_RCNTHI},
+                       {0x00,  EN0_RSARLO},    /* DMA starting at 0x0000. */
+                       {0x00,  EN0_RSARHI},
+                       {E8390_RREAD+E8390_START, E8390_CMD},
+               };
+               for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+                       outb(program_seq[i].value, ioaddr + program_seq[i].offset);
+
+       }
+
+       /* Note: all PCI cards have at least 16 bit access, so we don't have
+          to check for 8 bit cards.  Most cards permit 32 bit access. */
+       if (flags & ONLY_32BIT_IO) {
+               for (i = 0; i < 4 ; i++)
+                       ((u32 *)SA_prom)[i] = le32_to_cpu(inl(ioaddr + NE_DATAPORT));
+       } else
+               for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++)
+                       SA_prom[i] = inb(ioaddr + NE_DATAPORT);
+
+       /* We always set the 8390 registers for word mode. */
+       outb(0x49, ioaddr + EN0_DCFG);
+       start_page = NESM_START_PG;
+
+       stop_page = flags & STOP_PG_0x60 ? 0x60 : NESM_STOP_PG;
+
+       /* Set up the rest of the parameters. */
+       dev->irq = irq;
+       dev->base_addr = ioaddr;
+       pci_set_drvdata(pdev, dev);
+
+       ei_status.name = pci_clone_list[chip_idx].name;
+       ei_status.tx_start_page = start_page;
+       ei_status.stop_page = stop_page;
+       ei_status.word16 = 1;
+       ei_status.ne2k_flags = flags;
+       if (fnd_cnt < MAX_UNITS) {
+               if (full_duplex[fnd_cnt] > 0  ||  (options[fnd_cnt] & FORCE_FDX))
+                       ei_status.ne2k_flags |= FORCE_FDX;
+       }
+
+       ei_status.rx_start_page = start_page + TX_PAGES;
+#ifdef PACKETBUF_MEMSIZE
+       /* Allow the packet buffer size to be overridden by know-it-alls. */
+       ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
+#endif
+
+       ei_status.reset_8390 = &ne2k_pci_reset_8390;
+       ei_status.block_input = &ne2k_pci_block_input;
+       ei_status.block_output = &ne2k_pci_block_output;
+       ei_status.get_8390_hdr = &ne2k_pci_get_8390_hdr;
+       ei_status.priv = (unsigned long) pdev;
+
+       dev->ethtool_ops = &ne2k_pci_ethtool_ops;
+       NS8390_init(dev, 0);
+
+       memcpy(dev->dev_addr, SA_prom, dev->addr_len);
+       memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+       i = register_netdev(dev);
+       if (i)
+               goto err_out_free_netdev;
+
+       printk("%s: %s found at %#lx, IRQ %d, %pM.\n",
+              dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq,
+              dev->dev_addr);
+
+       return 0;
+
+err_out_free_netdev:
+       free_netdev (dev);
+err_out_free_res:
+       release_region (ioaddr, NE_IO_EXTENT);
+       pci_set_drvdata (pdev, NULL);
+       return -ENODEV;
+
+}
+
+/*
+ * Magic incantation sequence for full duplex on the supported cards.
+ */
+static inline int set_realtek_fdx(struct net_device *dev)
+{
+       long ioaddr = dev->base_addr;
+
+       outb(0xC0 + E8390_NODMA, ioaddr + NE_CMD); /* Page 3 */
+       outb(0xC0, ioaddr + 0x01); /* Enable writes to CONFIG3 */
+       outb(0x40, ioaddr + 0x06); /* Enable full duplex */
+       outb(0x00, ioaddr + 0x01); /* Disable writes to CONFIG3 */
+       outb(E8390_PAGE0 + E8390_NODMA, ioaddr + NE_CMD); /* Page 0 */
+       return 0;
+}
+
+static inline int set_holtek_fdx(struct net_device *dev)
+{
+       long ioaddr = dev->base_addr;
+
+       outb(inb(ioaddr + 0x20) | 0x80, ioaddr + 0x20);
+       return 0;
+}
+
+static int ne2k_pci_set_fdx(struct net_device *dev)
+{
+       if (ei_status.ne2k_flags & REALTEK_FDX)
+               return set_realtek_fdx(dev);
+       else if (ei_status.ne2k_flags & HOLTEK_FDX)
+               return set_holtek_fdx(dev);
+
+       return -EOPNOTSUPP;
+}
+
+static int ne2k_pci_open(struct net_device *dev)
+{
+       int ret = request_irq(dev->irq, ei_interrupt, IRQF_SHARED, dev->name, dev);
+       if (ret)
+               return ret;
+
+       if (ei_status.ne2k_flags & FORCE_FDX)
+               ne2k_pci_set_fdx(dev);
+
+       ei_open(dev);
+       return 0;
+}
+
+static int ne2k_pci_close(struct net_device *dev)
+{
+       ei_close(dev);
+       free_irq(dev->irq, dev);
+       return 0;
+}
+
+/* Hard reset the card.  This used to pause for the same period that a
+   8390 reset command required, but that shouldn't be necessary. */
+static void ne2k_pci_reset_8390(struct net_device *dev)
+{
+       unsigned long reset_start_time = jiffies;
+
+       if (debug > 1) printk("%s: Resetting the 8390 t=%ld...",
+                                                 dev->name, jiffies);
+
+       outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+       ei_status.txing = 0;
+       ei_status.dmaing = 0;
+
+       /* This check _should_not_ be necessary, omit eventually. */
+       while ((inb(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
+               if (jiffies - reset_start_time > 2) {
+                       printk("%s: ne2k_pci_reset_8390() did not complete.\n", dev->name);
+                       break;
+               }
+       outb(ENISR_RESET, NE_BASE + EN0_ISR);   /* Ack intr. */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+
+       long nic_base = dev->base_addr;
+
+       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+       if (ei_status.dmaing) {
+               printk("%s: DMAing conflict in ne2k_pci_get_8390_hdr "
+                          "[DMAstat:%d][irqlock:%d].\n",
+                          dev->name, ei_status.dmaing, ei_status.irqlock);
+               return;
+       }
+
+       ei_status.dmaing |= 0x01;
+       outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+       outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+       outb(0, nic_base + EN0_RCNTHI);
+       outb(0, nic_base + EN0_RSARLO);         /* On page boundary */
+       outb(ring_page, nic_base + EN0_RSARHI);
+       outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+       if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
+               insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+       } else {
+               *(u32*)hdr = le32_to_cpu(inl(NE_BASE + NE_DATAPORT));
+               le16_to_cpus(&hdr->count);
+       }
+
+       outb(ENISR_RDC, nic_base + EN0_ISR);    /* Ack intr. */
+       ei_status.dmaing &= ~0x01;
+}
+
+/* Block input and output, similar to the Crynwr packet driver.  If you
+   are porting to a new ethercard, look at the packet driver source for hints.
+   The NEx000 doesn't share the on-board packet memory -- you have to put
+   the packet out through the "remote DMA" dataport using outb. */
+
+static void ne2k_pci_block_input(struct net_device *dev, int count,
+                                struct sk_buff *skb, int ring_offset)
+{
+       long nic_base = dev->base_addr;
+       char *buf = skb->data;
+
+       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+       if (ei_status.dmaing) {
+               printk("%s: DMAing conflict in ne2k_pci_block_input "
+                          "[DMAstat:%d][irqlock:%d].\n",
+                          dev->name, ei_status.dmaing, ei_status.irqlock);
+               return;
+       }
+       ei_status.dmaing |= 0x01;
+       if (ei_status.ne2k_flags & ONLY_32BIT_IO)
+               count = (count + 3) & 0xFFFC;
+       outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+       outb(count & 0xff, nic_base + EN0_RCNTLO);
+       outb(count >> 8, nic_base + EN0_RCNTHI);
+       outb(ring_offset & 0xff, nic_base + EN0_RSARLO);
+       outb(ring_offset >> 8, nic_base + EN0_RSARHI);
+       outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+       if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
+               insw(NE_BASE + NE_DATAPORT,buf,count>>1);
+               if (count & 0x01) {
+                       buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+               }
+       } else {
+               insl(NE_BASE + NE_DATAPORT, buf, count>>2);
+               if (count & 3) {
+                       buf += count & ~3;
+                       if (count & 2) {
+                               __le16 *b = (__le16 *)buf;
+
+                               *b++ = cpu_to_le16(inw(NE_BASE + NE_DATAPORT));
+                               buf = (char *)b;
+                       }
+                       if (count & 1)
+                               *buf = inb(NE_BASE + NE_DATAPORT);
+               }
+       }
+
+       outb(ENISR_RDC, nic_base + EN0_ISR);    /* Ack intr. */
+       ei_status.dmaing &= ~0x01;
+}
+
+static void ne2k_pci_block_output(struct net_device *dev, int count,
+                                 const unsigned char *buf, const int start_page)
+{
+       long nic_base = NE_BASE;
+       unsigned long dma_start;
+
+       /* On little-endian it's always safe to round the count up for
+          word writes. */
+       if (ei_status.ne2k_flags & ONLY_32BIT_IO)
+               count = (count + 3) & 0xFFFC;
+       else
+               if (count & 0x01)
+                       count++;
+
+       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+       if (ei_status.dmaing) {
+               printk("%s: DMAing conflict in ne2k_pci_block_output."
+                          "[DMAstat:%d][irqlock:%d]\n",
+                          dev->name, ei_status.dmaing, ei_status.irqlock);
+               return;
+       }
+       ei_status.dmaing |= 0x01;
+       /* We should already be in page 0, but to be safe... */
+       outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+#ifdef NE8390_RW_BUGFIX
+       /* Handle the read-before-write bug the same way as the
+          Crynwr packet driver -- the NatSemi method doesn't work.
+          Actually this doesn't always work either, but if you have
+          problems with your NEx000 this is better than nothing! */
+       outb(0x42, nic_base + EN0_RCNTLO);
+       outb(0x00, nic_base + EN0_RCNTHI);
+       outb(0x42, nic_base + EN0_RSARLO);
+       outb(0x00, nic_base + EN0_RSARHI);
+       outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+#endif
+       outb(ENISR_RDC, nic_base + EN0_ISR);
+
+   /* Now the normal output. */
+       outb(count & 0xff, nic_base + EN0_RCNTLO);
+       outb(count >> 8,   nic_base + EN0_RCNTHI);
+       outb(0x00, nic_base + EN0_RSARLO);
+       outb(start_page, nic_base + EN0_RSARHI);
+       outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+       if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
+               outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
+       } else {
+               outsl(NE_BASE + NE_DATAPORT, buf, count>>2);
+               if (count & 3) {
+                       buf += count & ~3;
+                       if (count & 2) {
+                               __le16 *b = (__le16 *)buf;
+
+                               outw(le16_to_cpu(*b++), NE_BASE + NE_DATAPORT);
+                               buf = (char *)b;
+                       }
+               }
+       }
+
+       dma_start = jiffies;
+
+       while ((inb(nic_base + EN0_ISR) & ENISR_RDC) == 0)
+               if (jiffies - dma_start > 2) {                  /* Avoid clock roll-over. */
+                       printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+                       ne2k_pci_reset_8390(dev);
+                       NS8390_init(dev,1);
+                       break;
+               }
+
+       outb(ENISR_RDC, nic_base + EN0_ISR);    /* Ack intr. */
+       ei_status.dmaing &= ~0x01;
+}
+
+static void ne2k_pci_get_drvinfo(struct net_device *dev,
+                                struct ethtool_drvinfo *info)
+{
+       struct ei_device *ei = netdev_priv(dev);
+       struct pci_dev *pci_dev = (struct pci_dev *) ei->priv;
+
+       strcpy(info->driver, DRV_NAME);
+       strcpy(info->version, DRV_VERSION);
+       strcpy(info->bus_info, pci_name(pci_dev));
+}
+
+static const struct ethtool_ops ne2k_pci_ethtool_ops = {
+       .get_drvinfo            = ne2k_pci_get_drvinfo,
+};
+
+static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+
+       BUG_ON(!dev);
+       unregister_netdev(dev);
+       release_region(dev->base_addr, NE_IO_EXTENT);
+       free_netdev(dev);
+       pci_disable_device(pdev);
+       pci_set_drvdata(pdev, NULL);
+}
+
+#ifdef CONFIG_PM
+static int ne2k_pci_suspend (struct pci_dev *pdev, pm_message_t state)
+{
+       struct net_device *dev = pci_get_drvdata (pdev);
+
+       netif_device_detach(dev);
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+       return 0;
+}
+
+static int ne2k_pci_resume (struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata (pdev);
+       int rc;
+
+       pci_set_power_state(pdev, 0);
+       pci_restore_state(pdev);
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       NS8390_init(dev, 1);
+       netif_device_attach(dev);
+
+       return 0;
+}
+
+#endif /* CONFIG_PM */
+
+
+static struct pci_driver ne2k_driver = {
+       .name           = DRV_NAME,
+       .probe          = ne2k_pci_init_one,
+       .remove         = __devexit_p(ne2k_pci_remove_one),
+       .id_table       = ne2k_pci_tbl,
+#ifdef CONFIG_PM
+       .suspend        = ne2k_pci_suspend,
+       .resume         = ne2k_pci_resume,
+#endif /* CONFIG_PM */
+
+};
+
+
+static int __init ne2k_pci_init(void)
+{
+/* when a module, this is printed whether or not devices are found in probe */
+#ifdef MODULE
+       printk(version);
+#endif
+       return pci_register_driver(&ne2k_driver);
+}
+
+
+static void __exit ne2k_pci_cleanup(void)
+{
+       pci_unregister_driver (&ne2k_driver);
+}
+
+module_init(ne2k_pci_init);
+module_exit(ne2k_pci_cleanup);
diff --git a/drivers/net/ethernet/8390/ne3210.c b/drivers/net/ethernet/8390/ne3210.c
new file mode 100644 (file)
index 0000000..243ed2a
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+       ne3210.c
+
+       Linux driver for Novell NE3210 EISA Network Adapter
+
+       Copyright (C) 1998, Paul Gortmaker.
+
+       This software may be used and distributed according to the terms
+       of the GNU General Public License, incorporated herein by reference.
+
+       Information and Code Sources:
+
+       1) Based upon my other EISA 8390 drivers (lne390, es3210, smc-ultra32)
+       2) The existing myriad of other Linux 8390 drivers by Donald Becker.
+       3) Info for getting IRQ and sh-mem gleaned from the EISA cfg file
+
+       The NE3210 is an EISA shared memory NS8390 implementation.  Shared
+       memory address > 1MB should work with this driver.
+
+       Note that the .cfg file (3/11/93, v1.0) has AUI and BNC switched
+       around (or perhaps there are some defective/backwards cards ???)
+
+       This driver WILL NOT WORK FOR THE NE3200 - it is completely different
+       and does not use an 8390 at all.
+
+       Updated to EISA probing API 5/2003 by Marc Zyngier.
+*/
+
+#include <linux/module.h>
+#include <linux/eisa.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+#define DRV_NAME "ne3210"
+
+static void ne3210_reset_8390(struct net_device *dev);
+
+static void ne3210_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
+static void ne3210_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset);
+static void ne3210_block_output(struct net_device *dev, int count, const unsigned char *buf, const int start_page);
+
+#define NE3210_START_PG                0x00    /* First page of TX buffer      */
+#define NE3210_STOP_PG         0x80    /* Last page +1 of RX ring      */
+
+#define NE3210_IO_EXTENT       0x20
+#define NE3210_SA_PROM         0x16    /* Start of e'net addr.         */
+#define NE3210_RESET_PORT      0xc84
+#define NE3210_NIC_OFFSET      0x00    /* Hello, the 8390 is *here*    */
+
+#define NE3210_ADDR0           0x00    /* 3 byte vendor prefix         */
+#define NE3210_ADDR1           0x00
+#define NE3210_ADDR2           0x1b
+
+#define NE3210_CFG1            0xc84   /* NB: 0xc84 is also "reset" port. */
+#define NE3210_CFG2            0xc90
+#define NE3210_CFG_EXTENT       (NE3210_CFG2 - NE3210_CFG1 + 1)
+
+/*
+ *     You can OR any of the following bits together and assign it
+ *     to NE3210_DEBUG to get verbose driver info during operation.
+ *     Currently only the probe one is implemented.
+ */
+
+#define NE3210_D_PROBE 0x01
+#define NE3210_D_RX_PKT        0x02
+#define NE3210_D_TX_PKT        0x04
+#define NE3210_D_IRQ   0x08
+
+#define NE3210_DEBUG   0x0
+
+static unsigned char irq_map[] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
+static unsigned int shmem_map[] __initdata = {0xff0, 0xfe0, 0xfff0, 0xd8, 0xffe0, 0xffc0, 0xd0, 0x0};
+static const char *ifmap[] __initdata = {"UTP", "?", "BNC", "AUI"};
+static int ifmap_val[] __initdata = {
+               IF_PORT_10BASET,
+               IF_PORT_UNKNOWN,
+               IF_PORT_10BASE2,
+               IF_PORT_AUI,
+};
+
+static int __init ne3210_eisa_probe (struct device *device)
+{
+       unsigned long ioaddr, phys_mem;
+       int i, retval, port_index;
+       struct eisa_device *edev = to_eisa_device (device);
+       struct net_device *dev;
+
+       /* Allocate dev->priv and fill in 8390 specific dev fields. */
+       if (!(dev = alloc_ei_netdev ())) {
+               printk ("ne3210.c: unable to allocate memory for dev!\n");
+               return -ENOMEM;
+       }
+
+       SET_NETDEV_DEV(dev, device);
+       dev_set_drvdata(device, dev);
+       ioaddr = edev->base_addr;
+
+       if (!request_region(ioaddr, NE3210_IO_EXTENT, DRV_NAME)) {
+               retval = -EBUSY;
+               goto out;
+       }
+
+       if (!request_region(ioaddr + NE3210_CFG1,
+                           NE3210_CFG_EXTENT, DRV_NAME)) {
+               retval = -EBUSY;
+               goto out1;
+       }
+
+#if NE3210_DEBUG & NE3210_D_PROBE
+       printk("ne3210-debug: probe at %#x, ID %s\n", ioaddr, edev->id.sig);
+       printk("ne3210-debug: config regs: %#x %#x\n",
+               inb(ioaddr + NE3210_CFG1), inb(ioaddr + NE3210_CFG2));
+#endif
+
+       port_index = inb(ioaddr + NE3210_CFG2) >> 6;
+       for(i = 0; i < ETHER_ADDR_LEN; i++)
+               dev->dev_addr[i] = inb(ioaddr + NE3210_SA_PROM + i);
+       printk("ne3210.c: NE3210 in EISA slot %d, media: %s, addr: %pM.\n",
+               edev->slot, ifmap[port_index], dev->dev_addr);
+
+       /* Snarf the interrupt now. CFG file has them all listed as `edge' with share=NO */
+       dev->irq = irq_map[(inb(ioaddr + NE3210_CFG2) >> 3) & 0x07];
+       printk("ne3210.c: using IRQ %d, ", dev->irq);
+
+       retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
+       if (retval) {
+               printk (" unable to get IRQ %d.\n", dev->irq);
+               goto out2;
+       }
+
+       phys_mem = shmem_map[inb(ioaddr + NE3210_CFG2) & 0x07] * 0x1000;
+
+       /*
+          BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
+          the card mem within the region covered by `normal' RAM  !!!
+       */
+       if (phys_mem > 1024*1024) {     /* phys addr > 1MB */
+               if (phys_mem < virt_to_phys(high_memory)) {
+                       printk(KERN_CRIT "ne3210.c: Card RAM overlaps with normal memory!!!\n");
+                       printk(KERN_CRIT "ne3210.c: Use EISA SCU to set card memory below 1MB,\n");
+                       printk(KERN_CRIT "ne3210.c: or to an address above 0x%llx.\n",
+                               (u64)virt_to_phys(high_memory));
+                       printk(KERN_CRIT "ne3210.c: Driver NOT installed.\n");
+                       retval = -EINVAL;
+                       goto out3;
+               }
+       }
+
+       if (!request_mem_region (phys_mem, NE3210_STOP_PG*0x100, DRV_NAME)) {
+               printk ("ne3210.c: Unable to request shared memory at physical address %#lx\n",
+                       phys_mem);
+               goto out3;
+       }
+
+       printk("%dkB memory at physical address %#lx\n",
+              NE3210_STOP_PG/4, phys_mem);
+
+       ei_status.mem = ioremap(phys_mem, NE3210_STOP_PG*0x100);
+       if (!ei_status.mem) {
+               printk(KERN_ERR "ne3210.c: Unable to remap card memory !!\n");
+               printk(KERN_ERR "ne3210.c: Driver NOT installed.\n");
+               retval = -EAGAIN;
+               goto out4;
+       }
+       printk("ne3210.c: remapped %dkB card memory to virtual address %p\n",
+              NE3210_STOP_PG/4, ei_status.mem);
+       dev->mem_start = (unsigned long)ei_status.mem;
+       dev->mem_end = dev->mem_start + (NE3210_STOP_PG - NE3210_START_PG)*256;
+
+       /* The 8390 offset is zero for the NE3210 */
+       dev->base_addr = ioaddr;
+
+       ei_status.name = "NE3210";
+       ei_status.tx_start_page = NE3210_START_PG;
+       ei_status.rx_start_page = NE3210_START_PG + TX_PAGES;
+       ei_status.stop_page = NE3210_STOP_PG;
+       ei_status.word16 = 1;
+       ei_status.priv = phys_mem;
+
+       if (ei_debug > 0)
+               printk("ne3210 loaded.\n");
+
+       ei_status.reset_8390 = &ne3210_reset_8390;
+       ei_status.block_input = &ne3210_block_input;
+       ei_status.block_output = &ne3210_block_output;
+       ei_status.get_8390_hdr = &ne3210_get_8390_hdr;
+
+       dev->netdev_ops = &ei_netdev_ops;
+
+       dev->if_port = ifmap_val[port_index];
+
+       if ((retval = register_netdev (dev)))
+               goto out5;
+
+       NS8390_init(dev, 0);
+       return 0;
+
+ out5:
+       iounmap(ei_status.mem);
+ out4:
+       release_mem_region (phys_mem, NE3210_STOP_PG*0x100);
+ out3:
+       free_irq (dev->irq, dev);
+ out2:
+       release_region (ioaddr + NE3210_CFG1, NE3210_CFG_EXTENT);
+ out1:
+       release_region (ioaddr, NE3210_IO_EXTENT);
+ out:
+       free_netdev (dev);
+
+       return retval;
+}
+
+static int __devexit ne3210_eisa_remove (struct device *device)
+{
+       struct net_device  *dev    = dev_get_drvdata(device);
+       unsigned long       ioaddr = to_eisa_device (device)->base_addr;
+
+       unregister_netdev (dev);
+       iounmap(ei_status.mem);
+       release_mem_region (ei_status.priv, NE3210_STOP_PG*0x100);
+       free_irq (dev->irq, dev);
+       release_region (ioaddr + NE3210_CFG1, NE3210_CFG_EXTENT);
+       release_region (ioaddr, NE3210_IO_EXTENT);
+       free_netdev (dev);
+
+       return 0;
+}
+
+/*
+ *     Reset by toggling the "Board Enable" bits (bit 2 and 0).
+ */
+
+static void ne3210_reset_8390(struct net_device *dev)
+{
+       unsigned short ioaddr = dev->base_addr;
+
+       outb(0x04, ioaddr + NE3210_RESET_PORT);
+       if (ei_debug > 1) printk("%s: resetting the NE3210...", dev->name);
+
+       mdelay(2);
+
+       ei_status.txing = 0;
+       outb(0x01, ioaddr + NE3210_RESET_PORT);
+       if (ei_debug > 1) printk("reset done\n");
+}
+
+/*
+ *     Note: In the following three functions is the implicit assumption
+ *     that the associated memcpy will only use "rep; movsl" as long as
+ *     we keep the counts as some multiple of doublewords. This is a
+ *     requirement of the hardware, and also prevents us from using
+ *     eth_io_copy_and_sum() since we can't guarantee it will limit
+ *     itself to doubleword access.
+ */
+
+/*
+ *     Grab the 8390 specific header. Similar to the block_input routine, but
+ *     we don't need to be concerned with ring wrap as the header will be at
+ *     the start of a page, so we optimize accordingly. (A single doubleword.)
+ */
+
+static void
+ne3210_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+       void __iomem *hdr_start = ei_status.mem + ((ring_page - NE3210_START_PG)<<8);
+       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+       hdr->count = (hdr->count + 3) & ~3;     /* Round up allocation. */
+}
+
+/*
+ *     Block input and output are easy on shared memory ethercards, the only
+ *     complication is when the ring buffer wraps. The count will already
+ *     be rounded up to a doubleword value via ne3210_get_8390_hdr() above.
+ */
+
+static void ne3210_block_input(struct net_device *dev, int count, struct sk_buff *skb,
+                                                 int ring_offset)
+{
+       void __iomem *start = ei_status.mem + ring_offset - NE3210_START_PG*256;
+
+       if (ring_offset + count > NE3210_STOP_PG*256) {
+               /* Packet wraps over end of ring buffer. */
+               int semi_count = NE3210_STOP_PG*256 - ring_offset;
+               memcpy_fromio(skb->data, start, semi_count);
+               count -= semi_count;
+               memcpy_fromio(skb->data + semi_count,
+                               ei_status.mem + TX_PAGES*256, count);
+       } else {
+               /* Packet is in one chunk. */
+               memcpy_fromio(skb->data, start, count);
+       }
+}
+
+static void ne3210_block_output(struct net_device *dev, int count,
+                               const unsigned char *buf, int start_page)
+{
+       void __iomem *shmem = ei_status.mem + ((start_page - NE3210_START_PG)<<8);
+
+       count = (count + 3) & ~3;     /* Round up to doubleword */
+       memcpy_toio(shmem, buf, count);
+}
+
+static struct eisa_device_id ne3210_ids[] = {
+       { "EGL0101" },
+       { "NVL1801" },
+       { "" },
+};
+MODULE_DEVICE_TABLE(eisa, ne3210_ids);
+
+static struct eisa_driver ne3210_eisa_driver = {
+       .id_table = ne3210_ids,
+       .driver   = {
+               .name   = "ne3210",
+               .probe  = ne3210_eisa_probe,
+               .remove = __devexit_p (ne3210_eisa_remove),
+       },
+};
+
+MODULE_DESCRIPTION("NE3210 EISA Ethernet driver");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(eisa, ne3210_ids);
+
+static int ne3210_init(void)
+{
+       return eisa_driver_register (&ne3210_eisa_driver);
+}
+
+static void ne3210_cleanup(void)
+{
+       eisa_driver_unregister (&ne3210_eisa_driver);
+}
+
+module_init (ne3210_init);
+module_exit (ne3210_cleanup);
diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c
new file mode 100644 (file)
index 0000000..4010761
--- /dev/null
@@ -0,0 +1,1710 @@
+/*======================================================================
+
+    A PCMCIA ethernet driver for NS8390-based cards
+
+    This driver supports the D-Link DE-650 and Linksys EthernetCard
+    cards, the newer D-Link and Linksys combo cards, Accton EN2212
+    cards, the RPTI EP400, and the PreMax PE-200 in non-shared-memory
+    mode, and the IBM Credit Card Adapter, the NE4100, the Thomas
+    Conrad ethernet card, and the Kingston KNE-PCM/x in shared-memory
+    mode.  It will also handle the Socket EA card in either mode.
+
+    Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
+
+    pcnet_cs.c 1.153 2003/11/09 18:53:09
+
+    The network driver code is based on Donald Becker's NE2000 code:
+
+    Written 1992,1993 by Donald Becker.
+    Copyright 1993 United States Government as represented by the
+    Director, National Security Agency.  This software may be used and
+    distributed according to the terms of the GNU General Public License,
+    incorporated herein by reference.
+    Donald Becker may be reached at becker@scyld.com
+
+    Based also on Keith Moore's changes to Don Becker's code, for IBM
+    CCAE support.  Drivers merged back together, and shared-memory
+    Socket EA support added, by Ken Raeburn, September 1995.
+
+======================================================================*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/log2.h>
+#include <linux/etherdevice.h>
+#include <linux/mii.h>
+#include "8390.h"
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ciscode.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#define PCNET_CMD      0x00
+#define PCNET_DATAPORT 0x10    /* NatSemi-defined port window offset. */
+#define PCNET_RESET    0x1f    /* Issue a read to reset, a write to clear. */
+#define PCNET_MISC     0x18    /* For IBM CCAE and Socket EA cards */
+
+#define PCNET_START_PG 0x40    /* First page of TX buffer */
+#define PCNET_STOP_PG  0x80    /* Last page +1 of RX ring */
+
+/* Socket EA cards have a larger packet buffer */
+#define SOCKET_START_PG        0x01
+#define SOCKET_STOP_PG 0xff
+
+#define PCNET_RDC_TIMEOUT (2*HZ/100)   /* Max wait in jiffies for Tx RDC */
+
+static const char *if_names[] = { "auto", "10baseT", "10base2"};
+
+
+/*====================================================================*/
+
+/* Module parameters */
+
+MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
+MODULE_DESCRIPTION("NE2000 compatible PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");
+
+#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
+
+INT_MODULE_PARM(if_port,       1);     /* Transceiver type */
+INT_MODULE_PARM(use_big_buf,   1);     /* use 64K packet buffer? */
+INT_MODULE_PARM(mem_speed,     0);     /* shared mem speed, in ns */
+INT_MODULE_PARM(delay_output,  0);     /* pause after xmit? */
+INT_MODULE_PARM(delay_time,    4);     /* in usec */
+INT_MODULE_PARM(use_shmem,     -1);    /* use shared memory? */
+INT_MODULE_PARM(full_duplex,   0);     /* full duplex? */
+
+/* Ugh!  Let the user hardwire the hardware address for queer cards */
+static int hw_addr[6] = { 0, /* ... */ };
+module_param_array(hw_addr, int, NULL, 0);
+
+/*====================================================================*/
+
+static void mii_phy_probe(struct net_device *dev);
+static int pcnet_config(struct pcmcia_device *link);
+static void pcnet_release(struct pcmcia_device *link);
+static int pcnet_open(struct net_device *dev);
+static int pcnet_close(struct net_device *dev);
+static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
+static void ei_watchdog(u_long arg);
+static void pcnet_reset_8390(struct net_device *dev);
+static int set_config(struct net_device *dev, struct ifmap *map);
+static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
+                             int stop_pg, int cm_offset);
+static int setup_dma_config(struct pcmcia_device *link, int start_pg,
+                           int stop_pg);
+
+static void pcnet_detach(struct pcmcia_device *p_dev);
+
+/*====================================================================*/
+
+typedef struct hw_info_t {
+    u_int      offset;
+    u_char     a0, a1, a2;
+    u_int      flags;
+} hw_info_t;
+
+#define DELAY_OUTPUT   0x01
+#define HAS_MISC_REG   0x02
+#define USE_BIG_BUF    0x04
+#define HAS_IBM_MISC   0x08
+#define IS_DL10019     0x10
+#define IS_DL10022     0x20
+#define HAS_MII                0x40
+#define USE_SHMEM      0x80    /* autodetected */
+
+#define AM79C9XX_HOME_PHY      0x00006B90  /* HomePNA PHY */
+#define AM79C9XX_ETH_PHY       0x00006B70  /* 10baseT PHY */
+#define MII_PHYID_REV_MASK     0xfffffff0
+#define MII_PHYID_REG1         0x02
+#define MII_PHYID_REG2         0x03
+
+static hw_info_t hw_info[] = {
+    { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT },
+    { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 },
+    { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 },
+    { /* ASANTE FriendlyNet */ 0x4910, 0x00, 0x00, 0x94,
+      DELAY_OUTPUT | HAS_IBM_MISC },
+    { /* Danpex EN-6200P2 */ 0x0110, 0x00, 0x40, 0xc7, 0 },
+    { /* DataTrek NetCard */ 0x0ff0, 0x00, 0x20, 0xe8, 0 },
+    { /* Dayna CommuniCard E */ 0x0110, 0x00, 0x80, 0x19, 0 },
+    { /* D-Link DE-650 */ 0x0040, 0x00, 0x80, 0xc8, 0 },
+    { /* EP-210 Ethernet */ 0x0110, 0x00, 0x40, 0x33, 0 },
+    { /* EP4000 Ethernet */ 0x01c0, 0x00, 0x00, 0xb4, 0 },
+    { /* Epson EEN10B */ 0x0ff0, 0x00, 0x00, 0x48,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* ELECOM Laneed LD-CDWA */ 0xb8, 0x08, 0x00, 0x42, 0 },
+    { /* Hypertec Ethernet */ 0x01c0, 0x00, 0x40, 0x4c, 0 },
+    { /* IBM CCAE */ 0x0ff0, 0x08, 0x00, 0x5a,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* IBM CCAE */ 0x0ff0, 0x00, 0x04, 0xac,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* IBM CCAE */ 0x0ff0, 0x00, 0x06, 0x29,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* IBM FME */ 0x0374, 0x08, 0x00, 0x5a,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* IBM FME */ 0x0374, 0x00, 0x04, 0xac,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* Kansai KLA-PCM/T */ 0x0ff0, 0x00, 0x60, 0x87,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* NSC DP83903 */ 0x0374, 0x08, 0x00, 0x17,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* NSC DP83903 */ 0x0374, 0x00, 0xc0, 0xa8,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* NSC DP83903 */ 0x0374, 0x00, 0xa0, 0xb0,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* NSC DP83903 */ 0x0198, 0x00, 0x20, 0xe0,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* I-O DATA PCLA/T */ 0x0ff0, 0x00, 0xa0, 0xb0, 0 },
+    { /* Katron PE-520 */ 0x0110, 0x00, 0x40, 0xf6, 0 },
+    { /* Kingston KNE-PCM/x */ 0x0ff0, 0x00, 0xc0, 0xf0,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* Kingston KNE-PCM/x */ 0x0ff0, 0xe2, 0x0c, 0x0f,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* Kingston KNE-PC2 */ 0x0180, 0x00, 0xc0, 0xf0, 0 },
+    { /* Maxtech PCN2000 */ 0x5000, 0x00, 0x00, 0xe8, 0 },
+    { /* NDC Instant-Link */ 0x003a, 0x00, 0x80, 0xc6, 0 },
+    { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 },
+    { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45,
+      HAS_MISC_REG | HAS_IBM_MISC },
+    { /* PreMax PE-200 */ 0x07f0, 0x00, 0x20, 0xe0, 0 },
+    { /* RPTI EP400 */ 0x0110, 0x00, 0x40, 0x95, 0 },
+    { /* SCM Ethernet */ 0x0ff0, 0x00, 0x20, 0xcb, 0 },
+    { /* Socket EA */ 0x4000, 0x00, 0xc0, 0x1b,
+      DELAY_OUTPUT | HAS_MISC_REG | USE_BIG_BUF },
+    { /* Socket LP-E CF+ */ 0x01c0, 0x00, 0xc0, 0x1b, 0 },
+    { /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 },
+    { /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 },
+    { /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 },
+    { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 }
+};
+
+#define NR_INFO                ARRAY_SIZE(hw_info)
+
+static hw_info_t default_info = { 0, 0, 0, 0, 0 };
+static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII };
+static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII };
+
+typedef struct pcnet_dev_t {
+       struct pcmcia_device    *p_dev;
+    u_int              flags;
+    void               __iomem *base;
+    struct timer_list  watchdog;
+    int                        stale, fast_poll;
+    u_char             phy_id;
+    u_char             eth_phy, pna_phy;
+    u_short            link_status;
+    u_long             mii_reset;
+} pcnet_dev_t;
+
+static inline pcnet_dev_t *PRIV(struct net_device *dev)
+{
+       char *p = netdev_priv(dev);
+       return (pcnet_dev_t *)(p + sizeof(struct ei_device));
+}
+
+static const struct net_device_ops pcnet_netdev_ops = {
+       .ndo_open               = pcnet_open,
+       .ndo_stop               = pcnet_close,
+       .ndo_set_config         = set_config,
+       .ndo_start_xmit         = ei_start_xmit,
+       .ndo_get_stats          = ei_get_stats,
+       .ndo_do_ioctl           = ei_ioctl,
+       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_tx_timeout         = ei_tx_timeout,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = ei_poll,
+#endif
+};
+
+static int pcnet_probe(struct pcmcia_device *link)
+{
+    pcnet_dev_t *info;
+    struct net_device *dev;
+
+    dev_dbg(&link->dev, "pcnet_attach()\n");
+
+    /* Create new ethernet device */
+    dev = __alloc_ei_netdev(sizeof(pcnet_dev_t));
+    if (!dev) return -ENOMEM;
+    info = PRIV(dev);
+    info->p_dev = link;
+    link->priv = dev;
+
+    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
+    dev->netdev_ops = &pcnet_netdev_ops;
+
+    return pcnet_config(link);
+} /* pcnet_attach */
+
+static void pcnet_detach(struct pcmcia_device *link)
+{
+       struct net_device *dev = link->priv;
+
+       dev_dbg(&link->dev, "pcnet_detach\n");
+
+       unregister_netdev(dev);
+
+       pcnet_release(link);
+
+       free_netdev(dev);
+} /* pcnet_detach */
+
+/*======================================================================
+
+    This probes for a card's hardware address, for card types that
+    encode this information in their CIS.
+
+======================================================================*/
+
+static hw_info_t *get_hwinfo(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    u_char __iomem *base, *virt;
+    int i, j;
+
+    /* Allocate a small memory window */
+    link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+    link->resource[2]->start = 0; link->resource[2]->end = 0;
+    i = pcmcia_request_window(link, link->resource[2], 0);
+    if (i != 0)
+       return NULL;
+
+    virt = ioremap(link->resource[2]->start,
+           resource_size(link->resource[2]));
+    for (i = 0; i < NR_INFO; i++) {
+       pcmcia_map_mem_page(link, link->resource[2],
+               hw_info[i].offset & ~(resource_size(link->resource[2])-1));
+       base = &virt[hw_info[i].offset & (resource_size(link->resource[2])-1)];
+       if ((readb(base+0) == hw_info[i].a0) &&
+           (readb(base+2) == hw_info[i].a1) &&
+           (readb(base+4) == hw_info[i].a2)) {
+               for (j = 0; j < 6; j++)
+                   dev->dev_addr[j] = readb(base + (j<<1));
+               break;
+       }
+    }
+
+    iounmap(virt);
+    j = pcmcia_release_window(link, link->resource[2]);
+    return (i < NR_INFO) ? hw_info+i : NULL;
+} /* get_hwinfo */
+
+/*======================================================================
+
+    This probes for a card's hardware address by reading the PROM.
+    It checks the address against a list of known types, then falls
+    back to a simple NE2000 clone signature check.
+
+======================================================================*/
+
+static hw_info_t *get_prom(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    unsigned int ioaddr = dev->base_addr;
+    u_char prom[32];
+    int i, j;
+
+    /* This is lifted straight from drivers/net/ne.c */
+    struct {
+       u_char value, offset;
+    } program_seq[] = {
+       {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+       {0x48,  EN0_DCFG},      /* Set byte-wide (0x48) access. */
+       {0x00,  EN0_RCNTLO},    /* Clear the count regs. */
+       {0x00,  EN0_RCNTHI},
+       {0x00,  EN0_IMR},       /* Mask completion irq. */
+       {0xFF,  EN0_ISR},
+       {E8390_RXOFF, EN0_RXCR},        /* 0x20  Set to monitor */
+       {E8390_TXOFF, EN0_TXCR},        /* 0x02  and loopback mode. */
+       {32,    EN0_RCNTLO},
+       {0x00,  EN0_RCNTHI},
+       {0x00,  EN0_RSARLO},    /* DMA starting at 0x0000. */
+       {0x00,  EN0_RSARHI},
+       {E8390_RREAD+E8390_START, E8390_CMD},
+    };
+
+    pcnet_reset_8390(dev);
+    mdelay(10);
+
+    for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+       outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
+
+    for (i = 0; i < 32; i++)
+       prom[i] = inb(ioaddr + PCNET_DATAPORT);
+    for (i = 0; i < NR_INFO; i++) {
+       if ((prom[0] == hw_info[i].a0) &&
+           (prom[2] == hw_info[i].a1) &&
+           (prom[4] == hw_info[i].a2))
+           break;
+    }
+    if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) {
+       for (j = 0; j < 6; j++)
+           dev->dev_addr[j] = prom[j<<1];
+       return (i < NR_INFO) ? hw_info+i : &default_info;
+    }
+    return NULL;
+} /* get_prom */
+
+/*======================================================================
+
+    For DL10019 based cards, like the Linksys EtherFast
+
+======================================================================*/
+
+static hw_info_t *get_dl10019(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    int i;
+    u_char sum;
+
+    for (sum = 0, i = 0x14; i < 0x1c; i++)
+       sum += inb_p(dev->base_addr + i);
+    if (sum != 0xff)
+       return NULL;
+    for (i = 0; i < 6; i++)
+       dev->dev_addr[i] = inb_p(dev->base_addr + 0x14 + i);
+    i = inb(dev->base_addr + 0x1f);
+    return ((i == 0x91)||(i == 0x99)) ? &dl10022_info : &dl10019_info;
+}
+
+/*======================================================================
+
+    For Asix AX88190 based cards
+
+======================================================================*/
+
+static hw_info_t *get_ax88190(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    unsigned int ioaddr = dev->base_addr;
+    int i, j;
+
+    /* Not much of a test, but the alternatives are messy */
+    if (link->config_base != 0x03c0)
+       return NULL;
+
+    outb_p(0x01, ioaddr + EN0_DCFG);   /* Set word-wide access. */
+    outb_p(0x00, ioaddr + EN0_RSARLO); /* DMA starting at 0x0400. */
+    outb_p(0x04, ioaddr + EN0_RSARHI);
+    outb_p(E8390_RREAD+E8390_START, ioaddr + E8390_CMD);
+
+    for (i = 0; i < 6; i += 2) {
+       j = inw(ioaddr + PCNET_DATAPORT);
+       dev->dev_addr[i] = j & 0xff;
+       dev->dev_addr[i+1] = j >> 8;
+    }
+    return NULL;
+}
+
+/*======================================================================
+
+    This should be totally unnecessary... but when we can't figure
+    out the hardware address any other way, we'll let the user hard
+    wire it when the module is initialized.
+
+======================================================================*/
+
+static hw_info_t *get_hwired(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    int i;
+
+    for (i = 0; i < 6; i++)
+       if (hw_addr[i] != 0) break;
+    if (i == 6)
+       return NULL;
+
+    for (i = 0; i < 6; i++)
+       dev->dev_addr[i] = hw_addr[i];
+
+    return &default_info;
+} /* get_hwired */
+
+static int try_io_port(struct pcmcia_device *link)
+{
+    int j, ret;
+    link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+    link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+    if (link->resource[0]->end == 32) {
+       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+       if (link->resource[1]->end > 0) {
+           /* for master/slave multifunction cards */
+           link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+       }
+    } else {
+       /* This should be two 16-port windows */
+       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+       link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
+    }
+    if (link->resource[0]->start == 0) {
+       for (j = 0; j < 0x400; j += 0x20) {
+           link->resource[0]->start = j ^ 0x300;
+           link->resource[1]->start = (j ^ 0x300) + 0x10;
+           link->io_lines = 16;
+           ret = pcmcia_request_io(link);
+           if (ret == 0)
+                   return ret;
+       }
+       return ret;
+    } else {
+       return pcmcia_request_io(link);
+    }
+}
+
+static int pcnet_confcheck(struct pcmcia_device *p_dev, void *priv_data)
+{
+       int *priv = priv_data;
+       int try = (*priv & 0x1);
+
+       *priv &= (p_dev->resource[2]->end >= 0x4000) ? 0x10 : ~0x10;
+
+       if (p_dev->config_index == 0)
+               return -EINVAL;
+
+       if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
+               return -EINVAL;
+
+       if (try)
+               p_dev->io_lines = 16;
+       return try_io_port(p_dev);
+}
+
+static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
+                                  int *has_shmem, int try)
+{
+       struct net_device *dev = link->priv;
+       hw_info_t *local_hw_info;
+       pcnet_dev_t *info = PRIV(dev);
+       int priv = try;
+       int ret;
+
+       ret = pcmcia_loop_config(link, pcnet_confcheck, &priv);
+       if (ret) {
+               dev_warn(&link->dev, "no useable port range found\n");
+               return NULL;
+       }
+       *has_shmem = (priv & 0x10);
+
+       if (!link->irq)
+               return NULL;
+
+       if (resource_size(link->resource[1]) == 8)
+               link->config_flags |= CONF_ENABLE_SPKR;
+
+       if ((link->manf_id == MANFID_IBM) &&
+           (link->card_id == PRODID_IBM_HOME_AND_AWAY))
+               link->config_index |= 0x10;
+
+       ret = pcmcia_enable_device(link);
+       if (ret)
+               return NULL;
+
+       dev->irq = link->irq;
+       dev->base_addr = link->resource[0]->start;
+
+       if (info->flags & HAS_MISC_REG) {
+               if ((if_port == 1) || (if_port == 2))
+                       dev->if_port = if_port;
+               else
+                       dev_notice(&link->dev, "invalid if_port requested\n");
+       } else
+               dev->if_port = 0;
+
+       if ((link->config_base == 0x03c0) &&
+           (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) {
+               dev_info(&link->dev,
+                       "this is an AX88190 card - use axnet_cs instead.\n");
+               return NULL;
+       }
+
+       local_hw_info = get_hwinfo(link);
+       if (!local_hw_info)
+               local_hw_info = get_prom(link);
+       if (!local_hw_info)
+               local_hw_info = get_dl10019(link);
+       if (!local_hw_info)
+               local_hw_info = get_ax88190(link);
+       if (!local_hw_info)
+               local_hw_info = get_hwired(link);
+
+       return local_hw_info;
+}
+
+static int pcnet_config(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    pcnet_dev_t *info = PRIV(dev);
+    int start_pg, stop_pg, cm_offset;
+    int has_shmem = 0;
+    hw_info_t *local_hw_info;
+
+    dev_dbg(&link->dev, "pcnet_config\n");
+
+    local_hw_info = pcnet_try_config(link, &has_shmem, 0);
+    if (!local_hw_info) {
+           /* check whether forcing io_lines to 16 helps... */
+           pcmcia_disable_device(link);
+           local_hw_info = pcnet_try_config(link, &has_shmem, 1);
+           if (local_hw_info == NULL) {
+                   dev_notice(&link->dev, "unable to read hardware net"
+                           " address for io base %#3lx\n", dev->base_addr);
+                   goto failed;
+           }
+    }
+
+    info->flags = local_hw_info->flags;
+    /* Check for user overrides */
+    info->flags |= (delay_output) ? DELAY_OUTPUT : 0;
+    if ((link->manf_id == MANFID_SOCKET) &&
+       ((link->card_id == PRODID_SOCKET_LPE) ||
+        (link->card_id == PRODID_SOCKET_LPE_CF) ||
+        (link->card_id == PRODID_SOCKET_EIO)))
+       info->flags &= ~USE_BIG_BUF;
+    if (!use_big_buf)
+       info->flags &= ~USE_BIG_BUF;
+
+    if (info->flags & USE_BIG_BUF) {
+       start_pg = SOCKET_START_PG;
+       stop_pg = SOCKET_STOP_PG;
+       cm_offset = 0x10000;
+    } else {
+       start_pg = PCNET_START_PG;
+       stop_pg = PCNET_STOP_PG;
+       cm_offset = 0;
+    }
+
+    /* has_shmem is ignored if use_shmem != -1 */
+    if ((use_shmem == 0) || (!has_shmem && (use_shmem == -1)) ||
+       (setup_shmem_window(link, start_pg, stop_pg, cm_offset) != 0))
+       setup_dma_config(link, start_pg, stop_pg);
+
+    ei_status.name = "NE2000";
+    ei_status.word16 = 1;
+    ei_status.reset_8390 = pcnet_reset_8390;
+
+    if (info->flags & (IS_DL10019|IS_DL10022))
+       mii_phy_probe(dev);
+
+    SET_NETDEV_DEV(dev, &link->dev);
+
+    if (register_netdev(dev) != 0) {
+       pr_notice("register_netdev() failed\n");
+       goto failed;
+    }
+
+    if (info->flags & (IS_DL10019|IS_DL10022)) {
+       u_char id = inb(dev->base_addr + 0x1a);
+       netdev_info(dev, "NE2000 (DL100%d rev %02x): ",
+              (info->flags & IS_DL10022) ? 22 : 19, id);
+       if (info->pna_phy)
+           pr_cont("PNA, ");
+    } else {
+       netdev_info(dev, "NE2000 Compatible: ");
+    }
+    pr_cont("io %#3lx, irq %d,", dev->base_addr, dev->irq);
+    if (info->flags & USE_SHMEM)
+       pr_cont(" mem %#5lx,", dev->mem_start);
+    if (info->flags & HAS_MISC_REG)
+       pr_cont(" %s xcvr,", if_names[dev->if_port]);
+    pr_cont(" hw_addr %pM\n", dev->dev_addr);
+    return 0;
+
+failed:
+    pcnet_release(link);
+    return -ENODEV;
+} /* pcnet_config */
+
+static void pcnet_release(struct pcmcia_device *link)
+{
+       pcnet_dev_t *info = PRIV(link->priv);
+
+       dev_dbg(&link->dev, "pcnet_release\n");
+
+       if (info->flags & USE_SHMEM)
+               iounmap(info->base);
+
+       pcmcia_disable_device(link);
+}
+
+static int pcnet_suspend(struct pcmcia_device *link)
+{
+       struct net_device *dev = link->priv;
+
+       if (link->open)
+               netif_device_detach(dev);
+
+       return 0;
+}
+
+static int pcnet_resume(struct pcmcia_device *link)
+{
+       struct net_device *dev = link->priv;
+
+       if (link->open) {
+               pcnet_reset_8390(dev);
+               NS8390_init(dev, 1);
+               netif_device_attach(dev);
+       }
+
+       return 0;
+}
+
+
+/*======================================================================
+
+    MII interface support for DL10019 and DL10022 based cards
+
+    On the DL10019, the MII IO direction bit is 0x10; on the DL10022
+    it is 0x20.  Setting both bits seems to work on both card types.
+
+======================================================================*/
+
+#define DLINK_GPIO             0x1c
+#define DLINK_DIAG             0x1d
+#define DLINK_EEPROM           0x1e
+
+#define MDIO_SHIFT_CLK         0x80
+#define MDIO_DATA_OUT          0x40
+#define MDIO_DIR_WRITE         0x30
+#define MDIO_DATA_WRITE0       (MDIO_DIR_WRITE)
+#define MDIO_DATA_WRITE1       (MDIO_DIR_WRITE | MDIO_DATA_OUT)
+#define MDIO_DATA_READ         0x10
+#define MDIO_MASK              0x0f
+
+static void mdio_sync(unsigned int addr)
+{
+    int bits, mask = inb(addr) & MDIO_MASK;
+    for (bits = 0; bits < 32; bits++) {
+       outb(mask | MDIO_DATA_WRITE1, addr);
+       outb(mask | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
+    }
+}
+
+static int mdio_read(unsigned int addr, int phy_id, int loc)
+{
+    u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
+    int i, retval = 0, mask = inb(addr) & MDIO_MASK;
+
+    mdio_sync(addr);
+    for (i = 13; i >= 0; i--) {
+       int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+       outb(mask | dat, addr);
+       outb(mask | dat | MDIO_SHIFT_CLK, addr);
+    }
+    for (i = 19; i > 0; i--) {
+       outb(mask, addr);
+       retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0);
+       outb(mask | MDIO_SHIFT_CLK, addr);
+    }
+    return (retval>>1) & 0xffff;
+}
+
+static void mdio_write(unsigned int addr, int phy_id, int loc, int value)
+{
+    u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
+    int i, mask = inb(addr) & MDIO_MASK;
+
+    mdio_sync(addr);
+    for (i = 31; i >= 0; i--) {
+       int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+       outb(mask | dat, addr);
+       outb(mask | dat | MDIO_SHIFT_CLK, addr);
+    }
+    for (i = 1; i >= 0; i--) {
+       outb(mask, addr);
+       outb(mask | MDIO_SHIFT_CLK, addr);
+    }
+}
+
+/*======================================================================
+
+    EEPROM access routines for DL10019 and DL10022 based cards
+
+======================================================================*/
+
+#define EE_EEP         0x40
+#define EE_ASIC                0x10
+#define EE_CS          0x08
+#define EE_CK          0x04
+#define EE_DO          0x02
+#define EE_DI          0x01
+#define EE_ADOT                0x01    /* DataOut for ASIC */
+#define EE_READ_CMD    0x06
+
+#define DL19FDUPLX     0x0400  /* DL10019 Full duplex mode */
+
+static int read_eeprom(unsigned int ioaddr, int location)
+{
+    int i, retval = 0;
+    unsigned int ee_addr = ioaddr + DLINK_EEPROM;
+    int read_cmd = location | (EE_READ_CMD << 8);
+
+    outb(0, ee_addr);
+    outb(EE_EEP|EE_CS, ee_addr);
+
+    /* Shift the read command bits out. */
+    for (i = 10; i >= 0; i--) {
+       short dataval = (read_cmd & (1 << i)) ? EE_DO : 0;
+       outb_p(EE_EEP|EE_CS|dataval, ee_addr);
+       outb_p(EE_EEP|EE_CS|dataval|EE_CK, ee_addr);
+    }
+    outb(EE_EEP|EE_CS, ee_addr);
+
+    for (i = 16; i > 0; i--) {
+       outb_p(EE_EEP|EE_CS | EE_CK, ee_addr);
+       retval = (retval << 1) | ((inb(ee_addr) & EE_DI) ? 1 : 0);
+       outb_p(EE_EEP|EE_CS, ee_addr);
+    }
+
+    /* Terminate the EEPROM access. */
+    outb(0, ee_addr);
+    return retval;
+}
+
+/*
+    The internal ASIC registers can be changed by EEPROM READ access
+    with EE_ASIC bit set.
+    In ASIC mode, EE_ADOT is used to output the data to the ASIC.
+*/
+
+static void write_asic(unsigned int ioaddr, int location, short asic_data)
+{
+       int i;
+       unsigned int ee_addr = ioaddr + DLINK_EEPROM;
+       short dataval;
+       int read_cmd = location | (EE_READ_CMD << 8);
+
+       asic_data |= read_eeprom(ioaddr, location);
+
+       outb(0, ee_addr);
+       outb(EE_ASIC|EE_CS|EE_DI, ee_addr);
+
+       read_cmd = read_cmd >> 1;
+
+       /* Shift the read command bits out. */
+       for (i = 9; i >= 0; i--) {
+               dataval = (read_cmd & (1 << i)) ? EE_DO : 0;
+               outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr);
+               outb_p(EE_ASIC|EE_CS|EE_DI|dataval|EE_CK, ee_addr);
+               outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr);
+       }
+       // sync
+       outb(EE_ASIC|EE_CS, ee_addr);
+       outb(EE_ASIC|EE_CS|EE_CK, ee_addr);
+       outb(EE_ASIC|EE_CS, ee_addr);
+
+       for (i = 15; i >= 0; i--) {
+               dataval = (asic_data & (1 << i)) ? EE_ADOT : 0;
+               outb_p(EE_ASIC|EE_CS|dataval, ee_addr);
+               outb_p(EE_ASIC|EE_CS|dataval|EE_CK, ee_addr);
+               outb_p(EE_ASIC|EE_CS|dataval, ee_addr);
+       }
+
+       /* Terminate the ASIC access. */
+       outb(EE_ASIC|EE_DI, ee_addr);
+       outb(EE_ASIC|EE_DI| EE_CK, ee_addr);
+       outb(EE_ASIC|EE_DI, ee_addr);
+
+       outb(0, ee_addr);
+}
+
+/*====================================================================*/
+
+static void set_misc_reg(struct net_device *dev)
+{
+    unsigned int nic_base = dev->base_addr;
+    pcnet_dev_t *info = PRIV(dev);
+    u_char tmp;
+
+    if (info->flags & HAS_MISC_REG) {
+       tmp = inb_p(nic_base + PCNET_MISC) & ~3;
+       if (dev->if_port == 2)
+           tmp |= 1;
+       if (info->flags & USE_BIG_BUF)
+           tmp |= 2;
+       if (info->flags & HAS_IBM_MISC)
+           tmp |= 8;
+       outb_p(tmp, nic_base + PCNET_MISC);
+    }
+    if (info->flags & IS_DL10022) {
+       if (info->flags & HAS_MII) {
+           /* Advertise 100F, 100H, 10F, 10H */
+           mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1);
+           /* Restart MII autonegotiation */
+           mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000);
+           mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200);
+           info->mii_reset = jiffies;
+       } else {
+           outb(full_duplex ? 4 : 0, nic_base + DLINK_DIAG);
+       }
+    } else if (info->flags & IS_DL10019) {
+       /* Advertise 100F, 100H, 10F, 10H */
+       mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1);
+       /* Restart MII autonegotiation */
+       mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000);
+       mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200);
+    }
+}
+
+/*====================================================================*/
+
+static void mii_phy_probe(struct net_device *dev)
+{
+    pcnet_dev_t *info = PRIV(dev);
+    unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
+    int i;
+    u_int tmp, phyid;
+
+    for (i = 31; i >= 0; i--) {
+       tmp = mdio_read(mii_addr, i, 1);
+       if ((tmp == 0) || (tmp == 0xffff))
+           continue;
+       tmp = mdio_read(mii_addr, i, MII_PHYID_REG1);
+       phyid = tmp << 16;
+       phyid |= mdio_read(mii_addr, i, MII_PHYID_REG2);
+       phyid &= MII_PHYID_REV_MASK;
+       netdev_dbg(dev, "MII at %d is 0x%08x\n", i, phyid);
+       if (phyid == AM79C9XX_HOME_PHY) {
+           info->pna_phy = i;
+       } else if (phyid != AM79C9XX_ETH_PHY) {
+           info->eth_phy = i;
+       }
+    }
+}
+
+static int pcnet_open(struct net_device *dev)
+{
+    int ret;
+    pcnet_dev_t *info = PRIV(dev);
+    struct pcmcia_device *link = info->p_dev;
+    unsigned int nic_base = dev->base_addr;
+
+    dev_dbg(&link->dev, "pcnet_open('%s')\n", dev->name);
+
+    if (!pcmcia_dev_present(link))
+       return -ENODEV;
+
+    set_misc_reg(dev);
+
+    outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */
+    ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev->name, dev);
+    if (ret)
+           return ret;
+
+    link->open++;
+
+    info->phy_id = info->eth_phy;
+    info->link_status = 0x00;
+    init_timer(&info->watchdog);
+    info->watchdog.function = ei_watchdog;
+    info->watchdog.data = (u_long)dev;
+    info->watchdog.expires = jiffies + HZ;
+    add_timer(&info->watchdog);
+
+    return ei_open(dev);
+} /* pcnet_open */
+
+/*====================================================================*/
+
+static int pcnet_close(struct net_device *dev)
+{
+    pcnet_dev_t *info = PRIV(dev);
+    struct pcmcia_device *link = info->p_dev;
+
+    dev_dbg(&link->dev, "pcnet_close('%s')\n", dev->name);
+
+    ei_close(dev);
+    free_irq(dev->irq, dev);
+
+    link->open--;
+    netif_stop_queue(dev);
+    del_timer_sync(&info->watchdog);
+
+    return 0;
+} /* pcnet_close */
+
+/*======================================================================
+
+    Hard reset the card.  This used to pause for the same period that
+    a 8390 reset command required, but that shouldn't be necessary.
+
+======================================================================*/
+
+static void pcnet_reset_8390(struct net_device *dev)
+{
+    unsigned int nic_base = dev->base_addr;
+    int i;
+
+    ei_status.txing = ei_status.dmaing = 0;
+
+    outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, nic_base + E8390_CMD);
+
+    outb(inb(nic_base + PCNET_RESET), nic_base + PCNET_RESET);
+
+    for (i = 0; i < 100; i++) {
+       if ((inb_p(nic_base+EN0_ISR) & ENISR_RESET) != 0)
+           break;
+       udelay(100);
+    }
+    outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
+
+    if (i == 100)
+       netdev_err(dev, "pcnet_reset_8390() did not complete.\n");
+
+    set_misc_reg(dev);
+
+} /* pcnet_reset_8390 */
+
+/*====================================================================*/
+
+static int set_config(struct net_device *dev, struct ifmap *map)
+{
+    pcnet_dev_t *info = PRIV(dev);
+    if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
+       if (!(info->flags & HAS_MISC_REG))
+           return -EOPNOTSUPP;
+       else if ((map->port < 1) || (map->port > 2))
+           return -EINVAL;
+       dev->if_port = map->port;
+       netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
+       NS8390_init(dev, 1);
+    }
+    return 0;
+}
+
+/*====================================================================*/
+
+static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
+{
+    struct net_device *dev = dev_id;
+    pcnet_dev_t *info;
+    irqreturn_t ret = ei_interrupt(irq, dev_id);
+
+    if (ret == IRQ_HANDLED) {
+           info = PRIV(dev);
+           info->stale = 0;
+    }
+    return ret;
+}
+
+static void ei_watchdog(u_long arg)
+{
+    struct net_device *dev = (struct net_device *)arg;
+    pcnet_dev_t *info = PRIV(dev);
+    unsigned int nic_base = dev->base_addr;
+    unsigned int mii_addr = nic_base + DLINK_GPIO;
+    u_short link;
+
+    if (!netif_device_present(dev)) goto reschedule;
+
+    /* Check for pending interrupt with expired latency timer: with
+       this, we can limp along even if the interrupt is blocked */
+    if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
+       if (!info->fast_poll)
+           netdev_info(dev, "interrupt(s) dropped!\n");
+       ei_irq_wrapper(dev->irq, dev);
+       info->fast_poll = HZ;
+    }
+    if (info->fast_poll) {
+       info->fast_poll--;
+       info->watchdog.expires = jiffies + 1;
+       add_timer(&info->watchdog);
+       return;
+    }
+
+    if (!(info->flags & HAS_MII))
+       goto reschedule;
+
+    mdio_read(mii_addr, info->phy_id, 1);
+    link = mdio_read(mii_addr, info->phy_id, 1);
+    if (!link || (link == 0xffff)) {
+       if (info->eth_phy) {
+           info->phy_id = info->eth_phy = 0;
+       } else {
+           netdev_info(dev, "MII is missing!\n");
+           info->flags &= ~HAS_MII;
+       }
+       goto reschedule;
+    }
+
+    link &= 0x0004;
+    if (link != info->link_status) {
+       u_short p = mdio_read(mii_addr, info->phy_id, 5);
+       netdev_info(dev, "%s link beat\n", link ? "found" : "lost");
+       if (link && (info->flags & IS_DL10022)) {
+           /* Disable collision detection on full duplex links */
+           outb((p & 0x0140) ? 4 : 0, nic_base + DLINK_DIAG);
+       } else if (link && (info->flags & IS_DL10019)) {
+           /* Disable collision detection on full duplex links */
+           write_asic(dev->base_addr, 4, (p & 0x140) ? DL19FDUPLX : 0);
+       }
+       if (link) {
+           if (info->phy_id == info->eth_phy) {
+               if (p)
+                   netdev_info(dev, "autonegotiation complete: "
+                          "%sbaseT-%cD selected\n",
+                          ((p & 0x0180) ? "100" : "10"),
+                          ((p & 0x0140) ? 'F' : 'H'));
+               else
+                   netdev_info(dev, "link partner did not autonegotiate\n");
+           }
+           NS8390_init(dev, 1);
+       }
+       info->link_status = link;
+    }
+    if (info->pna_phy && time_after(jiffies, info->mii_reset + 6*HZ)) {
+       link = mdio_read(mii_addr, info->eth_phy, 1) & 0x0004;
+       if (((info->phy_id == info->pna_phy) && link) ||
+           ((info->phy_id != info->pna_phy) && !link)) {
+           /* isolate this MII and try flipping to the other one */
+           mdio_write(mii_addr, info->phy_id, 0, 0x0400);
+           info->phy_id ^= info->pna_phy ^ info->eth_phy;
+           netdev_info(dev, "switched to %s transceiver\n",
+                  (info->phy_id == info->eth_phy) ? "ethernet" : "PNA");
+           mdio_write(mii_addr, info->phy_id, 0,
+                      (info->phy_id == info->eth_phy) ? 0x1000 : 0);
+           info->link_status = 0;
+           info->mii_reset = jiffies;
+       }
+    }
+
+reschedule:
+    info->watchdog.expires = jiffies + HZ;
+    add_timer(&info->watchdog);
+}
+
+/*====================================================================*/
+
+
+static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+    pcnet_dev_t *info = PRIV(dev);
+    struct mii_ioctl_data *data = if_mii(rq);
+    unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
+
+    if (!(info->flags & (IS_DL10019|IS_DL10022)))
+       return -EINVAL;
+
+    switch (cmd) {
+    case SIOCGMIIPHY:
+       data->phy_id = info->phy_id;
+    case SIOCGMIIREG:          /* Read MII PHY register. */
+       data->val_out = mdio_read(mii_addr, data->phy_id, data->reg_num & 0x1f);
+       return 0;
+    case SIOCSMIIREG:          /* Write MII PHY register. */
+       mdio_write(mii_addr, data->phy_id, data->reg_num & 0x1f, data->val_in);
+       return 0;
+    }
+    return -EOPNOTSUPP;
+}
+
+/*====================================================================*/
+
+static void dma_get_8390_hdr(struct net_device *dev,
+                            struct e8390_pkt_hdr *hdr,
+                            int ring_page)
+{
+    unsigned int nic_base = dev->base_addr;
+
+    if (ei_status.dmaing) {
+       netdev_notice(dev, "DMAing conflict in dma_block_input."
+              "[DMAstat:%1x][irqlock:%1x]\n",
+              ei_status.dmaing, ei_status.irqlock);
+       return;
+    }
+
+    ei_status.dmaing |= 0x01;
+    outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD);
+    outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+    outb_p(0, nic_base + EN0_RCNTHI);
+    outb_p(0, nic_base + EN0_RSARLO);          /* On page boundary */
+    outb_p(ring_page, nic_base + EN0_RSARHI);
+    outb_p(E8390_RREAD+E8390_START, nic_base + PCNET_CMD);
+
+    insw(nic_base + PCNET_DATAPORT, hdr,
+           sizeof(struct e8390_pkt_hdr)>>1);
+    /* Fix for big endian systems */
+    hdr->count = le16_to_cpu(hdr->count);
+
+    outb_p(ENISR_RDC, nic_base + EN0_ISR);     /* Ack intr. */
+    ei_status.dmaing &= ~0x01;
+}
+
+/*====================================================================*/
+
+static void dma_block_input(struct net_device *dev, int count,
+                           struct sk_buff *skb, int ring_offset)
+{
+    unsigned int nic_base = dev->base_addr;
+    int xfer_count = count;
+    char *buf = skb->data;
+
+    if ((ei_debug > 4) && (count != 4))
+       netdev_dbg(dev, "[bi=%d]\n", count+4);
+    if (ei_status.dmaing) {
+       netdev_notice(dev, "DMAing conflict in dma_block_input."
+              "[DMAstat:%1x][irqlock:%1x]\n",
+              ei_status.dmaing, ei_status.irqlock);
+       return;
+    }
+    ei_status.dmaing |= 0x01;
+    outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD);
+    outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+    outb_p(count >> 8, nic_base + EN0_RCNTHI);
+    outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+    outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+    outb_p(E8390_RREAD+E8390_START, nic_base + PCNET_CMD);
+
+    insw(nic_base + PCNET_DATAPORT,buf,count>>1);
+    if (count & 0x01)
+       buf[count-1] = inb(nic_base + PCNET_DATAPORT), xfer_count++;
+
+    /* This was for the ALPHA version only, but enough people have been
+       encountering problems that it is still here. */
+#ifdef PCMCIA_DEBUG
+    if (ei_debug > 4) {                /* DMA termination address check... */
+       int addr, tries = 20;
+       do {
+           /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
+              -- it's broken for Rx on some cards! */
+           int high = inb_p(nic_base + EN0_RSARHI);
+           int low = inb_p(nic_base + EN0_RSARLO);
+           addr = (high << 8) + low;
+           if (((ring_offset + xfer_count) & 0xff) == (addr & 0xff))
+               break;
+       } while (--tries > 0);
+       if (tries <= 0)
+           netdev_notice(dev, "RX transfer address mismatch,"
+                  "%#4.4x (expected) vs. %#4.4x (actual).\n",
+                  ring_offset + xfer_count, addr);
+    }
+#endif
+    outb_p(ENISR_RDC, nic_base + EN0_ISR);     /* Ack intr. */
+    ei_status.dmaing &= ~0x01;
+} /* dma_block_input */
+
+/*====================================================================*/
+
+static void dma_block_output(struct net_device *dev, int count,
+                            const u_char *buf, const int start_page)
+{
+    unsigned int nic_base = dev->base_addr;
+    pcnet_dev_t *info = PRIV(dev);
+#ifdef PCMCIA_DEBUG
+    int retries = 0;
+#endif
+    u_long dma_start;
+
+#ifdef PCMCIA_DEBUG
+    if (ei_debug > 4)
+       netdev_dbg(dev, "[bo=%d]\n", count);
+#endif
+
+    /* Round the count up for word writes.  Do we need to do this?
+       What effect will an odd byte count have on the 8390?
+       I should check someday. */
+    if (count & 0x01)
+       count++;
+    if (ei_status.dmaing) {
+       netdev_notice(dev, "DMAing conflict in dma_block_output."
+              "[DMAstat:%1x][irqlock:%1x]\n",
+              ei_status.dmaing, ei_status.irqlock);
+       return;
+    }
+    ei_status.dmaing |= 0x01;
+    /* We should already be in page 0, but to be safe... */
+    outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base+PCNET_CMD);
+
+#ifdef PCMCIA_DEBUG
+  retry:
+#endif
+
+    outb_p(ENISR_RDC, nic_base + EN0_ISR);
+
+    /* Now the normal output. */
+    outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+    outb_p(count >> 8,   nic_base + EN0_RCNTHI);
+    outb_p(0x00, nic_base + EN0_RSARLO);
+    outb_p(start_page, nic_base + EN0_RSARHI);
+
+    outb_p(E8390_RWRITE+E8390_START, nic_base + PCNET_CMD);
+    outsw(nic_base + PCNET_DATAPORT, buf, count>>1);
+
+    dma_start = jiffies;
+
+#ifdef PCMCIA_DEBUG
+    /* This was for the ALPHA version only, but enough people have been
+       encountering problems that it is still here. */
+    if (ei_debug > 4) {        /* DMA termination address check... */
+       int addr, tries = 20;
+       do {
+           int high = inb_p(nic_base + EN0_RSARHI);
+           int low = inb_p(nic_base + EN0_RSARLO);
+           addr = (high << 8) + low;
+           if ((start_page << 8) + count == addr)
+               break;
+       } while (--tries > 0);
+       if (tries <= 0) {
+           netdev_notice(dev, "Tx packet transfer address mismatch,"
+                  "%#4.4x (expected) vs. %#4.4x (actual).\n",
+                  (start_page << 8) + count, addr);
+           if (retries++ == 0)
+               goto retry;
+       }
+    }
+#endif
+
+    while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
+       if (time_after(jiffies, dma_start + PCNET_RDC_TIMEOUT)) {
+           netdev_notice(dev, "timeout waiting for Tx RDC.\n");
+           pcnet_reset_8390(dev);
+           NS8390_init(dev, 1);
+           break;
+       }
+
+    outb_p(ENISR_RDC, nic_base + EN0_ISR);     /* Ack intr. */
+    if (info->flags & DELAY_OUTPUT)
+       udelay((long)delay_time);
+    ei_status.dmaing &= ~0x01;
+}
+
+/*====================================================================*/
+
+static int setup_dma_config(struct pcmcia_device *link, int start_pg,
+                           int stop_pg)
+{
+    struct net_device *dev = link->priv;
+
+    ei_status.tx_start_page = start_pg;
+    ei_status.rx_start_page = start_pg + TX_PAGES;
+    ei_status.stop_page = stop_pg;
+
+    /* set up block i/o functions */
+    ei_status.get_8390_hdr = dma_get_8390_hdr;
+    ei_status.block_input = dma_block_input;
+    ei_status.block_output = dma_block_output;
+
+    return 0;
+}
+
+/*====================================================================*/
+
+static void copyin(void *dest, void __iomem *src, int c)
+{
+    u_short *d = dest;
+    u_short __iomem *s = src;
+    int odd;
+
+    if (c <= 0)
+       return;
+    odd = (c & 1); c >>= 1;
+
+    if (c) {
+       do { *d++ = __raw_readw(s++); } while (--c);
+    }
+    /* get last byte by fetching a word and masking */
+    if (odd)
+       *((u_char *)d) = readw(s) & 0xff;
+}
+
+static void copyout(void __iomem *dest, const void *src, int c)
+{
+    u_short __iomem *d = dest;
+    const u_short *s = src;
+    int odd;
+
+    if (c <= 0)
+       return;
+    odd = (c & 1); c >>= 1;
+
+    if (c) {
+       do { __raw_writew(*s++, d++); } while (--c);
+    }
+    /* copy last byte doing a read-modify-write */
+    if (odd)
+       writew((readw(d) & 0xff00) | *(u_char *)s, d);
+}
+
+/*====================================================================*/
+
+static void shmem_get_8390_hdr(struct net_device *dev,
+                              struct e8390_pkt_hdr *hdr,
+                              int ring_page)
+{
+    void __iomem *xfer_start = ei_status.mem + (TX_PAGES<<8)
+                               + (ring_page << 8)
+                               - (ei_status.rx_start_page << 8);
+
+    copyin(hdr, xfer_start, sizeof(struct e8390_pkt_hdr));
+    /* Fix for big endian systems */
+    hdr->count = le16_to_cpu(hdr->count);
+}
+
+/*====================================================================*/
+
+static void shmem_block_input(struct net_device *dev, int count,
+                             struct sk_buff *skb, int ring_offset)
+{
+    void __iomem *base = ei_status.mem;
+    unsigned long offset = (TX_PAGES<<8) + ring_offset
+                               - (ei_status.rx_start_page << 8);
+    char *buf = skb->data;
+
+    if (offset + count > ei_status.priv) {
+       /* We must wrap the input move. */
+       int semi_count = ei_status.priv - offset;
+       copyin(buf, base + offset, semi_count);
+       buf += semi_count;
+       offset = TX_PAGES<<8;
+       count -= semi_count;
+    }
+    copyin(buf, base + offset, count);
+}
+
+/*====================================================================*/
+
+static void shmem_block_output(struct net_device *dev, int count,
+                              const u_char *buf, const int start_page)
+{
+    void __iomem *shmem = ei_status.mem + (start_page << 8);
+    shmem -= ei_status.tx_start_page << 8;
+    copyout(shmem, buf, count);
+}
+
+/*====================================================================*/
+
+static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
+                             int stop_pg, int cm_offset)
+{
+    struct net_device *dev = link->priv;
+    pcnet_dev_t *info = PRIV(dev);
+    int i, window_size, offset, ret;
+
+    window_size = (stop_pg - start_pg) << 8;
+    if (window_size > 32 * 1024)
+       window_size = 32 * 1024;
+
+    /* Make sure it's a power of two.  */
+    window_size = roundup_pow_of_two(window_size);
+
+    /* Allocate a memory window */
+    link->resource[3]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+    link->resource[3]->flags |= WIN_USE_WAIT;
+    link->resource[3]->start = 0; link->resource[3]->end = window_size;
+    ret = pcmcia_request_window(link, link->resource[3], mem_speed);
+    if (ret)
+           goto failed;
+
+    offset = (start_pg << 8) + cm_offset;
+    offset -= offset % window_size;
+    ret = pcmcia_map_mem_page(link, link->resource[3], offset);
+    if (ret)
+           goto failed;
+
+    /* Try scribbling on the buffer */
+    info->base = ioremap(link->resource[3]->start,
+                       resource_size(link->resource[3]));
+    for (i = 0; i < (TX_PAGES<<8); i += 2)
+       __raw_writew((i>>1), info->base+offset+i);
+    udelay(100);
+    for (i = 0; i < (TX_PAGES<<8); i += 2)
+       if (__raw_readw(info->base+offset+i) != (i>>1)) break;
+    pcnet_reset_8390(dev);
+    if (i != (TX_PAGES<<8)) {
+       iounmap(info->base);
+       pcmcia_release_window(link, link->resource[3]);
+       info->base = NULL;
+       goto failed;
+    }
+
+    ei_status.mem = info->base + offset;
+    ei_status.priv = resource_size(link->resource[3]);
+    dev->mem_start = (u_long)ei_status.mem;
+    dev->mem_end = dev->mem_start + resource_size(link->resource[3]);
+
+    ei_status.tx_start_page = start_pg;
+    ei_status.rx_start_page = start_pg + TX_PAGES;
+    ei_status.stop_page = start_pg + (
+           (resource_size(link->resource[3]) - offset) >> 8);
+
+    /* set up block i/o functions */
+    ei_status.get_8390_hdr = shmem_get_8390_hdr;
+    ei_status.block_input = shmem_block_input;
+    ei_status.block_output = shmem_block_output;
+
+    info->flags |= USE_SHMEM;
+    return 0;
+
+failed:
+    return 1;
+}
+
+/*====================================================================*/
+
+static const struct pcmcia_device_id pcnet_ids[] = {
+       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0057, 0x0021),
+       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0104, 0x000a),
+       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0xea15),
+       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0x3341),
+       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0xc0ab),
+       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x021b, 0x0101),
+       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x08a1, 0xc0ab),
+       PCMCIA_PFC_DEVICE_PROD_ID12(0, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
+       PCMCIA_PFC_DEVICE_PROD_ID12(0, "ATKK", "LM33-PCM-T", 0xba9eb7e2, 0x077c174e),
+       PCMCIA_PFC_DEVICE_PROD_ID12(0, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
+       PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
+       PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
+       PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
+       PCMCIA_PFC_DEVICE_PROD_ID12(0, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
+       PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
+       PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
+       PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card       ", 0xb569a6e5, 0x5bd4ff2c),
+       PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3),
+       PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15),
+       PCMCIA_MFC_DEVICE_PROD_ID123(0, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f),
+       PCMCIA_MFC_DEVICE_PROD_ID2(0, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
+       PCMCIA_DEVICE_MANF_CARD(0x0057, 0x1004),
+       PCMCIA_DEVICE_MANF_CARD(0x0104, 0x000d),
+       PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0075),
+       PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0145),
+       PCMCIA_DEVICE_MANF_CARD(0x0149, 0x0230),
+       PCMCIA_DEVICE_MANF_CARD(0x0149, 0x4530),
+       PCMCIA_DEVICE_MANF_CARD(0x0149, 0xc1ab),
+       PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0110),
+       PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x8041),
+       PCMCIA_DEVICE_MANF_CARD(0x0213, 0x2452),
+       PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0300),
+       PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0307),
+       PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030a),
+       PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103),
+       PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121),
+       PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941),
+       PCMCIA_DEVICE_PROD_ID1234("Socket", "CF 10/100 Ethernet Card", "Revision B", "05/11/06", 0xb38bcc2e, 0x4de88352, 0xeaca6c8d, 0x7e57c22e),
+       PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b),
+       PCMCIA_DEVICE_PROD_ID123("CNet  ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b),
+       PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e),
+       PCMCIA_DEVICE_PROD_ID123("Edimax Technology Inc.", "PCMCIA", "Ethernet Card", 0x738a0019, 0x281f1c5d, 0x5e9d92c0),
+       PCMCIA_DEVICE_PROD_ID123("EFA   ", "EFA207", "ETHERNET", 0x3d294be4, 0xeb9aab6c, 0x3ff7175b),
+       PCMCIA_DEVICE_PROD_ID123("I-O DATA", "PCLA", "ETHERNET", 0x1d55d7ec, 0xe4c64d34, 0x3ff7175b),
+       PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCLATE", "ETHERNET", 0x547e66dc, 0x6b260753, 0x3ff7175b),
+       PCMCIA_DEVICE_PROD_ID123("KingMax Technology Inc.", "EN10-T2", "PCMCIA Ethernet Card", 0x932b7189, 0x699e4436, 0x6f6652e0),
+       PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2216", 0x281f1c5d, 0xd4cd2f20, 0xb87add82),
+       PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2620", 0x281f1c5d, 0xd4cd2f20, 0x7d3d83a8),
+       PCMCIA_DEVICE_PROD_ID1("2412LAN", 0x67f236ab),
+       PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2212", 0xdfc6b5b2, 0xcb112a11),
+       PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2216-PCMCIA-ETHERNET", 0xdfc6b5b2, 0x5542bfff),
+       PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA100-PCM-T V2 100/10M LAN PC Card", 0xbb7fbdd7, 0xcd91cc68),
+       PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA100-PCM V2", 0x36634a66, 0xc6d05997),
+       PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA-PCM_V2", 0xbb7fBdd7, 0x28e299f8),
+       PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA-PCM V3", 0x36634a66, 0x62241d96),
+       PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8010", 0x5070a7f9, 0x82f96e96),
+       PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8610", 0x5070a7f9, 0x86741224),
+       PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002", 0x93b15570, 0x75ec3efb),
+       PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002T", 0x93b15570, 0x461c5247),
+       PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8010", 0x93b15570, 0x82f96e96),
+       PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet", 0x578ba6e7, 0x0a9888c1),
+       PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet 10/100", 0x578ba6e7, 0x939fedbd),
+       PCMCIA_DEVICE_PROD_ID12("AROWANA", "PCMCIA Ethernet LAN Card", 0x313adbc8, 0x08d9f190),
+       PCMCIA_DEVICE_PROD_ID12("ASANTE", "FriendlyNet PC Card", 0x3a7ade0f, 0x41c64504),
+       PCMCIA_DEVICE_PROD_ID12("Billionton", "LNT-10TB", 0x552ab682, 0xeeb1ba6a),
+       PCMCIA_DEVICE_PROD_ID12("CF", "10Base-Ethernet", 0x44ebf863, 0x93ae4d79),
+       PCMCIA_DEVICE_PROD_ID12("CNet", "CN40BC Ethernet", 0xbc477dde, 0xfba775a7),
+       PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "BASEline PCMCIA 10 MBit Ethernetadapter", 0xfa2e424d, 0xe9190d8a),
+       PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "FASTline PCMCIA 10/100 Fast-Ethernet", 0xfa2e424d, 0x3953d9b9),
+       PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722),
+       PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2),
+       PCMCIA_DEVICE_PROD_ID12("corega", "Ether CF-TD", 0x0a21501a, 0x6589340a),
+       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether CF-TD LAN Card", 0x5261440f, 0x8797663b),
+       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd),
+       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d),
+       PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d),
+       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa),
+       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-TD", 0x5261440f, 0x47d5ca83),
+       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9),
+       PCMCIA_DEVICE_PROD_ID12("Corega,K.K.", "Ethernet LAN Card", 0x110d26d9, 0x9fd2f0a2),
+       PCMCIA_DEVICE_PROD_ID12("corega,K.K.", "Ethernet LAN Card", 0x9791a90e, 0x9fd2f0a2),
+       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "(CG-LAPCCTXD)", 0x5261440f, 0x73ec0d88),
+       PCMCIA_DEVICE_PROD_ID12("CouplerlessPCMCIA", "100BASE", 0xee5af0ad, 0x7c2add04),
+       PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-010", 0x77008979, 0x9d8d445d),
+       PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-110E 10/100M LAN Card", 0x77008979, 0xfd184814),
+       PCMCIA_DEVICE_PROD_ID12("DataTrek.", "NetCard ", 0x5cd66d9d, 0x84697ce0),
+       PCMCIA_DEVICE_PROD_ID12("Dayna Communications, Inc.", "CommuniCard E", 0x0c629325, 0xb4e7dbaf),
+       PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100", 0x697403d8, 0xe160b995),
+       PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100 Dongless", 0x697403d8, 0xa6d3b233),
+       PCMCIA_DEVICE_PROD_ID12("DIGITAL", "DEPCM-XX", 0x69616cb3, 0xe600e76e),
+       PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-650", 0x1a424a1c, 0xf28c8398),
+       PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660", 0x1a424a1c, 0xd9a1d05b),
+       PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660+", 0x1a424a1c, 0x50dcd0ec),
+       PCMCIA_DEVICE_PROD_ID12("D-Link", "DFE-650", 0x1a424a1c, 0x0f0073f9),
+       PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 PC Card", 0x725b842d, 0xf1efee84),
+       PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 Port Attached PC Card", 0x725b842d, 0x2db1f8e9),
+       PCMCIA_DEVICE_PROD_ID12("Dynalink", "L10BC", 0x55632fd5, 0xdc65f2b1),
+       PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10BC", 0x6a26d1cf, 0xdc65f2b1),
+       PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10C", 0x6a26d1cf, 0xc4f84efb),
+       PCMCIA_DEVICE_PROD_ID12("E-CARD", "E-CARD", 0x6701da11, 0x6701da11),
+       PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet 10BaseT card", 0x53c864c6, 0xedd059f6),
+       PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet Combo card", 0x53c864c6, 0x929c486c),
+       PCMCIA_DEVICE_PROD_ID12("Ethernet", "Adapter", 0x00b2e941, 0x4b0d829e),
+       PCMCIA_DEVICE_PROD_ID12("Ethernet Adapter", "E2000 PCMCIA Ethernet", 0x96767301, 0x71fbbc61),
+       PCMCIA_DEVICE_PROD_ID12("Ethernet PCMCIA adapter", "EP-210", 0x8dd86181, 0xf2b52517),
+       PCMCIA_DEVICE_PROD_ID12("Fast Ethernet", "Adapter", 0xb4be14e3, 0x4b0d829e),
+       PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2000", 0x2a151fac, 0xf00555cb),
+       PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2220", 0x2a151fac, 0xc1b7e327),
+       PCMCIA_DEVICE_PROD_ID12("GVC", "NIC-2000p", 0x76e171bd, 0x6eb1c947),
+       PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "Ethernet", 0xe3736c88, 0x00b2e941),
+       PCMCIA_DEVICE_PROD_ID12("IC-CARD", "IC-CARD", 0x60cb09a6, 0x60cb09a6),
+       PCMCIA_DEVICE_PROD_ID12("IC-CARD+", "IC-CARD+", 0x93693494, 0x93693494),
+       PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCETTX", 0x547e66dc, 0x6fc5459b),
+       PCMCIA_DEVICE_PROD_ID12("iPort", "10/100 Ethernet Card", 0x56c538d2, 0x11b0ffc0),
+       PCMCIA_DEVICE_PROD_ID12("KANSAI ELECTRIC CO.,LTD", "KLA-PCM/T", 0xb18dc3b4, 0xcc51a956),
+       PCMCIA_DEVICE_PROD_ID12("KENTRONICS", "KEP-230", 0xaf8144c9, 0x868f6616),
+       PCMCIA_DEVICE_PROD_ID12("KCI", "PE520 PCMCIA Ethernet Adapter", 0xa89b87d3, 0x1eb88e64),
+       PCMCIA_DEVICE_PROD_ID12("KINGMAX", "EN10T2T", 0x7bcb459a, 0xa5c81fa5),
+       PCMCIA_DEVICE_PROD_ID12("Kingston", "KNE-PC2", 0x1128e633, 0xce2a89b3),
+       PCMCIA_DEVICE_PROD_ID12("Kingston Technology Corp.", "EtheRx PC Card Ethernet Adapter", 0x313c7be3, 0x0afb54a2),
+       PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-10/100CD", 0x1b7827b2, 0xcda71d1c),
+       PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDF", 0x1b7827b2, 0xfec71e40),
+       PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDL/T", 0x1b7827b2, 0x79fba4f7),
+       PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDS", 0x1b7827b2, 0x931afaab),
+       PCMCIA_DEVICE_PROD_ID12("LEMEL", "LM-N89TX PRO", 0xbbefb52f, 0xd2897a97),
+       PCMCIA_DEVICE_PROD_ID12("Linksys", "Combo PCMCIA EthernetCard (EC2T)", 0x0733cc81, 0x32ee8c78),
+       PCMCIA_DEVICE_PROD_ID12("LINKSYS", "E-CARD", 0xf7cb0b07, 0x6701da11),
+       PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 Integrated PC Card (PCM100)", 0x0733cc81, 0x453c3f9d),
+       PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100)", 0x0733cc81, 0x66c5a389),
+       PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V2)", 0x0733cc81, 0x3a3b28e9),
+       PCMCIA_DEVICE_PROD_ID12("Linksys", "HomeLink Phoneline + 10/100 Network PC Card (PCM100H1)", 0x733cc81, 0x7a3e5c3a),
+       PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TX", 0x88fcdeda, 0x6d772737),
+       PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TE", 0x88fcdeda, 0x0e714bee),
+       PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN20T", 0x88fcdeda, 0x81090922),
+       PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN10TE", 0x88fcdeda, 0xc1e2521c),
+       PCMCIA_DEVICE_PROD_ID12("LONGSHINE", "PCMCIA Ethernet Card", 0xf866b0b0, 0x6f6652e0),
+       PCMCIA_DEVICE_PROD_ID12("MACNICA", "ME1-JEIDA", 0x20841b68, 0xaf8a3578),
+       PCMCIA_DEVICE_PROD_ID12("Macsense", "MPC-10", 0xd830297f, 0xd265c307),
+       PCMCIA_DEVICE_PROD_ID12("Matsushita Electric Industrial Co.,LTD.", "CF-VEL211", 0x44445376, 0x8ded41d4),
+       PCMCIA_DEVICE_PROD_ID12("MAXTECH", "PCN2000", 0x78d64bc0, 0xca0ca4b8),
+       PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-T", 0x481e0094, 0xa2eb0cf3),
+       PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-TX", 0x481e0094, 0x41a6916c),
+       PCMCIA_DEVICE_PROD_ID12("Microcom C.E.", "Travel Card LAN 10/100", 0x4b91cec7, 0xe70220d6),
+       PCMCIA_DEVICE_PROD_ID12("Microdyne", "NE4200", 0x2e6da59b, 0x0478e472),
+       PCMCIA_DEVICE_PROD_ID12("MIDORI ELEC.", "LT-PCMT", 0x648d55c1, 0xbde526c7),
+       PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover 4100", 0x36e1191f, 0x60c229b9),
+       PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover NE4100", 0x36e1191f, 0xa6617ec8),
+       PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J12", 0x18df0ba0, 0xbc912d76),
+       PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA410TX", 0x9aa79dc3, 0x60e5bc0e),
+       PCMCIA_DEVICE_PROD_ID12("Network Everywhere", "Fast Ethernet 10/100 PC Card", 0x820a67b6, 0x31ed1a5f),
+       PCMCIA_DEVICE_PROD_ID12("NextCom K.K.", "Next Hawk", 0xaedaec74, 0xad050ef1),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100Mbps Ethernet Card", 0x281f1c5d, 0x6e41773b),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet", 0x281f1c5d, 0x00b2e941),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET", 0x281f1c5d, 0x3ff7175b),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet 10BaseT Card", 0x281f1c5d, 0x4de2f6c8),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Card", 0x281f1c5d, 0x5e9d92c0),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Combo card", 0x281f1c5d, 0x929c486c),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET V1.0", 0x281f1c5d, 0x4d8817c8),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEthernet", 0x281f1c5d, 0xfe871eeb),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast-Ethernet", 0x281f1c5d, 0x45f1f3b4),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FAST ETHERNET CARD", 0x281f1c5d, 0xec5dbca7),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA LAN", "Ethernet", 0x7500e246, 0x00b2e941),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "LNT-10TN", 0x281f1c5d, 0xe707f641),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "UE2212", 0x281f1c5d, 0xbf17199b),
+       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "    Ethernet NE2000 Compatible", 0x281f1c5d, 0x42d5d7e1),
+       PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10baseT 3.3V", 0xebf91155, 0x30074c80),
+       PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50),
+       PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110),
+       PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941),
+       PCMCIA_DEVICE_PROD_ID12("RIOS Systems Co.", "PC CARD3 ETHERNET", 0x7dd33481, 0x10b41826),
+       PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df),
+       PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0),
+       PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd),
+       PCMCIA_DEVICE_PROD_ID12("RPTI LTD.", "EP400", 0xc53ac515, 0x81e39388),
+       PCMCIA_DEVICE_PROD_ID12("SCM", "Ethernet Combo card", 0xbdc3b102, 0x929c486c),
+       PCMCIA_DEVICE_PROD_ID12("Seiko Epson Corp.", "Ethernet", 0x09928730, 0x00b2e941),
+       PCMCIA_DEVICE_PROD_ID12("SMC", "EZCard-10-PCMCIA", 0xc4f8b18b, 0xfb21d265),
+       PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision D", 0xc70a4760, 0x2ade483e),
+       PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision E", 0xc70a4760, 0x5dd978a8),
+       PCMCIA_DEVICE_PROD_ID12("TDK", "LAK-CD031 for PCMCIA", 0x1eae9475, 0x0ed386fa),
+       PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE450T", 0x466b05f0, 0x8b74bc4f),
+       PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE550T", 0x466b05f0, 0x33c8db2a),
+       PCMCIA_DEVICE_PROD_ID13("Hypertec",  "EP401", 0x8787bec7, 0xf6e4a31e),
+       PCMCIA_DEVICE_PROD_ID13("KingMax Technology Inc.", "Ethernet Card", 0x932b7189, 0x5e9d92c0),
+       PCMCIA_DEVICE_PROD_ID13("LONGSHINE", "EP401", 0xf866b0b0, 0xf6e4a31e),
+       PCMCIA_DEVICE_PROD_ID13("Xircom", "CFE-10", 0x2e3ee845, 0x22a49f89),
+       PCMCIA_DEVICE_PROD_ID1("CyQ've 10 Base-T LAN CARD", 0x94faf360),
+       PCMCIA_DEVICE_PROD_ID1("EP-210 PCMCIA LAN CARD.", 0x8850b4de),
+       PCMCIA_DEVICE_PROD_ID1("ETHER-C16", 0x06a8514f),
+       PCMCIA_DEVICE_PROD_ID1("NE2000 Compatible", 0x75b8ad5a),
+       PCMCIA_DEVICE_PROD_ID2("EN-6200P2", 0xa996d078),
+       /* too generic! */
+       /* PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100 Ethernet Card", 0x281f1c5d, 0x11b0ffc0), */
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
+       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
+       PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
+       PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
+       PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID12("Allied Telesis,K.K", "Ethernet LAN Card", 0x2ad62f3c, 0x9fd2f0a2, "cis/LA-PCM.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "cis/PE520.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "cis/NE2K.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID12("PMX   ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "cis/PE-200.cis"),
+       PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "cis/tamarack.cis"),
+       PCMCIA_DEVICE_PROD_ID12("Ethernet", "CF Size PC Card", 0x00b2e941, 0x43ac239b),
+       PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0",
+               0xb4be14e3, 0x43ac239b, 0x0877b627),
+       PCMCIA_DEVICE_NULL
+};
+MODULE_DEVICE_TABLE(pcmcia, pcnet_ids);
+MODULE_FIRMWARE("cis/PCMLM28.cis");
+MODULE_FIRMWARE("cis/DP83903.cis");
+MODULE_FIRMWARE("cis/LA-PCM.cis");
+MODULE_FIRMWARE("cis/PE520.cis");
+MODULE_FIRMWARE("cis/NE2K.cis");
+MODULE_FIRMWARE("cis/PE-200.cis");
+MODULE_FIRMWARE("cis/tamarack.cis");
+
+static struct pcmcia_driver pcnet_driver = {
+       .name           = "pcnet_cs",
+       .probe          = pcnet_probe,
+       .remove         = pcnet_detach,
+       .owner          = THIS_MODULE,
+       .id_table       = pcnet_ids,
+       .suspend        = pcnet_suspend,
+       .resume         = pcnet_resume,
+};
+
+static int __init init_pcnet_cs(void)
+{
+    return pcmcia_register_driver(&pcnet_driver);
+}
+
+static void __exit exit_pcnet_cs(void)
+{
+    pcmcia_unregister_driver(&pcnet_driver);
+}
+
+module_init(init_pcnet_cs);
+module_exit(exit_pcnet_cs);
diff --git a/drivers/net/ethernet/8390/smc-mca.c b/drivers/net/ethernet/8390/smc-mca.c
new file mode 100644 (file)
index 0000000..34934fb
--- /dev/null
@@ -0,0 +1,576 @@
+/* smc-mca.c: A SMC Ultra ethernet driver for linux. */
+/*
+    Most of this driver, except for ultramca_probe is nearly
+    verbatim from smc-ultra.c by Donald Becker. The rest is
+    written and copyright 1996 by David Weis, weisd3458@uni.edu
+
+    This is a driver for the SMC Ultra and SMC EtherEZ ethercards.
+
+    This driver uses the cards in the 8390-compatible, shared memory mode.
+    Most of the run-time complexity is handled by the generic code in
+    8390.c.
+
+    This driver enables the shared memory only when doing the actual data
+    transfers to avoid a bug in early version of the card that corrupted
+    data transferred by a AHA1542.
+
+    This driver does not support the programmed-I/O data transfer mode of
+    the EtherEZ.  That support (if available) is smc-ez.c.  Nor does it
+    use the non-8390-compatible "Altego" mode. (No support currently planned.)
+
+    Changelog:
+
+    Paul Gortmaker      : multiple card support for module users.
+    David Weis          : Micro Channel-ized it.
+    Tom Sightler        : Added support for IBM PS/2 Ethernet Adapter/A
+    Christopher Turcksin : Changed MCA-probe so that multiple adapters are
+                          found correctly (Jul 16, 1997)
+    Chris Beauregard    : Tried to merge the two changes above (Dec 15, 1997)
+    Tom Sightler        : Fixed minor detection bug caused by above merge
+    Tom Sightler        : Added support for three more Western Digital
+                          MCA-adapters
+    Tom Sightler        : Added support for 2.2.x mca_find_unused_adapter
+    Hartmut Schmidt     : - Modified parameter detection to handle each
+                            card differently depending on a switch-list
+                          - 'card_ver' removed from the adapter list
+                          - Some minor bug fixes
+*/
+
+#include <linux/mca.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+#define DRV_NAME "smc-mca"
+
+static int ultramca_open(struct net_device *dev);
+static void ultramca_reset_8390(struct net_device *dev);
+static void ultramca_get_8390_hdr(struct net_device *dev,
+                                  struct e8390_pkt_hdr *hdr,
+                                  int ring_page);
+static void ultramca_block_input(struct net_device *dev, int count,
+                                 struct sk_buff *skb,
+                                 int ring_offset);
+static void ultramca_block_output(struct net_device *dev, int count,
+                                  const unsigned char *buf,
+                                  const int start_page);
+static int ultramca_close_card(struct net_device *dev);
+
+#define START_PG        0x00    /* First page of TX buffer */
+
+#define ULTRA_CMDREG 0      /* Offset to ASIC command register. */
+#define ULTRA_RESET  0x80   /* Board reset, in ULTRA_CMDREG. */
+#define ULTRA_MEMENB 0x40   /* Enable the shared memory. */
+#define ULTRA_NIC_OFFSET 16 /* NIC register offset from the base_addr. */
+#define ULTRA_IO_EXTENT 32
+#define EN0_ERWCNT      0x08  /* Early receive warning count. */
+
+#define _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A            0
+#define _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A            1
+#define _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A              2
+#define _6fc1_WD_Starcard_PLUS_A_WD8003ST_A                            3
+#define _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A                        4
+#define _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A        5
+#define _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A        6
+#define _efe5_IBM_PS2_Adapter_A_for_Ethernet                           7
+
+struct smc_mca_adapters_t {
+       unsigned int id;
+       char *name;
+};
+
+#define MAX_ULTRAMCA_CARDS 4   /* Max number of Ultra cards per module */
+
+static int ultra_io[MAX_ULTRAMCA_CARDS];
+static int ultra_irq[MAX_ULTRAMCA_CARDS];
+MODULE_LICENSE("GPL");
+
+module_param_array(ultra_io, int, NULL, 0);
+module_param_array(ultra_irq, int, NULL, 0);
+MODULE_PARM_DESC(ultra_io, "SMC Ultra/EtherEZ MCA I/O base address(es)");
+MODULE_PARM_DESC(ultra_irq, "SMC Ultra/EtherEZ MCA IRQ number(s)");
+
+static const struct {
+  unsigned int base_addr;
+} addr_table[] = {
+    { 0x0800 },
+    { 0x1800 },
+    { 0x2800 },
+    { 0x3800 },
+    { 0x4800 },
+    { 0x5800 },
+    { 0x6800 },
+    { 0x7800 },
+    { 0x8800 },
+    { 0x9800 },
+    { 0xa800 },
+    { 0xb800 },
+    { 0xc800 },
+    { 0xd800 },
+    { 0xe800 },
+    { 0xf800 }
+};
+
+#define MEM_MASK 64
+
+static const struct {
+  unsigned char mem_index;
+  unsigned long mem_start;
+  unsigned char num_pages;
+} mem_table[] = {
+    { 16, 0x0c0000, 40 },
+    { 18, 0x0c4000, 40 },
+    { 20, 0x0c8000, 40 },
+    { 22, 0x0cc000, 40 },
+    { 24, 0x0d0000, 40 },
+    { 26, 0x0d4000, 40 },
+    { 28, 0x0d8000, 40 },
+    { 30, 0x0dc000, 40 },
+    {144, 0xfc0000, 40 },
+    {148, 0xfc8000, 40 },
+    {154, 0xfd0000, 40 },
+    {156, 0xfd8000, 40 },
+    {  0, 0x0c0000, 20 },
+    {  1, 0x0c2000, 20 },
+    {  2, 0x0c4000, 20 },
+    {  3, 0x0c6000, 20 }
+};
+
+#define IRQ_MASK 243
+static const struct {
+   unsigned char new_irq;
+   unsigned char old_irq;
+} irq_table[] = {
+   {  3,  3 },
+   {  4,  4 },
+   { 10, 10 },
+   { 14, 15 }
+};
+
+static short smc_mca_adapter_ids[] __initdata = {
+       0x61c8,
+       0x61c9,
+       0x6fc0,
+       0x6fc1,
+       0x6fc2,
+       0xefd4,
+       0xefd5,
+       0xefe5,
+       0x0000
+};
+
+static char *smc_mca_adapter_names[] __initdata = {
+       "SMC Ethercard PLUS Elite/A BNC/AUI (WD8013EP/A)",
+       "SMC Ethercard PLUS Elite/A UTP/AUI (WD8013WP/A)",
+       "WD Ethercard PLUS/A (WD8003E/A or WD8003ET/A)",
+       "WD Starcard PLUS/A (WD8003ST/A)",
+       "WD Ethercard PLUS 10T/A (WD8003W/A)",
+       "IBM PS/2 Adapter/A for Ethernet UTP/AUI (WD8013WP/A)",
+       "IBM PS/2 Adapter/A for Ethernet BNC/AUI (WD8013EP/A)",
+       "IBM PS/2 Adapter/A for Ethernet",
+       NULL
+};
+
+static int ultra_found = 0;
+
+
+static const struct net_device_ops ultramca_netdev_ops = {
+       .ndo_open               = ultramca_open,
+       .ndo_stop               = ultramca_close_card,
+
+       .ndo_start_xmit         = ei_start_xmit,
+       .ndo_tx_timeout         = ei_tx_timeout,
+       .ndo_get_stats          = ei_get_stats,
+       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = ei_poll,
+#endif
+};
+
+static int __init ultramca_probe(struct device *gen_dev)
+{
+       unsigned short ioaddr;
+       struct net_device *dev;
+       unsigned char reg4, num_pages;
+       struct mca_device *mca_dev = to_mca_device(gen_dev);
+       char slot = mca_dev->slot;
+       unsigned char pos2 = 0xff, pos3 = 0xff, pos4 = 0xff, pos5 = 0xff;
+       int i, rc;
+       int adapter = mca_dev->index;
+       int tbase = 0;
+       int tirq = 0;
+       int base_addr = ultra_io[ultra_found];
+       int irq = ultra_irq[ultra_found];
+
+       if (base_addr || irq) {
+               printk(KERN_INFO "Probing for SMC MCA adapter");
+               if (base_addr) {
+                       printk(KERN_INFO " at I/O address 0x%04x%c",
+                              base_addr, irq ? ' ' : '\n');
+               }
+               if (irq) {
+                       printk(KERN_INFO "using irq %d\n", irq);
+               }
+       }
+
+       tirq = 0;
+       tbase = 0;
+
+       /* If we're trying to match a specificied irq or io address,
+        * we'll reject the adapter found unless it's the one we're
+        * looking for */
+
+       pos2 = mca_device_read_stored_pos(mca_dev, 2); /* io_addr */
+       pos3 = mca_device_read_stored_pos(mca_dev, 3); /* shared mem */
+       pos4 = mca_device_read_stored_pos(mca_dev, 4); /* ROM bios addr range */
+       pos5 = mca_device_read_stored_pos(mca_dev, 5); /* irq, media and RIPL */
+
+       /* Test the following conditions:
+        * - If an irq parameter is supplied, compare it
+        *   with the irq of the adapter we found
+        * - If a base_addr paramater is given, compare it
+        *   with the base_addr of the adapter we found
+        * - Check that the irq and the base_addr of the
+        *   adapter we found is not already in use by
+        *   this driver
+        */
+
+       switch (mca_dev->index) {
+       case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A:
+       case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A:
+       case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A:
+       case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A:
+               {
+                       tbase = addr_table[(pos2 & 0xf0) >> 4].base_addr;
+                       tirq  = irq_table[(pos5 & 0xc) >> 2].new_irq;
+                       break;
+               }
+       case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A:
+       case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A:
+       case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
+       case _efe5_IBM_PS2_Adapter_A_for_Ethernet:
+               {
+                       tbase = ((pos2 & 0x0fe) * 0x10);
+                       tirq  = irq_table[(pos5 & 3)].old_irq;
+                       break;
+               }
+       }
+
+       if(!tirq || !tbase ||
+          (irq && irq != tirq) ||
+          (base_addr && tbase != base_addr))
+               /* FIXME: we're trying to force the ordering of the
+                * devices here, there should be a way of getting this
+                * to happen */
+               return -ENXIO;
+
+        /* Adapter found. */
+       dev  = alloc_ei_netdev();
+       if(!dev)
+               return -ENODEV;
+
+       SET_NETDEV_DEV(dev, gen_dev);
+       mca_device_set_name(mca_dev, smc_mca_adapter_names[adapter]);
+       mca_device_set_claim(mca_dev, 1);
+
+       printk(KERN_INFO "smc_mca: %s found in slot %d\n",
+                      smc_mca_adapter_names[adapter], slot + 1);
+
+       ultra_found++;
+
+       dev->base_addr = ioaddr = mca_device_transform_ioport(mca_dev, tbase);
+       dev->irq       = mca_device_transform_irq(mca_dev, tirq);
+       dev->mem_start = 0;
+       num_pages      = 40;
+
+       switch (adapter) {      /* card-# in const array above [hs] */
+               case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A:
+               case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A:
+               {
+                       for (i = 0; i < 16; i++) { /* taking 16 counts
+                                                   * up to 15 [hs] */
+                               if (mem_table[i].mem_index == (pos3 & ~MEM_MASK)) {
+                                       dev->mem_start = (unsigned long)
+                                         mca_device_transform_memory(mca_dev, (void *)mem_table[i].mem_start);
+                                       num_pages = mem_table[i].num_pages;
+                               }
+                       }
+                       break;
+               }
+               case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A:
+               case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A:
+               case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
+               case _efe5_IBM_PS2_Adapter_A_for_Ethernet:
+               {
+                       dev->mem_start = (unsigned long)
+                         mca_device_transform_memory(mca_dev, (void *)((pos3 & 0xfc) * 0x1000));
+                       num_pages = 0x40;
+                       break;
+               }
+               case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A:
+               case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A:
+               {
+                       /* courtesy of gamera@quartz.ocn.ne.jp, pos3 indicates
+                        * the index of the 0x2000 step.
+                        * beware different number of pages [hs]
+                        */
+                       dev->mem_start = (unsigned long)
+                         mca_device_transform_memory(mca_dev, (void *)(0xc0000 + (0x2000 * (pos3 & 0xf))));
+                       num_pages = 0x20 + (2 * (pos3 & 0x10));
+                       break;
+               }
+       }
+
+       /* sanity check, shouldn't happen */
+       if (dev->mem_start == 0) {
+               rc = -ENODEV;
+               goto err_unclaim;
+       }
+
+       if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME)) {
+               rc = -ENODEV;
+               goto err_unclaim;
+       }
+
+       reg4 = inb(ioaddr + 4) & 0x7f;
+       outb(reg4, ioaddr + 4);
+
+       for (i = 0; i < 6; i++)
+               dev->dev_addr[i] = inb(ioaddr + 8 + i);
+
+       printk(KERN_INFO "smc_mca[%d]: Parameters: %#3x, %pM",
+              slot + 1, ioaddr, dev->dev_addr);
+
+       /* Switch from the station address to the alternate register set
+        * and read the useful registers there.
+        */
+
+       outb(0x80 | reg4, ioaddr + 4);
+
+       /* Enable FINE16 mode to avoid BIOS ROM width mismatches @ reboot.
+        */
+
+       outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
+
+       /* Switch back to the station address register set so that
+        * the MS-DOS driver can find the card after a warm boot.
+        */
+
+       outb(reg4, ioaddr + 4);
+
+       dev_set_drvdata(gen_dev, dev);
+
+       /* The 8390 isn't at the base address, so fake the offset
+        */
+
+       dev->base_addr = ioaddr + ULTRA_NIC_OFFSET;
+
+       ei_status.name = "SMC Ultra MCA";
+       ei_status.word16 = 1;
+       ei_status.tx_start_page = START_PG;
+       ei_status.rx_start_page = START_PG + TX_PAGES;
+       ei_status.stop_page = num_pages;
+
+       ei_status.mem = ioremap(dev->mem_start, (ei_status.stop_page - START_PG) * 256);
+       if (!ei_status.mem) {
+               rc = -ENOMEM;
+               goto err_release_region;
+       }
+
+       dev->mem_end = dev->mem_start + (ei_status.stop_page - START_PG) * 256;
+
+       printk(", IRQ %d memory %#lx-%#lx.\n",
+       dev->irq, dev->mem_start, dev->mem_end - 1);
+
+       ei_status.reset_8390 = &ultramca_reset_8390;
+       ei_status.block_input = &ultramca_block_input;
+       ei_status.block_output = &ultramca_block_output;
+       ei_status.get_8390_hdr = &ultramca_get_8390_hdr;
+
+       ei_status.priv = slot;
+
+       dev->netdev_ops = &ultramca_netdev_ops;
+
+       NS8390_init(dev, 0);
+
+       rc = register_netdev(dev);
+       if (rc)
+               goto err_unmap;
+
+       return 0;
+
+err_unmap:
+       iounmap(ei_status.mem);
+err_release_region:
+       release_region(ioaddr, ULTRA_IO_EXTENT);
+err_unclaim:
+       mca_device_set_claim(mca_dev, 0);
+       free_netdev(dev);
+       return rc;
+}
+
+static int ultramca_open(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+       int retval;
+
+       if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev)))
+               return retval;
+
+       outb(ULTRA_MEMENB, ioaddr); /* Enable memory */
+       outb(0x80, ioaddr + 5);     /* ??? */
+       outb(0x01, ioaddr + 6);     /* Enable interrupts and memory. */
+       outb(0x04, ioaddr + 5);     /* ??? */
+
+       /* Set the early receive warning level in window 0 high enough not
+        * to receive ERW interrupts.
+        */
+
+       /* outb_p(E8390_NODMA + E8390_PAGE0, dev->base_addr);
+        * outb(0xff, dev->base_addr + EN0_ERWCNT);
+        */
+
+       ei_open(dev);
+       return 0;
+}
+
+static void ultramca_reset_8390(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+
+       outb(ULTRA_RESET, ioaddr);
+       if (ei_debug > 1)
+               printk("resetting Ultra, t=%ld...", jiffies);
+       ei_status.txing = 0;
+
+       outb(0x80, ioaddr + 5);     /* ??? */
+       outb(0x01, ioaddr + 6);     /* Enable interrupts and memory. */
+
+       if (ei_debug > 1)
+               printk("reset done\n");
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+ * we don't need to be concerned with ring wrap as the header will be at
+ * the start of a page, so we optimize accordingly.
+ */
+
+static void ultramca_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+       void __iomem *hdr_start = ei_status.mem + ((ring_page - START_PG) << 8);
+
+#ifdef notdef
+       /* Officially this is what we are doing, but the readl() is faster */
+       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+#else
+       ((unsigned int*)hdr)[0] = readl(hdr_start);
+#endif
+}
+
+/* Block input and output are easy on shared memory ethercards, the only
+ * complication is when the ring buffer wraps.
+ */
+
+static void ultramca_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+       void __iomem *xfer_start = ei_status.mem + ring_offset - START_PG * 256;
+
+       if (ring_offset + count > ei_status.stop_page * 256) {
+               /* We must wrap the input move. */
+               int semi_count = ei_status.stop_page * 256 - ring_offset;
+               memcpy_fromio(skb->data, xfer_start, semi_count);
+               count -= semi_count;
+               memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
+       } else {
+               memcpy_fromio(skb->data, xfer_start, count);
+       }
+
+}
+
+static void ultramca_block_output(struct net_device *dev, int count, const unsigned char *buf,
+                int start_page)
+{
+       void __iomem *shmem = ei_status.mem + ((start_page - START_PG) << 8);
+
+       memcpy_toio(shmem, buf, count);
+}
+
+static int ultramca_close_card(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+
+       netif_stop_queue(dev);
+
+       if (ei_debug > 1)
+               printk("%s: Shutting down ethercard.\n", dev->name);
+
+       outb(0x00, ioaddr + 6);     /* Disable interrupts. */
+       free_irq(dev->irq, dev);
+
+       NS8390_init(dev, 0);
+       /* We should someday disable shared memory and change to 8-bit mode
+         * "just in case"...
+        */
+
+       return 0;
+}
+
+static int ultramca_remove(struct device *gen_dev)
+{
+       struct mca_device *mca_dev = to_mca_device(gen_dev);
+       struct net_device *dev = dev_get_drvdata(gen_dev);
+
+       if (dev) {
+               /* NB: ultra_close_card() does free_irq */
+               int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
+
+               unregister_netdev(dev);
+               mca_device_set_claim(mca_dev, 0);
+               release_region(ioaddr, ULTRA_IO_EXTENT);
+               iounmap(ei_status.mem);
+               free_netdev(dev);
+       }
+       return 0;
+}
+
+
+static struct mca_driver ultra_driver = {
+       .id_table = smc_mca_adapter_ids,
+       .driver = {
+               .name = "smc-mca",
+               .bus = &mca_bus_type,
+               .probe = ultramca_probe,
+               .remove = ultramca_remove,
+       }
+};
+
+static int __init ultramca_init_module(void)
+{
+       if(!MCA_bus)
+               return -ENXIO;
+
+       mca_register_driver(&ultra_driver);
+
+       return ultra_found ? 0 : -ENXIO;
+}
+
+static void __exit ultramca_cleanup_module(void)
+{
+       mca_unregister_driver(&ultra_driver);
+}
+module_init(ultramca_init_module);
+module_exit(ultramca_cleanup_module);
+
diff --git a/drivers/net/ethernet/8390/smc-ultra.c b/drivers/net/ethernet/8390/smc-ultra.c
new file mode 100644 (file)
index 0000000..ba44ede
--- /dev/null
@@ -0,0 +1,622 @@
+/* smc-ultra.c: A SMC Ultra ethernet driver for linux. */
+/*
+       This is a driver for the SMC Ultra and SMC EtherEZ ISA ethercards.
+
+       Written 1993-1998 by Donald Becker.
+
+       Copyright 1993 United States Government as represented by the
+       Director, National Security Agency.
+
+       This software may be used and distributed according to the terms
+       of the GNU General Public License, incorporated herein by reference.
+
+       The author may be reached as becker@scyld.com, or C/O
+       Scyld Computing Corporation
+       410 Severn Ave., Suite 210
+       Annapolis MD 21403
+
+       This driver uses the cards in the 8390-compatible mode.
+       Most of the run-time complexity is handled by the generic code in
+       8390.c.  The code in this file is responsible for
+
+               ultra_probe()           Detecting and initializing the card.
+               ultra_probe1()
+               ultra_probe_isapnp()
+
+               ultra_open()            The card-specific details of starting, stopping
+               ultra_reset_8390()      and resetting the 8390 NIC core.
+               ultra_close()
+
+               ultra_block_input()             Routines for reading and writing blocks of
+               ultra_block_output()    packet buffer memory.
+               ultra_pio_input()
+               ultra_pio_output()
+
+       This driver enables the shared memory only when doing the actual data
+       transfers to avoid a bug in early version of the card that corrupted
+       data transferred by a AHA1542.
+
+       This driver now supports the programmed-I/O (PIO) data transfer mode of
+       the EtherEZ. It does not use the non-8390-compatible "Altego" mode.
+       That support (if available) is in smc-ez.c.
+
+       Changelog:
+
+       Paul Gortmaker  : multiple card support for module users.
+       Donald Becker   : 4/17/96 PIO support, minor potential problems avoided.
+       Donald Becker   : 6/6/96 correctly set auto-wrap bit.
+       Alexander Sotirov : 1/20/01 Added support for ISAPnP cards
+
+       Note about the ISA PnP support:
+
+       This driver can not autoprobe for more than one SMC EtherEZ PnP card.
+       You have to configure the second card manually through the /proc/isapnp
+       interface and then load the module with an explicit io=0x___ option.
+*/
+
+static const char version[] =
+       "smc-ultra.c:v2.02 2/3/98 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/isapnp.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+#define DRV_NAME "smc-ultra"
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int ultra_portlist[] __initdata =
+{0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0};
+
+static int ultra_probe1(struct net_device *dev, int ioaddr);
+
+#ifdef __ISAPNP__
+static int ultra_probe_isapnp(struct net_device *dev);
+#endif
+
+static int ultra_open(struct net_device *dev);
+static void ultra_reset_8390(struct net_device *dev);
+static void ultra_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                                               int ring_page);
+static void ultra_block_input(struct net_device *dev, int count,
+                                                 struct sk_buff *skb, int ring_offset);
+static void ultra_block_output(struct net_device *dev, int count,
+                                                       const unsigned char *buf, const int start_page);
+static void ultra_pio_get_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                                               int ring_page);
+static void ultra_pio_input(struct net_device *dev, int count,
+                                                 struct sk_buff *skb, int ring_offset);
+static void ultra_pio_output(struct net_device *dev, int count,
+                                                        const unsigned char *buf, const int start_page);
+static int ultra_close_card(struct net_device *dev);
+
+#ifdef __ISAPNP__
+static struct isapnp_device_id ultra_device_ids[] __initdata = {
+        {       ISAPNP_VENDOR('S','M','C'), ISAPNP_FUNCTION(0x8416),
+                ISAPNP_VENDOR('S','M','C'), ISAPNP_FUNCTION(0x8416),
+                (long) "SMC EtherEZ (8416)" },
+        { }    /* terminate list */
+};
+
+MODULE_DEVICE_TABLE(isapnp, ultra_device_ids);
+#endif
+
+
+#define START_PG               0x00    /* First page of TX buffer */
+
+#define ULTRA_CMDREG   0               /* Offset to ASIC command register. */
+#define         ULTRA_RESET    0x80    /* Board reset, in ULTRA_CMDREG. */
+#define         ULTRA_MEMENB   0x40    /* Enable the shared memory. */
+#define IOPD   0x02                    /* I/O Pipe Data (16 bits), PIO operation. */
+#define IOPA   0x07                    /* I/O Pipe Address for PIO operation. */
+#define ULTRA_NIC_OFFSET  16   /* NIC register offset from the base_addr. */
+#define ULTRA_IO_EXTENT 32
+#define EN0_ERWCNT             0x08    /* Early receive warning count. */
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void ultra_poll(struct net_device *dev)
+{
+       disable_irq(dev->irq);
+       ei_interrupt(dev->irq, dev);
+       enable_irq(dev->irq);
+}
+#endif
+/*     Probe for the Ultra.  This looks like a 8013 with the station
+       address PROM at I/O ports <base>+8 to <base>+13, with a checksum
+       following.
+*/
+
+static int __init do_ultra_probe(struct net_device *dev)
+{
+       int i;
+       int base_addr = dev->base_addr;
+       int irq = dev->irq;
+
+       if (base_addr > 0x1ff)          /* Check a single specified location. */
+               return ultra_probe1(dev, base_addr);
+       else if (base_addr != 0)        /* Don't probe at all. */
+               return -ENXIO;
+
+#ifdef __ISAPNP__
+       /* Look for any installed ISAPnP cards */
+       if (isapnp_present() && (ultra_probe_isapnp(dev) == 0))
+               return 0;
+#endif
+
+       for (i = 0; ultra_portlist[i]; i++) {
+               dev->irq = irq;
+               if (ultra_probe1(dev, ultra_portlist[i]) == 0)
+                       return 0;
+       }
+
+       return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init ultra_probe(int unit)
+{
+       struct net_device *dev = alloc_ei_netdev();
+       int err;
+
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       sprintf(dev->name, "eth%d", unit);
+       netdev_boot_setup_check(dev);
+
+       err = do_ultra_probe(dev);
+       if (err)
+               goto out;
+       return dev;
+out:
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops ultra_netdev_ops = {
+       .ndo_open               = ultra_open,
+       .ndo_stop               = ultra_close_card,
+
+       .ndo_start_xmit         = ei_start_xmit,
+       .ndo_tx_timeout         = ei_tx_timeout,
+       .ndo_get_stats          = ei_get_stats,
+       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = ultra_poll,
+#endif
+};
+
+static int __init ultra_probe1(struct net_device *dev, int ioaddr)
+{
+       int i, retval;
+       int checksum = 0;
+       const char *model_name;
+       unsigned char eeprom_irq = 0;
+       static unsigned version_printed;
+       /* Values from various config regs. */
+       unsigned char num_pages, irqreg, addr, piomode;
+       unsigned char idreg = inb(ioaddr + 7);
+       unsigned char reg4 = inb(ioaddr + 4) & 0x7f;
+
+       if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME))
+               return -EBUSY;
+
+       /* Check the ID nibble. */
+       if ((idreg & 0xF0) != 0x20                      /* SMC Ultra */
+               && (idreg & 0xF0) != 0x40) {            /* SMC EtherEZ */
+               retval = -ENODEV;
+               goto out;
+       }
+
+       /* Select the station address register set. */
+       outb(reg4, ioaddr + 4);
+
+       for (i = 0; i < 8; i++)
+               checksum += inb(ioaddr + 8 + i);
+       if ((checksum & 0xff) != 0xFF) {
+               retval = -ENODEV;
+               goto out;
+       }
+
+       if (ei_debug  &&  version_printed++ == 0)
+               printk(version);
+
+       model_name = (idreg & 0xF0) == 0x20 ? "SMC Ultra" : "SMC EtherEZ";
+
+       for (i = 0; i < 6; i++)
+               dev->dev_addr[i] = inb(ioaddr + 8 + i);
+
+       printk("%s: %s at %#3x, %pM", dev->name, model_name,
+              ioaddr, dev->dev_addr);
+
+       /* Switch from the station address to the alternate register set and
+          read the useful registers there. */
+       outb(0x80 | reg4, ioaddr + 4);
+
+       /* Enabled FINE16 mode to avoid BIOS ROM width mismatches @ reboot. */
+       outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
+       piomode = inb(ioaddr + 0x8);
+       addr = inb(ioaddr + 0xb);
+       irqreg = inb(ioaddr + 0xd);
+
+       /* Switch back to the station address register set so that the MS-DOS driver
+          can find the card after a warm boot. */
+       outb(reg4, ioaddr + 4);
+
+       if (dev->irq < 2) {
+               unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15};
+               int irq;
+
+               /* The IRQ bits are split. */
+               irq = irqmap[((irqreg & 0x40) >> 4) + ((irqreg & 0x0c) >> 2)];
+
+               if (irq == 0) {
+                       printk(", failed to detect IRQ line.\n");
+                       retval =  -EAGAIN;
+                       goto out;
+               }
+               dev->irq = irq;
+               eeprom_irq = 1;
+       }
+
+       /* The 8390 isn't at the base address, so fake the offset */
+       dev->base_addr = ioaddr+ULTRA_NIC_OFFSET;
+
+       {
+               static const int addr_tbl[4] = {
+                       0x0C0000, 0x0E0000, 0xFC0000, 0xFE0000
+               };
+               static const short num_pages_tbl[4] = {
+                       0x20, 0x40, 0x80, 0xff
+               };
+
+               dev->mem_start = ((addr & 0x0f) << 13) + addr_tbl[(addr >> 6) & 3] ;
+               num_pages = num_pages_tbl[(addr >> 4) & 3];
+       }
+
+       ei_status.name = model_name;
+       ei_status.word16 = 1;
+       ei_status.tx_start_page = START_PG;
+       ei_status.rx_start_page = START_PG + TX_PAGES;
+       ei_status.stop_page = num_pages;
+
+       ei_status.mem = ioremap(dev->mem_start, (ei_status.stop_page - START_PG)*256);
+       if (!ei_status.mem) {
+               printk(", failed to ioremap.\n");
+               retval =  -ENOMEM;
+               goto out;
+       }
+
+       dev->mem_end = dev->mem_start + (ei_status.stop_page - START_PG)*256;
+
+       if (piomode) {
+               printk(",%s IRQ %d programmed-I/O mode.\n",
+                          eeprom_irq ? "EEPROM" : "assigned ", dev->irq);
+               ei_status.block_input = &ultra_pio_input;
+               ei_status.block_output = &ultra_pio_output;
+               ei_status.get_8390_hdr = &ultra_pio_get_hdr;
+       } else {
+               printk(",%s IRQ %d memory %#lx-%#lx.\n", eeprom_irq ? "" : "assigned ",
+                          dev->irq, dev->mem_start, dev->mem_end-1);
+               ei_status.block_input = &ultra_block_input;
+               ei_status.block_output = &ultra_block_output;
+               ei_status.get_8390_hdr = &ultra_get_8390_hdr;
+       }
+       ei_status.reset_8390 = &ultra_reset_8390;
+
+       dev->netdev_ops = &ultra_netdev_ops;
+       NS8390_init(dev, 0);
+
+       retval = register_netdev(dev);
+       if (retval)
+               goto out;
+       return 0;
+out:
+       release_region(ioaddr, ULTRA_IO_EXTENT);
+       return retval;
+}
+
+#ifdef __ISAPNP__
+static int __init ultra_probe_isapnp(struct net_device *dev)
+{
+        int i;
+
+        for (i = 0; ultra_device_ids[i].vendor != 0; i++) {
+               struct pnp_dev *idev = NULL;
+
+                while ((idev = pnp_find_dev(NULL,
+                                            ultra_device_ids[i].vendor,
+                                            ultra_device_ids[i].function,
+                                            idev))) {
+                        /* Avoid already found cards from previous calls */
+                        if (pnp_device_attach(idev) < 0)
+                               continue;
+                        if (pnp_activate_dev(idev) < 0) {
+                              __again:
+                               pnp_device_detach(idev);
+                               continue;
+                        }
+                       /* if no io and irq, search for next */
+                       if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0))
+                               goto __again;
+                        /* found it */
+                       dev->base_addr = pnp_port_start(idev, 0);
+                       dev->irq = pnp_irq(idev, 0);
+                        printk(KERN_INFO "smc-ultra.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
+                                (char *) ultra_device_ids[i].driver_data,
+                                dev->base_addr, dev->irq);
+                        if (ultra_probe1(dev, dev->base_addr) != 0) {      /* Shouldn't happen. */
+                                printk(KERN_ERR "smc-ultra.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr);
+                                pnp_device_detach(idev);
+                               return -ENXIO;
+                        }
+                        ei_status.priv = (unsigned long)idev;
+                        break;
+                }
+                if (!idev)
+                        continue;
+                return 0;
+        }
+
+        return -ENODEV;
+}
+#endif
+
+static int
+ultra_open(struct net_device *dev)
+{
+       int retval;
+       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+       unsigned char irq2reg[] = {0, 0, 0x04, 0x08, 0, 0x0C, 0, 0x40,
+                                  0, 0x04, 0x44, 0x48, 0, 0, 0, 0x4C, };
+
+       retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev);
+       if (retval)
+               return retval;
+
+       outb(0x00, ioaddr);     /* Disable shared memory for safety. */
+       outb(0x80, ioaddr + 5);
+       /* Set the IRQ line. */
+       outb(inb(ioaddr + 4) | 0x80, ioaddr + 4);
+       outb((inb(ioaddr + 13) & ~0x4C) | irq2reg[dev->irq], ioaddr + 13);
+       outb(inb(ioaddr + 4) & 0x7f, ioaddr + 4);
+
+       if (ei_status.block_input == &ultra_pio_input) {
+               outb(0x11, ioaddr + 6);         /* Enable interrupts and PIO. */
+               outb(0x01, ioaddr + 0x19);      /* Enable ring read auto-wrap. */
+       } else
+               outb(0x01, ioaddr + 6);         /* Enable interrupts and memory. */
+       /* Set the early receive warning level in window 0 high enough not
+          to receive ERW interrupts. */
+       outb_p(E8390_NODMA+E8390_PAGE0, dev->base_addr);
+       outb(0xff, dev->base_addr + EN0_ERWCNT);
+       ei_open(dev);
+       return 0;
+}
+
+static void
+ultra_reset_8390(struct net_device *dev)
+{
+       int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */
+
+       outb(ULTRA_RESET, cmd_port);
+       if (ei_debug > 1) printk("resetting Ultra, t=%ld...", jiffies);
+       ei_status.txing = 0;
+
+       outb(0x00, cmd_port);   /* Disable shared memory for safety. */
+       outb(0x80, cmd_port + 5);
+       if (ei_status.block_input == &ultra_pio_input)
+               outb(0x11, cmd_port + 6);               /* Enable interrupts and PIO. */
+       else
+               outb(0x01, cmd_port + 6);               /* Enable interrupts and memory. */
+
+       if (ei_debug > 1) printk("reset done\n");
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void
+ultra_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+       void __iomem *hdr_start = ei_status.mem + ((ring_page - START_PG)<<8);
+
+       outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);  /* shmem on */
+#ifdef __BIG_ENDIAN
+       /* Officially this is what we are doing, but the readl() is faster */
+       /* unfortunately it isn't endian aware of the struct               */
+       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+       hdr->count = le16_to_cpu(hdr->count);
+#else
+       ((unsigned int*)hdr)[0] = readl(hdr_start);
+#endif
+       outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem off */
+}
+
+/* Block input and output are easy on shared memory ethercards, the only
+   complication is when the ring buffer wraps. */
+
+static void
+ultra_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+       void __iomem *xfer_start = ei_status.mem + ring_offset - (START_PG<<8);
+
+       /* Enable shared memory. */
+       outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
+
+       if (ring_offset + count > ei_status.stop_page*256) {
+               /* We must wrap the input move. */
+               int semi_count = ei_status.stop_page*256 - ring_offset;
+               memcpy_fromio(skb->data, xfer_start, semi_count);
+               count -= semi_count;
+               memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
+       } else {
+               memcpy_fromio(skb->data, xfer_start, count);
+       }
+
+       outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET);  /* Disable memory. */
+}
+
+static void
+ultra_block_output(struct net_device *dev, int count, const unsigned char *buf,
+                               int start_page)
+{
+       void __iomem *shmem = ei_status.mem + ((start_page - START_PG)<<8);
+
+       /* Enable shared memory. */
+       outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
+
+       memcpy_toio(shmem, buf, count);
+
+       outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */
+}
+
+/* The identical operations for programmed I/O cards.
+   The PIO model is trivial to use: the 16 bit start address is written
+   byte-sequentially to IOPA, with no intervening I/O operations, and the
+   data is read or written to the IOPD data port.
+   The only potential complication is that the address register is shared
+   and must be always be rewritten between each read/write direction change.
+   This is no problem for us, as the 8390 code ensures that we are single
+   threaded. */
+static void ultra_pio_get_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                                               int ring_page)
+{
+       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+       outb(0x00, ioaddr + IOPA);      /* Set the address, LSB first. */
+       outb(ring_page, ioaddr + IOPA);
+       insw(ioaddr + IOPD, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+}
+
+static void ultra_pio_input(struct net_device *dev, int count,
+                                                 struct sk_buff *skb, int ring_offset)
+{
+       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+    char *buf = skb->data;
+
+       /* For now set the address again, although it should already be correct. */
+       outb(ring_offset, ioaddr + IOPA);       /* Set the address, LSB first. */
+       outb(ring_offset >> 8, ioaddr + IOPA);
+       /* We know skbuffs are padded to at least word alignment. */
+       insw(ioaddr + IOPD, buf, (count+1)>>1);
+}
+
+static void ultra_pio_output(struct net_device *dev, int count,
+                                                       const unsigned char *buf, const int start_page)
+{
+       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
+       outb(0x00, ioaddr + IOPA);      /* Set the address, LSB first. */
+       outb(start_page, ioaddr + IOPA);
+       /* An extra odd byte is OK here as well. */
+       outsw(ioaddr + IOPD, buf, (count+1)>>1);
+}
+
+static int
+ultra_close_card(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* CMDREG */
+
+       netif_stop_queue(dev);
+
+       if (ei_debug > 1)
+               printk("%s: Shutting down ethercard.\n", dev->name);
+
+       outb(0x00, ioaddr + 6);         /* Disable interrupts. */
+       free_irq(dev->irq, dev);
+
+       NS8390_init(dev, 0);
+
+       /* We should someday disable shared memory and change to 8-bit mode
+          "just in case"... */
+
+       return 0;
+}
+
+
+#ifdef MODULE
+#define MAX_ULTRA_CARDS        4       /* Max number of Ultra cards per module */
+static struct net_device *dev_ultra[MAX_ULTRA_CARDS];
+static int io[MAX_ULTRA_CARDS];
+static int irq[MAX_ULTRA_CARDS];
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
+MODULE_DESCRIPTION("SMC Ultra/EtherEZ ISA/PnP Ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that only a single autoprobe takes place per call.
+ISA device autoprobes on a running machine are not recommended. */
+int __init
+init_module(void)
+{
+       struct net_device *dev;
+       int this_dev, found = 0;
+
+       for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) {
+               if (io[this_dev] == 0)  {
+                       if (this_dev != 0) break; /* only autoprobe 1st one */
+                       printk(KERN_NOTICE "smc-ultra.c: Presently autoprobing (not recommended) for a single card.\n");
+               }
+               dev = alloc_ei_netdev();
+               if (!dev)
+                       break;
+               dev->irq = irq[this_dev];
+               dev->base_addr = io[this_dev];
+               if (do_ultra_probe(dev) == 0) {
+                       dev_ultra[found++] = dev;
+                       continue;
+               }
+               free_netdev(dev);
+               printk(KERN_WARNING "smc-ultra.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]);
+               break;
+       }
+       if (found)
+               return 0;
+       return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+       /* NB: ultra_close_card() does free_irq */
+#ifdef __ISAPNP__
+       struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+       if (idev)
+               pnp_device_detach(idev);
+#endif
+       release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT);
+       iounmap(ei_status.mem);
+}
+
+void __exit
+cleanup_module(void)
+{
+       int this_dev;
+
+       for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) {
+               struct net_device *dev = dev_ultra[this_dev];
+               if (dev) {
+                       unregister_netdev(dev);
+                       cleanup_card(dev);
+                       free_netdev(dev);
+               }
+       }
+}
+#endif /* MODULE */
diff --git a/drivers/net/ethernet/8390/smc-ultra32.c b/drivers/net/ethernet/8390/smc-ultra32.c
new file mode 100644 (file)
index 0000000..e459c3b
--- /dev/null
@@ -0,0 +1,464 @@
+/*     smc-ultra32.c: An SMC Ultra32 EISA ethernet driver for linux.
+
+Sources:
+
+       This driver is based on (cloned from) the ISA SMC Ultra driver
+       written by Donald Becker. Modifications to support the EISA
+       version of the card by Paul Gortmaker and Leonard N. Zubkoff.
+
+       This software may be used and distributed according to the terms
+       of the GNU General Public License, incorporated herein by reference.
+
+Theory of Operation:
+
+       The SMC Ultra32C card uses the SMC 83c790 chip which is also
+       found on the ISA SMC Ultra cards. It has a shared memory mode of
+       operation that makes it similar to the ISA version of the card.
+       The main difference is that the EISA card has 32KB of RAM, but
+       only an 8KB window into that memory. The EISA card also can be
+       set for a bus-mastering mode of operation via the ECU, but that
+       is not (and probably will never be) supported by this driver.
+       The ECU should be run to enable shared memory and to disable the
+       bus-mastering feature for use with linux.
+
+       By programming the 8390 to use only 8KB RAM, the modifications
+       to the ISA driver can be limited to the probe and initialization
+       code. This allows easy integration of EISA support into the ISA
+       driver. However, the driver development kit from SMC provided the
+       register information for sliding the 8KB window, and hence the 8390
+       is programmed to use the full 32KB RAM.
+
+       Unfortunately this required code changes outside the probe/init
+       routines, and thus we decided to separate the EISA driver from
+       the ISA one. In this way, ISA users don't end up with a larger
+       driver due to the EISA code, and EISA users don't end up with a
+       larger driver due to the ISA EtherEZ PIO code. The driver is
+       similar to the 3c503/16 driver, in that the window must be set
+       back to the 1st 8KB of space for access to the two 8390 Tx slots.
+
+       In testing, using only 8KB RAM (3 Tx / 5 Rx) didn't appear to
+       be a limiting factor, since the EISA bus could get packets off
+       the card fast enough, but having the use of lots of RAM as Rx
+       space is extra insurance if interrupt latencies become excessive.
+
+*/
+
+static const char *version = "smc-ultra32.c: 06/97 v1.00\n";
+
+
+#include <linux/module.h>
+#include <linux/eisa.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+#define DRV_NAME "smc-ultra32"
+
+static int ultra32_probe1(struct net_device *dev, int ioaddr);
+static int ultra32_open(struct net_device *dev);
+static void ultra32_reset_8390(struct net_device *dev);
+static void ultra32_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                                int ring_page);
+static void ultra32_block_input(struct net_device *dev, int count,
+                               struct sk_buff *skb, int ring_offset);
+static void ultra32_block_output(struct net_device *dev, int count,
+                                const unsigned char *buf,
+                                const int start_page);
+static int ultra32_close(struct net_device *dev);
+
+#define ULTRA32_CMDREG 0       /* Offset to ASIC command register. */
+#define         ULTRA32_RESET  0x80    /* Board reset, in ULTRA32_CMDREG. */
+#define         ULTRA32_MEMENB 0x40    /* Enable the shared memory. */
+#define ULTRA32_NIC_OFFSET 16  /* NIC register offset from the base_addr. */
+#define ULTRA32_IO_EXTENT 32
+#define EN0_ERWCNT             0x08    /* Early receive warning count. */
+
+/*
+ * Defines that apply only to the Ultra32 EISA card. Note that
+ * "smc" = 10011 01101 00011 = 0x4da3, and hence !smc8010.cfg translates
+ * into an EISA ID of 0x1080A34D
+ */
+#define ULTRA32_BASE   0xca0
+#define ULTRA32_ID     0x1080a34d
+#define ULTRA32_IDPORT (-0x20) /* 0xc80 */
+/* Config regs 1->7 from the EISA !SMC8010.CFG file. */
+#define ULTRA32_CFG1   0x04    /* 0xca4 */
+#define ULTRA32_CFG2   0x05    /* 0xca5 */
+#define ULTRA32_CFG3   (-0x18) /* 0xc88 */
+#define ULTRA32_CFG4   (-0x17) /* 0xc89 */
+#define ULTRA32_CFG5   (-0x16) /* 0xc8a */
+#define ULTRA32_CFG6   (-0x15) /* 0xc8b */
+#define ULTRA32_CFG7   0x0d    /* 0xcad */
+
+static void cleanup_card(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET;
+       /* NB: ultra32_close_card() does free_irq */
+       release_region(ioaddr, ULTRA32_IO_EXTENT);
+       iounmap(ei_status.mem);
+}
+
+/*     Probe for the Ultra32.  This looks like a 8013 with the station
+       address PROM at I/O ports <base>+8 to <base>+13, with a checksum
+       following.
+*/
+
+struct net_device * __init ultra32_probe(int unit)
+{
+       struct net_device *dev;
+       int base;
+       int irq;
+       int err = -ENODEV;
+
+       if (!EISA_bus)
+               return ERR_PTR(-ENODEV);
+
+       dev = alloc_ei_netdev();
+
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       if (unit >= 0) {
+               sprintf(dev->name, "eth%d", unit);
+               netdev_boot_setup_check(dev);
+       }
+
+       irq = dev->irq;
+
+       /* EISA spec allows for up to 16 slots, but 8 is typical. */
+       for (base = 0x1000 + ULTRA32_BASE; base < 0x9000; base += 0x1000) {
+               if (ultra32_probe1(dev, base) == 0)
+                       break;
+               dev->irq = irq;
+       }
+       if (base >= 0x9000)
+               goto out;
+       err = register_netdev(dev);
+       if (err)
+               goto out1;
+       return dev;
+out1:
+       cleanup_card(dev);
+out:
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+
+
+static const struct net_device_ops ultra32_netdev_ops = {
+       .ndo_open               = ultra32_open,
+       .ndo_stop               = ultra32_close,
+       .ndo_start_xmit         = ei_start_xmit,
+       .ndo_tx_timeout         = ei_tx_timeout,
+       .ndo_get_stats          = ei_get_stats,
+       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = ei_poll,
+#endif
+};
+
+static int __init ultra32_probe1(struct net_device *dev, int ioaddr)
+{
+       int i, edge, media, retval;
+       int checksum = 0;
+       const char *model_name;
+       static unsigned version_printed;
+       /* Values from various config regs. */
+       unsigned char idreg;
+       unsigned char reg4;
+       const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"};
+
+       if (!request_region(ioaddr, ULTRA32_IO_EXTENT, DRV_NAME))
+               return -EBUSY;
+
+       if (inb(ioaddr + ULTRA32_IDPORT) == 0xff ||
+           inl(ioaddr + ULTRA32_IDPORT) != ULTRA32_ID) {
+               retval = -ENODEV;
+               goto out;
+       }
+
+       media = inb(ioaddr + ULTRA32_CFG7) & 0x03;
+       edge = inb(ioaddr + ULTRA32_CFG5) & 0x08;
+       printk("SMC Ultra32 in EISA Slot %d, Media: %s, %s IRQs.\n",
+               ioaddr >> 12, ifmap[media],
+               (edge ? "Edge Triggered" : "Level Sensitive"));
+
+       idreg = inb(ioaddr + 7);
+       reg4 = inb(ioaddr + 4) & 0x7f;
+
+       /* Check the ID nibble. */
+       if ((idreg & 0xf0) != 0x20) {                   /* SMC Ultra */
+               retval = -ENODEV;
+               goto out;
+       }
+
+       /* Select the station address register set. */
+       outb(reg4, ioaddr + 4);
+
+       for (i = 0; i < 8; i++)
+               checksum += inb(ioaddr + 8 + i);
+       if ((checksum & 0xff) != 0xff) {
+               retval = -ENODEV;
+               goto out;
+       }
+
+       if (ei_debug  &&  version_printed++ == 0)
+               printk(version);
+
+       model_name = "SMC Ultra32";
+
+       for (i = 0; i < 6; i++)
+               dev->dev_addr[i] = inb(ioaddr + 8 + i);
+
+       printk("%s: %s at 0x%X, %pM",
+              dev->name, model_name, ioaddr, dev->dev_addr);
+
+       /* Switch from the station address to the alternate register set and
+          read the useful registers there. */
+       outb(0x80 | reg4, ioaddr + 4);
+
+       /* Enable FINE16 mode to avoid BIOS ROM width mismatches @ reboot. */
+       outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
+
+       /* Reset RAM addr. */
+       outb(0x00, ioaddr + 0x0b);
+
+       /* Switch back to the station address register set so that the
+          MS-DOS driver can find the card after a warm boot. */
+       outb(reg4, ioaddr + 4);
+
+       if ((inb(ioaddr + ULTRA32_CFG5) & 0x40) == 0) {
+               printk("\nsmc-ultra32: Card RAM is disabled!  "
+                      "Run EISA config utility.\n");
+               retval = -ENODEV;
+               goto out;
+       }
+       if ((inb(ioaddr + ULTRA32_CFG2) & 0x04) == 0)
+               printk("\nsmc-ultra32: Ignoring Bus-Master enable bit.  "
+                      "Run EISA config utility.\n");
+
+       if (dev->irq < 2) {
+               unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15};
+               int irq = irqmap[inb(ioaddr + ULTRA32_CFG5) & 0x07];
+               if (irq == 0) {
+                       printk(", failed to detect IRQ line.\n");
+                       retval = -EAGAIN;
+                       goto out;
+               }
+               dev->irq = irq;
+       }
+
+       /* The 8390 isn't at the base address, so fake the offset */
+       dev->base_addr = ioaddr + ULTRA32_NIC_OFFSET;
+
+       /* Save RAM address in the unused reg0 to avoid excess inb's. */
+       ei_status.reg0 = inb(ioaddr + ULTRA32_CFG3) & 0xfc;
+
+       dev->mem_start =  0xc0000 + ((ei_status.reg0 & 0x7c) << 11);
+
+       ei_status.name = model_name;
+       ei_status.word16 = 1;
+       ei_status.tx_start_page = 0;
+       ei_status.rx_start_page = TX_PAGES;
+       /* All Ultra32 cards have 32KB memory with an 8KB window. */
+       ei_status.stop_page = 128;
+
+       ei_status.mem = ioremap(dev->mem_start, 0x2000);
+       if (!ei_status.mem) {
+               printk(", failed to ioremap.\n");
+               retval = -ENOMEM;
+               goto out;
+       }
+       dev->mem_end = dev->mem_start + 0x1fff;
+
+       printk(", IRQ %d, 32KB memory, 8KB window at 0x%lx-0x%lx.\n",
+              dev->irq, dev->mem_start, dev->mem_end);
+       ei_status.block_input = &ultra32_block_input;
+       ei_status.block_output = &ultra32_block_output;
+       ei_status.get_8390_hdr = &ultra32_get_8390_hdr;
+       ei_status.reset_8390 = &ultra32_reset_8390;
+
+       dev->netdev_ops = &ultra32_netdev_ops;
+       NS8390_init(dev, 0);
+
+       return 0;
+out:
+       release_region(ioaddr, ULTRA32_IO_EXTENT);
+       return retval;
+}
+
+static int ultra32_open(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* ASIC addr */
+       int irq_flags = (inb(ioaddr + ULTRA32_CFG5) & 0x08) ? 0 : IRQF_SHARED;
+       int retval;
+
+       retval = request_irq(dev->irq, ei_interrupt, irq_flags, dev->name, dev);
+       if (retval)
+               return retval;
+
+       outb(ULTRA32_MEMENB, ioaddr); /* Enable Shared Memory. */
+       outb(0x80, ioaddr + ULTRA32_CFG6); /* Enable Interrupts. */
+       outb(0x84, ioaddr + 5); /* Enable MEM16 & Disable Bus Master. */
+       outb(0x01, ioaddr + 6); /* Enable Interrupts. */
+       /* Set the early receive warning level in window 0 high enough not
+          to receive ERW interrupts. */
+       outb_p(E8390_NODMA+E8390_PAGE0, dev->base_addr);
+       outb(0xff, dev->base_addr + EN0_ERWCNT);
+       ei_open(dev);
+       return 0;
+}
+
+static int ultra32_close(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* CMDREG */
+
+       netif_stop_queue(dev);
+
+       if (ei_debug > 1)
+               printk("%s: Shutting down ethercard.\n", dev->name);
+
+       outb(0x00, ioaddr + ULTRA32_CFG6); /* Disable Interrupts. */
+       outb(0x00, ioaddr + 6);         /* Disable interrupts. */
+       free_irq(dev->irq, dev);
+
+       NS8390_init(dev, 0);
+
+       return 0;
+}
+
+static void ultra32_reset_8390(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* ASIC base addr */
+
+       outb(ULTRA32_RESET, ioaddr);
+       if (ei_debug > 1) printk("resetting Ultra32, t=%ld...", jiffies);
+       ei_status.txing = 0;
+
+       outb(ULTRA32_MEMENB, ioaddr); /* Enable Shared Memory. */
+       outb(0x80, ioaddr + ULTRA32_CFG6); /* Enable Interrupts. */
+       outb(0x84, ioaddr + 5); /* Enable MEM16 & Disable Bus Master. */
+       outb(0x01, ioaddr + 6); /* Enable Interrupts. */
+       if (ei_debug > 1) printk("reset done\n");
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void ultra32_get_8390_hdr(struct net_device *dev,
+                                struct e8390_pkt_hdr *hdr,
+                                int ring_page)
+{
+       void __iomem *hdr_start = ei_status.mem + ((ring_page & 0x1f) << 8);
+       unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3;
+
+       /* Select correct 8KB Window. */
+       outb(ei_status.reg0 | ((ring_page & 0x60) >> 5), RamReg);
+
+#ifdef __BIG_ENDIAN
+       /* Officially this is what we are doing, but the readl() is faster */
+       /* unfortunately it isn't endian aware of the struct               */
+       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+       hdr->count = le16_to_cpu(hdr->count);
+#else
+       ((unsigned int*)hdr)[0] = readl(hdr_start);
+#endif
+}
+
+/* Block input and output are easy on shared memory ethercards, the only
+   complication is when the ring buffer wraps, or in this case, when a
+   packet spans an 8KB boundary. Note that the current 8KB segment is
+   already set by the get_8390_hdr routine. */
+
+static void ultra32_block_input(struct net_device *dev,
+                               int count,
+                               struct sk_buff *skb,
+                               int ring_offset)
+{
+       void __iomem *xfer_start = ei_status.mem + (ring_offset & 0x1fff);
+       unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3;
+
+       if ((ring_offset & ~0x1fff) != ((ring_offset + count - 1) & ~0x1fff)) {
+               int semi_count = 8192 - (ring_offset & 0x1FFF);
+               memcpy_fromio(skb->data, xfer_start, semi_count);
+               count -= semi_count;
+               if (ring_offset < 96*256) {
+                       /* Select next 8KB Window. */
+                       ring_offset += semi_count;
+                       outb(ei_status.reg0 | ((ring_offset & 0x6000) >> 13), RamReg);
+                       memcpy_fromio(skb->data + semi_count, ei_status.mem, count);
+               } else {
+                       /* Select first 8KB Window. */
+                       outb(ei_status.reg0, RamReg);
+                       memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
+               }
+       } else {
+               memcpy_fromio(skb->data, xfer_start, count);
+       }
+}
+
+static void ultra32_block_output(struct net_device *dev,
+                                int count,
+                                const unsigned char *buf,
+                                int start_page)
+{
+       void __iomem *xfer_start = ei_status.mem + (start_page<<8);
+       unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3;
+
+       /* Select first 8KB Window. */
+       outb(ei_status.reg0, RamReg);
+
+       memcpy_toio(xfer_start, buf, count);
+}
+
+#ifdef MODULE
+#define MAX_ULTRA32_CARDS   4  /* Max number of Ultra cards per module */
+static struct net_device *dev_ultra[MAX_ULTRA32_CARDS];
+
+MODULE_DESCRIPTION("SMC Ultra32 EISA ethernet driver");
+MODULE_LICENSE("GPL");
+
+int __init init_module(void)
+{
+       int this_dev, found = 0;
+
+       for (this_dev = 0; this_dev < MAX_ULTRA32_CARDS; this_dev++) {
+               struct net_device *dev = ultra32_probe(-1);
+               if (IS_ERR(dev))
+                       break;
+               dev_ultra[found++] = dev;
+       }
+       if (found)
+               return 0;
+       printk(KERN_WARNING "smc-ultra32.c: No SMC Ultra32 found.\n");
+       return -ENXIO;
+}
+
+void __exit cleanup_module(void)
+{
+       int this_dev;
+
+       for (this_dev = 0; this_dev < MAX_ULTRA32_CARDS; this_dev++) {
+               struct net_device *dev = dev_ultra[this_dev];
+               if (dev) {
+                       unregister_netdev(dev);
+                       cleanup_card(dev);
+                       free_netdev(dev);
+               }
+       }
+}
+#endif /* MODULE */
+
diff --git a/drivers/net/ethernet/8390/stnic.c b/drivers/net/ethernet/8390/stnic.c
new file mode 100644 (file)
index 0000000..d85f0a8
--- /dev/null
@@ -0,0 +1,294 @@
+/* stnic.c : A SH7750 specific part of driver for NS DP83902A ST-NIC.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999 kaz Kojima
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <mach-se/mach/se.h>
+#include <asm/machvec.h>
+#ifdef CONFIG_SH_STANDARD_BIOS
+#include <asm/sh_bios.h>
+#endif
+
+#include "8390.h"
+
+#define DRV_NAME "stnic"
+
+#define byte   unsigned char
+#define half   unsigned short
+#define word   unsigned int
+#define vbyte  volatile unsigned char
+#define vhalf  volatile unsigned short
+#define vword  volatile unsigned int
+
+#define STNIC_RUN      0x01    /* 1 == Run, 0 == reset. */
+
+#define START_PG       0       /* First page of TX buffer */
+#define STOP_PG                128     /* Last page +1 of RX ring */
+
+/* Alias */
+#define STNIC_CR       E8390_CMD
+#define PG0_RSAR0      EN0_RSARLO
+#define PG0_RSAR1      EN0_RSARHI
+#define PG0_RBCR0      EN0_RCNTLO
+#define PG0_RBCR1      EN0_RCNTHI
+
+#define CR_RRD         E8390_RREAD
+#define CR_RWR         E8390_RWRITE
+#define CR_PG0         E8390_PAGE0
+#define CR_STA         E8390_START
+#define CR_RDMA                E8390_NODMA
+
+/* FIXME! YOU MUST SET YOUR OWN ETHER ADDRESS.  */
+static byte stnic_eadr[6] =
+{0x00, 0xc0, 0x6e, 0x00, 0x00, 0x07};
+
+static struct net_device *stnic_dev;
+
+static void stnic_reset (struct net_device *dev);
+static void stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                          int ring_page);
+static void stnic_block_input (struct net_device *dev, int count,
+                              struct sk_buff *skb , int ring_offset);
+static void stnic_block_output (struct net_device *dev, int count,
+                               const unsigned char *buf, int start_page);
+
+static void stnic_init (struct net_device *dev);
+
+/* SH7750 specific read/write io. */
+static inline void
+STNIC_DELAY (void)
+{
+  vword trash;
+  trash = *(vword *) 0xa0000000;
+  trash = *(vword *) 0xa0000000;
+  trash = *(vword *) 0xa0000000;
+}
+
+static inline byte
+STNIC_READ (int reg)
+{
+  byte val;
+
+  val = (*(vhalf *) (PA_83902 + ((reg) << 1)) >> 8) & 0xff;
+  STNIC_DELAY ();
+  return val;
+}
+
+static inline void
+STNIC_WRITE (int reg, byte val)
+{
+  *(vhalf *) (PA_83902 + ((reg) << 1)) = ((half) (val) << 8);
+  STNIC_DELAY ();
+}
+
+static int __init stnic_probe(void)
+{
+  struct net_device *dev;
+  int i, err;
+
+  /* If we are not running on a SolutionEngine, give up now */
+  if (! MACH_SE)
+    return -ENODEV;
+
+  /* New style probing API */
+  dev = alloc_ei_netdev();
+  if (!dev)
+       return -ENOMEM;
+
+#ifdef CONFIG_SH_STANDARD_BIOS
+  sh_bios_get_node_addr (stnic_eadr);
+#endif
+  for (i = 0; i < ETHER_ADDR_LEN; i++)
+    dev->dev_addr[i] = stnic_eadr[i];
+
+  /* Set the base address to point to the NIC, not the "real" base! */
+  dev->base_addr = 0x1000;
+  dev->irq = IRQ_STNIC;
+  dev->netdev_ops = &ei_netdev_ops;
+
+  /* Snarf the interrupt now.  There's no point in waiting since we cannot
+     share and the board will usually be enabled. */
+  err = request_irq (dev->irq, ei_interrupt, 0, DRV_NAME, dev);
+  if (err)  {
+      printk (KERN_EMERG " unable to get IRQ %d.\n", dev->irq);
+      free_netdev(dev);
+      return err;
+    }
+
+  ei_status.name = dev->name;
+  ei_status.word16 = 1;
+#ifdef __LITTLE_ENDIAN__
+  ei_status.bigendian = 0;
+#else
+  ei_status.bigendian = 1;
+#endif
+  ei_status.tx_start_page = START_PG;
+  ei_status.rx_start_page = START_PG + TX_PAGES;
+  ei_status.stop_page = STOP_PG;
+
+  ei_status.reset_8390 = &stnic_reset;
+  ei_status.get_8390_hdr = &stnic_get_hdr;
+  ei_status.block_input = &stnic_block_input;
+  ei_status.block_output = &stnic_block_output;
+
+  stnic_init (dev);
+
+  err = register_netdev(dev);
+  if (err) {
+    free_irq(dev->irq, dev);
+    free_netdev(dev);
+    return err;
+  }
+  stnic_dev = dev;
+
+  printk (KERN_INFO "NS ST-NIC 83902A\n");
+
+  return 0;
+}
+
+static void
+stnic_reset (struct net_device *dev)
+{
+  *(vhalf *) PA_83902_RST = 0;
+  udelay (5);
+  if (ei_debug > 1)
+    printk (KERN_WARNING "8390 reset done (%ld).\n", jiffies);
+  *(vhalf *) PA_83902_RST = ~0;
+  udelay (5);
+}
+
+static void
+stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
+              int ring_page)
+{
+  half buf[2];
+
+  STNIC_WRITE (PG0_RSAR0, 0);
+  STNIC_WRITE (PG0_RSAR1, ring_page);
+  STNIC_WRITE (PG0_RBCR0, 4);
+  STNIC_WRITE (PG0_RBCR1, 0);
+  STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
+
+  buf[0] = *(vhalf *) PA_83902_IF;
+  STNIC_DELAY ();
+  buf[1] = *(vhalf *) PA_83902_IF;
+  STNIC_DELAY ();
+  hdr->next = buf[0] >> 8;
+  hdr->status = buf[0] & 0xff;
+#ifdef __LITTLE_ENDIAN__
+  hdr->count = buf[1];
+#else
+  hdr->count = ((buf[1] >> 8) & 0xff) | (buf[1] << 8);
+#endif
+
+  if (ei_debug > 1)
+    printk (KERN_DEBUG "ring %x status %02x next %02x count %04x.\n",
+           ring_page, hdr->status, hdr->next, hdr->count);
+
+  STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
+}
+
+/* Block input and output, similar to the Crynwr packet driver. If you are
+   porting to a new ethercard look at the packet driver source for hints.
+   The HP LAN doesn't use shared memory -- we put the packet
+   out through the "remote DMA" dataport. */
+
+static void
+stnic_block_input (struct net_device *dev, int length, struct sk_buff *skb,
+                  int offset)
+{
+  char *buf = skb->data;
+  half val;
+
+  STNIC_WRITE (PG0_RSAR0, offset & 0xff);
+  STNIC_WRITE (PG0_RSAR1, offset >> 8);
+  STNIC_WRITE (PG0_RBCR0, length & 0xff);
+  STNIC_WRITE (PG0_RBCR1, length >> 8);
+  STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
+
+  if (length & 1)
+    length++;
+
+  while (length > 0)
+    {
+      val = *(vhalf *) PA_83902_IF;
+#ifdef __LITTLE_ENDIAN__
+      *buf++ = val & 0xff;
+      *buf++ = val >> 8;
+#else
+      *buf++ = val >> 8;
+      *buf++ = val & 0xff;
+#endif
+      STNIC_DELAY ();
+      length -= sizeof (half);
+    }
+
+  STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
+}
+
+static void
+stnic_block_output (struct net_device *dev, int length,
+                   const unsigned char *buf, int output_page)
+{
+  STNIC_WRITE (PG0_RBCR0, 1);  /* Write non-zero value */
+  STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
+  STNIC_DELAY ();
+
+  STNIC_WRITE (PG0_RBCR0, length & 0xff);
+  STNIC_WRITE (PG0_RBCR1, length >> 8);
+  STNIC_WRITE (PG0_RSAR0, 0);
+  STNIC_WRITE (PG0_RSAR1, output_page);
+  STNIC_WRITE (STNIC_CR, CR_RWR | CR_PG0 | CR_STA);
+
+  if (length & 1)
+    length++;
+
+  while (length > 0)
+    {
+#ifdef __LITTLE_ENDIAN__
+      *(vhalf *) PA_83902_IF = ((half) buf[1] << 8) | buf[0];
+#else
+      *(vhalf *) PA_83902_IF = ((half) buf[0] << 8) | buf[1];
+#endif
+      STNIC_DELAY ();
+      buf += sizeof (half);
+      length -= sizeof (half);
+    }
+
+  STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
+}
+
+/* This function resets the STNIC if something screws up.  */
+static void
+stnic_init (struct net_device *dev)
+{
+  stnic_reset (dev);
+  NS8390_init (dev, 0);
+}
+
+static void __exit stnic_cleanup(void)
+{
+       unregister_netdev(stnic_dev);
+       free_irq(stnic_dev->irq, stnic_dev);
+       free_netdev(stnic_dev);
+}
+
+module_init(stnic_probe);
+module_exit(stnic_cleanup);
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/8390/wd.c b/drivers/net/ethernet/8390/wd.c
new file mode 100644 (file)
index 0000000..8831a33
--- /dev/null
@@ -0,0 +1,567 @@
+/* wd.c: A WD80x3 ethernet driver for linux. */
+/*
+       Written 1993-94 by Donald Becker.
+
+       Copyright 1993 United States Government as represented by the
+       Director, National Security Agency.
+
+       This software may be used and distributed according to the terms
+       of the GNU General Public License, incorporated herein by reference.
+
+       The author may be reached as becker@scyld.com, or C/O
+       Scyld Computing Corporation
+       410 Severn Ave., Suite 210
+       Annapolis MD 21403
+
+       This is a driver for WD8003 and WD8013 "compatible" ethercards.
+
+       Thanks to Russ Nelson (nelson@crnwyr.com) for loaning me a WD8013.
+
+       Changelog:
+
+       Paul Gortmaker  : multiple card support for module users, support
+                         for non-standard memory sizes.
+
+
+*/
+
+static const char version[] =
+       "wd.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include "8390.h"
+
+#define DRV_NAME "wd"
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int wd_portlist[] __initdata =
+{0x300, 0x280, 0x380, 0x240, 0};
+
+static int wd_probe1(struct net_device *dev, int ioaddr);
+
+static int wd_open(struct net_device *dev);
+static void wd_reset_8390(struct net_device *dev);
+static void wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                                               int ring_page);
+static void wd_block_input(struct net_device *dev, int count,
+                                                 struct sk_buff *skb, int ring_offset);
+static void wd_block_output(struct net_device *dev, int count,
+                                                       const unsigned char *buf, int start_page);
+static int wd_close(struct net_device *dev);
+
+
+#define WD_START_PG            0x00    /* First page of TX buffer */
+#define WD03_STOP_PG   0x20    /* Last page +1 of RX ring */
+#define WD13_STOP_PG   0x40    /* Last page +1 of RX ring */
+
+#define WD_CMDREG              0               /* Offset to ASIC command register. */
+#define         WD_RESET               0x80    /* Board reset, in WD_CMDREG. */
+#define         WD_MEMENB              0x40    /* Enable the shared memory. */
+#define WD_CMDREG5             5               /* Offset to 16-bit-only ASIC register 5. */
+#define         ISA16                  0x80    /* Enable 16 bit access from the ISA bus. */
+#define         NIC16                  0x40    /* Enable 16 bit access from the 8390. */
+#define WD_NIC_OFFSET  16              /* Offset to the 8390 from the base_addr. */
+#define WD_IO_EXTENT   32
+
+
+/*     Probe for the WD8003 and WD8013.  These cards have the station
+       address PROM at I/O ports <base>+8 to <base>+13, with a checksum
+       following. A Soundblaster can have the same checksum as an WDethercard,
+       so we have an extra exclusionary check for it.
+
+       The wd_probe1() routine initializes the card and fills the
+       station address field. */
+
+static int __init do_wd_probe(struct net_device *dev)
+{
+       int i;
+       struct resource *r;
+       int base_addr = dev->base_addr;
+       int irq = dev->irq;
+       int mem_start = dev->mem_start;
+       int mem_end = dev->mem_end;
+
+       if (base_addr > 0x1ff) {        /* Check a user specified location. */
+               r = request_region(base_addr, WD_IO_EXTENT, "wd-probe");
+               if ( r == NULL)
+                       return -EBUSY;
+               i = wd_probe1(dev, base_addr);
+               if (i != 0)
+                       release_region(base_addr, WD_IO_EXTENT);
+               else
+                       r->name = dev->name;
+               return i;
+       }
+       else if (base_addr != 0)        /* Don't probe at all. */
+               return -ENXIO;
+
+       for (i = 0; wd_portlist[i]; i++) {
+               int ioaddr = wd_portlist[i];
+               r = request_region(ioaddr, WD_IO_EXTENT, "wd-probe");
+               if (r == NULL)
+                       continue;
+               if (wd_probe1(dev, ioaddr) == 0) {
+                       r->name = dev->name;
+                       return 0;
+               }
+               release_region(ioaddr, WD_IO_EXTENT);
+               dev->irq = irq;
+               dev->mem_start = mem_start;
+               dev->mem_end = mem_end;
+       }
+
+       return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init wd_probe(int unit)
+{
+       struct net_device *dev = alloc_ei_netdev();
+       int err;
+
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       sprintf(dev->name, "eth%d", unit);
+       netdev_boot_setup_check(dev);
+
+       err = do_wd_probe(dev);
+       if (err)
+               goto out;
+       return dev;
+out:
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops wd_netdev_ops = {
+       .ndo_open               = wd_open,
+       .ndo_stop               = wd_close,
+       .ndo_start_xmit         = ei_start_xmit,
+       .ndo_tx_timeout         = ei_tx_timeout,
+       .ndo_get_stats          = ei_get_stats,
+       .ndo_set_multicast_list = ei_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = ei_poll,
+#endif
+};
+
+static int __init wd_probe1(struct net_device *dev, int ioaddr)
+{
+       int i;
+       int err;
+       int checksum = 0;
+       int ancient = 0;                        /* An old card without config registers. */
+       int word16 = 0;                         /* 0 = 8 bit, 1 = 16 bit */
+       const char *model_name;
+       static unsigned version_printed;
+
+       for (i = 0; i < 8; i++)
+               checksum += inb(ioaddr + 8 + i);
+       if (inb(ioaddr + 8) == 0xff     /* Extra check to avoid soundcard. */
+               || inb(ioaddr + 9) == 0xff
+               || (checksum & 0xff) != 0xFF)
+               return -ENODEV;
+
+       /* Check for semi-valid mem_start/end values if supplied. */
+       if ((dev->mem_start % 0x2000) || (dev->mem_end % 0x2000)) {
+               printk(KERN_WARNING "wd.c: user supplied mem_start or mem_end not on 8kB boundary - ignored.\n");
+               dev->mem_start = 0;
+               dev->mem_end = 0;
+       }
+
+       if (ei_debug  &&  version_printed++ == 0)
+               printk(version);
+
+       for (i = 0; i < 6; i++)
+               dev->dev_addr[i] = inb(ioaddr + 8 + i);
+
+       printk("%s: WD80x3 at %#3x, %pM",
+              dev->name, ioaddr, dev->dev_addr);
+
+       /* The following PureData probe code was contributed by
+          Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata does software
+          configuration differently from others so we have to check for them.
+          This detects an 8 bit, 16 bit or dumb (Toshiba, jumpered) card.
+          */
+       if (inb(ioaddr+0) == 'P' && inb(ioaddr+1) == 'D') {
+               unsigned char reg5 = inb(ioaddr+5);
+
+               switch (inb(ioaddr+2)) {
+               case 0x03: word16 = 0; model_name = "PDI8023-8";        break;
+               case 0x05: word16 = 0; model_name = "PDUC8023"; break;
+               case 0x0a: word16 = 1; model_name = "PDI8023-16"; break;
+                       /* Either 0x01 (dumb) or they've released a new version. */
+               default:         word16 = 0; model_name = "PDI8023";    break;
+               }
+               dev->mem_start = ((reg5 & 0x1c) + 0xc0) << 12;
+               dev->irq = (reg5 & 0xe0) == 0xe0 ? 10 : (reg5 >> 5) + 1;
+       } else {                                                                /* End of PureData probe */
+               /* This method of checking for a 16-bit board is borrowed from the
+                  we.c driver.  A simpler method is just to look in ASIC reg. 0x03.
+                  I'm comparing the two method in alpha test to make certain they
+                  return the same result. */
+               /* Check for the old 8 bit board - it has register 0/8 aliasing.
+                  Do NOT check i>=6 here -- it hangs the old 8003 boards! */
+               for (i = 0; i < 6; i++)
+                       if (inb(ioaddr+i) != inb(ioaddr+8+i))
+                               break;
+               if (i >= 6) {
+                       ancient = 1;
+                       model_name = "WD8003-old";
+                       word16 = 0;
+               } else {
+                       int tmp = inb(ioaddr+1); /* fiddle with 16bit bit */
+                       outb( tmp ^ 0x01, ioaddr+1 ); /* attempt to clear 16bit bit */
+                       if (((inb( ioaddr+1) & 0x01) == 0x01) /* A 16 bit card */
+                               && (tmp & 0x01) == 0x01 ) {                             /* In a 16 slot. */
+                               int asic_reg5 = inb(ioaddr+WD_CMDREG5);
+                               /* Magic to set ASIC to word-wide mode. */
+                               outb( NIC16 | (asic_reg5&0x1f), ioaddr+WD_CMDREG5);
+                               outb(tmp, ioaddr+1);
+                               model_name = "WD8013";
+                               word16 = 1;             /* We have a 16bit board here! */
+                       } else {
+                               model_name = "WD8003";
+                               word16 = 0;
+                       }
+                       outb(tmp, ioaddr+1);                    /* Restore original reg1 value. */
+               }
+#ifndef final_version
+               if ( !ancient && (inb(ioaddr+1) & 0x01) != (word16 & 0x01))
+                       printk("\nWD80?3: Bus width conflict, %d (probe) != %d (reg report).",
+                                  word16 ? 16 : 8, (inb(ioaddr+1) & 0x01) ? 16 : 8);
+#endif
+       }
+
+#if defined(WD_SHMEM) && WD_SHMEM > 0x80000
+       /* Allow a compile-time override.        */
+       dev->mem_start = WD_SHMEM;
+#else
+       if (dev->mem_start == 0) {
+               /* Sanity and old 8003 check */
+               int reg0 = inb(ioaddr);
+               if (reg0 == 0xff || reg0 == 0) {
+                       /* Future plan: this could check a few likely locations first. */
+                       dev->mem_start = 0xd0000;
+                       printk(" assigning address %#lx", dev->mem_start);
+               } else {
+                       int high_addr_bits = inb(ioaddr+WD_CMDREG5) & 0x1f;
+                       /* Some boards don't have the register 5 -- it returns 0xff. */
+                       if (high_addr_bits == 0x1f || word16 == 0)
+                               high_addr_bits = 0x01;
+                       dev->mem_start = ((reg0&0x3f) << 13) + (high_addr_bits << 19);
+               }
+       }
+#endif
+
+       /* The 8390 isn't at the base address -- the ASIC regs are there! */
+       dev->base_addr = ioaddr+WD_NIC_OFFSET;
+
+       if (dev->irq < 2) {
+               static const int irqmap[] = {9, 3, 5, 7, 10, 11, 15, 4};
+               int reg1 = inb(ioaddr+1);
+               int reg4 = inb(ioaddr+4);
+               if (ancient || reg1 == 0xff) {  /* Ack!! No way to read the IRQ! */
+                       short nic_addr = ioaddr+WD_NIC_OFFSET;
+                       unsigned long irq_mask;
+
+                       /* We have an old-style ethercard that doesn't report its IRQ
+                          line.  Do autoirq to find the IRQ line. Note that this IS NOT
+                          a reliable way to trigger an interrupt. */
+                       outb_p(E8390_NODMA + E8390_STOP, nic_addr);
+                       outb(0x00, nic_addr+EN0_IMR);   /* Disable all intrs. */
+
+                       irq_mask = probe_irq_on();
+                       outb_p(0xff, nic_addr + EN0_IMR);       /* Enable all interrupts. */
+                       outb_p(0x00, nic_addr + EN0_RCNTLO);
+                       outb_p(0x00, nic_addr + EN0_RCNTHI);
+                       outb(E8390_RREAD+E8390_START, nic_addr); /* Trigger it... */
+                       mdelay(20);
+                       dev->irq = probe_irq_off(irq_mask);
+
+                       outb_p(0x00, nic_addr+EN0_IMR); /* Mask all intrs. again. */
+
+                       if (ei_debug > 2)
+                               printk(" autoirq is %d", dev->irq);
+                       if (dev->irq < 2)
+                               dev->irq = word16 ? 10 : 5;
+               } else
+                       dev->irq = irqmap[((reg4 >> 5) & 0x03) + (reg1 & 0x04)];
+       } else if (dev->irq == 2)               /* Fixup bogosity: IRQ2 is really IRQ9 */
+               dev->irq = 9;
+
+       /* Snarf the interrupt now.  There's no point in waiting since we cannot
+          share and the board will usually be enabled. */
+       i = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
+       if (i) {
+               printk (" unable to get IRQ %d.\n", dev->irq);
+               return i;
+       }
+
+       /* OK, were are certain this is going to work.  Setup the device. */
+       ei_status.name = model_name;
+       ei_status.word16 = word16;
+       ei_status.tx_start_page = WD_START_PG;
+       ei_status.rx_start_page = WD_START_PG + TX_PAGES;
+
+       /* Don't map in the shared memory until the board is actually opened. */
+
+       /* Some cards (eg WD8003EBT) can be jumpered for more (32k!) memory. */
+       if (dev->mem_end != 0) {
+               ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
+               ei_status.priv = dev->mem_end - dev->mem_start;
+       } else {
+               ei_status.stop_page = word16 ? WD13_STOP_PG : WD03_STOP_PG;
+               dev->mem_end = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256;
+               ei_status.priv = (ei_status.stop_page - WD_START_PG)*256;
+       }
+
+       ei_status.mem = ioremap(dev->mem_start, ei_status.priv);
+       if (!ei_status.mem) {
+               free_irq(dev->irq, dev);
+               return -ENOMEM;
+       }
+
+       printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
+                  model_name, dev->irq, dev->mem_start, dev->mem_end-1);
+
+       ei_status.reset_8390 = wd_reset_8390;
+       ei_status.block_input = wd_block_input;
+       ei_status.block_output = wd_block_output;
+       ei_status.get_8390_hdr = wd_get_8390_hdr;
+
+       dev->netdev_ops = &wd_netdev_ops;
+       NS8390_init(dev, 0);
+
+#if 1
+       /* Enable interrupt generation on softconfig cards -- M.U */
+       /* .. but possibly potentially unsafe - Donald */
+       if (inb(ioaddr+14) & 0x20)
+               outb(inb(ioaddr+4)|0x80, ioaddr+4);
+#endif
+
+       err = register_netdev(dev);
+       if (err) {
+               free_irq(dev->irq, dev);
+               iounmap(ei_status.mem);
+       }
+       return err;
+}
+
+static int
+wd_open(struct net_device *dev)
+{
+  int ioaddr = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
+
+  /* Map in the shared memory. Always set register 0 last to remain
+        compatible with very old boards. */
+  ei_status.reg0 = ((dev->mem_start>>13) & 0x3f) | WD_MEMENB;
+  ei_status.reg5 = ((dev->mem_start>>19) & 0x1f) | NIC16;
+
+  if (ei_status.word16)
+         outb(ei_status.reg5, ioaddr+WD_CMDREG5);
+  outb(ei_status.reg0, ioaddr); /* WD_CMDREG */
+
+  return ei_open(dev);
+}
+
+static void
+wd_reset_8390(struct net_device *dev)
+{
+       int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
+
+       outb(WD_RESET, wd_cmd_port);
+       if (ei_debug > 1) printk("resetting the WD80x3 t=%lu...", jiffies);
+       ei_status.txing = 0;
+
+       /* Set up the ASIC registers, just in case something changed them. */
+       outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmd_port);
+       if (ei_status.word16)
+               outb(NIC16 | ((dev->mem_start>>19) & 0x1f), wd_cmd_port+WD_CMDREG5);
+
+       if (ei_debug > 1) printk("reset done\n");
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void
+wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+{
+
+       int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
+       void __iomem *hdr_start = ei_status.mem + ((ring_page - WD_START_PG)<<8);
+
+       /* We'll always get a 4 byte header read followed by a packet read, so
+          we enable 16 bit mode before the header, and disable after the body. */
+       if (ei_status.word16)
+               outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
+
+#ifdef __BIG_ENDIAN
+       /* Officially this is what we are doing, but the readl() is faster */
+       /* unfortunately it isn't endian aware of the struct               */
+       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+       hdr->count = le16_to_cpu(hdr->count);
+#else
+       ((unsigned int*)hdr)[0] = readl(hdr_start);
+#endif
+}
+
+/* Block input and output are easy on shared memory ethercards, and trivial
+   on the Western digital card where there is no choice of how to do it.
+   The only complications are that the ring buffer wraps, and need to map
+   switch between 8- and 16-bit modes. */
+
+static void
+wd_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
+{
+       int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
+       unsigned long offset = ring_offset - (WD_START_PG<<8);
+       void __iomem *xfer_start = ei_status.mem + offset;
+
+       if (offset + count > ei_status.priv) {
+               /* We must wrap the input move. */
+               int semi_count = ei_status.priv - offset;
+               memcpy_fromio(skb->data, xfer_start, semi_count);
+               count -= semi_count;
+               memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
+       } else {
+               /* Packet is in one chunk -- we can copy + cksum. */
+               memcpy_fromio(skb->data, xfer_start, count);
+       }
+
+       /* Turn off 16 bit access so that reboot works.  ISA brain-damage */
+       if (ei_status.word16)
+               outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
+}
+
+static void
+wd_block_output(struct net_device *dev, int count, const unsigned char *buf,
+                               int start_page)
+{
+       int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
+       void __iomem *shmem = ei_status.mem + ((start_page - WD_START_PG)<<8);
+
+
+       if (ei_status.word16) {
+               /* Turn on and off 16 bit access so that reboot works. */
+               outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
+               memcpy_toio(shmem, buf, count);
+               outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
+       } else
+               memcpy_toio(shmem, buf, count);
+}
+
+
+static int
+wd_close(struct net_device *dev)
+{
+       int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
+
+       if (ei_debug > 1)
+               printk("%s: Shutting down ethercard.\n", dev->name);
+       ei_close(dev);
+
+       /* Change from 16-bit to 8-bit shared memory so reboot works. */
+       if (ei_status.word16)
+               outb(ei_status.reg5, wd_cmdreg + WD_CMDREG5 );
+
+       /* And disable the shared memory. */
+       outb(ei_status.reg0 & ~WD_MEMENB, wd_cmdreg);
+
+       return 0;
+}
+
+
+#ifdef MODULE
+#define MAX_WD_CARDS   4       /* Max number of wd cards per module */
+static struct net_device *dev_wd[MAX_WD_CARDS];
+static int io[MAX_WD_CARDS];
+static int irq[MAX_WD_CARDS];
+static int mem[MAX_WD_CARDS];
+static int mem_end[MAX_WD_CARDS];      /* for non std. mem size */
+
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(mem, int, NULL, 0);
+module_param_array(mem_end, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es)");
+MODULE_PARM_DESC(irq, "IRQ number(s) (ignored for PureData boards)");
+MODULE_PARM_DESC(mem, "memory base address(es)(ignored for PureData boards)");
+MODULE_PARM_DESC(mem_end, "memory end address(es)");
+MODULE_DESCRIPTION("ISA Western Digital wd8003/wd8013 ; SMC Elite, Elite16 ethernet driver");
+MODULE_LICENSE("GPL");
+
+/* This is set up so that only a single autoprobe takes place per call.
+ISA device autoprobes on a running machine are not recommended. */
+
+int __init init_module(void)
+{
+       struct net_device *dev;
+       int this_dev, found = 0;
+
+       for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
+               if (io[this_dev] == 0)  {
+                       if (this_dev != 0) break; /* only autoprobe 1st one */
+                       printk(KERN_NOTICE "wd.c: Presently autoprobing (not recommended) for a single card.\n");
+               }
+               dev = alloc_ei_netdev();
+               if (!dev)
+                       break;
+               dev->irq = irq[this_dev];
+               dev->base_addr = io[this_dev];
+               dev->mem_start = mem[this_dev];
+               dev->mem_end = mem_end[this_dev];
+               if (do_wd_probe(dev) == 0) {
+                       dev_wd[found++] = dev;
+                       continue;
+               }
+               free_netdev(dev);
+               printk(KERN_WARNING "wd.c: No wd80x3 card found (i/o = 0x%x).\n", io[this_dev]);
+               break;
+       }
+       if (found)
+               return 0;
+       return -ENXIO;
+}
+
+static void cleanup_card(struct net_device *dev)
+{
+       free_irq(dev->irq, dev);
+       release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT);
+       iounmap(ei_status.mem);
+}
+
+void __exit
+cleanup_module(void)
+{
+       int this_dev;
+
+       for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
+               struct net_device *dev = dev_wd[this_dev];
+               if (dev) {
+                       unregister_netdev(dev);
+                       cleanup_card(dev);
+                       free_netdev(dev);
+               }
+       }
+}
+#endif /* MODULE */
diff --git a/drivers/net/ethernet/8390/zorro8390.c b/drivers/net/ethernet/8390/zorro8390.c
new file mode 100644 (file)
index 0000000..15e7751
--- /dev/null
@@ -0,0 +1,452 @@
+/*
+ *  Amiga Linux/m68k and Linux/PPC Zorro NS8390 Ethernet Driver
+ *
+ *  (C) Copyright 1998-2000 by some Elitist 680x0 Users(TM)
+ *
+ *  ---------------------------------------------------------------------------
+ *
+ *  This program is based on all the other NE2000 drivers for Linux
+ *
+ *  ---------------------------------------------------------------------------
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of the Linux
+ *  distribution for more details.
+ *
+ *  ---------------------------------------------------------------------------
+ *
+ *  The Ariadne II and X-Surf are Zorro-II boards containing Realtek RTL8019AS
+ *  Ethernet Controllers.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/zorro.h>
+#include <linux/jiffies.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+
+#define EI_SHIFT(x)            (ei_local->reg_offset[x])
+#define ei_inb(port)           in_8(port)
+#define ei_outb(val, port)     out_8(port, val)
+#define ei_inb_p(port)         in_8(port)
+#define ei_outb_p(val, port)   out_8(port, val)
+
+static const char version[] =
+       "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#include "lib8390.c"
+
+#define DRV_NAME       "zorro8390"
+
+#define NE_BASE                (dev->base_addr)
+#define NE_CMD         (0x00 * 2)
+#define NE_DATAPORT    (0x10 * 2)      /* NatSemi-defined port window offset */
+#define NE_RESET       (0x1f * 2)      /* Issue a read to reset,
+                                        * a write to clear. */
+#define NE_IO_EXTENT   (0x20 * 2)
+
+#define NE_EN0_ISR     (0x07 * 2)
+#define NE_EN0_DCFG    (0x0e * 2)
+
+#define NE_EN0_RSARLO  (0x08 * 2)
+#define NE_EN0_RSARHI  (0x09 * 2)
+#define NE_EN0_RCNTLO  (0x0a * 2)
+#define NE_EN0_RXCR    (0x0c * 2)
+#define NE_EN0_TXCR    (0x0d * 2)
+#define NE_EN0_RCNTHI  (0x0b * 2)
+#define NE_EN0_IMR     (0x0f * 2)
+
+#define NESM_START_PG  0x40    /* First page of TX buffer */
+#define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
+
+#define WORDSWAP(a)    ((((a) >> 8) & 0xff) | ((a) << 8))
+
+static struct card_info {
+       zorro_id id;
+       const char *name;
+       unsigned int offset;
+} cards[] __devinitdata = {
+       { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 },
+       { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 },
+};
+
+/* Hard reset the card.  This used to pause for the same period that a
+ * 8390 reset command required, but that shouldn't be necessary.
+ */
+static void zorro8390_reset_8390(struct net_device *dev)
+{
+       unsigned long reset_start_time = jiffies;
+
+       if (ei_debug > 1)
+               netdev_dbg(dev, "resetting - t=%ld...\n", jiffies);
+
+       z_writeb(z_readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+       ei_status.txing = 0;
+       ei_status.dmaing = 0;
+
+       /* This check _should_not_ be necessary, omit eventually. */
+       while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RESET) == 0)
+               if (time_after(jiffies, reset_start_time + 2 * HZ / 100)) {
+                       netdev_warn(dev, "%s: did not complete\n", __func__);
+                       break;
+               }
+       z_writeb(ENISR_RESET, NE_BASE + NE_EN0_ISR);    /* Ack intr */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+ * we don't need to be concerned with ring wrap as the header will be at
+ * the start of a page, so we optimize accordingly.
+ */
+static void zorro8390_get_8390_hdr(struct net_device *dev,
+                                  struct e8390_pkt_hdr *hdr, int ring_page)
+{
+       int nic_base = dev->base_addr;
+       int cnt;
+       short *ptrs;
+
+       /* This *shouldn't* happen.
+        * If it does, it's the last thing you'll see
+        */
+       if (ei_status.dmaing) {
+               netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+                          __func__, ei_status.dmaing, ei_status.irqlock);
+               return;
+       }
+
+       ei_status.dmaing |= 0x01;
+       z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
+       z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+       z_writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
+       z_writeb(0, nic_base + NE_EN0_RCNTHI);
+       z_writeb(0, nic_base + NE_EN0_RSARLO);          /* On page boundary */
+       z_writeb(ring_page, nic_base + NE_EN0_RSARHI);
+       z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+       ptrs = (short *)hdr;
+       for (cnt = 0; cnt < sizeof(struct e8390_pkt_hdr) >> 1; cnt++)
+               *ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
+
+       z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);     /* Ack intr */
+
+       hdr->count = WORDSWAP(hdr->count);
+
+       ei_status.dmaing &= ~0x01;
+}
+
+/* Block input and output, similar to the Crynwr packet driver.
+ * If you are porting to a new ethercard, look at the packet driver source
+ * for hints. The NEx000 doesn't share the on-board packet memory --
+ * you have to put the packet out through the "remote DMA" dataport
+ * using z_writeb.
+ */
+static void zorro8390_block_input(struct net_device *dev, int count,
+                                 struct sk_buff *skb, int ring_offset)
+{
+       int nic_base = dev->base_addr;
+       char *buf = skb->data;
+       short *ptrs;
+       int cnt;
+
+       /* This *shouldn't* happen.
+        * If it does, it's the last thing you'll see
+        */
+       if (ei_status.dmaing) {
+               netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+                          __func__, ei_status.dmaing, ei_status.irqlock);
+               return;
+       }
+       ei_status.dmaing |= 0x01;
+       z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
+       z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+       z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+       z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
+       z_writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
+       z_writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
+       z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+       ptrs = (short *)buf;
+       for (cnt = 0; cnt < count >> 1; cnt++)
+               *ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
+       if (count & 0x01)
+               buf[count - 1] = z_readb(NE_BASE + NE_DATAPORT);
+
+       z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);     /* Ack intr */
+       ei_status.dmaing &= ~0x01;
+}
+
+static void zorro8390_block_output(struct net_device *dev, int count,
+                                  const unsigned char *buf,
+                                  const int start_page)
+{
+       int nic_base = NE_BASE;
+       unsigned long dma_start;
+       short *ptrs;
+       int cnt;
+
+       /* Round the count up for word writes.  Do we need to do this?
+        * What effect will an odd byte count have on the 8390?
+        * I should check someday.
+        */
+       if (count & 0x01)
+               count++;
+
+       /* This *shouldn't* happen.
+        * If it does, it's the last thing you'll see
+        */
+       if (ei_status.dmaing) {
+               netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
+                          __func__, ei_status.dmaing, ei_status.irqlock);
+               return;
+       }
+       ei_status.dmaing |= 0x01;
+       /* We should already be in page 0, but to be safe... */
+       z_writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+       z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+
+       /* Now the normal output. */
+       z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+       z_writeb(count >> 8,   nic_base + NE_EN0_RCNTHI);
+       z_writeb(0x00, nic_base + NE_EN0_RSARLO);
+       z_writeb(start_page, nic_base + NE_EN0_RSARHI);
+
+       z_writeb(E8390_RWRITE + E8390_START, nic_base + NE_CMD);
+       ptrs = (short *)buf;
+       for (cnt = 0; cnt < count >> 1; cnt++)
+               z_writew(*ptrs++, NE_BASE + NE_DATAPORT);
+
+       dma_start = jiffies;
+
+       while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
+               if (time_after(jiffies, dma_start + 2 * HZ / 100)) {
+                                       /* 20ms */
+                       netdev_err(dev, "timeout waiting for Tx RDC\n");
+                       zorro8390_reset_8390(dev);
+                       __NS8390_init(dev, 1);
+                       break;
+               }
+
+       z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);     /* Ack intr */
+       ei_status.dmaing &= ~0x01;
+}
+
+static int zorro8390_open(struct net_device *dev)
+{
+       __ei_open(dev);
+       return 0;
+}
+
+static int zorro8390_close(struct net_device *dev)
+{
+       if (ei_debug > 1)
+               netdev_dbg(dev, "Shutting down ethercard\n");
+       __ei_close(dev);
+       return 0;
+}
+
+static void __devexit zorro8390_remove_one(struct zorro_dev *z)
+{
+       struct net_device *dev = zorro_get_drvdata(z);
+
+       unregister_netdev(dev);
+       free_irq(IRQ_AMIGA_PORTS, dev);
+       release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT * 2);
+       free_netdev(dev);
+}
+
+static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = {
+       { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, },
+       { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
+       { 0 }
+};
+MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl);
+
+static const struct net_device_ops zorro8390_netdev_ops = {
+       .ndo_open               = zorro8390_open,
+       .ndo_stop               = zorro8390_close,
+       .ndo_start_xmit         = __ei_start_xmit,
+       .ndo_tx_timeout         = __ei_tx_timeout,
+       .ndo_get_stats          = __ei_get_stats,
+       .ndo_set_multicast_list = __ei_set_multicast_list,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_change_mtu         = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = __ei_poll,
+#endif
+};
+
+static int __devinit zorro8390_init(struct net_device *dev,
+                                   unsigned long board, const char *name,
+                                   unsigned long ioaddr)
+{
+       int i;
+       int err;
+       unsigned char SA_prom[32];
+       int start_page, stop_page;
+       static u32 zorro8390_offsets[16] = {
+               0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+               0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
+       };
+
+       /* Reset card. Who knows what dain-bramaged state it was left in. */
+       {
+               unsigned long reset_start_time = jiffies;
+
+               z_writeb(z_readb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+
+               while ((z_readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
+                       if (time_after(jiffies,
+                                      reset_start_time + 2 * HZ / 100)) {
+                               netdev_warn(dev, "not found (no reset ack)\n");
+                               return -ENODEV;
+                       }
+
+               z_writeb(0xff, ioaddr + NE_EN0_ISR);    /* Ack all intr. */
+       }
+
+       /* Read the 16 bytes of station address PROM.
+        * We must first initialize registers,
+        * similar to NS8390_init(eifdev, 0).
+        * We can't reliably read the SAPROM address without this.
+        * (I learned the hard way!).
+        */
+       {
+               static const struct {
+                       u32 value;
+                       u32 offset;
+               } program_seq[] = {
+                       {E8390_NODMA + E8390_PAGE0 + E8390_STOP, NE_CMD},
+                                               /* Select page 0 */
+                       {0x48,  NE_EN0_DCFG},   /* 0x48: Set byte-wide access */
+                       {0x00,  NE_EN0_RCNTLO}, /* Clear the count regs */
+                       {0x00,  NE_EN0_RCNTHI},
+                       {0x00,  NE_EN0_IMR},    /* Mask completion irq */
+                       {0xFF,  NE_EN0_ISR},
+                       {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */
+                       {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode */
+                       {32,    NE_EN0_RCNTLO},
+                       {0x00,  NE_EN0_RCNTHI},
+                       {0x00,  NE_EN0_RSARLO}, /* DMA starting at 0x0000 */
+                       {0x00,  NE_EN0_RSARHI},
+                       {E8390_RREAD + E8390_START, NE_CMD},
+               };
+               for (i = 0; i < ARRAY_SIZE(program_seq); i++)
+                       z_writeb(program_seq[i].value,
+                                ioaddr + program_seq[i].offset);
+       }
+       for (i = 0; i < 16; i++) {
+               SA_prom[i] = z_readb(ioaddr + NE_DATAPORT);
+               (void)z_readb(ioaddr + NE_DATAPORT);
+       }
+
+       /* We must set the 8390 for word mode. */
+       z_writeb(0x49, ioaddr + NE_EN0_DCFG);
+       start_page = NESM_START_PG;
+       stop_page = NESM_STOP_PG;
+
+       dev->base_addr = ioaddr;
+       dev->irq = IRQ_AMIGA_PORTS;
+
+       /* Install the Interrupt handler */
+       i = request_irq(IRQ_AMIGA_PORTS, __ei_interrupt,
+                       IRQF_SHARED, DRV_NAME, dev);
+       if (i)
+               return i;
+
+       for (i = 0; i < ETHER_ADDR_LEN; i++)
+               dev->dev_addr[i] = SA_prom[i];
+
+       pr_debug("Found ethernet address: %pM\n", dev->dev_addr);
+
+       ei_status.name = name;
+       ei_status.tx_start_page = start_page;
+       ei_status.stop_page = stop_page;
+       ei_status.word16 = 1;
+
+       ei_status.rx_start_page = start_page + TX_PAGES;
+
+       ei_status.reset_8390 = zorro8390_reset_8390;
+       ei_status.block_input = zorro8390_block_input;
+       ei_status.block_output = zorro8390_block_output;
+       ei_status.get_8390_hdr = zorro8390_get_8390_hdr;
+       ei_status.reg_offset = zorro8390_offsets;
+
+       dev->netdev_ops = &zorro8390_netdev_ops;
+       __NS8390_init(dev, 0);
+       err = register_netdev(dev);
+       if (err) {
+               free_irq(IRQ_AMIGA_PORTS, dev);
+               return err;
+       }
+
+       netdev_info(dev, "%s at 0x%08lx, Ethernet Address %pM\n",
+                   name, board, dev->dev_addr);
+
+       return 0;
+}
+
+static int __devinit zorro8390_init_one(struct zorro_dev *z,
+                                       const struct zorro_device_id *ent)
+{
+       struct net_device *dev;
+       unsigned long board, ioaddr;
+       int err, i;
+
+       for (i = ARRAY_SIZE(cards) - 1; i >= 0; i--)
+               if (z->id == cards[i].id)
+                       break;
+       if (i < 0)
+               return -ENODEV;
+
+       board = z->resource.start;
+       ioaddr = board + cards[i].offset;
+       dev = ____alloc_ei_netdev(0);
+       if (!dev)
+               return -ENOMEM;
+       if (!request_mem_region(ioaddr, NE_IO_EXTENT * 2, DRV_NAME)) {
+               free_netdev(dev);
+               return -EBUSY;
+       }
+       err = zorro8390_init(dev, board, cards[i].name, ZTWO_VADDR(ioaddr));
+       if (err) {
+               release_mem_region(ioaddr, NE_IO_EXTENT * 2);
+               free_netdev(dev);
+               return err;
+       }
+       zorro_set_drvdata(z, dev);
+       return 0;
+}
+
+static struct zorro_driver zorro8390_driver = {
+       .name           = "zorro8390",
+       .id_table       = zorro8390_zorro_tbl,
+       .probe          = zorro8390_init_one,
+       .remove         = __devexit_p(zorro8390_remove_one),
+};
+
+static int __init zorro8390_init_module(void)
+{
+       return zorro_register_driver(&zorro8390_driver);
+}
+
+static void __exit zorro8390_cleanup_module(void)
+{
+       zorro_unregister_driver(&zorro8390_driver);
+}
+
+module_init(zorro8390_init_module);
+module_exit(zorro8390_cleanup_module);
+
+MODULE_LICENSE("GPL");
index 5e62efd58172d188f66434d8fa91cffe212f070c..56ed5ec9a5036ea3451f967eac7897a6135f1788 100644 (file)
@@ -12,6 +12,7 @@ menuconfig ETHERNET
 if ETHERNET
 
 source "drivers/net/ethernet/3com/Kconfig"
+source "drivers/net/ethernet/8390/Kconfig"
 source "drivers/net/ethernet/amd/Kconfig"
 
 endif # ETHERNET
index 1bc2ac25bab0bdcb7de4f10bbb9dc4c810b11e12..fc82588fb2f48dd049d011eeace484edda855606 100644 (file)
@@ -3,4 +3,5 @@
 #
 
 obj-$(CONFIG_NET_VENDOR_3COM) += 3com/
+obj-$(CONFIG_NET_VENDOR_8390) += 8390/
 obj-$(CONFIG_NET_VENDOR_AMD) += amd/
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
deleted file mode 100644 (file)
index 2991736..0000000
+++ /dev/null
@@ -1,506 +0,0 @@
-/* hp-plus.c: A HP PCLAN/plus ethernet driver for linux. */
-/*
-       Written 1994 by Donald Becker.
-
-       This driver is for the Hewlett Packard PC LAN (27***) plus ethercards.
-       These cards are sold under several model numbers, usually 2724*.
-
-       This software may be used and distributed according to the terms
-       of the GNU General Public License, incorporated herein by reference.
-
-       The author may be reached as becker@scyld.com, or C/O
-       Scyld Computing Corporation
-       410 Severn Ave., Suite 210
-       Annapolis MD 21403
-
-       As is often the case, a great deal of credit is owed to Russ Nelson.
-       The Crynwr packet driver was my primary source of HP-specific
-       programming information.
-*/
-
-static const char version[] =
-"hp-plus.c:v1.10 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include <linux/module.h>
-
-#include <linux/string.h>              /* Important -- this inlines word moves. */
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include "8390.h"
-
-#define DRV_NAME "hp-plus"
-
-/* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int hpplus_portlist[] __initdata =
-{0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0};
-
-/*
-   The HP EtherTwist chip implementation is a fairly routine DP8390
-   implementation.  It allows both shared memory and programmed-I/O buffer
-   access, using a custom interface for both.  The programmed-I/O mode is
-   entirely implemented in the HP EtherTwist chip, bypassing the problem
-   ridden built-in 8390 facilities used on NE2000 designs.  The shared
-   memory mode is likewise special, with an offset register used to make
-   packets appear at the shared memory base.  Both modes use a base and bounds
-   page register to hide the Rx ring buffer wrap -- a packet that spans the
-   end of physical buffer memory appears continuous to the driver. (c.f. the
-   3c503 and Cabletron E2100)
-
-   A special note: the internal buffer of the board is only 8 bits wide.
-   This lays several nasty traps for the unaware:
-   - the 8390 must be programmed for byte-wide operations
-   - all I/O and memory operations must work on whole words (the access
-     latches are serially preloaded and have no byte-swapping ability).
-
-   This board is laid out in I/O space much like the earlier HP boards:
-   the first 16 locations are for the board registers, and the second 16 are
-   for the 8390.  The board is easy to identify, with both a dedicated 16 bit
-   ID register and a constant 0x530* value in the upper bits of the paging
-   register.
-*/
-
-#define HP_ID                  0x00    /* ID register, always 0x4850. */
-#define HP_PAGING              0x02    /* Registers visible @ 8-f, see PageName. */
-#define HPP_OPTION             0x04    /* Bitmapped options, see HP_Option.    */
-#define HPP_OUT_ADDR   0x08    /* I/O output location in Perf_Page.    */
-#define HPP_IN_ADDR            0x0A    /* I/O input location in Perf_Page.             */
-#define HP_DATAPORT            0x0c    /* I/O data transfer in Perf_Page.              */
-#define NIC_OFFSET             0x10    /* Offset to the 8390 registers.                */
-#define HP_IO_EXTENT   32
-
-#define HP_START_PG            0x00    /* First page of TX buffer */
-#define HP_STOP_PG             0x80    /* Last page +1 of RX ring */
-
-/* The register set selected in HP_PAGING. */
-enum PageName {
-       Perf_Page = 0,                          /* Normal operation. */
-       MAC_Page = 1,                           /* The ethernet address (+checksum). */
-       HW_Page = 2,                            /* EEPROM-loaded hardware parameters. */
-       LAN_Page = 4,                           /* Transceiver selection, testing, etc. */
-       ID_Page = 6 };
-
-/* The bit definitions for the HPP_OPTION register. */
-enum HP_Option {
-       NICReset = 1, ChipReset = 2,    /* Active low, really UNreset. */
-       EnableIRQ = 4, FakeIntr = 8, BootROMEnb = 0x10, IOEnb = 0x20,
-       MemEnable = 0x40, ZeroWait = 0x80, MemDisable = 0x1000, };
-
-static int hpp_probe1(struct net_device *dev, int ioaddr);
-
-static void hpp_reset_8390(struct net_device *dev);
-static int hpp_open(struct net_device *dev);
-static int hpp_close(struct net_device *dev);
-static void hpp_mem_block_input(struct net_device *dev, int count,
-                                                 struct sk_buff *skb, int ring_offset);
-static void hpp_mem_block_output(struct net_device *dev, int count,
-                                                       const unsigned char *buf, int start_page);
-static void hpp_mem_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                                                 int ring_page);
-static void hpp_io_block_input(struct net_device *dev, int count,
-                                                 struct sk_buff *skb, int ring_offset);
-static void hpp_io_block_output(struct net_device *dev, int count,
-                                                       const unsigned char *buf, int start_page);
-static void hpp_io_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                                                 int ring_page);
-
-
-/*     Probe a list of addresses for an HP LAN+ adaptor.
-       This routine is almost boilerplate. */
-
-static int __init do_hpp_probe(struct net_device *dev)
-{
-       int i;
-       int base_addr = dev->base_addr;
-       int irq = dev->irq;
-
-       if (base_addr > 0x1ff)          /* Check a single specified location. */
-               return hpp_probe1(dev, base_addr);
-       else if (base_addr != 0)        /* Don't probe at all. */
-               return -ENXIO;
-
-       for (i = 0; hpplus_portlist[i]; i++) {
-               if (hpp_probe1(dev, hpplus_portlist[i]) == 0)
-                       return 0;
-               dev->irq = irq;
-       }
-
-       return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init hp_plus_probe(int unit)
-{
-       struct net_device *dev = alloc_eip_netdev();
-       int err;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       sprintf(dev->name, "eth%d", unit);
-       netdev_boot_setup_check(dev);
-
-       err = do_hpp_probe(dev);
-       if (err)
-               goto out;
-       return dev;
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-#endif
-
-static const struct net_device_ops hpp_netdev_ops = {
-       .ndo_open               = hpp_open,
-       .ndo_stop               = hpp_close,
-       .ndo_start_xmit         = eip_start_xmit,
-       .ndo_tx_timeout         = eip_tx_timeout,
-       .ndo_get_stats          = eip_get_stats,
-       .ndo_set_multicast_list = eip_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = eip_poll,
-#endif
-};
-
-
-/* Do the interesting part of the probe at a single address. */
-static int __init hpp_probe1(struct net_device *dev, int ioaddr)
-{
-       int i, retval;
-       unsigned char checksum = 0;
-       const char name[] = "HP-PC-LAN+";
-       int mem_start;
-       static unsigned version_printed;
-
-       if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME))
-               return -EBUSY;
-
-       /* Check for the HP+ signature, 50 48 0x 53. */
-       if (inw(ioaddr + HP_ID) != 0x4850 ||
-           (inw(ioaddr + HP_PAGING) & 0xfff0) != 0x5300) {
-               retval = -ENODEV;
-               goto out;
-       }
-
-       if (ei_debug  &&  version_printed++ == 0)
-               printk(version);
-
-       printk("%s: %s at %#3x, ", dev->name, name, ioaddr);
-
-       /* Retrieve and checksum the station address. */
-       outw(MAC_Page, ioaddr + HP_PAGING);
-
-       for(i = 0; i < ETHER_ADDR_LEN; i++) {
-               unsigned char inval = inb(ioaddr + 8 + i);
-               dev->dev_addr[i] = inval;
-               checksum += inval;
-       }
-       checksum += inb(ioaddr + 14);
-
-       printk("%pM", dev->dev_addr);
-
-       if (checksum != 0xff) {
-               printk(" bad checksum %2.2x.\n", checksum);
-               retval = -ENODEV;
-               goto out;
-       } else {
-               /* Point at the Software Configuration Flags. */
-               outw(ID_Page, ioaddr + HP_PAGING);
-               printk(" ID %4.4x", inw(ioaddr + 12));
-       }
-
-       /* Read the IRQ line. */
-       outw(HW_Page, ioaddr + HP_PAGING);
-       {
-               int irq = inb(ioaddr + 13) & 0x0f;
-               int option = inw(ioaddr + HPP_OPTION);
-
-               dev->irq = irq;
-               if (option & MemEnable) {
-                       mem_start = inw(ioaddr + 9) << 8;
-                       printk(", IRQ %d, memory address %#x.\n", irq, mem_start);
-               } else {
-                       mem_start = 0;
-                       printk(", IRQ %d, programmed-I/O mode.\n", irq);
-               }
-       }
-
-       /* Set the wrap registers for string I/O reads.   */
-       outw((HP_START_PG + TX_PAGES/2) | ((HP_STOP_PG - 1) << 8), ioaddr + 14);
-
-       /* Set the base address to point to the NIC, not the "real" base! */
-       dev->base_addr = ioaddr + NIC_OFFSET;
-
-       dev->netdev_ops = &hpp_netdev_ops;
-
-       ei_status.name = name;
-       ei_status.word16 = 0;           /* Agggghhhhh! Debug time: 2 days! */
-       ei_status.tx_start_page = HP_START_PG;
-       ei_status.rx_start_page = HP_START_PG + TX_PAGES/2;
-       ei_status.stop_page = HP_STOP_PG;
-
-       ei_status.reset_8390 = &hpp_reset_8390;
-       ei_status.block_input = &hpp_io_block_input;
-       ei_status.block_output = &hpp_io_block_output;
-       ei_status.get_8390_hdr = &hpp_io_get_8390_hdr;
-
-       /* Check if the memory_enable flag is set in the option register. */
-       if (mem_start) {
-               ei_status.block_input = &hpp_mem_block_input;
-               ei_status.block_output = &hpp_mem_block_output;
-               ei_status.get_8390_hdr = &hpp_mem_get_8390_hdr;
-               dev->mem_start = mem_start;
-               ei_status.mem = ioremap(mem_start,
-                                       (HP_STOP_PG - HP_START_PG)*256);
-               if (!ei_status.mem) {
-                       retval = -ENOMEM;
-                       goto out;
-               }
-               ei_status.rmem_start = dev->mem_start + TX_PAGES/2*256;
-               dev->mem_end = ei_status.rmem_end
-                       = dev->mem_start + (HP_STOP_PG - HP_START_PG)*256;
-       }
-
-       outw(Perf_Page, ioaddr + HP_PAGING);
-       NS8390p_init(dev, 0);
-       /* Leave the 8390 and HP chip reset. */
-       outw(inw(ioaddr + HPP_OPTION) & ~EnableIRQ, ioaddr + HPP_OPTION);
-
-       retval = register_netdev(dev);
-       if (retval)
-               goto out1;
-       return 0;
-out1:
-       iounmap(ei_status.mem);
-out:
-       release_region(ioaddr, HP_IO_EXTENT);
-       return retval;
-}
-
-static int
-hpp_open(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr - NIC_OFFSET;
-       int option_reg;
-       int retval;
-
-       if ((retval = request_irq(dev->irq, eip_interrupt, 0, dev->name, dev))) {
-           return retval;
-       }
-
-       /* Reset the 8390 and HP chip. */
-       option_reg = inw(ioaddr + HPP_OPTION);
-       outw(option_reg & ~(NICReset + ChipReset), ioaddr + HPP_OPTION);
-       udelay(5);
-       /* Unreset the board and enable interrupts. */
-       outw(option_reg | (EnableIRQ + NICReset + ChipReset), ioaddr + HPP_OPTION);
-
-       /* Set the wrap registers for programmed-I/O operation.   */
-       outw(HW_Page, ioaddr + HP_PAGING);
-       outw((HP_START_PG + TX_PAGES/2) | ((HP_STOP_PG - 1) << 8), ioaddr + 14);
-
-       /* Select the operational page. */
-       outw(Perf_Page, ioaddr + HP_PAGING);
-
-       return eip_open(dev);
-}
-
-static int
-hpp_close(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr - NIC_OFFSET;
-       int option_reg = inw(ioaddr + HPP_OPTION);
-
-       free_irq(dev->irq, dev);
-       eip_close(dev);
-       outw((option_reg & ~EnableIRQ) | MemDisable | NICReset | ChipReset,
-                ioaddr + HPP_OPTION);
-
-       return 0;
-}
-
-static void
-hpp_reset_8390(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr - NIC_OFFSET;
-       int option_reg = inw(ioaddr + HPP_OPTION);
-
-       if (ei_debug > 1) printk("resetting the 8390 time=%ld...", jiffies);
-
-       outw(option_reg & ~(NICReset + ChipReset), ioaddr + HPP_OPTION);
-       /* Pause a few cycles for the hardware reset to take place. */
-       udelay(5);
-       ei_status.txing = 0;
-       outw(option_reg | (EnableIRQ + NICReset + ChipReset), ioaddr + HPP_OPTION);
-
-       udelay(5);
-
-
-       if ((inb_p(ioaddr+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0)
-               printk("%s: hp_reset_8390() did not complete.\n", dev->name);
-
-       if (ei_debug > 1) printk("8390 reset done (%ld).", jiffies);
-}
-
-/* The programmed-I/O version of reading the 4 byte 8390 specific header.
-   Note that transfer with the EtherTwist+ must be on word boundaries. */
-
-static void
-hpp_io_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-       int ioaddr = dev->base_addr - NIC_OFFSET;
-
-       outw((ring_page<<8), ioaddr + HPP_IN_ADDR);
-       insw(ioaddr + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
-}
-
-/* Block input and output, similar to the Crynwr packet driver. */
-
-static void
-hpp_io_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-       int ioaddr = dev->base_addr - NIC_OFFSET;
-       char *buf = skb->data;
-
-       outw(ring_offset, ioaddr + HPP_IN_ADDR);
-       insw(ioaddr + HP_DATAPORT, buf, count>>1);
-       if (count & 0x01)
-        buf[count-1] = inw(ioaddr + HP_DATAPORT);
-}
-
-/* The corresponding shared memory versions of the above 2 functions. */
-
-static void
-hpp_mem_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-       int ioaddr = dev->base_addr - NIC_OFFSET;
-       int option_reg = inw(ioaddr + HPP_OPTION);
-
-       outw((ring_page<<8), ioaddr + HPP_IN_ADDR);
-       outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
-       memcpy_fromio(hdr, ei_status.mem, sizeof(struct e8390_pkt_hdr));
-       outw(option_reg, ioaddr + HPP_OPTION);
-       hdr->count = (le16_to_cpu(hdr->count) + 3) & ~3;        /* Round up allocation. */
-}
-
-static void
-hpp_mem_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-       int ioaddr = dev->base_addr - NIC_OFFSET;
-       int option_reg = inw(ioaddr + HPP_OPTION);
-
-       outw(ring_offset, ioaddr + HPP_IN_ADDR);
-
-       outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
-
-       /* Caution: this relies on get_8390_hdr() rounding up count!
-          Also note that we *can't* use eth_io_copy_and_sum() because
-          it will not always copy "count" bytes (e.g. padded IP).  */
-
-       memcpy_fromio(skb->data, ei_status.mem, count);
-       outw(option_reg, ioaddr + HPP_OPTION);
-}
-
-/* A special note: we *must* always transfer >=16 bit words.
-   It's always safe to round up, so we do. */
-static void
-hpp_io_block_output(struct net_device *dev, int count,
-                                       const unsigned char *buf, int start_page)
-{
-       int ioaddr = dev->base_addr - NIC_OFFSET;
-       outw(start_page << 8, ioaddr + HPP_OUT_ADDR);
-       outsl(ioaddr + HP_DATAPORT, buf, (count+3)>>2);
-}
-
-static void
-hpp_mem_block_output(struct net_device *dev, int count,
-                               const unsigned char *buf, int start_page)
-{
-       int ioaddr = dev->base_addr - NIC_OFFSET;
-       int option_reg = inw(ioaddr + HPP_OPTION);
-
-       outw(start_page << 8, ioaddr + HPP_OUT_ADDR);
-       outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
-       memcpy_toio(ei_status.mem, buf, (count + 3) & ~3);
-       outw(option_reg, ioaddr + HPP_OPTION);
-}
-
-
-#ifdef MODULE
-#define MAX_HPP_CARDS  4       /* Max number of HPP cards per module */
-static struct net_device *dev_hpp[MAX_HPP_CARDS];
-static int io[MAX_HPP_CARDS];
-static int irq[MAX_HPP_CARDS];
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O port address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s); ignored if properly detected");
-MODULE_DESCRIPTION("HP PC-LAN+ ISA ethernet driver");
-MODULE_LICENSE("GPL");
-
-/* This is set up so that only a single autoprobe takes place per call.
-ISA device autoprobes on a running machine are not recommended. */
-int __init
-init_module(void)
-{
-       struct net_device *dev;
-       int this_dev, found = 0;
-
-       for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) {
-               if (io[this_dev] == 0)  {
-                       if (this_dev != 0) break; /* only autoprobe 1st one */
-                       printk(KERN_NOTICE "hp-plus.c: Presently autoprobing (not recommended) for a single card.\n");
-               }
-               dev = alloc_eip_netdev();
-               if (!dev)
-                       break;
-               dev->irq = irq[this_dev];
-               dev->base_addr = io[this_dev];
-               if (do_hpp_probe(dev) == 0) {
-                       dev_hpp[found++] = dev;
-                       continue;
-               }
-               free_netdev(dev);
-               printk(KERN_WARNING "hp-plus.c: No HP-Plus card found (i/o = 0x%x).\n", io[this_dev]);
-               break;
-       }
-       if (found)
-               return 0;
-       return -ENXIO;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-       /* NB: hpp_close() handles free_irq */
-       iounmap(ei_status.mem);
-       release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
-}
-
-void __exit
-cleanup_module(void)
-{
-       int this_dev;
-
-       for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) {
-               struct net_device *dev = dev_hpp[this_dev];
-               if (dev) {
-                       unregister_netdev(dev);
-                       cleanup_card(dev);
-                       free_netdev(dev);
-               }
-       }
-}
-#endif /* MODULE */
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
deleted file mode 100644 (file)
index 18564d4..0000000
+++ /dev/null
@@ -1,439 +0,0 @@
-/* hp.c: A HP LAN ethernet driver for linux. */
-/*
-       Written 1993-94 by Donald Becker.
-
-       Copyright 1993 United States Government as represented by the
-       Director, National Security Agency.
-
-       This software may be used and distributed according to the terms
-       of the GNU General Public License, incorporated herein by reference.
-
-       The author may be reached as becker@scyld.com, or C/O
-       Scyld Computing Corporation
-       410 Severn Ave., Suite 210
-       Annapolis MD 21403
-
-       This is a driver for the HP PC-LAN adaptors.
-
-       Sources:
-         The Crynwr packet driver.
-*/
-
-static const char version[] =
-       "hp.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include "8390.h"
-
-#define DRV_NAME "hp"
-
-/* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int hppclan_portlist[] __initdata =
-{ 0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0};
-
-#define HP_IO_EXTENT   32
-
-#define HP_DATAPORT            0x0c    /* "Remote DMA" data port. */
-#define HP_ID                  0x07
-#define HP_CONFIGURE   0x08    /* Configuration register. */
-#define         HP_RUN                 0x01    /* 1 == Run, 0 == reset. */
-#define         HP_IRQ                 0x0E    /* Mask for software-configured IRQ line. */
-#define         HP_DATAON              0x10    /* Turn on dataport */
-#define NIC_OFFSET             0x10    /* Offset the 8390 registers. */
-
-#define HP_START_PG            0x00    /* First page of TX buffer */
-#define HP_8BSTOP_PG   0x80    /* Last page +1 of RX ring */
-#define HP_16BSTOP_PG  0xFF    /* Same, for 16 bit cards. */
-
-static int hp_probe1(struct net_device *dev, int ioaddr);
-
-static void hp_reset_8390(struct net_device *dev);
-static void hp_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                                       int ring_page);
-static void hp_block_input(struct net_device *dev, int count,
-                                       struct sk_buff *skb , int ring_offset);
-static void hp_block_output(struct net_device *dev, int count,
-                                                       const unsigned char *buf, int start_page);
-
-static void hp_init_card(struct net_device *dev);
-
-/* The map from IRQ number to HP_CONFIGURE register setting. */
-/* My default is IRQ5               0  1  2  3  4  5  6  7  8  9 10 11 */
-static char irqmap[16] __initdata= { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0};
-
-
-/*     Probe for an HP LAN adaptor.
-       Also initialize the card and fill in STATION_ADDR with the station
-       address. */
-
-static int __init do_hp_probe(struct net_device *dev)
-{
-       int i;
-       int base_addr = dev->base_addr;
-       int irq = dev->irq;
-
-       if (base_addr > 0x1ff)          /* Check a single specified location. */
-               return hp_probe1(dev, base_addr);
-       else if (base_addr != 0)        /* Don't probe at all. */
-               return -ENXIO;
-
-       for (i = 0; hppclan_portlist[i]; i++) {
-               if (hp_probe1(dev, hppclan_portlist[i]) == 0)
-                       return 0;
-               dev->irq = irq;
-       }
-
-       return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init hp_probe(int unit)
-{
-       struct net_device *dev = alloc_eip_netdev();
-       int err;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       sprintf(dev->name, "eth%d", unit);
-       netdev_boot_setup_check(dev);
-
-       err = do_hp_probe(dev);
-       if (err)
-               goto out;
-       return dev;
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-#endif
-
-static int __init hp_probe1(struct net_device *dev, int ioaddr)
-{
-       int i, retval, board_id, wordmode;
-       const char *name;
-       static unsigned version_printed;
-
-       if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME))
-               return -EBUSY;
-
-       /* Check for the HP physical address, 08 00 09 xx xx xx. */
-       /* This really isn't good enough: we may pick up HP LANCE boards
-          also!  Avoid the lance 0x5757 signature. */
-       if (inb(ioaddr) != 0x08
-               || inb(ioaddr+1) != 0x00
-               || inb(ioaddr+2) != 0x09
-               || inb(ioaddr+14) == 0x57) {
-               retval = -ENODEV;
-               goto out;
-       }
-
-       /* Set up the parameters based on the board ID.
-          If you have additional mappings, please mail them to me -djb. */
-       if ((board_id = inb(ioaddr + HP_ID)) & 0x80) {
-               name = "HP27247";
-               wordmode = 1;
-       } else {
-               name = "HP27250";
-               wordmode = 0;
-       }
-
-       if (ei_debug  &&  version_printed++ == 0)
-               printk(version);
-
-       printk("%s: %s (ID %02x) at %#3x,", dev->name, name, board_id, ioaddr);
-
-       for(i = 0; i < ETHER_ADDR_LEN; i++)
-               dev->dev_addr[i] = inb(ioaddr + i);
-
-       printk(" %pM", dev->dev_addr);
-
-       /* Snarf the interrupt now.  Someday this could be moved to open(). */
-       if (dev->irq < 2) {
-               static const int irq_16list[] = { 11, 10, 5, 3, 4, 7, 9, 0};
-               static const int irq_8list[] = { 7, 5, 3, 4, 9, 0};
-               const int *irqp = wordmode ? irq_16list : irq_8list;
-               do {
-                       int irq = *irqp;
-                       if (request_irq (irq, NULL, 0, "bogus", NULL) != -EBUSY) {
-                               unsigned long cookie = probe_irq_on();
-                               /* Twinkle the interrupt, and check if it's seen. */
-                               outb_p(irqmap[irq] | HP_RUN, ioaddr + HP_CONFIGURE);
-                               outb_p( 0x00 | HP_RUN, ioaddr + HP_CONFIGURE);
-                               if (irq == probe_irq_off(cookie)                 /* It's a good IRQ line! */
-                                       && request_irq (irq, eip_interrupt, 0, DRV_NAME, dev) == 0) {
-                                       printk(" selecting IRQ %d.\n", irq);
-                                       dev->irq = *irqp;
-                                       break;
-                               }
-                       }
-               } while (*++irqp);
-               if (*irqp == 0) {
-                       printk(" no free IRQ lines.\n");
-                       retval = -EBUSY;
-                       goto out;
-               }
-       } else {
-               if (dev->irq == 2)
-                       dev->irq = 9;
-               if ((retval = request_irq(dev->irq, eip_interrupt, 0, DRV_NAME, dev))) {
-                       printk (" unable to get IRQ %d.\n", dev->irq);
-                       goto out;
-               }
-       }
-
-       /* Set the base address to point to the NIC, not the "real" base! */
-       dev->base_addr = ioaddr + NIC_OFFSET;
-       dev->netdev_ops = &eip_netdev_ops;
-
-       ei_status.name = name;
-       ei_status.word16 = wordmode;
-       ei_status.tx_start_page = HP_START_PG;
-       ei_status.rx_start_page = HP_START_PG + TX_PAGES;
-       ei_status.stop_page = wordmode ? HP_16BSTOP_PG : HP_8BSTOP_PG;
-
-       ei_status.reset_8390 = hp_reset_8390;
-       ei_status.get_8390_hdr = hp_get_8390_hdr;
-       ei_status.block_input = hp_block_input;
-       ei_status.block_output = hp_block_output;
-       hp_init_card(dev);
-
-       retval = register_netdev(dev);
-       if (retval)
-               goto out1;
-       return 0;
-out1:
-       free_irq(dev->irq, dev);
-out:
-       release_region(ioaddr, HP_IO_EXTENT);
-       return retval;
-}
-
-static void
-hp_reset_8390(struct net_device *dev)
-{
-       int hp_base = dev->base_addr - NIC_OFFSET;
-       int saved_config = inb_p(hp_base + HP_CONFIGURE);
-
-       if (ei_debug > 1) printk("resetting the 8390 time=%ld...", jiffies);
-       outb_p(0x00, hp_base + HP_CONFIGURE);
-       ei_status.txing = 0;
-       /* Pause just a few cycles for the hardware reset to take place. */
-       udelay(5);
-
-       outb_p(saved_config, hp_base + HP_CONFIGURE);
-       udelay(5);
-
-       if ((inb_p(hp_base+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0)
-               printk("%s: hp_reset_8390() did not complete.\n", dev->name);
-
-       if (ei_debug > 1) printk("8390 reset done (%ld).", jiffies);
-}
-
-static void
-hp_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-       int nic_base = dev->base_addr;
-       int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
-
-       outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
-       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base);
-       outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
-       outb_p(0, nic_base + EN0_RCNTHI);
-       outb_p(0, nic_base + EN0_RSARLO);       /* On page boundary */
-       outb_p(ring_page, nic_base + EN0_RSARHI);
-       outb_p(E8390_RREAD+E8390_START, nic_base);
-
-       if (ei_status.word16)
-         insw(nic_base - NIC_OFFSET + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
-       else
-         insb(nic_base - NIC_OFFSET + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
-
-       outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
-}
-
-/* Block input and output, similar to the Crynwr packet driver. If you are
-   porting to a new ethercard look at the packet driver source for hints.
-   The HP LAN doesn't use shared memory -- we put the packet
-   out through the "remote DMA" dataport. */
-
-static void
-hp_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-       int nic_base = dev->base_addr;
-       int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
-       int xfer_count = count;
-       char *buf = skb->data;
-
-       outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
-       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base);
-       outb_p(count & 0xff, nic_base + EN0_RCNTLO);
-       outb_p(count >> 8, nic_base + EN0_RCNTHI);
-       outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
-       outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
-       outb_p(E8390_RREAD+E8390_START, nic_base);
-       if (ei_status.word16) {
-         insw(nic_base - NIC_OFFSET + HP_DATAPORT,buf,count>>1);
-         if (count & 0x01)
-               buf[count-1] = inb(nic_base - NIC_OFFSET + HP_DATAPORT), xfer_count++;
-       } else {
-               insb(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count);
-       }
-       /* This is for the ALPHA version only, remove for later releases. */
-       if (ei_debug > 0) {                     /* DMA termination address check... */
-         int high = inb_p(nic_base + EN0_RSARHI);
-         int low = inb_p(nic_base + EN0_RSARLO);
-         int addr = (high << 8) + low;
-         /* Check only the lower 8 bits so we can ignore ring wrap. */
-         if (((ring_offset + xfer_count) & 0xff) != (addr & 0xff))
-               printk("%s: RX transfer address mismatch, %#4.4x vs. %#4.4x (actual).\n",
-                          dev->name, ring_offset + xfer_count, addr);
-       }
-       outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
-}
-
-static void
-hp_block_output(struct net_device *dev, int count,
-                               const unsigned char *buf, int start_page)
-{
-       int nic_base = dev->base_addr;
-       int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE);
-
-       outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE);
-       /* Round the count up for word writes.  Do we need to do this?
-          What effect will an odd byte count have on the 8390?
-          I should check someday. */
-       if (ei_status.word16 && (count & 0x01))
-         count++;
-       /* We should already be in page 0, but to be safe... */
-       outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base);
-
-#ifdef NE8390_RW_BUGFIX
-       /* Handle the read-before-write bug the same way as the
-          Crynwr packet driver -- the NatSemi method doesn't work. */
-       outb_p(0x42, nic_base + EN0_RCNTLO);
-       outb_p(0,       nic_base + EN0_RCNTHI);
-       outb_p(0xff, nic_base + EN0_RSARLO);
-       outb_p(0x00, nic_base + EN0_RSARHI);
-#define NE_CMD         0x00
-       outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-       /* Make certain that the dummy read has occurred. */
-       inb_p(0x61);
-       inb_p(0x61);
-#endif
-
-       outb_p(count & 0xff, nic_base + EN0_RCNTLO);
-       outb_p(count >> 8,       nic_base + EN0_RCNTHI);
-       outb_p(0x00, nic_base + EN0_RSARLO);
-       outb_p(start_page, nic_base + EN0_RSARHI);
-
-       outb_p(E8390_RWRITE+E8390_START, nic_base);
-       if (ei_status.word16) {
-               /* Use the 'rep' sequence for 16 bit boards. */
-               outsw(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count>>1);
-       } else {
-               outsb(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count);
-       }
-
-       /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here -- it's broken! */
-
-       /* This is for the ALPHA version only, remove for later releases. */
-       if (ei_debug > 0) {                     /* DMA termination address check... */
-         int high = inb_p(nic_base + EN0_RSARHI);
-         int low  = inb_p(nic_base + EN0_RSARLO);
-         int addr = (high << 8) + low;
-         if ((start_page << 8) + count != addr)
-               printk("%s: TX Transfer address mismatch, %#4.4x vs. %#4.4x.\n",
-                          dev->name, (start_page << 8) + count, addr);
-       }
-       outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE);
-}
-
-/* This function resets the ethercard if something screws up. */
-static void __init
-hp_init_card(struct net_device *dev)
-{
-       int irq = dev->irq;
-       NS8390p_init(dev, 0);
-       outb_p(irqmap[irq&0x0f] | HP_RUN,
-                  dev->base_addr - NIC_OFFSET + HP_CONFIGURE);
-}
-
-#ifdef MODULE
-#define MAX_HP_CARDS   4       /* Max number of HP cards per module */
-static struct net_device *dev_hp[MAX_HP_CARDS];
-static int io[MAX_HP_CARDS];
-static int irq[MAX_HP_CARDS];
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
-MODULE_DESCRIPTION("HP PC-LAN ISA ethernet driver");
-MODULE_LICENSE("GPL");
-
-/* This is set up so that only a single autoprobe takes place per call.
-ISA device autoprobes on a running machine are not recommended. */
-int __init
-init_module(void)
-{
-       struct net_device *dev;
-       int this_dev, found = 0;
-
-       for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) {
-               if (io[this_dev] == 0)  {
-                       if (this_dev != 0) break; /* only autoprobe 1st one */
-                       printk(KERN_NOTICE "hp.c: Presently autoprobing (not recommended) for a single card.\n");
-               }
-               dev = alloc_eip_netdev();
-               if (!dev)
-                       break;
-               dev->irq = irq[this_dev];
-               dev->base_addr = io[this_dev];
-               if (do_hp_probe(dev) == 0) {
-                       dev_hp[found++] = dev;
-                       continue;
-               }
-               free_netdev(dev);
-               printk(KERN_WARNING "hp.c: No HP card found (i/o = 0x%x).\n", io[this_dev]);
-               break;
-       }
-       if (found)
-               return 0;
-       return -ENXIO;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-       free_irq(dev->irq, dev);
-       release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
-}
-
-void __exit
-cleanup_module(void)
-{
-       int this_dev;
-
-       for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) {
-               struct net_device *dev = dev_hp[this_dev];
-               if (dev) {
-                       unregister_netdev(dev);
-                       cleanup_card(dev);
-                       free_netdev(dev);
-               }
-       }
-}
-#endif /* MODULE */
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c
deleted file mode 100644 (file)
index 1cd481c..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-/* New Hydra driver using generic 8390 core */
-/* Based on old hydra driver by Topi Kanerva (topi@susanna.oulu.fi) */
-
-/* This file is subject to the terms and conditions of the GNU General      */
-/* Public License.  See the file COPYING in the main directory of the       */
-/* Linux distribution for more details.                                     */
-
-/* Peter De Schrijver (p2@mind.be) */
-/* Oldenburg 2000 */
-
-/* The Amiganet is a Zorro-II board made by Hydra Systems. It contains a    */
-/* NS8390 NIC (network interface controller) clone, 16 or 64K on-board RAM  */
-/* and 10BASE-2 (thin coax) and AUI connectors.                             */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-#include <linux/zorro.h>
-
-#define EI_SHIFT(x)    (ei_local->reg_offset[x])
-#define ei_inb(port)   in_8(port)
-#define ei_outb(val,port)  out_8(port,val)
-#define ei_inb_p(port)   in_8(port)
-#define ei_outb_p(val,port)  out_8(port,val)
-
-static const char version[] =
-    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include "lib8390.c"
-
-#define NE_EN0_DCFG     (0x0e*2)
-
-#define NESM_START_PG   0x0    /* First page of TX buffer */
-#define NESM_STOP_PG    0x40    /* Last page +1 of RX ring */
-
-#define HYDRA_NIC_BASE 0xffe1
-#define HYDRA_ADDRPROM 0xffc0
-#define HYDRA_VERSION "v3.0alpha"
-
-#define WORDSWAP(a)     ((((a)>>8)&0xff) | ((a)<<8))
-
-
-static int __devinit hydra_init_one(struct zorro_dev *z,
-                                   const struct zorro_device_id *ent);
-static int __devinit hydra_init(struct zorro_dev *z);
-static int hydra_open(struct net_device *dev);
-static int hydra_close(struct net_device *dev);
-static void hydra_reset_8390(struct net_device *dev);
-static void hydra_get_8390_hdr(struct net_device *dev,
-                              struct e8390_pkt_hdr *hdr, int ring_page);
-static void hydra_block_input(struct net_device *dev, int count,
-                             struct sk_buff *skb, int ring_offset);
-static void hydra_block_output(struct net_device *dev, int count,
-                              const unsigned char *buf, int start_page);
-static void __devexit hydra_remove_one(struct zorro_dev *z);
-
-static struct zorro_device_id hydra_zorro_tbl[] __devinitdata = {
-    { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET },
-    { 0 }
-};
-MODULE_DEVICE_TABLE(zorro, hydra_zorro_tbl);
-
-static struct zorro_driver hydra_driver = {
-    .name      = "hydra",
-    .id_table  = hydra_zorro_tbl,
-    .probe     = hydra_init_one,
-    .remove    = __devexit_p(hydra_remove_one),
-};
-
-static int __devinit hydra_init_one(struct zorro_dev *z,
-                                   const struct zorro_device_id *ent)
-{
-    int err;
-
-    if (!request_mem_region(z->resource.start, 0x10000, "Hydra"))
-       return -EBUSY;
-    if ((err = hydra_init(z))) {
-       release_mem_region(z->resource.start, 0x10000);
-       return -EBUSY;
-    }
-    return 0;
-}
-
-static const struct net_device_ops hydra_netdev_ops = {
-       .ndo_open               = hydra_open,
-       .ndo_stop               = hydra_close,
-
-       .ndo_start_xmit         = __ei_start_xmit,
-       .ndo_tx_timeout         = __ei_tx_timeout,
-       .ndo_get_stats          = __ei_get_stats,
-       .ndo_set_multicast_list = __ei_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = __ei_poll,
-#endif
-};
-
-static int __devinit hydra_init(struct zorro_dev *z)
-{
-    struct net_device *dev;
-    unsigned long board = ZTWO_VADDR(z->resource.start);
-    unsigned long ioaddr = board+HYDRA_NIC_BASE;
-    const char name[] = "NE2000";
-    int start_page, stop_page;
-    int j;
-    int err;
-
-    static u32 hydra_offsets[16] = {
-       0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
-       0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
-    };
-
-    dev = ____alloc_ei_netdev(0);
-    if (!dev)
-       return -ENOMEM;
-
-    for(j = 0; j < ETHER_ADDR_LEN; j++)
-       dev->dev_addr[j] = *((u8 *)(board + HYDRA_ADDRPROM + 2*j));
-
-    /* We must set the 8390 for word mode. */
-    z_writeb(0x4b, ioaddr + NE_EN0_DCFG);
-    start_page = NESM_START_PG;
-    stop_page = NESM_STOP_PG;
-
-    dev->base_addr = ioaddr;
-    dev->irq = IRQ_AMIGA_PORTS;
-
-    /* Install the Interrupt handler */
-    if (request_irq(IRQ_AMIGA_PORTS, __ei_interrupt, IRQF_SHARED, "Hydra Ethernet",
-                   dev)) {
-       free_netdev(dev);
-       return -EAGAIN;
-    }
-
-    ei_status.name = name;
-    ei_status.tx_start_page = start_page;
-    ei_status.stop_page = stop_page;
-    ei_status.word16 = 1;
-    ei_status.bigendian = 1;
-
-    ei_status.rx_start_page = start_page + TX_PAGES;
-
-    ei_status.reset_8390 = hydra_reset_8390;
-    ei_status.block_input = hydra_block_input;
-    ei_status.block_output = hydra_block_output;
-    ei_status.get_8390_hdr = hydra_get_8390_hdr;
-    ei_status.reg_offset = hydra_offsets;
-
-    dev->netdev_ops = &hydra_netdev_ops;
-    __NS8390_init(dev, 0);
-
-    err = register_netdev(dev);
-    if (err) {
-       free_irq(IRQ_AMIGA_PORTS, dev);
-       free_netdev(dev);
-       return err;
-    }
-
-    zorro_set_drvdata(z, dev);
-
-    pr_info("%s: Hydra at %pR, address %pM (hydra.c " HYDRA_VERSION ")\n",
-           dev->name, &z->resource, dev->dev_addr);
-
-    return 0;
-}
-
-static int hydra_open(struct net_device *dev)
-{
-    __ei_open(dev);
-    return 0;
-}
-
-static int hydra_close(struct net_device *dev)
-{
-    if (ei_debug > 1)
-       printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
-    __ei_close(dev);
-    return 0;
-}
-
-static void hydra_reset_8390(struct net_device *dev)
-{
-    printk(KERN_INFO "Hydra hw reset not there\n");
-}
-
-static void hydra_get_8390_hdr(struct net_device *dev,
-                              struct e8390_pkt_hdr *hdr, int ring_page)
-{
-    int nic_base = dev->base_addr;
-    short *ptrs;
-    unsigned long hdr_start= (nic_base-HYDRA_NIC_BASE) +
-                            ((ring_page - NESM_START_PG)<<8);
-    ptrs = (short *)hdr;
-
-    *(ptrs++) = z_readw(hdr_start);
-    *((short *)hdr) = WORDSWAP(*((short *)hdr));
-    hdr_start += 2;
-    *(ptrs++) = z_readw(hdr_start);
-    *((short *)hdr+1) = WORDSWAP(*((short *)hdr+1));
-}
-
-static void hydra_block_input(struct net_device *dev, int count,
-                             struct sk_buff *skb, int ring_offset)
-{
-    unsigned long nic_base = dev->base_addr;
-    unsigned long mem_base = nic_base - HYDRA_NIC_BASE;
-    unsigned long xfer_start = mem_base + ring_offset - (NESM_START_PG<<8);
-
-    if (count&1)
-       count++;
-
-    if (xfer_start+count >  mem_base + (NESM_STOP_PG<<8)) {
-       int semi_count = (mem_base + (NESM_STOP_PG<<8)) - xfer_start;
-
-       z_memcpy_fromio(skb->data,xfer_start,semi_count);
-       count -= semi_count;
-       z_memcpy_fromio(skb->data+semi_count, mem_base, count);
-    } else
-       z_memcpy_fromio(skb->data, xfer_start,count);
-
-}
-
-static void hydra_block_output(struct net_device *dev, int count,
-                              const unsigned char *buf, int start_page)
-{
-    unsigned long nic_base = dev->base_addr;
-    unsigned long mem_base = nic_base - HYDRA_NIC_BASE;
-
-    if (count&1)
-       count++;
-
-    z_memcpy_toio(mem_base+((start_page - NESM_START_PG)<<8), buf, count);
-}
-
-static void __devexit hydra_remove_one(struct zorro_dev *z)
-{
-    struct net_device *dev = zorro_get_drvdata(z);
-
-    unregister_netdev(dev);
-    free_irq(IRQ_AMIGA_PORTS, dev);
-    release_mem_region(ZTWO_PADDR(dev->base_addr)-HYDRA_NIC_BASE, 0x10000);
-    free_netdev(dev);
-}
-
-static int __init hydra_init_module(void)
-{
-    return zorro_register_driver(&hydra_driver);
-}
-
-static void __exit hydra_cleanup_module(void)
-{
-    zorro_unregister_driver(&hydra_driver);
-}
-
-module_init(hydra_init_module);
-module_exit(hydra_cleanup_module);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c
deleted file mode 100644 (file)
index 05ae214..0000000
+++ /dev/null
@@ -1,1080 +0,0 @@
-/* 8390.c: A general NS8390 ethernet driver core for linux. */
-/*
-       Written 1992-94 by Donald Becker.
-
-       Copyright 1993 United States Government as represented by the
-       Director, National Security Agency.
-
-       This software may be used and distributed according to the terms
-       of the GNU General Public License, incorporated herein by reference.
-
-       The author may be reached as becker@scyld.com, or C/O
-       Scyld Computing Corporation
-       410 Severn Ave., Suite 210
-       Annapolis MD 21403
-
-
-  This is the chip-specific code for many 8390-based ethernet adaptors.
-  This is not a complete driver, it must be combined with board-specific
-  code such as ne.c, wd.c, 3c503.c, etc.
-
-  Seeing how at least eight drivers use this code, (not counting the
-  PCMCIA ones either) it is easy to break some card by what seems like
-  a simple innocent change. Please contact me or Donald if you think
-  you have found something that needs changing. -- PG
-
-
-  Changelog:
-
-  Paul Gortmaker       : remove set_bit lock, other cleanups.
-  Paul Gortmaker       : add ei_get_8390_hdr() so we can pass skb's to
-                         ei_block_input() for eth_io_copy_and_sum().
-  Paul Gortmaker       : exchange static int ei_pingpong for a #define,
-                         also add better Tx error handling.
-  Paul Gortmaker       : rewrite Rx overrun handling as per NS specs.
-  Alexey Kuznetsov     : use the 8390's six bit hash multicast filter.
-  Paul Gortmaker       : tweak ANK's above multicast changes a bit.
-  Paul Gortmaker       : update packet statistics for v2.1.x
-  Alan Cox             : support arbitrary stupid port mappings on the
-                         68K Macintosh. Support >16bit I/O spaces
-  Paul Gortmaker       : add kmod support for auto-loading of the 8390
-                         module by all drivers that require it.
-  Alan Cox             : Spinlocking work, added 'BUG_83C690'
-  Paul Gortmaker       : Separate out Tx timeout code from Tx path.
-  Paul Gortmaker       : Remove old unused single Tx buffer code.
-  Hayato Fujiwara      : Add m32r support.
-  Paul Gortmaker       : use skb_padto() instead of stack scratch area
-
-  Sources:
-  The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
-
-  */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/jiffies.h>
-#include <linux/fs.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/bitops.h>
-#include <asm/system.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-#include <asm/irq.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/in.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/crc32.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
-#define NS8390_CORE
-#include "8390.h"
-
-#define BUG_83C690
-
-/* These are the operational function interfaces to board-specific
-   routines.
-       void reset_8390(struct net_device *dev)
-               Resets the board associated with DEV, including a hardware reset of
-               the 8390.  This is only called when there is a transmit timeout, and
-               it is always followed by 8390_init().
-       void block_output(struct net_device *dev, int count, const unsigned char *buf,
-                                         int start_page)
-               Write the COUNT bytes of BUF to the packet buffer at START_PAGE.  The
-               "page" value uses the 8390's 256-byte pages.
-       void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page)
-               Read the 4 byte, page aligned 8390 header. *If* there is a
-               subsequent read, it will be of the rest of the packet.
-       void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-               Read COUNT bytes from the packet buffer into the skb data area. Start
-               reading from RING_OFFSET, the address as the 8390 sees it.  This will always
-               follow the read of the 8390 header.
-*/
-#define ei_reset_8390 (ei_local->reset_8390)
-#define ei_block_output (ei_local->block_output)
-#define ei_block_input (ei_local->block_input)
-#define ei_get_8390_hdr (ei_local->get_8390_hdr)
-
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifndef ei_debug
-int ei_debug = 1;
-#endif
-
-/* Index to functions. */
-static void ei_tx_intr(struct net_device *dev);
-static void ei_tx_err(struct net_device *dev);
-static void ei_receive(struct net_device *dev);
-static void ei_rx_overrun(struct net_device *dev);
-
-/* Routines generic to NS8390-based boards. */
-static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
-                                                               int start_page);
-static void do_set_multicast_list(struct net_device *dev);
-static void __NS8390_init(struct net_device *dev, int startp);
-
-/*
- *     SMP and the 8390 setup.
- *
- *     The 8390 isn't exactly designed to be multithreaded on RX/TX. There is
- *     a page register that controls bank and packet buffer access. We guard
- *     this with ei_local->page_lock. Nobody should assume or set the page other
- *     than zero when the lock is not held. Lock holders must restore page 0
- *     before unlocking. Even pure readers must take the lock to protect in
- *     page 0.
- *
- *     To make life difficult the chip can also be very slow. We therefore can't
- *     just use spinlocks. For the longer lockups we disable the irq the device
- *     sits on and hold the lock. We must hold the lock because there is a dual
- *     processor case other than interrupts (get stats/set multicast list in
- *     parallel with each other and transmit).
- *
- *     Note: in theory we can just disable the irq on the card _but_ there is
- *     a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs"
- *     enter lock, take the queued irq. So we waddle instead of flying.
- *
- *     Finally by special arrangement for the purpose of being generally
- *     annoying the transmit function is called bh atomic. That places
- *     restrictions on the user context callers as disable_irq won't save
- *     them.
- *
- *     Additional explanation of problems with locking by Alan Cox:
- *
- *     "The author (me) didn't use spin_lock_irqsave because the slowness of the
- *     card means that approach caused horrible problems like losing serial data
- *     at 38400 baud on some chips. Remember many 8390 nics on PCI were ISA
- *     chips with FPGA front ends.
- *
- *     Ok the logic behind the 8390 is very simple:
- *
- *     Things to know
- *             - IRQ delivery is asynchronous to the PCI bus
- *             - Blocking the local CPU IRQ via spin locks was too slow
- *             - The chip has register windows needing locking work
- *
- *     So the path was once (I say once as people appear to have changed it
- *     in the mean time and it now looks rather bogus if the changes to use
- *     disable_irq_nosync_irqsave are disabling the local IRQ)
- *
- *
- *             Take the page lock
- *             Mask the IRQ on chip
- *             Disable the IRQ (but not mask locally- someone seems to have
- *                     broken this with the lock validator stuff)
- *                     [This must be _nosync as the page lock may otherwise
- *                             deadlock us]
- *             Drop the page lock and turn IRQs back on
- *
- *             At this point an existing IRQ may still be running but we can't
- *             get a new one
- *
- *             Take the lock (so we know the IRQ has terminated) but don't mask
- *     the IRQs on the processor
- *             Set irqlock [for debug]
- *
- *             Transmit (slow as ****)
- *
- *             re-enable the IRQ
- *
- *
- *     We have to use disable_irq because otherwise you will get delayed
- *     interrupts on the APIC bus deadlocking the transmit path.
- *
- *     Quite hairy but the chip simply wasn't designed for SMP and you can't
- *     even ACK an interrupt without risking corrupting other parallel
- *     activities on the chip." [lkml, 25 Jul 2007]
- */
-
-
-
-/**
- * ei_open - Open/initialize the board.
- * @dev: network device to initialize
- *
- * This routine goes all-out, setting everything
- * up anew at each open, even though many of these registers should only
- * need to be set once at boot.
- */
-static int __ei_open(struct net_device *dev)
-{
-       unsigned long flags;
-       struct ei_device *ei_local = netdev_priv(dev);
-
-       if (dev->watchdog_timeo <= 0)
-               dev->watchdog_timeo = TX_TIMEOUT;
-
-       /*
-        *      Grab the page lock so we own the register set, then call
-        *      the init function.
-        */
-
-       spin_lock_irqsave(&ei_local->page_lock, flags);
-       __NS8390_init(dev, 1);
-       /* Set the flag before we drop the lock, That way the IRQ arrives
-          after its set and we get no silly warnings */
-       netif_start_queue(dev);
-       spin_unlock_irqrestore(&ei_local->page_lock, flags);
-       ei_local->irqlock = 0;
-       return 0;
-}
-
-/**
- * ei_close - shut down network device
- * @dev: network device to close
- *
- * Opposite of ei_open(). Only used when "ifconfig <devname> down" is done.
- */
-static int __ei_close(struct net_device *dev)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       unsigned long flags;
-
-       /*
-        *      Hold the page lock during close
-        */
-
-       spin_lock_irqsave(&ei_local->page_lock, flags);
-       __NS8390_init(dev, 0);
-       spin_unlock_irqrestore(&ei_local->page_lock, flags);
-       netif_stop_queue(dev);
-       return 0;
-}
-
-/**
- * ei_tx_timeout - handle transmit time out condition
- * @dev: network device which has apparently fallen asleep
- *
- * Called by kernel when device never acknowledges a transmit has
- * completed (or failed) - i.e. never posted a Tx related interrupt.
- */
-
-static void __ei_tx_timeout(struct net_device *dev)
-{
-       unsigned long e8390_base = dev->base_addr;
-       struct ei_device *ei_local = netdev_priv(dev);
-       int txsr, isr, tickssofar = jiffies - dev_trans_start(dev);
-       unsigned long flags;
-
-       dev->stats.tx_errors++;
-
-       spin_lock_irqsave(&ei_local->page_lock, flags);
-       txsr = ei_inb(e8390_base+EN0_TSR);
-       isr = ei_inb(e8390_base+EN0_ISR);
-       spin_unlock_irqrestore(&ei_local->page_lock, flags);
-
-       netdev_dbg(dev, "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d\n",
-                  (txsr & ENTSR_ABT) ? "excess collisions." :
-                  (isr) ? "lost interrupt?" : "cable problem?",
-                  txsr, isr, tickssofar);
-
-       if (!isr && !dev->stats.tx_packets) {
-               /* The 8390 probably hasn't gotten on the cable yet. */
-               ei_local->interface_num ^= 1;   /* Try a different xcvr.  */
-       }
-
-       /* Ugly but a reset can be slow, yet must be protected */
-
-       disable_irq_nosync_lockdep(dev->irq);
-       spin_lock(&ei_local->page_lock);
-
-       /* Try to restart the card.  Perhaps the user has fixed something. */
-       ei_reset_8390(dev);
-       __NS8390_init(dev, 1);
-
-       spin_unlock(&ei_local->page_lock);
-       enable_irq_lockdep(dev->irq);
-       netif_wake_queue(dev);
-}
-
-/**
- * ei_start_xmit - begin packet transmission
- * @skb: packet to be sent
- * @dev: network device to which packet is sent
- *
- * Sends a packet to an 8390 network device.
- */
-
-static netdev_tx_t __ei_start_xmit(struct sk_buff *skb,
-                                  struct net_device *dev)
-{
-       unsigned long e8390_base = dev->base_addr;
-       struct ei_device *ei_local = netdev_priv(dev);
-       int send_length = skb->len, output_page;
-       unsigned long flags;
-       char buf[ETH_ZLEN];
-       char *data = skb->data;
-
-       if (skb->len < ETH_ZLEN) {
-               memset(buf, 0, ETH_ZLEN);       /* more efficient than doing just the needed bits */
-               memcpy(buf, data, skb->len);
-               send_length = ETH_ZLEN;
-               data = buf;
-       }
-
-       /* Mask interrupts from the ethercard.
-          SMP: We have to grab the lock here otherwise the IRQ handler
-          on another CPU can flip window and race the IRQ mask set. We end
-          up trashing the mcast filter not disabling irqs if we don't lock */
-
-       spin_lock_irqsave(&ei_local->page_lock, flags);
-       ei_outb_p(0x00, e8390_base + EN0_IMR);
-       spin_unlock_irqrestore(&ei_local->page_lock, flags);
-
-
-       /*
-        *      Slow phase with lock held.
-        */
-
-       disable_irq_nosync_lockdep_irqsave(dev->irq, &flags);
-
-       spin_lock(&ei_local->page_lock);
-
-       ei_local->irqlock = 1;
-
-       /*
-        * We have two Tx slots available for use. Find the first free
-        * slot, and then perform some sanity checks. With two Tx bufs,
-        * you get very close to transmitting back-to-back packets. With
-        * only one Tx buf, the transmitter sits idle while you reload the
-        * card, leaving a substantial gap between each transmitted packet.
-        */
-
-       if (ei_local->tx1 == 0) {
-               output_page = ei_local->tx_start_page;
-               ei_local->tx1 = send_length;
-               if (ei_debug  &&  ei_local->tx2 > 0)
-                       netdev_dbg(dev, "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
-                                  ei_local->tx2, ei_local->lasttx, ei_local->txing);
-       } else if (ei_local->tx2 == 0) {
-               output_page = ei_local->tx_start_page + TX_PAGES/2;
-               ei_local->tx2 = send_length;
-               if (ei_debug  &&  ei_local->tx1 > 0)
-                       netdev_dbg(dev, "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
-                                  ei_local->tx1, ei_local->lasttx, ei_local->txing);
-       } else {                        /* We should never get here. */
-               if (ei_debug)
-                       netdev_dbg(dev, "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
-                                  ei_local->tx1, ei_local->tx2, ei_local->lasttx);
-               ei_local->irqlock = 0;
-               netif_stop_queue(dev);
-               ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR);
-               spin_unlock(&ei_local->page_lock);
-               enable_irq_lockdep_irqrestore(dev->irq, &flags);
-               dev->stats.tx_errors++;
-               return NETDEV_TX_BUSY;
-       }
-
-       /*
-        * Okay, now upload the packet and trigger a send if the transmitter
-        * isn't already sending. If it is busy, the interrupt handler will
-        * trigger the send later, upon receiving a Tx done interrupt.
-        */
-
-       ei_block_output(dev, send_length, data, output_page);
-
-       if (!ei_local->txing) {
-               ei_local->txing = 1;
-               NS8390_trigger_send(dev, send_length, output_page);
-               if (output_page == ei_local->tx_start_page) {
-                       ei_local->tx1 = -1;
-                       ei_local->lasttx = -1;
-               } else {
-                       ei_local->tx2 = -1;
-                       ei_local->lasttx = -2;
-               }
-       } else
-               ei_local->txqueue++;
-
-       if (ei_local->tx1  &&  ei_local->tx2)
-               netif_stop_queue(dev);
-       else
-               netif_start_queue(dev);
-
-       /* Turn 8390 interrupts back on. */
-       ei_local->irqlock = 0;
-       ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR);
-
-       spin_unlock(&ei_local->page_lock);
-       enable_irq_lockdep_irqrestore(dev->irq, &flags);
-       skb_tx_timestamp(skb);
-       dev_kfree_skb(skb);
-       dev->stats.tx_bytes += send_length;
-
-       return NETDEV_TX_OK;
-}
-
-/**
- * ei_interrupt - handle the interrupts from an 8390
- * @irq: interrupt number
- * @dev_id: a pointer to the net_device
- *
- * Handle the ether interface interrupts. We pull packets from
- * the 8390 via the card specific functions and fire them at the networking
- * stack. We also handle transmit completions and wake the transmit path if
- * necessary. We also update the counters and do other housekeeping as
- * needed.
- */
-
-static irqreturn_t __ei_interrupt(int irq, void *dev_id)
-{
-       struct net_device *dev = dev_id;
-       unsigned long e8390_base = dev->base_addr;
-       int interrupts, nr_serviced = 0;
-       struct ei_device *ei_local = netdev_priv(dev);
-
-       /*
-        *      Protect the irq test too.
-        */
-
-       spin_lock(&ei_local->page_lock);
-
-       if (ei_local->irqlock) {
-               /*
-                * This might just be an interrupt for a PCI device sharing
-                * this line
-                */
-               netdev_err(dev, "Interrupted while interrupts are masked! isr=%#2x imr=%#2x\n",
-                          ei_inb_p(e8390_base + EN0_ISR),
-                          ei_inb_p(e8390_base + EN0_IMR));
-               spin_unlock(&ei_local->page_lock);
-               return IRQ_NONE;
-       }
-
-       /* Change to page 0 and read the intr status reg. */
-       ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
-       if (ei_debug > 3)
-               netdev_dbg(dev, "interrupt(isr=%#2.2x)\n",
-                          ei_inb_p(e8390_base + EN0_ISR));
-
-       /* !!Assumption!! -- we stay in page 0.  Don't break this. */
-       while ((interrupts = ei_inb_p(e8390_base + EN0_ISR)) != 0 &&
-              ++nr_serviced < MAX_SERVICE) {
-               if (!netif_running(dev)) {
-                       netdev_warn(dev, "interrupt from stopped card\n");
-                       /* rmk - acknowledge the interrupts */
-                       ei_outb_p(interrupts, e8390_base + EN0_ISR);
-                       interrupts = 0;
-                       break;
-               }
-               if (interrupts & ENISR_OVER)
-                       ei_rx_overrun(dev);
-               else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) {
-                       /* Got a good (?) packet. */
-                       ei_receive(dev);
-               }
-               /* Push the next to-transmit packet through. */
-               if (interrupts & ENISR_TX)
-                       ei_tx_intr(dev);
-               else if (interrupts & ENISR_TX_ERR)
-                       ei_tx_err(dev);
-
-               if (interrupts & ENISR_COUNTERS) {
-                       dev->stats.rx_frame_errors += ei_inb_p(e8390_base + EN0_COUNTER0);
-                       dev->stats.rx_crc_errors   += ei_inb_p(e8390_base + EN0_COUNTER1);
-                       dev->stats.rx_missed_errors += ei_inb_p(e8390_base + EN0_COUNTER2);
-                       ei_outb_p(ENISR_COUNTERS, e8390_base + EN0_ISR); /* Ack intr. */
-               }
-
-               /* Ignore any RDC interrupts that make it back to here. */
-               if (interrupts & ENISR_RDC)
-                       ei_outb_p(ENISR_RDC, e8390_base + EN0_ISR);
-
-               ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
-       }
-
-       if (interrupts && ei_debug) {
-               ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
-               if (nr_serviced >= MAX_SERVICE) {
-                       /* 0xFF is valid for a card removal */
-                       if (interrupts != 0xFF)
-                               netdev_warn(dev, "Too much work at interrupt, status %#2.2x\n",
-                                           interrupts);
-                       ei_outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
-               } else {
-                       netdev_warn(dev, "unknown interrupt %#2x\n", interrupts);
-                       ei_outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
-               }
-       }
-       spin_unlock(&ei_local->page_lock);
-       return IRQ_RETVAL(nr_serviced > 0);
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void __ei_poll(struct net_device *dev)
-{
-       disable_irq(dev->irq);
-       __ei_interrupt(dev->irq, dev);
-       enable_irq(dev->irq);
-}
-#endif
-
-/**
- * ei_tx_err - handle transmitter error
- * @dev: network device which threw the exception
- *
- * A transmitter error has happened. Most likely excess collisions (which
- * is a fairly normal condition). If the error is one where the Tx will
- * have been aborted, we try and send another one right away, instead of
- * letting the failed packet sit and collect dust in the Tx buffer. This
- * is a much better solution as it avoids kernel based Tx timeouts, and
- * an unnecessary card reset.
- *
- * Called with lock held.
- */
-
-static void ei_tx_err(struct net_device *dev)
-{
-       unsigned long e8390_base = dev->base_addr;
-       /* ei_local is used on some platforms via the EI_SHIFT macro */
-       struct ei_device *ei_local __maybe_unused = netdev_priv(dev);
-       unsigned char txsr = ei_inb_p(e8390_base+EN0_TSR);
-       unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
-
-#ifdef VERBOSE_ERROR_DUMP
-       netdev_dbg(dev, "transmitter error (%#2x):", txsr);
-       if (txsr & ENTSR_ABT)
-               pr_cont(" excess-collisions ");
-       if (txsr & ENTSR_ND)
-               pr_cont(" non-deferral ");
-       if (txsr & ENTSR_CRS)
-               pr_cont(" lost-carrier ");
-       if (txsr & ENTSR_FU)
-               pr_cont(" FIFO-underrun ");
-       if (txsr & ENTSR_CDH)
-               pr_cont(" lost-heartbeat ");
-       pr_cont("\n");
-#endif
-
-       ei_outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */
-
-       if (tx_was_aborted)
-               ei_tx_intr(dev);
-       else {
-               dev->stats.tx_errors++;
-               if (txsr & ENTSR_CRS)
-                       dev->stats.tx_carrier_errors++;
-               if (txsr & ENTSR_CDH)
-                       dev->stats.tx_heartbeat_errors++;
-               if (txsr & ENTSR_OWC)
-                       dev->stats.tx_window_errors++;
-       }
-}
-
-/**
- * ei_tx_intr - transmit interrupt handler
- * @dev: network device for which tx intr is handled
- *
- * We have finished a transmit: check for errors and then trigger the next
- * packet to be sent. Called with lock held.
- */
-
-static void ei_tx_intr(struct net_device *dev)
-{
-       unsigned long e8390_base = dev->base_addr;
-       struct ei_device *ei_local = netdev_priv(dev);
-       int status = ei_inb(e8390_base + EN0_TSR);
-
-       ei_outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */
-
-       /*
-        * There are two Tx buffers, see which one finished, and trigger
-        * the send of another one if it exists.
-        */
-       ei_local->txqueue--;
-
-       if (ei_local->tx1 < 0) {
-               if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
-                       pr_err("%s: bogus last_tx_buffer %d, tx1=%d\n",
-                              ei_local->name, ei_local->lasttx, ei_local->tx1);
-               ei_local->tx1 = 0;
-               if (ei_local->tx2 > 0) {
-                       ei_local->txing = 1;
-                       NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
-                       dev->trans_start = jiffies;
-                       ei_local->tx2 = -1,
-                       ei_local->lasttx = 2;
-               } else
-                       ei_local->lasttx = 20, ei_local->txing = 0;
-       } else if (ei_local->tx2 < 0) {
-               if (ei_local->lasttx != 2  &&  ei_local->lasttx != -2)
-                       pr_err("%s: bogus last_tx_buffer %d, tx2=%d\n",
-                              ei_local->name, ei_local->lasttx, ei_local->tx2);
-               ei_local->tx2 = 0;
-               if (ei_local->tx1 > 0) {
-                       ei_local->txing = 1;
-                       NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
-                       dev->trans_start = jiffies;
-                       ei_local->tx1 = -1;
-                       ei_local->lasttx = 1;
-               } else
-                       ei_local->lasttx = 10, ei_local->txing = 0;
-       } /* else
-               netdev_warn(dev, "unexpected TX-done interrupt, lasttx=%d\n",
-                           ei_local->lasttx);
-*/
-
-       /* Minimize Tx latency: update the statistics after we restart TXing. */
-       if (status & ENTSR_COL)
-               dev->stats.collisions++;
-       if (status & ENTSR_PTX)
-               dev->stats.tx_packets++;
-       else {
-               dev->stats.tx_errors++;
-               if (status & ENTSR_ABT) {
-                       dev->stats.tx_aborted_errors++;
-                       dev->stats.collisions += 16;
-               }
-               if (status & ENTSR_CRS)
-                       dev->stats.tx_carrier_errors++;
-               if (status & ENTSR_FU)
-                       dev->stats.tx_fifo_errors++;
-               if (status & ENTSR_CDH)
-                       dev->stats.tx_heartbeat_errors++;
-               if (status & ENTSR_OWC)
-                       dev->stats.tx_window_errors++;
-       }
-       netif_wake_queue(dev);
-}
-
-/**
- * ei_receive - receive some packets
- * @dev: network device with which receive will be run
- *
- * We have a good packet(s), get it/them out of the buffers.
- * Called with lock held.
- */
-
-static void ei_receive(struct net_device *dev)
-{
-       unsigned long e8390_base = dev->base_addr;
-       struct ei_device *ei_local = netdev_priv(dev);
-       unsigned char rxing_page, this_frame, next_frame;
-       unsigned short current_offset;
-       int rx_pkt_count = 0;
-       struct e8390_pkt_hdr rx_frame;
-       int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page;
-
-       while (++rx_pkt_count < 10) {
-               int pkt_len, pkt_stat;
-
-               /* Get the rx page (incoming packet pointer). */
-               ei_outb_p(E8390_NODMA+E8390_PAGE1, e8390_base + E8390_CMD);
-               rxing_page = ei_inb_p(e8390_base + EN1_CURPAG);
-               ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
-
-               /* Remove one frame from the ring.  Boundary is always a page behind. */
-               this_frame = ei_inb_p(e8390_base + EN0_BOUNDARY) + 1;
-               if (this_frame >= ei_local->stop_page)
-                       this_frame = ei_local->rx_start_page;
-
-               /* Someday we'll omit the previous, iff we never get this message.
-                  (There is at least one clone claimed to have a problem.)
-
-                  Keep quiet if it looks like a card removal. One problem here
-                  is that some clones crash in roughly the same way.
-                */
-               if (ei_debug > 0 &&
-                   this_frame != ei_local->current_page &&
-                   (this_frame != 0x0 || rxing_page != 0xFF))
-                       netdev_err(dev, "mismatched read page pointers %2x vs %2x\n",
-                                  this_frame, ei_local->current_page);
-
-               if (this_frame == rxing_page)   /* Read all the frames? */
-                       break;                          /* Done for now */
-
-               current_offset = this_frame << 8;
-               ei_get_8390_hdr(dev, &rx_frame, this_frame);
-
-               pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr);
-               pkt_stat = rx_frame.status;
-
-               next_frame = this_frame + 1 + ((pkt_len+4)>>8);
-
-               /* Check for bogosity warned by 3c503 book: the status byte is never
-                  written.  This happened a lot during testing! This code should be
-                  cleaned up someday. */
-               if (rx_frame.next != next_frame &&
-                   rx_frame.next != next_frame + 1 &&
-                   rx_frame.next != next_frame - num_rx_pages &&
-                   rx_frame.next != next_frame + 1 - num_rx_pages) {
-                       ei_local->current_page = rxing_page;
-                       ei_outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY);
-                       dev->stats.rx_errors++;
-                       continue;
-               }
-
-               if (pkt_len < 60  ||  pkt_len > 1518) {
-                       if (ei_debug)
-                               netdev_dbg(dev, "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
-                                          rx_frame.count, rx_frame.status,
-                                          rx_frame.next);
-                       dev->stats.rx_errors++;
-                       dev->stats.rx_length_errors++;
-               } else if ((pkt_stat & 0x0F) == ENRSR_RXOK) {
-                       struct sk_buff *skb;
-
-                       skb = dev_alloc_skb(pkt_len+2);
-                       if (skb == NULL) {
-                               if (ei_debug > 1)
-                                       netdev_dbg(dev, "Couldn't allocate a sk_buff of size %d\n",
-                                                  pkt_len);
-                               dev->stats.rx_dropped++;
-                               break;
-                       } else {
-                               skb_reserve(skb, 2);    /* IP headers on 16 byte boundaries */
-                               skb_put(skb, pkt_len);  /* Make room */
-                               ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
-                               skb->protocol = eth_type_trans(skb, dev);
-                               if (!skb_defer_rx_timestamp(skb))
-                                       netif_rx(skb);
-                               dev->stats.rx_packets++;
-                               dev->stats.rx_bytes += pkt_len;
-                               if (pkt_stat & ENRSR_PHY)
-                                       dev->stats.multicast++;
-                       }
-               } else {
-                       if (ei_debug)
-                               netdev_dbg(dev, "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
-                                          rx_frame.status, rx_frame.next,
-                                          rx_frame.count);
-                       dev->stats.rx_errors++;
-                       /* NB: The NIC counts CRC, frame and missed errors. */
-                       if (pkt_stat & ENRSR_FO)
-                               dev->stats.rx_fifo_errors++;
-               }
-               next_frame = rx_frame.next;
-
-               /* This _should_ never happen: it's here for avoiding bad clones. */
-               if (next_frame >= ei_local->stop_page) {
-                       netdev_notice(dev, "next frame inconsistency, %#2x\n",
-                                     next_frame);
-                       next_frame = ei_local->rx_start_page;
-               }
-               ei_local->current_page = next_frame;
-               ei_outb_p(next_frame-1, e8390_base+EN0_BOUNDARY);
-       }
-
-       /* We used to also ack ENISR_OVER here, but that would sometimes mask
-          a real overrun, leaving the 8390 in a stopped state with rec'vr off. */
-       ei_outb_p(ENISR_RX+ENISR_RX_ERR, e8390_base+EN0_ISR);
-}
-
-/**
- * ei_rx_overrun - handle receiver overrun
- * @dev: network device which threw exception
- *
- * We have a receiver overrun: we have to kick the 8390 to get it started
- * again. Problem is that you have to kick it exactly as NS prescribes in
- * the updated datasheets, or "the NIC may act in an unpredictable manner."
- * This includes causing "the NIC to defer indefinitely when it is stopped
- * on a busy network."  Ugh.
- * Called with lock held. Don't call this with the interrupts off or your
- * computer will hate you - it takes 10ms or so.
- */
-
-static void ei_rx_overrun(struct net_device *dev)
-{
-       unsigned long e8390_base = dev->base_addr;
-       unsigned char was_txing, must_resend = 0;
-       /* ei_local is used on some platforms via the EI_SHIFT macro */
-       struct ei_device *ei_local __maybe_unused = netdev_priv(dev);
-
-       /*
-        * Record whether a Tx was in progress and then issue the
-        * stop command.
-        */
-       was_txing = ei_inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
-       ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
-
-       if (ei_debug > 1)
-               netdev_dbg(dev, "Receiver overrun\n");
-       dev->stats.rx_over_errors++;
-
-       /*
-        * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
-        * Early datasheets said to poll the reset bit, but now they say that
-        * it "is not a reliable indicator and subsequently should be ignored."
-        * We wait at least 10ms.
-        */
-
-       mdelay(10);
-
-       /*
-        * Reset RBCR[01] back to zero as per magic incantation.
-        */
-       ei_outb_p(0x00, e8390_base+EN0_RCNTLO);
-       ei_outb_p(0x00, e8390_base+EN0_RCNTHI);
-
-       /*
-        * See if any Tx was interrupted or not. According to NS, this
-        * step is vital, and skipping it will cause no end of havoc.
-        */
-
-       if (was_txing) {
-               unsigned char tx_completed = ei_inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
-               if (!tx_completed)
-                       must_resend = 1;
-       }
-
-       /*
-        * Have to enter loopback mode and then restart the NIC before
-        * you are allowed to slurp packets up off the ring.
-        */
-       ei_outb_p(E8390_TXOFF, e8390_base + EN0_TXCR);
-       ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
-
-       /*
-        * Clear the Rx ring of all the debris, and ack the interrupt.
-        */
-       ei_receive(dev);
-       ei_outb_p(ENISR_OVER, e8390_base+EN0_ISR);
-
-       /*
-        * Leave loopback mode, and resend any packet that got stopped.
-        */
-       ei_outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR);
-       if (must_resend)
-               ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
-}
-
-/*
- *     Collect the stats. This is called unlocked and from several contexts.
- */
-
-static struct net_device_stats *__ei_get_stats(struct net_device *dev)
-{
-       unsigned long ioaddr = dev->base_addr;
-       struct ei_device *ei_local = netdev_priv(dev);
-       unsigned long flags;
-
-       /* If the card is stopped, just return the present stats. */
-       if (!netif_running(dev))
-               return &dev->stats;
-
-       spin_lock_irqsave(&ei_local->page_lock, flags);
-       /* Read the counter registers, assuming we are in page 0. */
-       dev->stats.rx_frame_errors  += ei_inb_p(ioaddr + EN0_COUNTER0);
-       dev->stats.rx_crc_errors    += ei_inb_p(ioaddr + EN0_COUNTER1);
-       dev->stats.rx_missed_errors += ei_inb_p(ioaddr + EN0_COUNTER2);
-       spin_unlock_irqrestore(&ei_local->page_lock, flags);
-
-       return &dev->stats;
-}
-
-/*
- * Form the 64 bit 8390 multicast table from the linked list of addresses
- * associated with this dev structure.
- */
-
-static inline void make_mc_bits(u8 *bits, struct net_device *dev)
-{
-       struct netdev_hw_addr *ha;
-
-       netdev_for_each_mc_addr(ha, dev) {
-               u32 crc = ether_crc(ETH_ALEN, ha->addr);
-               /*
-                * The 8390 uses the 6 most significant bits of the
-                * CRC to index the multicast table.
-                */
-               bits[crc>>29] |= (1<<((crc>>26)&7));
-       }
-}
-
-/**
- * do_set_multicast_list - set/clear multicast filter
- * @dev: net device for which multicast filter is adjusted
- *
- *     Set or clear the multicast filter for this adaptor. May be called
- *     from a BH in 2.1.x. Must be called with lock held.
- */
-
-static void do_set_multicast_list(struct net_device *dev)
-{
-       unsigned long e8390_base = dev->base_addr;
-       int i;
-       struct ei_device *ei_local = netdev_priv(dev);
-
-       if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
-               memset(ei_local->mcfilter, 0, 8);
-               if (!netdev_mc_empty(dev))
-                       make_mc_bits(ei_local->mcfilter, dev);
-       } else
-               memset(ei_local->mcfilter, 0xFF, 8);    /* mcast set to accept-all */
-
-       /*
-        * DP8390 manuals don't specify any magic sequence for altering
-        * the multicast regs on an already running card. To be safe, we
-        * ensure multicast mode is off prior to loading up the new hash
-        * table. If this proves to be not enough, we can always resort
-        * to stopping the NIC, loading the table and then restarting.
-        *
-        * Bug Alert!  The MC regs on the SMC 83C690 (SMC Elite and SMC
-        * Elite16) appear to be write-only. The NS 8390 data sheet lists
-        * them as r/w so this is a bug.  The SMC 83C790 (SMC Ultra and
-        * Ultra32 EISA) appears to have this bug fixed.
-        */
-
-       if (netif_running(dev))
-               ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
-       ei_outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
-       for (i = 0; i < 8; i++) {
-               ei_outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
-#ifndef BUG_83C690
-               if (ei_inb_p(e8390_base + EN1_MULT_SHIFT(i)) != ei_local->mcfilter[i])
-                       netdev_err(dev, "Multicast filter read/write mismap %d\n",
-                                  i);
-#endif
-       }
-       ei_outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
-
-       if (dev->flags&IFF_PROMISC)
-               ei_outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
-       else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev))
-               ei_outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
-       else
-               ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
-}
-
-/*
- *     Called without lock held. This is invoked from user context and may
- *     be parallel to just about everything else. Its also fairly quick and
- *     not called too often. Must protect against both bh and irq users
- */
-
-static void __ei_set_multicast_list(struct net_device *dev)
-{
-       unsigned long flags;
-       struct ei_device *ei_local = netdev_priv(dev);
-
-       spin_lock_irqsave(&ei_local->page_lock, flags);
-       do_set_multicast_list(dev);
-       spin_unlock_irqrestore(&ei_local->page_lock, flags);
-}
-
-/**
- * ethdev_setup - init rest of 8390 device struct
- * @dev: network device structure to init
- *
- * Initialize the rest of the 8390 device structure.  Do NOT __init
- * this, as it is used by 8390 based modular drivers too.
- */
-
-static void ethdev_setup(struct net_device *dev)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       if (ei_debug > 1)
-               printk(version);
-
-       ether_setup(dev);
-
-       spin_lock_init(&ei_local->page_lock);
-}
-
-/**
- * alloc_ei_netdev - alloc_etherdev counterpart for 8390
- * @size: extra bytes to allocate
- *
- * Allocate 8390-specific net_device.
- */
-static struct net_device *____alloc_ei_netdev(int size)
-{
-       return alloc_netdev(sizeof(struct ei_device) + size, "eth%d",
-                               ethdev_setup);
-}
-
-
-
-
-/* This page of functions should be 8390 generic */
-/* Follow National Semi's recommendations for initializing the "NIC". */
-
-/**
- * NS8390_init - initialize 8390 hardware
- * @dev: network device to initialize
- * @startp: boolean.  non-zero value to initiate chip processing
- *
- *     Must be called with lock held.
- */
-
-static void __NS8390_init(struct net_device *dev, int startp)
-{
-       unsigned long e8390_base = dev->base_addr;
-       struct ei_device *ei_local = netdev_priv(dev);
-       int i;
-       int endcfg = ei_local->word16
-           ? (0x48 | ENDCFG_WTS | (ei_local->bigendian ? ENDCFG_BOS : 0))
-           : 0x48;
-
-       if (sizeof(struct e8390_pkt_hdr) != 4)
-               panic("8390.c: header struct mispacked\n");
-       /* Follow National Semi's recommendations for initing the DP83902. */
-       ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */
-       ei_outb_p(endcfg, e8390_base + EN0_DCFG);       /* 0x48 or 0x49 */
-       /* Clear the remote byte count registers. */
-       ei_outb_p(0x00,  e8390_base + EN0_RCNTLO);
-       ei_outb_p(0x00,  e8390_base + EN0_RCNTHI);
-       /* Set to monitor and loopback mode -- this is vital!. */
-       ei_outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */
-       ei_outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
-       /* Set the transmit page and receive ring. */
-       ei_outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
-       ei_local->tx1 = ei_local->tx2 = 0;
-       ei_outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG);
-       ei_outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY);    /* 3c503 says 0x3f,NS0x26*/
-       ei_local->current_page = ei_local->rx_start_page;               /* assert boundary+1 */
-       ei_outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG);
-       /* Clear the pending interrupts and mask. */
-       ei_outb_p(0xFF, e8390_base + EN0_ISR);
-       ei_outb_p(0x00,  e8390_base + EN0_IMR);
-
-       /* Copy the station address into the DS8390 registers. */
-
-       ei_outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
-       for (i = 0; i < 6; i++) {
-               ei_outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
-               if (ei_debug > 1 &&
-                   ei_inb_p(e8390_base + EN1_PHYS_SHIFT(i)) != dev->dev_addr[i])
-                       netdev_err(dev, "Hw. address read/write mismap %d\n", i);
-       }
-
-       ei_outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
-       ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
-
-       ei_local->tx1 = ei_local->tx2 = 0;
-       ei_local->txing = 0;
-
-       if (startp) {
-               ei_outb_p(0xff,  e8390_base + EN0_ISR);
-               ei_outb_p(ENISR_ALL,  e8390_base + EN0_IMR);
-               ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
-               ei_outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */
-               /* 3c503 TechMan says rxconfig only after the NIC is started. */
-               ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on,  */
-               do_set_multicast_list(dev);     /* (re)load the mcast table */
-       }
-}
-
-/* Trigger a transmit start, assuming the length is valid.
-   Always called with the page lock held */
-
-static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
-                                                               int start_page)
-{
-       unsigned long e8390_base = dev->base_addr;
-       struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev);
-
-       ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
-
-       if (ei_inb_p(e8390_base + E8390_CMD) & E8390_TRANS) {
-               netdev_warn(dev, "trigger_send() called with the transmitter busy\n");
-               return;
-       }
-       ei_outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
-       ei_outb_p(length >> 8, e8390_base + EN0_TCNTHI);
-       ei_outb_p(start_page, e8390_base + EN0_TPSR);
-       ei_outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD);
-}
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
deleted file mode 100644 (file)
index f9888d2..0000000
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
-       lne390.c
-
-       Linux driver for Mylex LNE390 EISA Network Adapter
-
-       Copyright (C) 1996-1998, Paul Gortmaker.
-
-       This software may be used and distributed according to the terms
-       of the GNU General Public License, incorporated herein by reference.
-
-       Information and Code Sources:
-
-       1) Based upon framework of es3210 driver.
-       2) The existing myriad of other Linux 8390 drivers by Donald Becker.
-       3) Russ Nelson's asm packet driver provided additional info.
-       4) Info for getting IRQ and sh-mem gleaned from the EISA cfg files.
-
-       The LNE390 is an EISA shared memory NS8390 implementation. Note
-       that all memory copies to/from the board must be 32bit transfers.
-       There are two versions of the card: the lne390a and the lne390b.
-       Going by the EISA cfg files, the "a" has jumpers to select between
-       BNC/AUI, but the "b" also has RJ-45 and selection is via the SCU.
-       The shared memory address selection is also slightly different.
-       Note that shared memory address > 1MB are supported with this driver.
-
-       You can try <http://www.mylex.com> if you want more info, as I've
-       never even seen one of these cards.  :)
-
-       Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/09/01
-       - get rid of check_region
-       - no need to check if dev == NULL in lne390_probe1
-*/
-
-static const char *version =
-       "lne390.c: Driver revision v0.99.1, 01/09/2000\n";
-
-#include <linux/module.h>
-#include <linux/eisa.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include "8390.h"
-
-#define DRV_NAME "lne390"
-
-static int lne390_probe1(struct net_device *dev, int ioaddr);
-
-static void lne390_reset_8390(struct net_device *dev);
-
-static void lne390_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
-static void lne390_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset);
-static void lne390_block_output(struct net_device *dev, int count, const unsigned char *buf, const int start_page);
-
-#define LNE390_START_PG                0x00    /* First page of TX buffer      */
-#define LNE390_STOP_PG         0x80    /* Last page +1 of RX ring      */
-
-#define LNE390_ID_PORT         0xc80   /* Same for all EISA cards      */
-#define LNE390_IO_EXTENT       0x20
-#define LNE390_SA_PROM         0x16    /* Start of e'net addr.         */
-#define LNE390_RESET_PORT      0xc84   /* From the pkt driver source   */
-#define LNE390_NIC_OFFSET      0x00    /* Hello, the 8390 is *here*    */
-
-#define LNE390_ADDR0           0x00    /* 3 byte vendor prefix         */
-#define LNE390_ADDR1           0x80
-#define LNE390_ADDR2           0xe5
-
-#define LNE390_ID0     0x10009835      /* 0x3598 = 01101 01100 11000 = mlx */
-#define LNE390_ID1     0x11009835      /* above is the 390A, this is 390B  */
-
-#define LNE390_CFG1            0xc84   /* NB: 0xc84 is also "reset" port. */
-#define LNE390_CFG2            0xc90
-
-/*
- *     You can OR any of the following bits together and assign it
- *     to LNE390_DEBUG to get verbose driver info during operation.
- *     Currently only the probe one is implemented.
- */
-
-#define LNE390_D_PROBE 0x01
-#define LNE390_D_RX_PKT        0x02
-#define LNE390_D_TX_PKT        0x04
-#define LNE390_D_IRQ   0x08
-
-#define LNE390_DEBUG   0
-
-static unsigned char irq_map[] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
-static unsigned int shmem_mapA[] __initdata = {0xff, 0xfe, 0xfd, 0xfff, 0xffe, 0xffc, 0x0d, 0x0};
-static unsigned int shmem_mapB[] __initdata = {0xff, 0xfe, 0x0e, 0xfff, 0xffe, 0xffc, 0x0d, 0x0};
-
-/*
- *     Probe for the card. The best way is to read the EISA ID if it
- *     is known. Then we can check the prefix of the station address
- *     PROM for a match against the value assigned to Mylex.
- */
-
-static int __init do_lne390_probe(struct net_device *dev)
-{
-       unsigned short ioaddr = dev->base_addr;
-       int irq = dev->irq;
-       int mem_start = dev->mem_start;
-       int ret;
-
-       if (ioaddr > 0x1ff) {           /* Check a single specified location. */
-               if (!request_region(ioaddr, LNE390_IO_EXTENT, DRV_NAME))
-                       return -EBUSY;
-               ret = lne390_probe1(dev, ioaddr);
-               if (ret)
-                       release_region(ioaddr, LNE390_IO_EXTENT);
-               return ret;
-       }
-       else if (ioaddr > 0)            /* Don't probe at all. */
-               return -ENXIO;
-
-       if (!EISA_bus) {
-#if LNE390_DEBUG & LNE390_D_PROBE
-               printk("lne390-debug: Not an EISA bus. Not probing high ports.\n");
-#endif
-               return -ENXIO;
-       }
-
-       /* EISA spec allows for up to 16 slots, but 8 is typical. */
-       for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
-               if (!request_region(ioaddr, LNE390_IO_EXTENT, DRV_NAME))
-                       continue;
-               if (lne390_probe1(dev, ioaddr) == 0)
-                       return 0;
-               release_region(ioaddr, LNE390_IO_EXTENT);
-               dev->irq = irq;
-               dev->mem_start = mem_start;
-       }
-
-       return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init lne390_probe(int unit)
-{
-       struct net_device *dev = alloc_ei_netdev();
-       int err;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       sprintf(dev->name, "eth%d", unit);
-       netdev_boot_setup_check(dev);
-
-       err = do_lne390_probe(dev);
-       if (err)
-               goto out;
-       return dev;
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-#endif
-
-static int __init lne390_probe1(struct net_device *dev, int ioaddr)
-{
-       int i, revision, ret;
-       unsigned long eisa_id;
-
-       if (inb_p(ioaddr + LNE390_ID_PORT) == 0xff) return -ENODEV;
-
-#if LNE390_DEBUG & LNE390_D_PROBE
-       printk("lne390-debug: probe at %#x, ID %#8x\n", ioaddr, inl(ioaddr + LNE390_ID_PORT));
-       printk("lne390-debug: config regs: %#x %#x\n",
-               inb(ioaddr + LNE390_CFG1), inb(ioaddr + LNE390_CFG2));
-#endif
-
-
-/*     Check the EISA ID of the card. */
-       eisa_id = inl(ioaddr + LNE390_ID_PORT);
-       if ((eisa_id != LNE390_ID0) && (eisa_id != LNE390_ID1)) {
-               return -ENODEV;
-       }
-
-       revision = (eisa_id >> 24) & 0x01;      /* 0 = rev A, 1 rev B */
-
-#if 0
-/*     Check the Mylex vendor ID as well. Not really required. */
-       if (inb(ioaddr + LNE390_SA_PROM + 0) != LNE390_ADDR0
-               || inb(ioaddr + LNE390_SA_PROM + 1) != LNE390_ADDR1
-               || inb(ioaddr + LNE390_SA_PROM + 2) != LNE390_ADDR2 ) {
-               printk("lne390.c: card not found");
-               for(i = 0; i < ETHER_ADDR_LEN; i++)
-                       printk(" %02x", inb(ioaddr + LNE390_SA_PROM + i));
-               printk(" (invalid prefix).\n");
-               return -ENODEV;
-       }
-#endif
-
-       for(i = 0; i < ETHER_ADDR_LEN; i++)
-               dev->dev_addr[i] = inb(ioaddr + LNE390_SA_PROM + i);
-       printk("lne390.c: LNE390%X in EISA slot %d, address %pM.\n",
-              0xa+revision, ioaddr/0x1000, dev->dev_addr);
-
-       printk("lne390.c: ");
-
-       /* Snarf the interrupt now. CFG file has them all listed as `edge' with share=NO */
-       if (dev->irq == 0) {
-               unsigned char irq_reg = inb(ioaddr + LNE390_CFG2) >> 3;
-               dev->irq = irq_map[irq_reg & 0x07];
-               printk("using");
-       } else {
-               /* This is useless unless we reprogram the card here too */
-               if (dev->irq == 2) dev->irq = 9;        /* Doh! */
-               printk("assigning");
-       }
-       printk(" IRQ %d,", dev->irq);
-
-       if ((ret = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev))) {
-               printk (" unable to get IRQ %d.\n", dev->irq);
-               return ret;
-       }
-
-       if (dev->mem_start == 0) {
-               unsigned char mem_reg = inb(ioaddr + LNE390_CFG2) & 0x07;
-
-               if (revision)   /* LNE390B */
-                       dev->mem_start = shmem_mapB[mem_reg] * 0x10000;
-               else            /* LNE390A */
-                       dev->mem_start = shmem_mapA[mem_reg] * 0x10000;
-               printk(" using ");
-       } else {
-               /* Should check for value in shmem_map and reprogram the card to use it */
-               dev->mem_start &= 0xfff0000;
-               printk(" assigning ");
-       }
-
-       printk("%dkB memory at physical address %#lx\n",
-                       LNE390_STOP_PG/4, dev->mem_start);
-
-       /*
-          BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
-          the card mem within the region covered by `normal' RAM  !!!
-
-          ioremap() will fail in that case.
-       */
-       ei_status.mem = ioremap(dev->mem_start, LNE390_STOP_PG*0x100);
-       if (!ei_status.mem) {
-               printk(KERN_ERR "lne390.c: Unable to remap card memory above 1MB !!\n");
-               printk(KERN_ERR "lne390.c: Try using EISA SCU to set memory below 1MB.\n");
-               printk(KERN_ERR "lne390.c: Driver NOT installed.\n");
-               ret = -EAGAIN;
-               goto cleanup;
-       }
-       printk("lne390.c: remapped %dkB card memory to virtual address %p\n",
-                       LNE390_STOP_PG/4, ei_status.mem);
-
-       dev->mem_start = (unsigned long)ei_status.mem;
-       dev->mem_end = dev->mem_start + (LNE390_STOP_PG - LNE390_START_PG)*256;
-
-       /* The 8390 offset is zero for the LNE390 */
-       dev->base_addr = ioaddr;
-
-       ei_status.name = "LNE390";
-       ei_status.tx_start_page = LNE390_START_PG;
-       ei_status.rx_start_page = LNE390_START_PG + TX_PAGES;
-       ei_status.stop_page = LNE390_STOP_PG;
-       ei_status.word16 = 1;
-
-       if (ei_debug > 0)
-               printk(version);
-
-       ei_status.reset_8390 = &lne390_reset_8390;
-       ei_status.block_input = &lne390_block_input;
-       ei_status.block_output = &lne390_block_output;
-       ei_status.get_8390_hdr = &lne390_get_8390_hdr;
-
-       dev->netdev_ops = &ei_netdev_ops;
-       NS8390_init(dev, 0);
-
-       ret = register_netdev(dev);
-       if (ret)
-               goto unmap;
-       return 0;
-unmap:
-       if (ei_status.reg0)
-               iounmap(ei_status.mem);
-cleanup:
-       free_irq(dev->irq, dev);
-       return ret;
-}
-
-/*
- *     Reset as per the packet driver method. Judging by the EISA cfg
- *     file, this just toggles the "Board Enable" bits (bit 2 and 0).
- */
-
-static void lne390_reset_8390(struct net_device *dev)
-{
-       unsigned short ioaddr = dev->base_addr;
-
-       outb(0x04, ioaddr + LNE390_RESET_PORT);
-       if (ei_debug > 1) printk("%s: resetting the LNE390...", dev->name);
-
-       mdelay(2);
-
-       ei_status.txing = 0;
-       outb(0x01, ioaddr + LNE390_RESET_PORT);
-       if (ei_debug > 1) printk("reset done\n");
-}
-
-/*
- *     Note: In the following three functions is the implicit assumption
- *     that the associated memcpy will only use "rep; movsl" as long as
- *     we keep the counts as some multiple of doublewords. This is a
- *     requirement of the hardware, and also prevents us from using
- *     eth_io_copy_and_sum() since we can't guarantee it will limit
- *     itself to doubleword access.
- */
-
-/*
- *     Grab the 8390 specific header. Similar to the block_input routine, but
- *     we don't need to be concerned with ring wrap as the header will be at
- *     the start of a page, so we optimize accordingly. (A single doubleword.)
- */
-
-static void
-lne390_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-       void __iomem *hdr_start = ei_status.mem + ((ring_page - LNE390_START_PG)<<8);
-       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
-       hdr->count = (hdr->count + 3) & ~3;     /* Round up allocation. */
-}
-
-/*
- *     Block input and output are easy on shared memory ethercards, the only
- *     complication is when the ring buffer wraps. The count will already
- *     be rounded up to a doubleword value via lne390_get_8390_hdr() above.
- */
-
-static void lne390_block_input(struct net_device *dev, int count, struct sk_buff *skb,
-                                                 int ring_offset)
-{
-       void __iomem *xfer_start = ei_status.mem + ring_offset - (LNE390_START_PG<<8);
-
-       if (ring_offset + count > (LNE390_STOP_PG<<8)) {
-               /* Packet wraps over end of ring buffer. */
-               int semi_count = (LNE390_STOP_PG<<8) - ring_offset;
-               memcpy_fromio(skb->data, xfer_start, semi_count);
-               count -= semi_count;
-               memcpy_fromio(skb->data + semi_count,
-                       ei_status.mem + (TX_PAGES<<8), count);
-       } else {
-               /* Packet is in one chunk. */
-               memcpy_fromio(skb->data, xfer_start, count);
-       }
-}
-
-static void lne390_block_output(struct net_device *dev, int count,
-                               const unsigned char *buf, int start_page)
-{
-       void __iomem *shmem = ei_status.mem + ((start_page - LNE390_START_PG)<<8);
-
-       count = (count + 3) & ~3;     /* Round up to doubleword */
-       memcpy_toio(shmem, buf, count);
-}
-
-
-#ifdef MODULE
-#define MAX_LNE_CARDS  4       /* Max number of LNE390 cards per module */
-static struct net_device *dev_lne[MAX_LNE_CARDS];
-static int io[MAX_LNE_CARDS];
-static int irq[MAX_LNE_CARDS];
-static int mem[MAX_LNE_CARDS];
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(mem, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s)");
-MODULE_PARM_DESC(mem, "memory base address(es)");
-MODULE_DESCRIPTION("Mylex LNE390A/B EISA Ethernet driver");
-MODULE_LICENSE("GPL");
-
-int __init init_module(void)
-{
-       struct net_device *dev;
-       int this_dev, found = 0;
-
-       for (this_dev = 0; this_dev < MAX_LNE_CARDS; this_dev++) {
-               if (io[this_dev] == 0 && this_dev != 0)
-                       break;
-               dev = alloc_ei_netdev();
-               if (!dev)
-                       break;
-               dev->irq = irq[this_dev];
-               dev->base_addr = io[this_dev];
-               dev->mem_start = mem[this_dev];
-               if (do_lne390_probe(dev) == 0) {
-                       dev_lne[found++] = dev;
-                       continue;
-               }
-               free_netdev(dev);
-               printk(KERN_WARNING "lne390.c: No LNE390 card found (i/o = 0x%x).\n", io[this_dev]);
-               break;
-       }
-       if (found)
-               return 0;
-       return -ENXIO;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-       free_irq(dev->irq, dev);
-       release_region(dev->base_addr, LNE390_IO_EXTENT);
-       iounmap(ei_status.mem);
-}
-
-void __exit cleanup_module(void)
-{
-       int this_dev;
-
-       for (this_dev = 0; this_dev < MAX_LNE_CARDS; this_dev++) {
-               struct net_device *dev = dev_lne[this_dev];
-               if (dev) {
-                       unregister_netdev(dev);
-                       cleanup_card(dev);
-                       free_netdev(dev);
-               }
-       }
-}
-#endif /* MODULE */
-
diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c
deleted file mode 100644 (file)
index f84f5e6..0000000
+++ /dev/null
@@ -1,874 +0,0 @@
-/* mac8390.c: New driver for 8390-based Nubus (or Nubus-alike)
-   Ethernet cards on Linux */
-/* Based on the former daynaport.c driver, by Alan Cox.  Some code
-   taken from or inspired by skeleton.c by Donald Becker, acenic.c by
-   Jes Sorensen, and ne2k-pci.c by Donald Becker and Paul Gortmaker.
-
-   This software may be used and distributed according to the terms of
-   the GNU Public License, incorporated herein by reference.  */
-
-/* 2000-02-28: support added for Dayna and Kinetics cards by
-   A.G.deWijn@phys.uu.nl */
-/* 2000-04-04: support added for Dayna2 by bart@etpmod.phys.tue.nl */
-/* 2001-04-18: support for DaynaPort E/LC-M by rayk@knightsmanor.org */
-/* 2001-05-15: support for Cabletron ported from old daynaport driver
- * and fixed access to Sonic Sys card which masquerades as a Farallon
- * by rayk@knightsmanor.org */
-/* 2002-12-30: Try to support more cards, some clues from NetBSD driver */
-/* 2003-12-26: Make sure Asante cards always work. */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/nubus.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/dma.h>
-#include <asm/hwtest.h>
-#include <asm/macints.h>
-
-static char version[] =
-       "v0.4 2001-05-15 David Huggins-Daines <dhd@debian.org> and others\n";
-
-#define EI_SHIFT(x)    (ei_local->reg_offset[x])
-#define ei_inb(port)   in_8(port)
-#define ei_outb(val, port)     out_8(port, val)
-#define ei_inb_p(port) in_8(port)
-#define ei_outb_p(val, port)   out_8(port, val)
-
-#include "lib8390.c"
-
-#define WD_START_PG                    0x00    /* First page of TX buffer */
-#define CABLETRON_RX_START_PG          0x00    /* First page of RX buffer */
-#define CABLETRON_RX_STOP_PG           0x30    /* Last page +1 of RX ring */
-#define CABLETRON_TX_START_PG          CABLETRON_RX_STOP_PG
-                                               /* First page of TX buffer */
-
-/*
- * Unfortunately it seems we have to hardcode these for the moment
- * Shouldn't the card know about this?
- * Does anyone know where to read it off the card?
- * Do we trust the data provided by the card?
- */
-
-#define DAYNA_8390_BASE                0x80000
-#define DAYNA_8390_MEM         0x00000
-
-#define CABLETRON_8390_BASE    0x90000
-#define CABLETRON_8390_MEM     0x00000
-
-#define INTERLAN_8390_BASE     0xE0000
-#define INTERLAN_8390_MEM      0xD0000
-
-enum mac8390_type {
-       MAC8390_NONE = -1,
-       MAC8390_APPLE,
-       MAC8390_ASANTE,
-       MAC8390_FARALLON,
-       MAC8390_CABLETRON,
-       MAC8390_DAYNA,
-       MAC8390_INTERLAN,
-       MAC8390_KINETICS,
-};
-
-static const char *cardname[] = {
-       "apple",
-       "asante",
-       "farallon",
-       "cabletron",
-       "dayna",
-       "interlan",
-       "kinetics",
-};
-
-static const int word16[] = {
-       1, /* apple */
-       1, /* asante */
-       1, /* farallon */
-       1, /* cabletron */
-       0, /* dayna */
-       1, /* interlan */
-       0, /* kinetics */
-};
-
-/* on which cards do we use NuBus resources? */
-static const int useresources[] = {
-       1, /* apple */
-       1, /* asante */
-       1, /* farallon */
-       0, /* cabletron */
-       0, /* dayna */
-       0, /* interlan */
-       0, /* kinetics */
-};
-
-enum mac8390_access {
-       ACCESS_UNKNOWN = 0,
-       ACCESS_32,
-       ACCESS_16,
-};
-
-extern int mac8390_memtest(struct net_device *dev);
-static int mac8390_initdev(struct net_device *dev, struct nubus_dev *ndev,
-                          enum mac8390_type type);
-
-static int mac8390_open(struct net_device *dev);
-static int mac8390_close(struct net_device *dev);
-static void mac8390_no_reset(struct net_device *dev);
-static void interlan_reset(struct net_device *dev);
-
-/* Sane (32-bit chunk memory read/write) - Some Farallon and Apple do this*/
-static void sane_get_8390_hdr(struct net_device *dev,
-                             struct e8390_pkt_hdr *hdr, int ring_page);
-static void sane_block_input(struct net_device *dev, int count,
-                            struct sk_buff *skb, int ring_offset);
-static void sane_block_output(struct net_device *dev, int count,
-                             const unsigned char *buf, const int start_page);
-
-/* dayna_memcpy to and from card */
-static void dayna_memcpy_fromcard(struct net_device *dev, void *to,
-                               int from, int count);
-static void dayna_memcpy_tocard(struct net_device *dev, int to,
-                             const void *from, int count);
-
-/* Dayna - Dayna/Kinetics use this */
-static void dayna_get_8390_hdr(struct net_device *dev,
-                              struct e8390_pkt_hdr *hdr, int ring_page);
-static void dayna_block_input(struct net_device *dev, int count,
-                             struct sk_buff *skb, int ring_offset);
-static void dayna_block_output(struct net_device *dev, int count,
-                              const unsigned char *buf, int start_page);
-
-#define memcpy_fromio(a, b, c) memcpy((a), (void *)(b), (c))
-#define memcpy_toio(a, b, c)   memcpy((void *)(a), (b), (c))
-
-#define memcmp_withio(a, b, c) memcmp((a), (void *)(b), (c))
-
-/* Slow Sane (16-bit chunk memory read/write) Cabletron uses this */
-static void slow_sane_get_8390_hdr(struct net_device *dev,
-                                  struct e8390_pkt_hdr *hdr, int ring_page);
-static void slow_sane_block_input(struct net_device *dev, int count,
-                                 struct sk_buff *skb, int ring_offset);
-static void slow_sane_block_output(struct net_device *dev, int count,
-                                  const unsigned char *buf, int start_page);
-static void word_memcpy_tocard(unsigned long tp, const void *fp, int count);
-static void word_memcpy_fromcard(void *tp, unsigned long fp, int count);
-
-static enum mac8390_type __init mac8390_ident(struct nubus_dev *dev)
-{
-       switch (dev->dr_sw) {
-       case NUBUS_DRSW_3COM:
-               switch (dev->dr_hw) {
-               case NUBUS_DRHW_APPLE_SONIC_NB:
-               case NUBUS_DRHW_APPLE_SONIC_LC:
-               case NUBUS_DRHW_SONNET:
-                       return MAC8390_NONE;
-                       break;
-               default:
-                       return MAC8390_APPLE;
-                       break;
-               }
-               break;
-
-       case NUBUS_DRSW_APPLE:
-               switch (dev->dr_hw) {
-               case NUBUS_DRHW_ASANTE_LC:
-                       return MAC8390_NONE;
-                       break;
-               case NUBUS_DRHW_CABLETRON:
-                       return MAC8390_CABLETRON;
-                       break;
-               default:
-                       return MAC8390_APPLE;
-                       break;
-               }
-               break;
-
-       case NUBUS_DRSW_ASANTE:
-               return MAC8390_ASANTE;
-               break;
-
-       case NUBUS_DRSW_TECHWORKS:
-       case NUBUS_DRSW_DAYNA2:
-       case NUBUS_DRSW_DAYNA_LC:
-               if (dev->dr_hw == NUBUS_DRHW_CABLETRON)
-                       return MAC8390_CABLETRON;
-               else
-                       return MAC8390_APPLE;
-               break;
-
-       case NUBUS_DRSW_FARALLON:
-               return MAC8390_FARALLON;
-               break;
-
-       case NUBUS_DRSW_KINETICS:
-               switch (dev->dr_hw) {
-               case NUBUS_DRHW_INTERLAN:
-                       return MAC8390_INTERLAN;
-                       break;
-               default:
-                       return MAC8390_KINETICS;
-                       break;
-               }
-               break;
-
-       case NUBUS_DRSW_DAYNA:
-               /*
-                * These correspond to Dayna Sonic cards
-                * which use the macsonic driver
-                */
-               if (dev->dr_hw == NUBUS_DRHW_SMC9194 ||
-                   dev->dr_hw == NUBUS_DRHW_INTERLAN)
-                       return MAC8390_NONE;
-               else
-                       return MAC8390_DAYNA;
-               break;
-       }
-       return MAC8390_NONE;
-}
-
-static enum mac8390_access __init mac8390_testio(volatile unsigned long membase)
-{
-       unsigned long outdata = 0xA5A0B5B0;
-       unsigned long indata =  0x00000000;
-       /* Try writing 32 bits */
-       memcpy_toio(membase, &outdata, 4);
-       /* Now compare them */
-       if (memcmp_withio(&outdata, membase, 4) == 0)
-               return ACCESS_32;
-       /* Write 16 bit output */
-       word_memcpy_tocard(membase, &outdata, 4);
-       /* Now read it back */
-       word_memcpy_fromcard(&indata, membase, 4);
-       if (outdata == indata)
-               return ACCESS_16;
-       return ACCESS_UNKNOWN;
-}
-
-static int __init mac8390_memsize(unsigned long membase)
-{
-       unsigned long flags;
-       int i, j;
-
-       local_irq_save(flags);
-       /* Check up to 32K in 4K increments */
-       for (i = 0; i < 8; i++) {
-               volatile unsigned short *m = (unsigned short *)(membase + (i * 0x1000));
-
-               /* Unwriteable - we have a fully decoded card and the
-                  RAM end located */
-               if (hwreg_present(m) == 0)
-                       break;
-
-               /* write a distinctive byte */
-               *m = 0xA5A0 | i;
-               /* check that we read back what we wrote */
-               if (*m != (0xA5A0 | i))
-                       break;
-
-               /* check for partial decode and wrap */
-               for (j = 0; j < i; j++) {
-                       volatile unsigned short *p = (unsigned short *)(membase + (j * 0x1000));
-                       if (*p != (0xA5A0 | j))
-                               break;
-               }
-       }
-       local_irq_restore(flags);
-       /*
-        * in any case, we stopped once we tried one block too many,
-        * or once we reached 32K
-        */
-       return i * 0x1000;
-}
-
-static bool __init mac8390_init(struct net_device *dev, struct nubus_dev *ndev,
-                               enum mac8390_type cardtype)
-{
-       struct nubus_dir dir;
-       struct nubus_dirent ent;
-       int offset;
-       volatile unsigned short *i;
-
-       printk_once(KERN_INFO pr_fmt("%s"), version);
-
-       dev->irq = SLOT2IRQ(ndev->board->slot);
-       /* This is getting to be a habit */
-       dev->base_addr = (ndev->board->slot_addr |
-                         ((ndev->board->slot & 0xf) << 20));
-
-       /*
-        * Get some Nubus info - we will trust the card's idea
-        * of where its memory and registers are.
-        */
-
-       if (nubus_get_func_dir(ndev, &dir) == -1) {
-               pr_err("%s: Unable to get Nubus functional directory for slot %X!\n",
-                      dev->name, ndev->board->slot);
-               return false;
-       }
-
-       /* Get the MAC address */
-       if (nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent) == -1) {
-               pr_info("%s: Couldn't get MAC address!\n", dev->name);
-               return false;
-       }
-
-       nubus_get_rsrc_mem(dev->dev_addr, &ent, 6);
-
-       if (useresources[cardtype] == 1) {
-               nubus_rewinddir(&dir);
-               if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_BASEOS,
-                                   &ent) == -1) {
-                       pr_err("%s: Memory offset resource for slot %X not found!\n",
-                              dev->name, ndev->board->slot);
-                       return false;
-               }
-               nubus_get_rsrc_mem(&offset, &ent, 4);
-               dev->mem_start = dev->base_addr + offset;
-               /* yes, this is how the Apple driver does it */
-               dev->base_addr = dev->mem_start + 0x10000;
-               nubus_rewinddir(&dir);
-               if (nubus_find_rsrc(&dir, NUBUS_RESID_MINOR_LENGTH,
-                                   &ent) == -1) {
-                       pr_info("%s: Memory length resource for slot %X not found, probing\n",
-                               dev->name, ndev->board->slot);
-                       offset = mac8390_memsize(dev->mem_start);
-               } else {
-                       nubus_get_rsrc_mem(&offset, &ent, 4);
-               }
-               dev->mem_end = dev->mem_start + offset;
-       } else {
-               switch (cardtype) {
-               case MAC8390_KINETICS:
-               case MAC8390_DAYNA: /* it's the same */
-                       dev->base_addr = (int)(ndev->board->slot_addr +
-                                              DAYNA_8390_BASE);
-                       dev->mem_start = (int)(ndev->board->slot_addr +
-                                              DAYNA_8390_MEM);
-                       dev->mem_end = dev->mem_start +
-                                      mac8390_memsize(dev->mem_start);
-                       break;
-               case MAC8390_INTERLAN:
-                       dev->base_addr = (int)(ndev->board->slot_addr +
-                                              INTERLAN_8390_BASE);
-                       dev->mem_start = (int)(ndev->board->slot_addr +
-                                              INTERLAN_8390_MEM);
-                       dev->mem_end = dev->mem_start +
-                                      mac8390_memsize(dev->mem_start);
-                       break;
-               case MAC8390_CABLETRON:
-                       dev->base_addr = (int)(ndev->board->slot_addr +
-                                              CABLETRON_8390_BASE);
-                       dev->mem_start = (int)(ndev->board->slot_addr +
-                                              CABLETRON_8390_MEM);
-                       /* The base address is unreadable if 0x00
-                        * has been written to the command register
-                        * Reset the chip by writing E8390_NODMA +
-                        *   E8390_PAGE0 + E8390_STOP just to be
-                        *   sure
-                        */
-                       i = (void *)dev->base_addr;
-                       *i = 0x21;
-                       dev->mem_end = dev->mem_start +
-                                      mac8390_memsize(dev->mem_start);
-                       break;
-
-               default:
-                       pr_err("Card type %s is unsupported, sorry\n",
-                              ndev->board->name);
-                       return false;
-               }
-       }
-
-       return true;
-}
-
-struct net_device * __init mac8390_probe(int unit)
-{
-       struct net_device *dev;
-       struct nubus_dev *ndev = NULL;
-       int err = -ENODEV;
-
-       static unsigned int slots;
-
-       enum mac8390_type cardtype;
-
-       /* probably should check for Nubus instead */
-
-       if (!MACH_IS_MAC)
-               return ERR_PTR(-ENODEV);
-
-       dev = ____alloc_ei_netdev(0);
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       if (unit >= 0)
-               sprintf(dev->name, "eth%d", unit);
-
-       while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK, NUBUS_TYPE_ETHERNET,
-                                      ndev))) {
-               /* Have we seen it already? */
-               if (slots & (1 << ndev->board->slot))
-                       continue;
-               slots |= 1 << ndev->board->slot;
-
-               cardtype = mac8390_ident(ndev);
-               if (cardtype == MAC8390_NONE)
-                       continue;
-
-               if (!mac8390_init(dev, ndev, cardtype))
-                       continue;
-
-               /* Do the nasty 8390 stuff */
-               if (!mac8390_initdev(dev, ndev, cardtype))
-                       break;
-       }
-
-       if (!ndev)
-               goto out;
-       err = register_netdev(dev);
-       if (err)
-               goto out;
-       return dev;
-
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-
-#ifdef MODULE
-MODULE_AUTHOR("David Huggins-Daines <dhd@debian.org> and others");
-MODULE_DESCRIPTION("Macintosh NS8390-based Nubus Ethernet driver");
-MODULE_LICENSE("GPL");
-
-/* overkill, of course */
-static struct net_device *dev_mac8390[15];
-int init_module(void)
-{
-       int i;
-       for (i = 0; i < 15; i++) {
-               struct net_device *dev = mac8390_probe(-1);
-               if (IS_ERR(dev))
-                       break;
-               dev_mac890[i] = dev;
-       }
-       if (!i) {
-               pr_notice("No useable cards found, driver NOT installed.\n");
-               return -ENODEV;
-       }
-       return 0;
-}
-
-void cleanup_module(void)
-{
-       int i;
-       for (i = 0; i < 15; i++) {
-               struct net_device *dev = dev_mac890[i];
-               if (dev) {
-                       unregister_netdev(dev);
-                       free_netdev(dev);
-               }
-       }
-}
-
-#endif /* MODULE */
-
-static const struct net_device_ops mac8390_netdev_ops = {
-       .ndo_open               = mac8390_open,
-       .ndo_stop               = mac8390_close,
-       .ndo_start_xmit         = __ei_start_xmit,
-       .ndo_tx_timeout         = __ei_tx_timeout,
-       .ndo_get_stats          = __ei_get_stats,
-       .ndo_set_multicast_list = __ei_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = __ei_poll,
-#endif
-};
-
-static int __init mac8390_initdev(struct net_device *dev,
-                                 struct nubus_dev *ndev,
-                                 enum mac8390_type type)
-{
-       static u32 fwrd4_offsets[16] = {
-               0,      4,      8,      12,
-               16,     20,     24,     28,
-               32,     36,     40,     44,
-               48,     52,     56,     60
-       };
-       static u32 back4_offsets[16] = {
-               60,     56,     52,     48,
-               44,     40,     36,     32,
-               28,     24,     20,     16,
-               12,     8,      4,      0
-       };
-       static u32 fwrd2_offsets[16] = {
-               0,      2,      4,      6,
-               8,     10,     12,     14,
-               16,    18,     20,     22,
-               24,    26,     28,     30
-       };
-
-       int access_bitmode = 0;
-
-       /* Now fill in our stuff */
-       dev->netdev_ops = &mac8390_netdev_ops;
-
-       /* GAR, ei_status is actually a macro even though it looks global */
-       ei_status.name = cardname[type];
-       ei_status.word16 = word16[type];
-
-       /* Cabletron's TX/RX buffers are backwards */
-       if (type == MAC8390_CABLETRON) {
-               ei_status.tx_start_page = CABLETRON_TX_START_PG;
-               ei_status.rx_start_page = CABLETRON_RX_START_PG;
-               ei_status.stop_page = CABLETRON_RX_STOP_PG;
-               ei_status.rmem_start = dev->mem_start;
-               ei_status.rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256;
-       } else {
-               ei_status.tx_start_page = WD_START_PG;
-               ei_status.rx_start_page = WD_START_PG + TX_PAGES;
-               ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
-               ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
-               ei_status.rmem_end = dev->mem_end;
-       }
-
-       /* Fill in model-specific information and functions */
-       switch (type) {
-       case MAC8390_FARALLON:
-       case MAC8390_APPLE:
-               switch (mac8390_testio(dev->mem_start)) {
-               case ACCESS_UNKNOWN:
-                       pr_err("Don't know how to access card memory!\n");
-                       return -ENODEV;
-                       break;
-
-               case ACCESS_16:
-                       /* 16 bit card, register map is reversed */
-                       ei_status.reset_8390 = mac8390_no_reset;
-                       ei_status.block_input = slow_sane_block_input;
-                       ei_status.block_output = slow_sane_block_output;
-                       ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
-                       ei_status.reg_offset = back4_offsets;
-                       break;
-
-               case ACCESS_32:
-                       /* 32 bit card, register map is reversed */
-                       ei_status.reset_8390 = mac8390_no_reset;
-                       ei_status.block_input = sane_block_input;
-                       ei_status.block_output = sane_block_output;
-                       ei_status.get_8390_hdr = sane_get_8390_hdr;
-                       ei_status.reg_offset = back4_offsets;
-                       access_bitmode = 1;
-                       break;
-               }
-               break;
-
-       case MAC8390_ASANTE:
-               /* Some Asante cards pass the 32 bit test
-                * but overwrite system memory when run at 32 bit.
-                * so we run them all at 16 bit.
-                */
-               ei_status.reset_8390 = mac8390_no_reset;
-               ei_status.block_input = slow_sane_block_input;
-               ei_status.block_output = slow_sane_block_output;
-               ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
-               ei_status.reg_offset = back4_offsets;
-               break;
-
-       case MAC8390_CABLETRON:
-               /* 16 bit card, register map is short forward */
-               ei_status.reset_8390 = mac8390_no_reset;
-               ei_status.block_input = slow_sane_block_input;
-               ei_status.block_output = slow_sane_block_output;
-               ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
-               ei_status.reg_offset = fwrd2_offsets;
-               break;
-
-       case MAC8390_DAYNA:
-       case MAC8390_KINETICS:
-               /* 16 bit memory, register map is forward */
-               /* dayna and similar */
-               ei_status.reset_8390 = mac8390_no_reset;
-               ei_status.block_input = dayna_block_input;
-               ei_status.block_output = dayna_block_output;
-               ei_status.get_8390_hdr = dayna_get_8390_hdr;
-               ei_status.reg_offset = fwrd4_offsets;
-               break;
-
-       case MAC8390_INTERLAN:
-               /* 16 bit memory, register map is forward */
-               ei_status.reset_8390 = interlan_reset;
-               ei_status.block_input = slow_sane_block_input;
-               ei_status.block_output = slow_sane_block_output;
-               ei_status.get_8390_hdr = slow_sane_get_8390_hdr;
-               ei_status.reg_offset = fwrd4_offsets;
-               break;
-
-       default:
-               pr_err("Card type %s is unsupported, sorry\n",
-                      ndev->board->name);
-               return -ENODEV;
-       }
-
-       __NS8390_init(dev, 0);
-
-       /* Good, done, now spit out some messages */
-       pr_info("%s: %s in slot %X (type %s)\n",
-               dev->name, ndev->board->name, ndev->board->slot,
-               cardname[type]);
-       pr_info("MAC %pM IRQ %d, %d KB shared memory at %#lx, %d-bit access.\n",
-               dev->dev_addr, dev->irq,
-               (unsigned int)(dev->mem_end - dev->mem_start) >> 10,
-               dev->mem_start, access_bitmode ? 32 : 16);
-       return 0;
-}
-
-static int mac8390_open(struct net_device *dev)
-{
-       int err;
-
-       __ei_open(dev);
-       err = request_irq(dev->irq, __ei_interrupt, 0, "8390 Ethernet", dev);
-       if (err)
-               pr_err("%s: unable to get IRQ %d\n", dev->name, dev->irq);
-       return err;
-}
-
-static int mac8390_close(struct net_device *dev)
-{
-       free_irq(dev->irq, dev);
-       __ei_close(dev);
-       return 0;
-}
-
-static void mac8390_no_reset(struct net_device *dev)
-{
-       ei_status.txing = 0;
-       if (ei_debug > 1)
-               pr_info("reset not supported\n");
-}
-
-static void interlan_reset(struct net_device *dev)
-{
-       unsigned char *target = nubus_slot_addr(IRQ2SLOT(dev->irq));
-       if (ei_debug > 1)
-               pr_info("Need to reset the NS8390 t=%lu...", jiffies);
-       ei_status.txing = 0;
-       target[0xC0000] = 0;
-       if (ei_debug > 1)
-               pr_cont("reset complete\n");
-}
-
-/* dayna_memcpy_fromio/dayna_memcpy_toio */
-/* directly from daynaport.c by Alan Cox */
-static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from,
-                                 int count)
-{
-       volatile unsigned char *ptr;
-       unsigned char *target = to;
-       from <<= 1;     /* word, skip overhead */
-       ptr = (unsigned char *)(dev->mem_start+from);
-       /* Leading byte? */
-       if (from & 2) {
-               *target++ = ptr[-1];
-               ptr += 2;
-               count--;
-       }
-       while (count >= 2) {
-               *(unsigned short *)target = *(unsigned short volatile *)ptr;
-               ptr += 4;                       /* skip cruft */
-               target += 2;
-               count -= 2;
-       }
-       /* Trailing byte? */
-       if (count)
-               *target = *ptr;
-}
-
-static void dayna_memcpy_tocard(struct net_device *dev, int to,
-                               const void *from, int count)
-{
-       volatile unsigned short *ptr;
-       const unsigned char *src = from;
-       to <<= 1;       /* word, skip overhead */
-       ptr = (unsigned short *)(dev->mem_start+to);
-       /* Leading byte? */
-       if (to & 2) {           /* avoid a byte write (stomps on other data) */
-               ptr[-1] = (ptr[-1]&0xFF00)|*src++;
-               ptr++;
-               count--;
-       }
-       while (count >= 2) {
-               *ptr++ = *(unsigned short *)src;        /* Copy and */
-               ptr++;                  /* skip cruft */
-               src += 2;
-               count -= 2;
-       }
-       /* Trailing byte? */
-       if (count) {
-               /* card doesn't like byte writes */
-               *ptr = (*ptr & 0x00FF) | (*src << 8);
-       }
-}
-
-/* sane block input/output */
-static void sane_get_8390_hdr(struct net_device *dev,
-                             struct e8390_pkt_hdr *hdr, int ring_page)
-{
-       unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
-       memcpy_fromio(hdr, dev->mem_start + hdr_start, 4);
-       /* Fix endianness */
-       hdr->count = swab16(hdr->count);
-}
-
-static void sane_block_input(struct net_device *dev, int count,
-                            struct sk_buff *skb, int ring_offset)
-{
-       unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
-       unsigned long xfer_start = xfer_base + dev->mem_start;
-
-       if (xfer_start + count > ei_status.rmem_end) {
-               /* We must wrap the input move. */
-               int semi_count = ei_status.rmem_end - xfer_start;
-               memcpy_fromio(skb->data, dev->mem_start + xfer_base,
-                             semi_count);
-               count -= semi_count;
-               memcpy_fromio(skb->data + semi_count, ei_status.rmem_start,
-                             count);
-       } else {
-               memcpy_fromio(skb->data, dev->mem_start + xfer_base, count);
-       }
-}
-
-static void sane_block_output(struct net_device *dev, int count,
-                             const unsigned char *buf, int start_page)
-{
-       long shmem = (start_page - WD_START_PG)<<8;
-
-       memcpy_toio(dev->mem_start + shmem, buf, count);
-}
-
-/* dayna block input/output */
-static void dayna_get_8390_hdr(struct net_device *dev,
-                              struct e8390_pkt_hdr *hdr, int ring_page)
-{
-       unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
-
-       dayna_memcpy_fromcard(dev, hdr, hdr_start, 4);
-       /* Fix endianness */
-       hdr->count = (hdr->count & 0xFF) << 8 | (hdr->count >> 8);
-}
-
-static void dayna_block_input(struct net_device *dev, int count,
-                             struct sk_buff *skb, int ring_offset)
-{
-       unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
-       unsigned long xfer_start = xfer_base+dev->mem_start;
-
-       /* Note the offset math is done in card memory space which is word
-          per long onto our space. */
-
-       if (xfer_start + count > ei_status.rmem_end) {
-               /* We must wrap the input move. */
-               int semi_count = ei_status.rmem_end - xfer_start;
-               dayna_memcpy_fromcard(dev, skb->data, xfer_base, semi_count);
-               count -= semi_count;
-               dayna_memcpy_fromcard(dev, skb->data + semi_count,
-                                     ei_status.rmem_start - dev->mem_start,
-                                     count);
-       } else {
-               dayna_memcpy_fromcard(dev, skb->data, xfer_base, count);
-       }
-}
-
-static void dayna_block_output(struct net_device *dev, int count,
-                              const unsigned char *buf,
-                              int start_page)
-{
-       long shmem = (start_page - WD_START_PG)<<8;
-
-       dayna_memcpy_tocard(dev, shmem, buf, count);
-}
-
-/* Cabletron block I/O */
-static void slow_sane_get_8390_hdr(struct net_device *dev,
-                                  struct e8390_pkt_hdr *hdr,
-                                  int ring_page)
-{
-       unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
-       word_memcpy_fromcard(hdr, dev->mem_start + hdr_start, 4);
-       /* Register endianism - fix here rather than 8390.c */
-       hdr->count = (hdr->count&0xFF)<<8|(hdr->count>>8);
-}
-
-static void slow_sane_block_input(struct net_device *dev, int count,
-                                 struct sk_buff *skb, int ring_offset)
-{
-       unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
-       unsigned long xfer_start = xfer_base+dev->mem_start;
-
-       if (xfer_start + count > ei_status.rmem_end) {
-               /* We must wrap the input move. */
-               int semi_count = ei_status.rmem_end - xfer_start;
-               word_memcpy_fromcard(skb->data, dev->mem_start + xfer_base,
-                                    semi_count);
-               count -= semi_count;
-               word_memcpy_fromcard(skb->data + semi_count,
-                                    ei_status.rmem_start, count);
-       } else {
-               word_memcpy_fromcard(skb->data, dev->mem_start + xfer_base,
-                                    count);
-       }
-}
-
-static void slow_sane_block_output(struct net_device *dev, int count,
-                                  const unsigned char *buf, int start_page)
-{
-       long shmem = (start_page - WD_START_PG)<<8;
-
-       word_memcpy_tocard(dev->mem_start + shmem, buf, count);
-}
-
-static void word_memcpy_tocard(unsigned long tp, const void *fp, int count)
-{
-       volatile unsigned short *to = (void *)tp;
-       const unsigned short *from = fp;
-
-       count++;
-       count /= 2;
-
-       while (count--)
-               *to++ = *from++;
-}
-
-static void word_memcpy_fromcard(void *tp, unsigned long fp, int count)
-{
-       unsigned short *to = tp;
-       const volatile unsigned short *from = (const void *)fp;
-
-       count++;
-       count /= 2;
-
-       while (count--)
-               *to++ = *from++;
-}
-
-
diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c
deleted file mode 100644 (file)
index 7298a34..0000000
+++ /dev/null
@@ -1,685 +0,0 @@
-/* ne-h8300.c: A NE2000 clone on H8/300 driver for linux. */
-/*
-    original ne.c
-    Written 1992-94 by Donald Becker.
-
-    Copyright 1993 United States Government as represented by the
-    Director, National Security Agency.
-
-    This software may be used and distributed according to the terms
-    of the GNU General Public License, incorporated herein by reference.
-
-    The author may be reached as becker@scyld.com, or C/O
-    Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
-
-    H8/300 modified
-    Yoshinori Sato <ysato@users.sourceforge.jp>
-*/
-
-static const char version1[] =
-"ne-h8300.c:v1.00 2004/04/11 ysato\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/jiffies.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#define EI_SHIFT(x)    (ei_local->reg_offset[x])
-
-#include "8390.h"
-
-#define DRV_NAME "ne-h8300"
-
-/* Some defines that people can play with if so inclined. */
-
-/* Do we perform extra sanity checks on stuff ? */
-/* #define NE_SANITY_CHECK */
-
-/* Do we implement the read before write bugfix ? */
-/* #define NE_RW_BUGFIX */
-
-/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
-/* #define PACKETBUF_MEMSIZE   0x40 */
-
-/* A zero-terminated list of I/O addresses to be probed at boot. */
-
-/* ---- No user-serviceable parts below ---- */
-
-static const char version[] =
-    "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include "lib8390.c"
-
-#define NE_BASE         (dev->base_addr)
-#define NE_CMD         0x00
-#define NE_DATAPORT    (ei_status.word16?0x20:0x10)    /* NatSemi-defined port window offset. */
-#define NE_RESET       (ei_status.word16?0x3f:0x1f)    /* Issue a read to reset, a write to clear. */
-#define NE_IO_EXTENT   (ei_status.word16?0x40:0x20)
-
-#define NESM_START_PG  0x40    /* First page of TX buffer */
-#define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
-
-static int ne_probe1(struct net_device *dev, int ioaddr);
-
-static int ne_open(struct net_device *dev);
-static int ne_close(struct net_device *dev);
-
-static void ne_reset_8390(struct net_device *dev);
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                         int ring_page);
-static void ne_block_input(struct net_device *dev, int count,
-                         struct sk_buff *skb, int ring_offset);
-static void ne_block_output(struct net_device *dev, const int count,
-               const unsigned char *buf, const int start_page);
-
-
-static u32 reg_offset[16];
-
-static int __init init_reg_offset(struct net_device *dev,unsigned long base_addr)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       int i;
-       unsigned char bus_width;
-
-       bus_width = *(volatile unsigned char *)ABWCR;
-       bus_width &= 1 << ((base_addr >> 21) & 7);
-
-       for (i = 0; i < ARRAY_SIZE(reg_offset); i++)
-               if (bus_width == 0)
-                       reg_offset[i] = i * 2 + 1;
-               else
-                       reg_offset[i] = i;
-
-       ei_local->reg_offset = reg_offset;
-       return 0;
-}
-
-static int __initdata h8300_ne_count = 0;
-#ifdef CONFIG_H8300H_H8MAX
-static unsigned long __initdata h8300_ne_base[] = { 0x800600 };
-static int h8300_ne_irq[] = {EXT_IRQ4};
-#endif
-#ifdef CONFIG_H8300H_AKI3068NET
-static unsigned long __initdata h8300_ne_base[] = { 0x200000 };
-static int h8300_ne_irq[] = {EXT_IRQ5};
-#endif
-
-static inline int init_dev(struct net_device *dev)
-{
-       if (h8300_ne_count < ARRAY_SIZE(h8300_ne_base)) {
-               dev->base_addr = h8300_ne_base[h8300_ne_count];
-               dev->irq       = h8300_ne_irq[h8300_ne_count];
-               h8300_ne_count++;
-               return 0;
-       } else
-               return -ENODEV;
-}
-
-/*  Probe for various non-shared-memory ethercards.
-
-   NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
-   buffer memory space.  NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
-   the SAPROM, while other supposed NE2000 clones must be detected by their
-   SA prefix.
-
-   Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
-   mode results in doubled values, which can be detected and compensated for.
-
-   The probe is also responsible for initializing the card and filling
-   in the 'dev' and 'ei_status' structures.
-
-   We use the minimum memory size for some ethercard product lines, iff we can't
-   distinguish models.  You can increase the packet buffer size by setting
-   PACKETBUF_MEMSIZE.  Reported Cabletron packet buffer locations are:
-       E1010   starts at 0x100 and ends at 0x2000.
-       E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
-       E2010    starts at 0x100 and ends at 0x4000.
-       E2010-x starts at 0x100 and ends at 0xffff.  */
-
-static int __init do_ne_probe(struct net_device *dev)
-{
-       unsigned int base_addr = dev->base_addr;
-
-       /* First check any supplied i/o locations. User knows best. <cough> */
-       if (base_addr > 0x1ff)  /* Check a single specified location. */
-               return ne_probe1(dev, base_addr);
-       else if (base_addr != 0)        /* Don't probe at all. */
-               return -ENXIO;
-
-       return -ENODEV;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-       free_irq(dev->irq, dev);
-       release_region(dev->base_addr, NE_IO_EXTENT);
-}
-
-#ifndef MODULE
-struct net_device * __init ne_probe(int unit)
-{
-       struct net_device *dev = ____alloc_ei_netdev(0);
-       int err;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       if (init_dev(dev))
-               return ERR_PTR(-ENODEV);
-
-       sprintf(dev->name, "eth%d", unit);
-       netdev_boot_setup_check(dev);
-
-       err = init_reg_offset(dev, dev->base_addr);
-       if (err)
-               goto out;
-
-       err = do_ne_probe(dev);
-       if (err)
-               goto out;
-       return dev;
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-#endif
-
-static const struct net_device_ops ne_netdev_ops = {
-       .ndo_open               = ne_open,
-       .ndo_stop               = ne_close,
-
-       .ndo_start_xmit         = __ei_start_xmit,
-       .ndo_tx_timeout         = __ei_tx_timeout,
-       .ndo_get_stats          = __ei_get_stats,
-       .ndo_set_multicast_list = __ei_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = __ei_poll,
-#endif
-};
-
-static int __init ne_probe1(struct net_device *dev, int ioaddr)
-{
-       int i;
-       unsigned char SA_prom[16];
-       int wordlength = 2;
-       const char *name = NULL;
-       int start_page, stop_page;
-       int reg0, ret;
-       static unsigned version_printed;
-       struct ei_device *ei_local = netdev_priv(dev);
-       unsigned char bus_width;
-
-       if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
-               return -EBUSY;
-
-       reg0 = inb_p(ioaddr);
-       if (reg0 == 0xFF) {
-               ret = -ENODEV;
-               goto err_out;
-       }
-
-       /* Do a preliminary verification that we have a 8390. */
-       {
-               int regd;
-               outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
-               regd = inb_p(ioaddr + EI_SHIFT(0x0d));
-               outb_p(0xff, ioaddr + EI_SHIFT(0x0d));
-               outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
-               inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
-               if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
-                       outb_p(reg0, ioaddr + EI_SHIFT(0));
-                       outb_p(regd, ioaddr + EI_SHIFT(0x0d));  /* Restore the old values. */
-                       ret = -ENODEV;
-                       goto err_out;
-               }
-       }
-
-       if (ei_debug  &&  version_printed++ == 0)
-               printk(KERN_INFO "%s", version1);
-
-       printk(KERN_INFO "NE*000 ethercard probe at %08x:", ioaddr);
-
-       /* Read the 16 bytes of station address PROM.
-          We must first initialize registers, similar to NS8390_init(eifdev, 0).
-          We can't reliably read the SAPROM address without this.
-          (I learned the hard way!). */
-       {
-               struct {unsigned char value, offset; } program_seq[] =
-               {
-                       {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
-                       {0x48,  EN0_DCFG},      /* Set byte-wide (0x48) access. */
-                       {0x00,  EN0_RCNTLO},    /* Clear the count regs. */
-                       {0x00,  EN0_RCNTHI},
-                       {0x00,  EN0_IMR},       /* Mask completion irq. */
-                       {0xFF,  EN0_ISR},
-                       {E8390_RXOFF, EN0_RXCR},        /* 0x20  Set to monitor */
-                       {E8390_TXOFF, EN0_TXCR},        /* 0x02  and loopback mode. */
-                       {32,    EN0_RCNTLO},
-                       {0x00,  EN0_RCNTHI},
-                       {0x00,  EN0_RSARLO},    /* DMA starting at 0x0000. */
-                       {0x00,  EN0_RSARHI},
-                       {E8390_RREAD+E8390_START, E8390_CMD},
-               };
-
-               for (i = 0; i < ARRAY_SIZE(program_seq); i++)
-                       outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
-
-       }
-       bus_width = *(volatile unsigned char *)ABWCR;
-       bus_width &= 1 << ((ioaddr >> 21) & 7);
-       ei_status.word16 = (bus_width == 0); /* temporary setting */
-       for(i = 0; i < 16 /*sizeof(SA_prom)*/; i++) {
-               SA_prom[i] = inb_p(ioaddr + NE_DATAPORT);
-               inb_p(ioaddr + NE_DATAPORT); /* dummy read */
-       }
-
-       start_page = NESM_START_PG;
-       stop_page = NESM_STOP_PG;
-
-       if (bus_width)
-               wordlength = 1;
-       else
-               outb_p(0x49, ioaddr + EN0_DCFG);
-
-       /* Set up the rest of the parameters. */
-       name = (wordlength == 2) ? "NE2000" : "NE1000";
-
-       if (! dev->irq) {
-               printk(" failed to detect IRQ line.\n");
-               ret = -EAGAIN;
-               goto err_out;
-       }
-
-       /* Snarf the interrupt now.  There's no point in waiting since we cannot
-          share and the board will usually be enabled. */
-       ret = request_irq(dev->irq, __ei_interrupt, 0, name, dev);
-       if (ret) {
-               printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
-               goto err_out;
-       }
-
-       dev->base_addr = ioaddr;
-
-       for(i = 0; i < ETHER_ADDR_LEN; i++)
-               dev->dev_addr[i] = SA_prom[i];
-       printk(" %pM\n", dev->dev_addr);
-
-       printk("%s: %s found at %#x, using IRQ %d.\n",
-               dev->name, name, ioaddr, dev->irq);
-
-       ei_status.name = name;
-       ei_status.tx_start_page = start_page;
-       ei_status.stop_page = stop_page;
-       ei_status.word16 = (wordlength == 2);
-
-       ei_status.rx_start_page = start_page + TX_PAGES;
-#ifdef PACKETBUF_MEMSIZE
-        /* Allow the packet buffer size to be overridden by know-it-alls. */
-       ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
-#endif
-
-       ei_status.reset_8390 = &ne_reset_8390;
-       ei_status.block_input = &ne_block_input;
-       ei_status.block_output = &ne_block_output;
-       ei_status.get_8390_hdr = &ne_get_8390_hdr;
-       ei_status.priv = 0;
-
-       dev->netdev_ops = &ne_netdev_ops;
-
-       __NS8390_init(dev, 0);
-
-       ret = register_netdev(dev);
-       if (ret)
-               goto out_irq;
-       return 0;
-out_irq:
-       free_irq(dev->irq, dev);
-err_out:
-       release_region(ioaddr, NE_IO_EXTENT);
-       return ret;
-}
-
-static int ne_open(struct net_device *dev)
-{
-       __ei_open(dev);
-       return 0;
-}
-
-static int ne_close(struct net_device *dev)
-{
-       if (ei_debug > 1)
-               printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
-       __ei_close(dev);
-       return 0;
-}
-
-/* Hard reset the card.  This used to pause for the same period that a
-   8390 reset command required, but that shouldn't be necessary. */
-
-static void ne_reset_8390(struct net_device *dev)
-{
-       unsigned long reset_start_time = jiffies;
-       struct ei_device *ei_local = netdev_priv(dev);
-
-       if (ei_debug > 1)
-               printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
-
-       /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
-       outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
-       ei_status.txing = 0;
-       ei_status.dmaing = 0;
-
-       /* This check _should_not_ be necessary, omit eventually. */
-       while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
-               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
-                       printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
-                       break;
-               }
-       outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
-   we don't need to be concerned with ring wrap as the header will be at
-   the start of a page, so we optimize accordingly. */
-
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-
-       if (ei_status.dmaing)
-       {
-               printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
-                       "[DMAstat:%d][irqlock:%d].\n",
-                       dev->name, ei_status.dmaing, ei_status.irqlock);
-               return;
-       }
-
-       ei_status.dmaing |= 0x01;
-       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, NE_BASE + NE_CMD);
-       outb_p(sizeof(struct e8390_pkt_hdr), NE_BASE + EN0_RCNTLO);
-       outb_p(0, NE_BASE + EN0_RCNTHI);
-       outb_p(0, NE_BASE + EN0_RSARLO);                /* On page boundary */
-       outb_p(ring_page, NE_BASE + EN0_RSARHI);
-       outb_p(E8390_RREAD+E8390_START, NE_BASE + NE_CMD);
-
-       if (ei_status.word16) {
-               int len;
-               unsigned short *p = (unsigned short *)hdr;
-               for (len = sizeof(struct e8390_pkt_hdr)>>1; len > 0; len--)
-                       *p++ = inw(NE_BASE + NE_DATAPORT);
-       } else
-               insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
-
-       outb_p(ENISR_RDC, NE_BASE + EN0_ISR);   /* Ack intr. */
-       ei_status.dmaing &= ~0x01;
-
-       le16_to_cpus(&hdr->count);
-}
-
-/* Block input and output, similar to the Crynwr packet driver.  If you
-   are porting to a new ethercard, look at the packet driver source for hints.
-   The NEx000 doesn't share the on-board packet memory -- you have to put
-   the packet out through the "remote DMA" dataport using outb. */
-
-static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-#ifdef NE_SANITY_CHECK
-       int xfer_count = count;
-#endif
-       char *buf = skb->data;
-
-       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-       if (ei_status.dmaing)
-       {
-               printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
-                       "[DMAstat:%d][irqlock:%d].\n",
-                       dev->name, ei_status.dmaing, ei_status.irqlock);
-               return;
-       }
-       ei_status.dmaing |= 0x01;
-       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, NE_BASE + NE_CMD);
-       outb_p(count & 0xff, NE_BASE + EN0_RCNTLO);
-       outb_p(count >> 8, NE_BASE + EN0_RCNTHI);
-       outb_p(ring_offset & 0xff, NE_BASE + EN0_RSARLO);
-       outb_p(ring_offset >> 8, NE_BASE + EN0_RSARHI);
-       outb_p(E8390_RREAD+E8390_START, NE_BASE + NE_CMD);
-       if (ei_status.word16)
-       {
-               int len;
-               unsigned short *p = (unsigned short *)buf;
-               for (len = count>>1; len > 0; len--)
-                       *p++ = inw(NE_BASE + NE_DATAPORT);
-               if (count & 0x01)
-               {
-                       buf[count-1] = inb(NE_BASE + NE_DATAPORT);
-#ifdef NE_SANITY_CHECK
-                       xfer_count++;
-#endif
-               }
-       } else {
-               insb(NE_BASE + NE_DATAPORT, buf, count);
-       }
-
-#ifdef NE_SANITY_CHECK
-       /* This was for the ALPHA version only, but enough people have
-          been encountering problems so it is still here.  If you see
-          this message you either 1) have a slightly incompatible clone
-          or 2) have noise/speed problems with your bus. */
-
-       if (ei_debug > 1)
-       {
-               /* DMA termination address check... */
-               int addr, tries = 20;
-               do {
-                       /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
-                          -- it's broken for Rx on some cards! */
-                       int high = inb_p(NE_BASE + EN0_RSARHI);
-                       int low = inb_p(NE_BASE + EN0_RSARLO);
-                       addr = (high << 8) + low;
-                       if (((ring_offset + xfer_count) & 0xff) == low)
-                               break;
-               } while (--tries > 0);
-               if (tries <= 0)
-                       printk(KERN_WARNING "%s: RX transfer address mismatch,"
-                               "%#4.4x (expected) vs. %#4.4x (actual).\n",
-                               dev->name, ring_offset + xfer_count, addr);
-       }
-#endif
-       outb_p(ENISR_RDC, NE_BASE + EN0_ISR);   /* Ack intr. */
-       ei_status.dmaing &= ~0x01;
-}
-
-static void ne_block_output(struct net_device *dev, int count,
-               const unsigned char *buf, const int start_page)
-{
-       struct ei_device *ei_local = netdev_priv(dev);
-       unsigned long dma_start;
-#ifdef NE_SANITY_CHECK
-       int retries = 0;
-#endif
-
-       /* Round the count up for word writes.  Do we need to do this?
-          What effect will an odd byte count have on the 8390?
-          I should check someday. */
-
-       if (ei_status.word16 && (count & 0x01))
-               count++;
-
-       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-       if (ei_status.dmaing)
-       {
-               printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
-                       "[DMAstat:%d][irqlock:%d]\n",
-                       dev->name, ei_status.dmaing, ei_status.irqlock);
-               return;
-       }
-       ei_status.dmaing |= 0x01;
-       /* We should already be in page 0, but to be safe... */
-       outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, NE_BASE + NE_CMD);
-
-#ifdef NE_SANITY_CHECK
-retry:
-#endif
-
-#ifdef NE8390_RW_BUGFIX
-       /* Handle the read-before-write bug the same way as the
-          Crynwr packet driver -- the NatSemi method doesn't work.
-          Actually this doesn't always work either, but if you have
-          problems with your NEx000 this is better than nothing! */
-
-       outb_p(0x42, NE_BASE + EN0_RCNTLO);
-       outb_p(0x00, NE_BASE + EN0_RCNTHI);
-       outb_p(0x42, NE_BASE + EN0_RSARLO);
-       outb_p(0x00, NE_BASE + EN0_RSARHI);
-       outb_p(E8390_RREAD+E8390_START, NE_BASE + NE_CMD);
-       /* Make certain that the dummy read has occurred. */
-       udelay(6);
-#endif
-
-       outb_p(ENISR_RDC, NE_BASE + EN0_ISR);
-
-       /* Now the normal output. */
-       outb_p(count & 0xff, NE_BASE + EN0_RCNTLO);
-       outb_p(count >> 8,   NE_BASE + EN0_RCNTHI);
-       outb_p(0x00, NE_BASE + EN0_RSARLO);
-       outb_p(start_page, NE_BASE + EN0_RSARHI);
-
-       outb_p(E8390_RWRITE+E8390_START, NE_BASE + NE_CMD);
-       if (ei_status.word16) {
-               int len;
-               unsigned short *p = (unsigned short *)buf;
-               for (len = count>>1; len > 0; len--)
-                       outw(*p++, NE_BASE + NE_DATAPORT);
-       } else {
-               outsb(NE_BASE + NE_DATAPORT, buf, count);
-       }
-
-       dma_start = jiffies;
-
-#ifdef NE_SANITY_CHECK
-       /* This was for the ALPHA version only, but enough people have
-          been encountering problems so it is still here. */
-
-       if (ei_debug > 1)
-       {
-               /* DMA termination address check... */
-               int addr, tries = 20;
-               do {
-                       int high = inb_p(NE_BASE + EN0_RSARHI);
-                       int low = inb_p(NE_BASE + EN0_RSARLO);
-                       addr = (high << 8) + low;
-                       if ((start_page << 8) + count == addr)
-                               break;
-               } while (--tries > 0);
-
-               if (tries <= 0)
-               {
-                       printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
-                               "%#4.4x (expected) vs. %#4.4x (actual).\n",
-                               dev->name, (start_page << 8) + count, addr);
-                       if (retries++ == 0)
-                               goto retry;
-               }
-       }
-#endif
-
-       while ((inb_p(NE_BASE + EN0_ISR) & ENISR_RDC) == 0)
-               if (time_after(jiffies, dma_start + 2*HZ/100)) {                /* 20ms */
-                       printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
-                       ne_reset_8390(dev);
-                       __NS8390_init(dev,1);
-                       break;
-               }
-
-       outb_p(ENISR_RDC, NE_BASE + EN0_ISR);   /* Ack intr. */
-       ei_status.dmaing &= ~0x01;
-}
-
-
-#ifdef MODULE
-#define MAX_NE_CARDS   1       /* Max number of NE cards per module */
-static struct net_device *dev_ne[MAX_NE_CARDS];
-static int io[MAX_NE_CARDS];
-static int irq[MAX_NE_CARDS];
-static int bad[MAX_NE_CARDS];  /* 0xbad = bad sig or no reset ack */
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(bad, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s)");
-MODULE_DESCRIPTION("H8/300 NE2000 Ethernet driver");
-MODULE_LICENSE("GPL");
-
-/* This is set up so that no ISA autoprobe takes place. We can't guarantee
-that the ne2k probe is the last 8390 based probe to take place (as it
-is at boot) and so the probe will get confused by any other 8390 cards.
-ISA device autoprobes on a running machine are not recommended anyway. */
-
-int init_module(void)
-{
-       int this_dev, found = 0;
-       int err;
-
-       for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-               struct net_device *dev = ____alloc_ei_netdev(0);
-               if (!dev)
-                       break;
-               if (io[this_dev]) {
-                       dev->irq = irq[this_dev];
-                       dev->mem_end = bad[this_dev];
-                       dev->base_addr = io[this_dev];
-               } else {
-                       dev->base_addr = h8300_ne_base[this_dev];
-                       dev->irq = h8300_ne_irq[this_dev];
-               }
-               err = init_reg_offset(dev, dev->base_addr);
-               if (!err) {
-                       if (do_ne_probe(dev) == 0) {
-                               dev_ne[found++] = dev;
-                               continue;
-                       }
-               }
-               free_netdev(dev);
-               if (found)
-                       break;
-               if (io[this_dev] != 0)
-                       printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", dev->base_addr);
-               else
-                       printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
-               return -ENXIO;
-       }
-       if (found)
-               return 0;
-       return -ENODEV;
-}
-
-void cleanup_module(void)
-{
-       int this_dev;
-
-       for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-               struct net_device *dev = dev_ne[this_dev];
-               if (dev) {
-                       unregister_netdev(dev);
-                       cleanup_card(dev);
-                       free_netdev(dev);
-               }
-       }
-}
-#endif /* MODULE */
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
deleted file mode 100644 (file)
index 1063093..0000000
+++ /dev/null
@@ -1,1008 +0,0 @@
-/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
-/*
-    Written 1992-94 by Donald Becker.
-
-    Copyright 1993 United States Government as represented by the
-    Director, National Security Agency.
-
-    This software may be used and distributed according to the terms
-    of the GNU General Public License, incorporated herein by reference.
-
-    The author may be reached as becker@scyld.com, or C/O
-    Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
-
-    This driver should work with many programmed-I/O 8390-based ethernet
-    boards.  Currently it supports the NE1000, NE2000, many clones,
-    and some Cabletron products.
-
-    Changelog:
-
-    Paul Gortmaker     : use ENISR_RDC to monitor Tx PIO uploads, made
-                         sanity checks and bad clone support optional.
-    Paul Gortmaker     : new reset code, reset card after probe at boot.
-    Paul Gortmaker     : multiple card support for module users.
-    Paul Gortmaker     : Support for PCI ne2k clones, similar to lance.c
-    Paul Gortmaker     : Allow users with bad cards to avoid full probe.
-    Paul Gortmaker     : PCI probe changes, more PCI cards supported.
-    rjohnson@analogic.com : Changed init order so an interrupt will only
-    occur after memory is allocated for dev->priv. Deallocated memory
-    last in cleanup_modue()
-    Richard Guenther    : Added support for ISAPnP cards
-    Paul Gortmaker     : Discontinued PCI support - use ne2k-pci.c instead.
-    Hayato Fujiwara    : Add m32r support.
-
-*/
-
-/* Routines for the NatSemi-based designs (NE[12]000). */
-
-static const char version1[] =
-"ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)\n";
-static const char version2[] =
-"Last modified Nov 1, 2000 by Paul Gortmaker\n";
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/isapnp.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/jiffies.h>
-#include <linux/platform_device.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include "8390.h"
-
-#define DRV_NAME "ne"
-
-/* Some defines that people can play with if so inclined. */
-
-/* Do we support clones that don't adhere to 14,15 of the SAprom ? */
-#define SUPPORT_NE_BAD_CLONES
-/* 0xbad = bad sig or no reset ack */
-#define BAD 0xbad
-
-#define MAX_NE_CARDS   4       /* Max number of NE cards per module */
-static struct platform_device *pdev_ne[MAX_NE_CARDS];
-static int io[MAX_NE_CARDS];
-static int irq[MAX_NE_CARDS];
-static int bad[MAX_NE_CARDS];
-
-#ifdef MODULE
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(bad, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es),required");
-MODULE_PARM_DESC(irq, "IRQ number(s)");
-MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
-MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver");
-MODULE_LICENSE("GPL");
-#endif /* MODULE */
-
-/* Do we perform extra sanity checks on stuff ? */
-/* #define NE_SANITY_CHECK */
-
-/* Do we implement the read before write bugfix ? */
-/* #define NE_RW_BUGFIX */
-
-/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
-/* #define PACKETBUF_MEMSIZE   0x40 */
-
-/* This is set up so that no ISA autoprobe takes place. We can't guarantee
-that the ne2k probe is the last 8390 based probe to take place (as it
-is at boot) and so the probe will get confused by any other 8390 cards.
-ISA device autoprobes on a running machine are not recommended anyway. */
-#if !defined(MODULE) && (defined(CONFIG_ISA) || defined(CONFIG_M32R))
-/* Do we need a portlist for the ISA auto-probe ? */
-#define NEEDS_PORTLIST
-#endif
-
-/* A zero-terminated list of I/O addresses to be probed at boot. */
-#ifdef NEEDS_PORTLIST
-static unsigned int netcard_portlist[] __initdata = {
-       0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0
-};
-#endif
-
-static struct isapnp_device_id isapnp_clone_list[] __initdata = {
-       {       ISAPNP_CARD_ID('A','X','E',0x2011),
-               ISAPNP_VENDOR('A','X','E'), ISAPNP_FUNCTION(0x2011),
-               (long) "NetGear EA201" },
-       {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-               ISAPNP_VENDOR('E','D','I'), ISAPNP_FUNCTION(0x0216),
-               (long) "NN NE2000" },
-       {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
-               ISAPNP_VENDOR('P','N','P'), ISAPNP_FUNCTION(0x80d6),
-               (long) "Generic PNP" },
-       { }     /* terminate list */
-};
-
-MODULE_DEVICE_TABLE(isapnp, isapnp_clone_list);
-
-#ifdef SUPPORT_NE_BAD_CLONES
-/* A list of bad clones that we none-the-less recognize. */
-static struct { const char *name8, *name16; unsigned char SAprefix[4];}
-bad_clone_list[] __initdata = {
-    {"DE100", "DE200", {0x00, 0xDE, 0x01,}},
-    {"DE120", "DE220", {0x00, 0x80, 0xc8,}},
-    {"DFI1000", "DFI2000", {'D', 'F', 'I',}}, /* Original, eh?  */
-    {"EtherNext UTP8", "EtherNext UTP16", {0x00, 0x00, 0x79}},
-    {"NE1000","NE2000-invalid", {0x00, 0x00, 0xd8}}, /* Ancient real NE1000. */
-    {"NN1000", "NN2000",  {0x08, 0x03, 0x08}}, /* Outlaw no-name clone. */
-    {"4-DIM8","4-DIM16", {0x00,0x00,0x4d,}},  /* Outlaw 4-Dimension cards. */
-    {"Con-Intl_8", "Con-Intl_16", {0x00, 0x00, 0x24}}, /* Connect Int'nl */
-    {"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */
-    {"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */
-    {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
-    {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
-    {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
-#ifdef CONFIG_MACH_TX49XX
-    {"RBHMA4X00-RTL8019", "RBHMA4X00-RTL8019", {0x00, 0x60, 0x0a}},  /* Toshiba built-in */
-#endif
-    {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
-    {NULL,}
-};
-#endif
-
-/* ---- No user-serviceable parts below ---- */
-
-#define NE_BASE         (dev->base_addr)
-#define NE_CMD         0x00
-#define NE_DATAPORT    0x10    /* NatSemi-defined port window offset. */
-#define NE_RESET       0x1f    /* Issue a read to reset, a write to clear. */
-#define NE_IO_EXTENT   0x20
-
-#define NE1SM_START_PG 0x20    /* First page of TX buffer */
-#define NE1SM_STOP_PG  0x40    /* Last page +1 of RX ring */
-#define NESM_START_PG  0x40    /* First page of TX buffer */
-#define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
-
-#if defined(CONFIG_PLAT_MAPPI)
-#  define DCR_VAL 0x4b
-#elif defined(CONFIG_PLAT_OAKS32R)  || \
-   defined(CONFIG_MACH_TX49XX)
-#  define DCR_VAL 0x48         /* 8-bit mode */
-#else
-#  define DCR_VAL 0x49
-#endif
-
-static int ne_probe1(struct net_device *dev, unsigned long ioaddr);
-static int ne_probe_isapnp(struct net_device *dev);
-
-static void ne_reset_8390(struct net_device *dev);
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                         int ring_page);
-static void ne_block_input(struct net_device *dev, int count,
-                         struct sk_buff *skb, int ring_offset);
-static void ne_block_output(struct net_device *dev, const int count,
-               const unsigned char *buf, const int start_page);
-
-
-/*  Probe for various non-shared-memory ethercards.
-
-   NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
-   buffer memory space.  NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
-   the SAPROM, while other supposed NE2000 clones must be detected by their
-   SA prefix.
-
-   Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
-   mode results in doubled values, which can be detected and compensated for.
-
-   The probe is also responsible for initializing the card and filling
-   in the 'dev' and 'ei_status' structures.
-
-   We use the minimum memory size for some ethercard product lines, iff we can't
-   distinguish models.  You can increase the packet buffer size by setting
-   PACKETBUF_MEMSIZE.  Reported Cabletron packet buffer locations are:
-       E1010   starts at 0x100 and ends at 0x2000.
-       E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
-       E2010    starts at 0x100 and ends at 0x4000.
-       E2010-x starts at 0x100 and ends at 0xffff.  */
-
-static int __init do_ne_probe(struct net_device *dev)
-{
-       unsigned long base_addr = dev->base_addr;
-#ifdef NEEDS_PORTLIST
-       int orig_irq = dev->irq;
-#endif
-
-       /* First check any supplied i/o locations. User knows best. <cough> */
-       if (base_addr > 0x1ff) {        /* Check a single specified location. */
-               int ret = ne_probe1(dev, base_addr);
-               if (ret)
-                       printk(KERN_WARNING "ne.c: No NE*000 card found at "
-                               "i/o = %#lx\n", base_addr);
-               return ret;
-       }
-       else if (base_addr != 0)        /* Don't probe at all. */
-               return -ENXIO;
-
-       /* Then look for any installed ISAPnP clones */
-       if (isapnp_present() && (ne_probe_isapnp(dev) == 0))
-               return 0;
-
-#ifdef NEEDS_PORTLIST
-       /* Last resort. The semi-risky ISA auto-probe. */
-       for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
-               int ioaddr = netcard_portlist[base_addr];
-               dev->irq = orig_irq;
-               if (ne_probe1(dev, ioaddr) == 0)
-                       return 0;
-       }
-#endif
-
-       return -ENODEV;
-}
-
-static int __init ne_probe_isapnp(struct net_device *dev)
-{
-       int i;
-
-       for (i = 0; isapnp_clone_list[i].vendor != 0; i++) {
-               struct pnp_dev *idev = NULL;
-
-               while ((idev = pnp_find_dev(NULL,
-                                           isapnp_clone_list[i].vendor,
-                                           isapnp_clone_list[i].function,
-                                           idev))) {
-                       /* Avoid already found cards from previous calls */
-                       if (pnp_device_attach(idev) < 0)
-                               continue;
-                       if (pnp_activate_dev(idev) < 0) {
-                               pnp_device_detach(idev);
-                               continue;
-                       }
-                       /* if no io and irq, search for next */
-                       if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) {
-                               pnp_device_detach(idev);
-                               continue;
-                       }
-                       /* found it */
-                       dev->base_addr = pnp_port_start(idev, 0);
-                       dev->irq = pnp_irq(idev, 0);
-                       printk(KERN_INFO "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
-                               (char *) isapnp_clone_list[i].driver_data,
-                               dev->base_addr, dev->irq);
-                       if (ne_probe1(dev, dev->base_addr) != 0) {      /* Shouldn't happen. */
-                               printk(KERN_ERR "ne.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr);
-                               pnp_device_detach(idev);
-                               return -ENXIO;
-                       }
-                       ei_status.priv = (unsigned long)idev;
-                       break;
-               }
-               if (!idev)
-                       continue;
-               return 0;
-       }
-
-       return -ENODEV;
-}
-
-static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
-{
-       int i;
-       unsigned char SA_prom[32];
-       int wordlength = 2;
-       const char *name = NULL;
-       int start_page, stop_page;
-       int neX000, ctron, copam, bad_card;
-       int reg0, ret;
-       static unsigned version_printed;
-
-       if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
-               return -EBUSY;
-
-       reg0 = inb_p(ioaddr);
-       if (reg0 == 0xFF) {
-               ret = -ENODEV;
-               goto err_out;
-       }
-
-       /* Do a preliminary verification that we have a 8390. */
-       {
-               int regd;
-               outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
-               regd = inb_p(ioaddr + 0x0d);
-               outb_p(0xff, ioaddr + 0x0d);
-               outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
-               inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
-               if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
-                       outb_p(reg0, ioaddr);
-                       outb_p(regd, ioaddr + 0x0d);    /* Restore the old values. */
-                       ret = -ENODEV;
-                       goto err_out;
-               }
-       }
-
-       if (ei_debug  &&  version_printed++ == 0)
-               printk(KERN_INFO "%s%s", version1, version2);
-
-       printk(KERN_INFO "NE*000 ethercard probe at %#3lx:", ioaddr);
-
-       /* A user with a poor card that fails to ack the reset, or that
-          does not have a valid 0x57,0x57 signature can still use this
-          without having to recompile. Specifying an i/o address along
-          with an otherwise unused dev->mem_end value of "0xBAD" will
-          cause the driver to skip these parts of the probe. */
-
-       bad_card = ((dev->base_addr != 0) && (dev->mem_end == BAD));
-
-       /* Reset card. Who knows what dain-bramaged state it was left in. */
-
-       {
-               unsigned long reset_start_time = jiffies;
-
-               /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
-               outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
-
-               while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
-               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
-                       if (bad_card) {
-                               printk(" (warning: no reset ack)");
-                               break;
-                       } else {
-                               printk(" not found (no reset ack).\n");
-                               ret = -ENODEV;
-                               goto err_out;
-                       }
-               }
-
-               outb_p(0xff, ioaddr + EN0_ISR);         /* Ack all intr. */
-       }
-
-       /* Read the 16 bytes of station address PROM.
-          We must first initialize registers, similar to NS8390p_init(eifdev, 0).
-          We can't reliably read the SAPROM address without this.
-          (I learned the hard way!). */
-       {
-               struct {unsigned char value, offset; } program_seq[] =
-               {
-                       {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
-                       {0x48,  EN0_DCFG},      /* Set byte-wide (0x48) access. */
-                       {0x00,  EN0_RCNTLO},    /* Clear the count regs. */
-                       {0x00,  EN0_RCNTHI},
-                       {0x00,  EN0_IMR},       /* Mask completion irq. */
-                       {0xFF,  EN0_ISR},
-                       {E8390_RXOFF, EN0_RXCR},        /* 0x20  Set to monitor */
-                       {E8390_TXOFF, EN0_TXCR},        /* 0x02  and loopback mode. */
-                       {32,    EN0_RCNTLO},
-                       {0x00,  EN0_RCNTHI},
-                       {0x00,  EN0_RSARLO},    /* DMA starting at 0x0000. */
-                       {0x00,  EN0_RSARHI},
-                       {E8390_RREAD+E8390_START, E8390_CMD},
-               };
-
-               for (i = 0; i < ARRAY_SIZE(program_seq); i++)
-                       outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
-
-       }
-       for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
-               SA_prom[i] = inb(ioaddr + NE_DATAPORT);
-               SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
-               if (SA_prom[i] != SA_prom[i+1])
-                       wordlength = 1;
-       }
-
-       if (wordlength == 2)
-       {
-               for (i = 0; i < 16; i++)
-                       SA_prom[i] = SA_prom[i+i];
-               /* We must set the 8390 for word mode. */
-               outb_p(DCR_VAL, ioaddr + EN0_DCFG);
-               start_page = NESM_START_PG;
-
-               /*
-                * Realtek RTL8019AS datasheet says that the PSTOP register
-                * shouldn't exceed 0x60 in 8-bit mode.
-                * This chip can be identified by reading the signature from
-                * the  remote byte count registers (otherwise write-only)...
-                */
-               if ((DCR_VAL & 0x01) == 0 &&            /* 8-bit mode */
-                   inb(ioaddr + EN0_RCNTLO) == 0x50 &&
-                   inb(ioaddr + EN0_RCNTHI) == 0x70)
-                       stop_page = 0x60;
-               else
-                       stop_page = NESM_STOP_PG;
-       } else {
-               start_page = NE1SM_START_PG;
-               stop_page  = NE1SM_STOP_PG;
-       }
-
-#if  defined(CONFIG_PLAT_MAPPI) || defined(CONFIG_PLAT_OAKS32R)
-       neX000 = ((SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57)
-               || (SA_prom[14] == 0x42 && SA_prom[15] == 0x42));
-#else
-       neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
-#endif
-       ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
-       copam =  (SA_prom[14] == 0x49 && SA_prom[15] == 0x00);
-
-       /* Set up the rest of the parameters. */
-       if (neX000 || bad_card || copam) {
-               name = (wordlength == 2) ? "NE2000" : "NE1000";
-       }
-       else if (ctron)
-       {
-               name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
-               start_page = 0x01;
-               stop_page = (wordlength == 2) ? 0x40 : 0x20;
-       }
-       else
-       {
-#ifdef SUPPORT_NE_BAD_CLONES
-               /* Ack!  Well, there might be a *bad* NE*000 clone there.
-                  Check for total bogus addresses. */
-               for (i = 0; bad_clone_list[i].name8; i++)
-               {
-                       if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
-                               SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
-                               SA_prom[2] == bad_clone_list[i].SAprefix[2])
-                       {
-                               if (wordlength == 2)
-                               {
-                                       name = bad_clone_list[i].name16;
-                               } else {
-                                       name = bad_clone_list[i].name8;
-                               }
-                               break;
-                       }
-               }
-               if (bad_clone_list[i].name8 == NULL)
-               {
-                       printk(" not found (invalid signature %2.2x %2.2x).\n",
-                               SA_prom[14], SA_prom[15]);
-                       ret = -ENXIO;
-                       goto err_out;
-               }
-#else
-               printk(" not found.\n");
-               ret = -ENXIO;
-               goto err_out;
-#endif
-       }
-
-       if (dev->irq < 2)
-       {
-               unsigned long cookie = probe_irq_on();
-               outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */
-               outb_p(0x00, ioaddr + EN0_RCNTLO);
-               outb_p(0x00, ioaddr + EN0_RCNTHI);
-               outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
-               mdelay(10);             /* wait 10ms for interrupt to propagate */
-               outb_p(0x00, ioaddr + EN0_IMR);                 /* Mask it again. */
-               dev->irq = probe_irq_off(cookie);
-               if (ei_debug > 2)
-                       printk(" autoirq is %d\n", dev->irq);
-       } else if (dev->irq == 2)
-               /* Fixup for users that don't know that IRQ 2 is really IRQ 9,
-                  or don't know which one to set. */
-               dev->irq = 9;
-
-       if (! dev->irq) {
-               printk(" failed to detect IRQ line.\n");
-               ret = -EAGAIN;
-               goto err_out;
-       }
-
-       /* Snarf the interrupt now.  There's no point in waiting since we cannot
-          share and the board will usually be enabled. */
-       ret = request_irq(dev->irq, eip_interrupt, 0, name, dev);
-       if (ret) {
-               printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
-               goto err_out;
-       }
-
-       dev->base_addr = ioaddr;
-
-#ifdef CONFIG_PLAT_MAPPI
-       outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
-               ioaddr + E8390_CMD); /* 0x61 */
-       for (i = 0 ; i < ETHER_ADDR_LEN ; i++) {
-               dev->dev_addr[i] = SA_prom[i]
-                       = inb_p(ioaddr + EN1_PHYS_SHIFT(i));
-       }
-#else
-       for(i = 0; i < ETHER_ADDR_LEN; i++) {
-               dev->dev_addr[i] = SA_prom[i];
-       }
-#endif
-
-       printk("%pM\n", dev->dev_addr);
-
-       ei_status.name = name;
-       ei_status.tx_start_page = start_page;
-       ei_status.stop_page = stop_page;
-
-       /* Use 16-bit mode only if this wasn't overridden by DCR_VAL */
-       ei_status.word16 = (wordlength == 2 && (DCR_VAL & 0x01));
-
-       ei_status.rx_start_page = start_page + TX_PAGES;
-#ifdef PACKETBUF_MEMSIZE
-        /* Allow the packet buffer size to be overridden by know-it-alls. */
-       ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
-#endif
-
-       ei_status.reset_8390 = &ne_reset_8390;
-       ei_status.block_input = &ne_block_input;
-       ei_status.block_output = &ne_block_output;
-       ei_status.get_8390_hdr = &ne_get_8390_hdr;
-       ei_status.priv = 0;
-
-       dev->netdev_ops = &eip_netdev_ops;
-       NS8390p_init(dev, 0);
-
-       ret = register_netdev(dev);
-       if (ret)
-               goto out_irq;
-       printk(KERN_INFO "%s: %s found at %#lx, using IRQ %d.\n",
-              dev->name, name, ioaddr, dev->irq);
-       return 0;
-
-out_irq:
-       free_irq(dev->irq, dev);
-err_out:
-       release_region(ioaddr, NE_IO_EXTENT);
-       return ret;
-}
-
-/* Hard reset the card.  This used to pause for the same period that a
-   8390 reset command required, but that shouldn't be necessary. */
-
-static void ne_reset_8390(struct net_device *dev)
-{
-       unsigned long reset_start_time = jiffies;
-
-       if (ei_debug > 1)
-               printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
-
-       /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
-       outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
-       ei_status.txing = 0;
-       ei_status.dmaing = 0;
-
-       /* This check _should_not_ be necessary, omit eventually. */
-       while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
-               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
-                       printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
-                       break;
-               }
-       outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
-   we don't need to be concerned with ring wrap as the header will be at
-   the start of a page, so we optimize accordingly. */
-
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-       int nic_base = dev->base_addr;
-
-       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-
-       if (ei_status.dmaing)
-       {
-               printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
-                       "[DMAstat:%d][irqlock:%d].\n",
-                       dev->name, ei_status.dmaing, ei_status.irqlock);
-               return;
-       }
-
-       ei_status.dmaing |= 0x01;
-       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-       outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
-       outb_p(0, nic_base + EN0_RCNTHI);
-       outb_p(0, nic_base + EN0_RSARLO);               /* On page boundary */
-       outb_p(ring_page, nic_base + EN0_RSARHI);
-       outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
-       if (ei_status.word16)
-               insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
-       else
-               insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
-
-       outb_p(ENISR_RDC, nic_base + EN0_ISR);  /* Ack intr. */
-       ei_status.dmaing &= ~0x01;
-
-       le16_to_cpus(&hdr->count);
-}
-
-/* Block input and output, similar to the Crynwr packet driver.  If you
-   are porting to a new ethercard, look at the packet driver source for hints.
-   The NEx000 doesn't share the on-board packet memory -- you have to put
-   the packet out through the "remote DMA" dataport using outb. */
-
-static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-#ifdef NE_SANITY_CHECK
-       int xfer_count = count;
-#endif
-       int nic_base = dev->base_addr;
-       char *buf = skb->data;
-
-       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-       if (ei_status.dmaing)
-       {
-               printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
-                       "[DMAstat:%d][irqlock:%d].\n",
-                       dev->name, ei_status.dmaing, ei_status.irqlock);
-               return;
-       }
-       ei_status.dmaing |= 0x01;
-       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-       outb_p(count & 0xff, nic_base + EN0_RCNTLO);
-       outb_p(count >> 8, nic_base + EN0_RCNTHI);
-       outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
-       outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
-       outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-       if (ei_status.word16)
-       {
-               insw(NE_BASE + NE_DATAPORT,buf,count>>1);
-               if (count & 0x01)
-               {
-                       buf[count-1] = inb(NE_BASE + NE_DATAPORT);
-#ifdef NE_SANITY_CHECK
-                       xfer_count++;
-#endif
-               }
-       } else {
-               insb(NE_BASE + NE_DATAPORT, buf, count);
-       }
-
-#ifdef NE_SANITY_CHECK
-       /* This was for the ALPHA version only, but enough people have
-          been encountering problems so it is still here.  If you see
-          this message you either 1) have a slightly incompatible clone
-          or 2) have noise/speed problems with your bus. */
-
-       if (ei_debug > 1)
-       {
-               /* DMA termination address check... */
-               int addr, tries = 20;
-               do {
-                       /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
-                          -- it's broken for Rx on some cards! */
-                       int high = inb_p(nic_base + EN0_RSARHI);
-                       int low = inb_p(nic_base + EN0_RSARLO);
-                       addr = (high << 8) + low;
-                       if (((ring_offset + xfer_count) & 0xff) == low)
-                               break;
-               } while (--tries > 0);
-               if (tries <= 0)
-                       printk(KERN_WARNING "%s: RX transfer address mismatch,"
-                               "%#4.4x (expected) vs. %#4.4x (actual).\n",
-                               dev->name, ring_offset + xfer_count, addr);
-       }
-#endif
-       outb_p(ENISR_RDC, nic_base + EN0_ISR);  /* Ack intr. */
-       ei_status.dmaing &= ~0x01;
-}
-
-static void ne_block_output(struct net_device *dev, int count,
-               const unsigned char *buf, const int start_page)
-{
-       int nic_base = NE_BASE;
-       unsigned long dma_start;
-#ifdef NE_SANITY_CHECK
-       int retries = 0;
-#endif
-
-       /* Round the count up for word writes.  Do we need to do this?
-          What effect will an odd byte count have on the 8390?
-          I should check someday. */
-
-       if (ei_status.word16 && (count & 0x01))
-               count++;
-
-       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-       if (ei_status.dmaing)
-       {
-               printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
-                       "[DMAstat:%d][irqlock:%d]\n",
-                       dev->name, ei_status.dmaing, ei_status.irqlock);
-               return;
-       }
-       ei_status.dmaing |= 0x01;
-       /* We should already be in page 0, but to be safe... */
-       outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
-#ifdef NE_SANITY_CHECK
-retry:
-#endif
-
-#ifdef NE8390_RW_BUGFIX
-       /* Handle the read-before-write bug the same way as the
-          Crynwr packet driver -- the NatSemi method doesn't work.
-          Actually this doesn't always work either, but if you have
-          problems with your NEx000 this is better than nothing! */
-
-       outb_p(0x42, nic_base + EN0_RCNTLO);
-       outb_p(0x00,   nic_base + EN0_RCNTHI);
-       outb_p(0x42, nic_base + EN0_RSARLO);
-       outb_p(0x00, nic_base + EN0_RSARHI);
-       outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-       /* Make certain that the dummy read has occurred. */
-       udelay(6);
-#endif
-
-       outb_p(ENISR_RDC, nic_base + EN0_ISR);
-
-       /* Now the normal output. */
-       outb_p(count & 0xff, nic_base + EN0_RCNTLO);
-       outb_p(count >> 8,   nic_base + EN0_RCNTHI);
-       outb_p(0x00, nic_base + EN0_RSARLO);
-       outb_p(start_page, nic_base + EN0_RSARHI);
-
-       outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
-       if (ei_status.word16) {
-               outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
-       } else {
-               outsb(NE_BASE + NE_DATAPORT, buf, count);
-       }
-
-       dma_start = jiffies;
-
-#ifdef NE_SANITY_CHECK
-       /* This was for the ALPHA version only, but enough people have
-          been encountering problems so it is still here. */
-
-       if (ei_debug > 1)
-       {
-               /* DMA termination address check... */
-               int addr, tries = 20;
-               do {
-                       int high = inb_p(nic_base + EN0_RSARHI);
-                       int low = inb_p(nic_base + EN0_RSARLO);
-                       addr = (high << 8) + low;
-                       if ((start_page << 8) + count == addr)
-                               break;
-               } while (--tries > 0);
-
-               if (tries <= 0)
-               {
-                       printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
-                               "%#4.4x (expected) vs. %#4.4x (actual).\n",
-                               dev->name, (start_page << 8) + count, addr);
-                       if (retries++ == 0)
-                               goto retry;
-               }
-       }
-#endif
-
-       while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
-               if (time_after(jiffies, dma_start + 2*HZ/100)) {                /* 20ms */
-                       printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
-                       ne_reset_8390(dev);
-                       NS8390p_init(dev, 1);
-                       break;
-               }
-
-       outb_p(ENISR_RDC, nic_base + EN0_ISR);  /* Ack intr. */
-       ei_status.dmaing &= ~0x01;
-}
-
-static int __init ne_drv_probe(struct platform_device *pdev)
-{
-       struct net_device *dev;
-       int err, this_dev = pdev->id;
-       struct resource *res;
-
-       dev = alloc_eip_netdev();
-       if (!dev)
-               return -ENOMEM;
-
-       /* ne.c doesn't populate resources in platform_device, but
-        * rbtx4927_ne_init and rbtx4938_ne_init do register devices
-        * with resources.
-        */
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       if (res) {
-               dev->base_addr = res->start;
-               dev->irq = platform_get_irq(pdev, 0);
-       } else {
-               if (this_dev < 0 || this_dev >= MAX_NE_CARDS) {
-                       free_netdev(dev);
-                       return -EINVAL;
-               }
-               dev->base_addr = io[this_dev];
-               dev->irq = irq[this_dev];
-               dev->mem_end = bad[this_dev];
-       }
-       err = do_ne_probe(dev);
-       if (err) {
-               free_netdev(dev);
-               return err;
-       }
-       platform_set_drvdata(pdev, dev);
-
-       /* Update with any values found by probing, don't update if
-        * resources were specified.
-        */
-       if (!res) {
-               io[this_dev] = dev->base_addr;
-               irq[this_dev] = dev->irq;
-       }
-       return 0;
-}
-
-static int ne_drv_remove(struct platform_device *pdev)
-{
-       struct net_device *dev = platform_get_drvdata(pdev);
-
-       if (dev) {
-               struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
-               netif_device_detach(dev);
-               unregister_netdev(dev);
-               if (idev)
-                       pnp_device_detach(idev);
-               /* Careful ne_drv_remove can be called twice, once from
-                * the platform_driver.remove and again when the
-                * platform_device is being removed.
-                */
-               ei_status.priv = 0;
-               free_irq(dev->irq, dev);
-               release_region(dev->base_addr, NE_IO_EXTENT);
-               free_netdev(dev);
-               platform_set_drvdata(pdev, NULL);
-       }
-       return 0;
-}
-
-/* Remove unused devices or all if true. */
-static void ne_loop_rm_unreg(int all)
-{
-       int this_dev;
-       struct platform_device *pdev;
-       for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-               pdev = pdev_ne[this_dev];
-               /* No network device == unused */
-               if (pdev && (!platform_get_drvdata(pdev) || all)) {
-                       ne_drv_remove(pdev);
-                       platform_device_unregister(pdev);
-                       pdev_ne[this_dev] = NULL;
-               }
-       }
-}
-
-#ifdef CONFIG_PM
-static int ne_drv_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       struct net_device *dev = platform_get_drvdata(pdev);
-
-       if (netif_running(dev)) {
-               struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
-               netif_device_detach(dev);
-               if (idev)
-                       pnp_stop_dev(idev);
-       }
-       return 0;
-}
-
-static int ne_drv_resume(struct platform_device *pdev)
-{
-       struct net_device *dev = platform_get_drvdata(pdev);
-
-       if (netif_running(dev)) {
-               struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
-               if (idev)
-                       pnp_start_dev(idev);
-               ne_reset_8390(dev);
-               NS8390p_init(dev, 1);
-               netif_device_attach(dev);
-       }
-       return 0;
-}
-#else
-#define ne_drv_suspend NULL
-#define ne_drv_resume NULL
-#endif
-
-static struct platform_driver ne_driver = {
-       .remove         = ne_drv_remove,
-       .suspend        = ne_drv_suspend,
-       .resume         = ne_drv_resume,
-       .driver         = {
-               .name   = DRV_NAME,
-               .owner  = THIS_MODULE,
-       },
-};
-
-static void __init ne_add_devices(void)
-{
-       int this_dev;
-       struct platform_device *pdev;
-
-       for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-               if (pdev_ne[this_dev])
-                       continue;
-               pdev = platform_device_register_simple(
-                       DRV_NAME, this_dev, NULL, 0);
-               if (IS_ERR(pdev))
-                       continue;
-               pdev_ne[this_dev] = pdev;
-       }
-}
-
-#ifdef MODULE
-int __init init_module(void)
-{
-       int retval;
-       ne_add_devices();
-       retval = platform_driver_probe(&ne_driver, ne_drv_probe);
-       if (retval) {
-               if (io[0] == 0)
-                       printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\""
-                               " value(s) for ISA cards.\n");
-               ne_loop_rm_unreg(1);
-               return retval;
-       }
-
-       /* Unregister unused platform_devices. */
-       ne_loop_rm_unreg(0);
-       return retval;
-}
-#else /* MODULE */
-static int __init ne_init(void)
-{
-       int retval = platform_driver_probe(&ne_driver, ne_drv_probe);
-
-       /* Unregister unused platform_devices. */
-       ne_loop_rm_unreg(0);
-       return retval;
-}
-module_init(ne_init);
-
-struct net_device * __init ne_probe(int unit)
-{
-       int this_dev;
-       struct net_device *dev;
-
-       /* Find an empty slot, that is no net_device and zero io port. */
-       this_dev = 0;
-       while ((pdev_ne[this_dev] && platform_get_drvdata(pdev_ne[this_dev])) ||
-               io[this_dev]) {
-               if (++this_dev == MAX_NE_CARDS)
-                       return ERR_PTR(-ENOMEM);
-       }
-
-       /* Get irq, io from kernel command line */
-       dev = alloc_eip_netdev();
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       sprintf(dev->name, "eth%d", unit);
-       netdev_boot_setup_check(dev);
-
-       io[this_dev] = dev->base_addr;
-       irq[this_dev] = dev->irq;
-       bad[this_dev] = dev->mem_end;
-
-       free_netdev(dev);
-
-       ne_add_devices();
-
-       /* return the first device found */
-       for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-               if (pdev_ne[this_dev]) {
-                       dev = platform_get_drvdata(pdev_ne[this_dev]);
-                       if (dev)
-                               return dev;
-               }
-       }
-
-       return ERR_PTR(-ENODEV);
-}
-#endif /* MODULE */
-
-static void __exit ne_exit(void)
-{
-       platform_driver_unregister(&ne_driver);
-       ne_loop_rm_unreg(1);
-}
-module_exit(ne_exit);
diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c
deleted file mode 100644 (file)
index 70cdc69..0000000
+++ /dev/null
@@ -1,799 +0,0 @@
-/* ne2.c: A NE/2 Ethernet Driver for Linux. */
-/*
-   Based on the NE2000 driver written by Donald Becker (1992-94).
-   modified by Wim Dumon (Apr 1996)
-
-   This software may be used and distributed according to the terms
-   of the GNU General Public License, incorporated herein by reference.
-
-   The author may be reached as wimpie@linux.cc.kuleuven.ac.be
-
-   Currently supported: NE/2
-   This patch was never tested on other MCA-ethernet adapters, but it
-   might work. Just give it a try and let me know if you have problems.
-   Also mail me if it really works, please!
-
-   Changelog:
-   Mon Feb  3 16:26:02 MET 1997
-   - adapted the driver to work with the 2.1.25 kernel
-   - multiple ne2 support (untested)
-   - module support (untested)
-
-   Fri Aug 28 00:18:36 CET 1998 (David Weinehall)
-   - fixed a few minor typos
-   - made the MODULE_PARM conditional (it only works with the v2.1.x kernels)
-   - fixed the module support (Now it's working...)
-
-   Mon Sep  7 19:01:44 CET 1998 (David Weinehall)
-   - added support for Arco Electronics AE/2-card (experimental)
-
-   Mon Sep 14 09:53:42 CET 1998 (David Weinehall)
-   - added support for Compex ENET-16MC/P (experimental)
-
-   Tue Sep 15 16:21:12 CET 1998 (David Weinehall, Magnus Jonsson, Tomas Ogren)
-   - Miscellaneous bugfixes
-
-   Tue Sep 19 16:21:12 CET 1998 (Magnus Jonsson)
-   - Cleanup
-
-   Wed Sep 23 14:33:34 CET 1998 (David Weinehall)
-   - Restructuring and rewriting for v2.1.x compliance
-
-   Wed Oct 14 17:19:21 CET 1998 (David Weinehall)
-   - Added code that unregisters irq and proc-info
-   - Version# bump
-
-   Mon Nov 16 15:28:23 CET 1998 (Wim Dumon)
-   - pass 'dev' as last parameter of request_irq in stead of 'NULL'
-
-   Wed Feb  7 21:24:00 CET 2001 (Alfred Arnold)
-   - added support for the D-Link DE-320CT
-
-   *    WARNING
-       -------
-       This is alpha-test software.  It is not guaranteed to work. As a
-       matter of fact, I'm quite sure there are *LOTS* of bugs in here. I
-       would like to hear from you if you use this driver, even if it works.
-       If it doesn't work, be sure to send me a mail with the problems !
-*/
-
-static const char *version = "ne2.c:v0.91 Nov 16 1998 Wim Dumon <wimpie@kotnet.org>\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/mca-legacy.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-#include <linux/jiffies.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#include "8390.h"
-
-#define DRV_NAME "ne2"
-
-/* Some defines that people can play with if so inclined. */
-
-/* Do we perform extra sanity checks on stuff ? */
-/* #define NE_SANITY_CHECK */
-
-/* Do we implement the read before write bugfix ? */
-/* #define NE_RW_BUGFIX */
-
-/* Do we have a non std. amount of memory? (in units of 256 byte pages) */
-/* #define PACKETBUF_MEMSIZE   0x40 */
-
-
-/* ---- No user-serviceable parts below ---- */
-
-#define NE_BASE         (dev->base_addr)
-#define NE_CMD         0x00
-#define NE_DATAPORT    0x10    /* NatSemi-defined port window offset. */
-#define NE_RESET       0x20    /* Issue a read to reset, a write to clear. */
-#define NE_IO_EXTENT   0x30
-
-#define NE1SM_START_PG 0x20    /* First page of TX buffer */
-#define NE1SM_STOP_PG  0x40    /* Last page +1 of RX ring */
-#define NESM_START_PG  0x40    /* First page of TX buffer */
-#define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
-
-/* From the .ADF file: */
-static unsigned int addresses[7] __initdata =
-               {0x1000, 0x2020, 0x8020, 0xa0a0, 0xb0b0, 0xc0c0, 0xc3d0};
-static int irqs[4] __initdata = {3, 4, 5, 9};
-
-/* From the D-Link ADF file: */
-static unsigned int dlink_addresses[4] __initdata =
-                {0x300, 0x320, 0x340, 0x360};
-static int dlink_irqs[8] __initdata = {3, 4, 5, 9, 10, 11, 14, 15};
-
-struct ne2_adapters_t {
-       unsigned int    id;
-       char            *name;
-};
-
-static struct ne2_adapters_t ne2_adapters[] __initdata = {
-       { 0x6354, "Arco Ethernet Adapter AE/2" },
-       { 0x70DE, "Compex ENET-16 MC/P" },
-       { 0x7154, "Novell Ethernet Adapter NE/2" },
-        { 0x56ea, "D-Link DE-320CT" },
-       { 0x0000, NULL }
-};
-
-extern int netcard_probe(struct net_device *dev);
-
-static int ne2_probe1(struct net_device *dev, int slot);
-
-static void ne_reset_8390(struct net_device *dev);
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-               int ring_page);
-static void ne_block_input(struct net_device *dev, int count,
-               struct sk_buff *skb, int ring_offset);
-static void ne_block_output(struct net_device *dev, const int count,
-               const unsigned char *buf, const int start_page);
-
-
-/*
- * special code to read the DE-320's MAC address EEPROM.  In contrast to a
- * standard NE design, this is a serial EEPROM (93C46) that has to be read
- * bit by bit.  The EEPROM cotrol port at base + 0x1e has the following
- * layout:
- *
- * Bit 0 = Data out (read from EEPROM)
- * Bit 1 = Data in  (write to EEPROM)
- * Bit 2 = Clock
- * Bit 3 = Chip Select
- * Bit 7 = ~50 kHz clock for defined delays
- *
- */
-
-static void __init dlink_put_eeprom(unsigned char value, unsigned int addr)
-{
-       int z;
-       unsigned char v1, v2;
-
-       /* write the value to the NIC EEPROM register */
-
-       outb(value, addr + 0x1e);
-
-       /* now wait the clock line to toggle twice.  Effectively, we are
-          waiting (at least) for one clock cycle */
-
-       for (z = 0; z < 2; z++) {
-               do {
-                       v1 = inb(addr + 0x1e);
-                       v2 = inb(addr + 0x1e);
-               }
-               while (!((v1 ^ v2) & 0x80));
-       }
-}
-
-static void __init dlink_send_eeprom_bit(unsigned int bit, unsigned int addr)
-{
-       /* shift data bit into correct position */
-
-       bit = bit << 1;
-
-       /* write value, keep clock line high for two cycles */
-
-       dlink_put_eeprom(0x09 | bit, addr);
-       dlink_put_eeprom(0x0d | bit, addr);
-       dlink_put_eeprom(0x0d | bit, addr);
-       dlink_put_eeprom(0x09 | bit, addr);
-}
-
-static void __init dlink_send_eeprom_word(unsigned int value, unsigned int len, unsigned int addr)
-{
-       int z;
-
-       /* adjust bits so that they are left-aligned in a 16-bit-word */
-
-       value = value << (16 - len);
-
-       /* shift bits out to the EEPROM */
-
-       for (z = 0; z < len; z++) {
-               dlink_send_eeprom_bit((value & 0x8000) >> 15, addr);
-               value = value << 1;
-       }
-}
-
-static unsigned int __init dlink_get_eeprom(unsigned int eeaddr, unsigned int addr)
-{
-       int z;
-       unsigned int value = 0;
-
-       /* pull the CS line low for a moment.  This resets the EEPROM-
-          internal logic, and makes it ready for a new command. */
-
-       dlink_put_eeprom(0x01, addr);
-       dlink_put_eeprom(0x09, addr);
-
-       /* send one start bit, read command (1 - 0), plus the address to
-           the EEPROM */
-
-       dlink_send_eeprom_word(0x0180 | (eeaddr & 0x3f), 9, addr);
-
-       /* get the data word.  We clock by sending 0s to the EEPROM, which
-          get ignored during the read process */
-
-       for (z = 0; z < 16; z++) {
-               dlink_send_eeprom_bit(0, addr);
-               value = (value << 1) | (inb(addr + 0x1e) & 0x01);
-       }
-
-       return value;
-}
-
-/*
- * Note that at boot, this probe only picks up one card at a time.
- */
-
-static int __init do_ne2_probe(struct net_device *dev)
-{
-       static int current_mca_slot = -1;
-       int i;
-       int adapter_found = 0;
-
-       /* Do not check any supplied i/o locations.
-          POS registers usually don't fail :) */
-
-       /* MCA cards have POS registers.
-          Autodetecting MCA cards is extremely simple.
-          Just search for the card. */
-
-       for(i = 0; (ne2_adapters[i].name != NULL) && !adapter_found; i++) {
-               current_mca_slot =
-                       mca_find_unused_adapter(ne2_adapters[i].id, 0);
-
-               if((current_mca_slot != MCA_NOTFOUND) && !adapter_found) {
-                       int res;
-                       mca_set_adapter_name(current_mca_slot,
-                                       ne2_adapters[i].name);
-                       mca_mark_as_used(current_mca_slot);
-
-                       res = ne2_probe1(dev, current_mca_slot);
-                       if (res)
-                               mca_mark_as_unused(current_mca_slot);
-                       return res;
-               }
-       }
-       return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init ne2_probe(int unit)
-{
-       struct net_device *dev = alloc_eip_netdev();
-       int err;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       sprintf(dev->name, "eth%d", unit);
-       netdev_boot_setup_check(dev);
-
-       err = do_ne2_probe(dev);
-       if (err)
-               goto out;
-       return dev;
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-#endif
-
-static int ne2_procinfo(char *buf, int slot, struct net_device *dev)
-{
-       int len=0;
-
-       len += sprintf(buf+len, "The NE/2 Ethernet Adapter\n" );
-       len += sprintf(buf+len, "Driver written by Wim Dumon ");
-       len += sprintf(buf+len, "<wimpie@kotnet.org>\n");
-       len += sprintf(buf+len, "Modified by ");
-       len += sprintf(buf+len, "David Weinehall <tao@acc.umu.se>\n");
-       len += sprintf(buf+len, "and by Magnus Jonsson <bigfoot@acc.umu.se>\n");
-       len += sprintf(buf+len, "Based on the original NE2000 drivers\n" );
-       len += sprintf(buf+len, "Base IO: %#x\n", (unsigned int)dev->base_addr);
-       len += sprintf(buf+len, "IRQ    : %d\n", dev->irq);
-       len += sprintf(buf+len, "HW addr : %pM\n", dev->dev_addr);
-
-       return len;
-}
-
-static int __init ne2_probe1(struct net_device *dev, int slot)
-{
-       int i, base_addr, irq, retval;
-       unsigned char POS;
-       unsigned char SA_prom[32];
-       const char *name = "NE/2";
-       int start_page, stop_page;
-       static unsigned version_printed;
-
-       if (ei_debug && version_printed++ == 0)
-               printk(version);
-
-       printk("NE/2 ethercard found in slot %d:", slot);
-
-       /* Read base IO and IRQ from the POS-registers */
-       POS = mca_read_stored_pos(slot, 2);
-       if(!(POS % 2)) {
-               printk(" disabled.\n");
-               return -ENODEV;
-       }
-
-       /* handle different POS register structure for D-Link card */
-
-       if (mca_read_stored_pos(slot, 0) == 0xea) {
-               base_addr = dlink_addresses[(POS >> 5) & 0x03];
-               irq = dlink_irqs[(POS >> 2) & 0x07];
-       }
-        else {
-               i = (POS & 0xE)>>1;
-               /* printk("Halleluja sdog, als er na de pijl een 1 staat is 1 - 1 == 0"
-               " en zou het moeten werken -> %d\n", i);
-               The above line was for remote testing, thanx to sdog ... */
-               base_addr = addresses[i - 1];
-               irq = irqs[(POS & 0x60)>>5];
-       }
-
-       if (!request_region(base_addr, NE_IO_EXTENT, DRV_NAME))
-               return -EBUSY;
-
-#ifdef DEBUG
-       printk("POS info : pos 2 = %#x ; base = %#x ; irq = %ld\n", POS,
-                       base_addr, irq);
-#endif
-
-#ifndef CRYNWR_WAY
-       /* Reset the card the way they do it in the Crynwr packet driver */
-       for (i=0; i<8; i++)
-               outb(0x0, base_addr + NE_RESET);
-       inb(base_addr + NE_RESET);
-       outb(0x21, base_addr + NE_CMD);
-       if (inb(base_addr + NE_CMD) != 0x21) {
-               printk("NE/2 adapter not responding\n");
-               retval = -ENODEV;
-               goto out;
-       }
-
-       /* In the crynwr sources they do a RAM-test here. I skip it. I suppose
-          my RAM is okay.  Suppose your memory is broken.  Then this test
-          should fail and you won't be able to use your card.  But if I do not
-          test, you won't be able to use your card, neither.  So this test
-          won't help you. */
-
-#else  /* _I_ never tested it this way .. Go ahead and try ...*/
-       /* Reset card. Who knows what dain-bramaged state it was left in. */
-       {
-               unsigned long reset_start_time = jiffies;
-
-               /* DON'T change these to inb_p/outb_p or reset will fail on
-                  clones.. */
-               outb(inb(base_addr + NE_RESET), base_addr + NE_RESET);
-
-               while ((inb_p(base_addr + EN0_ISR) & ENISR_RESET) == 0)
-                       if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
-                               printk(" not found (no reset ack).\n");
-                               retval = -ENODEV;
-                               goto out;
-                       }
-
-               outb_p(0xff, base_addr + EN0_ISR);         /* Ack all intr. */
-       }
-#endif
-
-
-       /* Read the 16 bytes of station address PROM.
-          We must first initialize registers, similar to
-          NS8390p_init(eifdev, 0).
-          We can't reliably read the SAPROM address without this.
-          (I learned the hard way!). */
-       {
-               struct {
-                       unsigned char value, offset;
-               } program_seq[] = {
-                                               /* Select page 0 */
-                       {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD},
-                       {0x49,  EN0_DCFG},  /* Set WORD-wide (0x49) access. */
-                       {0x00,  EN0_RCNTLO},  /* Clear the count regs. */
-                       {0x00,  EN0_RCNTHI},
-                       {0x00,  EN0_IMR},  /* Mask completion irq. */
-                       {0xFF,  EN0_ISR},
-                       {E8390_RXOFF, EN0_RXCR},  /* 0x20  Set to monitor */
-                       {E8390_TXOFF, EN0_TXCR},  /* 0x02  and loopback mode. */
-                       {32,    EN0_RCNTLO},
-                       {0x00,  EN0_RCNTHI},
-                       {0x00,  EN0_RSARLO},  /* DMA starting at 0x0000. */
-                       {0x00,  EN0_RSARHI},
-                       {E8390_RREAD+E8390_START, E8390_CMD},
-               };
-
-               for (i = 0; i < ARRAY_SIZE(program_seq); i++)
-                       outb_p(program_seq[i].value, base_addr +
-                               program_seq[i].offset);
-
-       }
-       for(i = 0; i < 6 /*sizeof(SA_prom)*/; i+=1) {
-               SA_prom[i] = inb(base_addr + NE_DATAPORT);
-       }
-
-       /* I don't know whether the previous sequence includes the general
-           board reset procedure, so better don't omit it and just overwrite
-           the garbage read from a DE-320 with correct stuff. */
-
-       if (mca_read_stored_pos(slot, 0) == 0xea) {
-               unsigned int v;
-
-               for (i = 0; i < 3; i++) {
-                       v = dlink_get_eeprom(i, base_addr);
-                       SA_prom[(i << 1)    ] = v & 0xff;
-                       SA_prom[(i << 1) + 1] = (v >> 8) & 0xff;
-               }
-       }
-
-       start_page = NESM_START_PG;
-       stop_page = NESM_STOP_PG;
-
-       dev->irq=irq;
-
-       /* Snarf the interrupt now.  There's no point in waiting since we cannot
-          share and the board will usually be enabled. */
-       retval = request_irq(dev->irq, eip_interrupt, 0, DRV_NAME, dev);
-       if (retval) {
-               printk (" unable to get IRQ %d (irqval=%d).\n",
-                               dev->irq, retval);
-               goto out;
-       }
-
-       dev->base_addr = base_addr;
-
-       for(i = 0; i < ETHER_ADDR_LEN; i++)
-               dev->dev_addr[i] = SA_prom[i];
-
-       printk(" %pM\n", dev->dev_addr);
-
-       printk("%s: %s found at %#x, using IRQ %d.\n",
-                       dev->name, name, base_addr, dev->irq);
-
-       mca_set_adapter_procfn(slot, (MCA_ProcFn) ne2_procinfo, dev);
-
-       ei_status.name = name;
-       ei_status.tx_start_page = start_page;
-       ei_status.stop_page = stop_page;
-       ei_status.word16 = (2 == 2);
-
-       ei_status.rx_start_page = start_page + TX_PAGES;
-#ifdef PACKETBUF_MEMSIZE
-       /* Allow the packet buffer size to be overridden by know-it-alls. */
-       ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
-#endif
-
-       ei_status.reset_8390 = &ne_reset_8390;
-       ei_status.block_input = &ne_block_input;
-       ei_status.block_output = &ne_block_output;
-       ei_status.get_8390_hdr = &ne_get_8390_hdr;
-
-       ei_status.priv = slot;
-
-       dev->netdev_ops = &eip_netdev_ops;
-       NS8390p_init(dev, 0);
-
-       retval = register_netdev(dev);
-       if (retval)
-               goto out1;
-       return 0;
-out1:
-       mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
-       free_irq(dev->irq, dev);
-out:
-       release_region(base_addr, NE_IO_EXTENT);
-       return retval;
-}
-
-/* Hard reset the card.  This used to pause for the same period that a
-   8390 reset command required, but that shouldn't be necessary. */
-static void ne_reset_8390(struct net_device *dev)
-{
-       unsigned long reset_start_time = jiffies;
-
-       if (ei_debug > 1)
-               printk("resetting the 8390 t=%ld...", jiffies);
-
-       /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
-       outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
-       ei_status.txing = 0;
-       ei_status.dmaing = 0;
-
-       /* This check _should_not_ be necessary, omit eventually. */
-       while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
-               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
-                       printk("%s: ne_reset_8390() did not complete.\n",
-                                       dev->name);
-                       break;
-               }
-       outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
-   we don't need to be concerned with ring wrap as the header will be at
-   the start of a page, so we optimize accordingly. */
-
-static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-               int ring_page)
-{
-
-       int nic_base = dev->base_addr;
-
-       /* This *shouldn't* happen.
-          If it does, it's the last thing you'll see */
-       if (ei_status.dmaing) {
-               printk("%s: DMAing conflict in ne_get_8390_hdr "
-                               "[DMAstat:%d][irqlock:%d].\n",
-                               dev->name, ei_status.dmaing, ei_status.irqlock);
-               return;
-       }
-
-       ei_status.dmaing |= 0x01;
-       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-       outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
-       outb_p(0, nic_base + EN0_RCNTHI);
-       outb_p(0, nic_base + EN0_RSARLO);               /* On page boundary */
-       outb_p(ring_page, nic_base + EN0_RSARHI);
-       outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
-       if (ei_status.word16)
-               insw(NE_BASE + NE_DATAPORT, hdr,
-                               sizeof(struct e8390_pkt_hdr)>>1);
-       else
-               insb(NE_BASE + NE_DATAPORT, hdr,
-                               sizeof(struct e8390_pkt_hdr));
-
-       outb_p(ENISR_RDC, nic_base + EN0_ISR);  /* Ack intr. */
-       ei_status.dmaing &= ~0x01;
-}
-
-/* Block input and output, similar to the Crynwr packet driver.  If you
-   are porting to a new ethercard, look at the packet driver source for
-   hints. The NEx000 doesn't share the on-board packet memory -- you have
-   to put the packet out through the "remote DMA" dataport using outb. */
-
-static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb,
-               int ring_offset)
-{
-#ifdef NE_SANITY_CHECK
-       int xfer_count = count;
-#endif
-       int nic_base = dev->base_addr;
-       char *buf = skb->data;
-
-       /* This *shouldn't* happen.
-          If it does, it's the last thing you'll see */
-       if (ei_status.dmaing) {
-               printk("%s: DMAing conflict in ne_block_input "
-                               "[DMAstat:%d][irqlock:%d].\n",
-                               dev->name, ei_status.dmaing, ei_status.irqlock);
-               return;
-       }
-       ei_status.dmaing |= 0x01;
-       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-       outb_p(count & 0xff, nic_base + EN0_RCNTLO);
-       outb_p(count >> 8, nic_base + EN0_RCNTHI);
-       outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
-       outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
-       outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-       if (ei_status.word16) {
-               insw(NE_BASE + NE_DATAPORT,buf,count>>1);
-               if (count & 0x01) {
-                       buf[count-1] = inb(NE_BASE + NE_DATAPORT);
-#ifdef NE_SANITY_CHECK
-                       xfer_count++;
-#endif
-               }
-       } else {
-               insb(NE_BASE + NE_DATAPORT, buf, count);
-       }
-
-#ifdef NE_SANITY_CHECK
-       /* This was for the ALPHA version only, but enough people have
-          been encountering problems so it is still here.  If you see
-          this message you either 1) have a slightly incompatible clone
-          or 2) have noise/speed problems with your bus. */
-       if (ei_debug > 1) {     /* DMA termination address check... */
-               int addr, tries = 20;
-               do {
-                       /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
-                          -- it's broken for Rx on some cards! */
-                       int high = inb_p(nic_base + EN0_RSARHI);
-                       int low = inb_p(nic_base + EN0_RSARLO);
-                       addr = (high << 8) + low;
-                       if (((ring_offset + xfer_count) & 0xff) == low)
-                               break;
-               } while (--tries > 0);
-               if (tries <= 0)
-                       printk("%s: RX transfer address mismatch,"
-                               "%#4.4x (expected) vs. %#4.4x (actual).\n",
-                               dev->name, ring_offset + xfer_count, addr);
-       }
-#endif
-       outb_p(ENISR_RDC, nic_base + EN0_ISR);  /* Ack intr. */
-       ei_status.dmaing &= ~0x01;
-}
-
-static void ne_block_output(struct net_device *dev, int count,
-               const unsigned char *buf, const int start_page)
-{
-       int nic_base = NE_BASE;
-       unsigned long dma_start;
-#ifdef NE_SANITY_CHECK
-       int retries = 0;
-#endif
-
-       /* Round the count up for word writes. Do we need to do this?
-          What effect will an odd byte count have on the 8390?
-          I should check someday. */
-       if (ei_status.word16 && (count & 0x01))
-               count++;
-
-       /* This *shouldn't* happen.
-          If it does, it's the last thing you'll see */
-       if (ei_status.dmaing) {
-               printk("%s: DMAing conflict in ne_block_output."
-                               "[DMAstat:%d][irqlock:%d]\n",
-                               dev->name, ei_status.dmaing, ei_status.irqlock);
-               return;
-       }
-       ei_status.dmaing |= 0x01;
-       /* We should already be in page 0, but to be safe... */
-       outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
-#ifdef NE_SANITY_CHECK
-retry:
-#endif
-
-#ifdef NE8390_RW_BUGFIX
-       /* Handle the read-before-write bug the same way as the
-          Crynwr packet driver -- the NatSemi method doesn't work.
-          Actually this doesn't always work either, but if you have
-          problems with your NEx000 this is better than nothing! */
-       outb_p(0x42, nic_base + EN0_RCNTLO);
-       outb_p(0x00, nic_base + EN0_RCNTHI);
-       outb_p(0x42, nic_base + EN0_RSARLO);
-       outb_p(0x00, nic_base + EN0_RSARHI);
-       outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-       /* Make certain that the dummy read has occurred. */
-       SLOW_DOWN_IO;
-       SLOW_DOWN_IO;
-       SLOW_DOWN_IO;
-#endif
-
-       outb_p(ENISR_RDC, nic_base + EN0_ISR);
-
-       /* Now the normal output. */
-       outb_p(count & 0xff, nic_base + EN0_RCNTLO);
-       outb_p(count >> 8,   nic_base + EN0_RCNTHI);
-       outb_p(0x00, nic_base + EN0_RSARLO);
-       outb_p(start_page, nic_base + EN0_RSARHI);
-
-       outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
-       if (ei_status.word16) {
-               outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
-       } else {
-               outsb(NE_BASE + NE_DATAPORT, buf, count);
-       }
-
-       dma_start = jiffies;
-
-#ifdef NE_SANITY_CHECK
-       /* This was for the ALPHA version only, but enough people have
-          been encountering problems so it is still here. */
-
-       if (ei_debug > 1) {             /* DMA termination address check... */
-               int addr, tries = 20;
-               do {
-                       int high = inb_p(nic_base + EN0_RSARHI);
-                       int low = inb_p(nic_base + EN0_RSARLO);
-                       addr = (high << 8) + low;
-                       if ((start_page << 8) + count == addr)
-                               break;
-               } while (--tries > 0);
-               if (tries <= 0) {
-                       printk("%s: Tx packet transfer address mismatch,"
-                                       "%#4.4x (expected) vs. %#4.4x (actual).\n",
-                                       dev->name, (start_page << 8) + count, addr);
-                       if (retries++ == 0)
-                               goto retry;
-               }
-       }
-#endif
-
-       while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
-               if (time_after(jiffies, dma_start + 2*HZ/100)) {                /* 20ms */
-                       printk("%s: timeout waiting for Tx RDC.\n", dev->name);
-                       ne_reset_8390(dev);
-                       NS8390p_init(dev, 1);
-                       break;
-               }
-
-       outb_p(ENISR_RDC, nic_base + EN0_ISR);  /* Ack intr. */
-       ei_status.dmaing &= ~0x01;
-}
-
-
-#ifdef MODULE
-#define MAX_NE_CARDS   4       /* Max number of NE cards per module */
-static struct net_device *dev_ne[MAX_NE_CARDS];
-static int io[MAX_NE_CARDS];
-static int irq[MAX_NE_CARDS];
-static int bad[MAX_NE_CARDS];  /* 0xbad = bad sig or no reset ack */
-MODULE_LICENSE("GPL");
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(bad, int, NULL, 0);
-MODULE_PARM_DESC(io, "(ignored)");
-MODULE_PARM_DESC(irq, "(ignored)");
-MODULE_PARM_DESC(bad, "(ignored)");
-
-/* Module code fixed by David Weinehall */
-
-int __init init_module(void)
-{
-       struct net_device *dev;
-       int this_dev, found = 0;
-
-       for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-               dev = alloc_eip_netdev();
-               if (!dev)
-                       break;
-               dev->irq = irq[this_dev];
-               dev->mem_end = bad[this_dev];
-               dev->base_addr = io[this_dev];
-               if (do_ne2_probe(dev) == 0) {
-                       dev_ne[found++] = dev;
-                       continue;
-               }
-               free_netdev(dev);
-               break;
-       }
-       if (found)
-               return 0;
-       printk(KERN_WARNING "ne2.c: No NE/2 card found\n");
-       return -ENXIO;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-       mca_mark_as_unused(ei_status.priv);
-       mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
-       free_irq(dev->irq, dev);
-       release_region(dev->base_addr, NE_IO_EXTENT);
-}
-
-void __exit cleanup_module(void)
-{
-       int this_dev;
-
-       for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-               struct net_device *dev = dev_ne[this_dev];
-               if (dev) {
-                       unregister_netdev(dev);
-                       cleanup_card(dev);
-                       free_netdev(dev);
-               }
-       }
-}
-#endif /* MODULE */
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
deleted file mode 100644 (file)
index 3c333cb..0000000
+++ /dev/null
@@ -1,726 +0,0 @@
-/* ne2k-pci.c: A NE2000 clone on PCI bus driver for Linux. */
-/*
-       A Linux device driver for PCI NE2000 clones.
-
-       Authors and other copyright holders:
-       1992-2000 by Donald Becker, NE2000 core and various modifications.
-       1995-1998 by Paul Gortmaker, core modifications and PCI support.
-       Copyright 1993 assigned to the United States Government as represented
-       by the Director, National Security Agency.
-
-       This software may be used and distributed according to the terms of
-       the GNU General Public License (GPL), incorporated herein by reference.
-       Drivers based on or derived from this code fall under the GPL and must
-       retain the authorship, copyright and license notice.  This file is not
-       a complete program and may only be used when the entire operating
-       system is licensed under the GPL.
-
-       The author may be reached as becker@scyld.com, or C/O
-       Scyld Computing Corporation
-       410 Severn Ave., Suite 210
-       Annapolis MD 21403
-
-       Issues remaining:
-       People are making PCI ne2000 clones! Oh the horror, the horror...
-       Limited full-duplex support.
-*/
-
-#define DRV_NAME       "ne2k-pci"
-#define DRV_VERSION    "1.03"
-#define DRV_RELDATE    "9/22/2003"
-
-
-/* The user-configurable values.
-   These may be modified when a driver module is loaded.*/
-
-static int debug = 1;                  /* 1 normal messages, 0 quiet .. 7 verbose. */
-
-#define MAX_UNITS 8                            /* More are supported, limit only on options */
-/* Used to pass the full-duplex flag, etc. */
-static int full_duplex[MAX_UNITS];
-static int options[MAX_UNITS];
-
-/* Force a non std. amount of memory.  Units are 256 byte pages. */
-/* #define PACKETBUF_MEMSIZE   0x40 */
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/ethtool.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-
-#include "8390.h"
-
-/* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
-       KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE
-       " D. Becker/P. Gortmaker\n";
-
-#if defined(__powerpc__)
-#define inl_le(addr)  le32_to_cpu(inl(addr))
-#define inw_le(addr)  le16_to_cpu(inw(addr))
-#endif
-
-#define PFX DRV_NAME ": "
-
-MODULE_AUTHOR("Donald Becker / Paul Gortmaker");
-MODULE_DESCRIPTION("PCI NE2000 clone driver");
-MODULE_LICENSE("GPL");
-
-module_param(debug, int, 0);
-module_param_array(options, int, NULL, 0);
-module_param_array(full_duplex, int, NULL, 0);
-MODULE_PARM_DESC(debug, "debug level (1-2)");
-MODULE_PARM_DESC(options, "Bit 5: full duplex");
-MODULE_PARM_DESC(full_duplex, "full duplex setting(s) (1)");
-
-/* Some defines that people can play with if so inclined. */
-
-/* Use 32 bit data-movement operations instead of 16 bit. */
-#define USE_LONGIO
-
-/* Do we implement the read before write bugfix ? */
-/* #define NE_RW_BUGFIX */
-
-/* Flags.  We rename an existing ei_status field to store flags! */
-/* Thus only the low 8 bits are usable for non-init-time flags. */
-#define ne2k_flags reg0
-enum {
-       ONLY_16BIT_IO=8, ONLY_32BIT_IO=4,       /* Chip can do only 16/32-bit xfers. */
-       FORCE_FDX=0x20,                                         /* User override. */
-       REALTEK_FDX=0x40, HOLTEK_FDX=0x80,
-       STOP_PG_0x60=0x100,
-};
-
-enum ne2k_pci_chipsets {
-       CH_RealTek_RTL_8029 = 0,
-       CH_Winbond_89C940,
-       CH_Compex_RL2000,
-       CH_KTI_ET32P2,
-       CH_NetVin_NV5000SC,
-       CH_Via_86C926,
-       CH_SureCom_NE34,
-       CH_Winbond_W89C940F,
-       CH_Holtek_HT80232,
-       CH_Holtek_HT80229,
-       CH_Winbond_89C940_8c4a,
-};
-
-
-static struct {
-       char *name;
-       int flags;
-} pci_clone_list[] __devinitdata = {
-       {"RealTek RTL-8029", REALTEK_FDX},
-       {"Winbond 89C940", 0},
-       {"Compex RL2000", 0},
-       {"KTI ET32P2", 0},
-       {"NetVin NV5000SC", 0},
-       {"Via 86C926", ONLY_16BIT_IO},
-       {"SureCom NE34", 0},
-       {"Winbond W89C940F", 0},
-       {"Holtek HT80232", ONLY_16BIT_IO | HOLTEK_FDX},
-       {"Holtek HT80229", ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60 },
-       {"Winbond W89C940(misprogrammed)", 0},
-       {NULL,}
-};
-
-
-static DEFINE_PCI_DEVICE_TABLE(ne2k_pci_tbl) = {
-       { 0x10ec, 0x8029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RealTek_RTL_8029 },
-       { 0x1050, 0x0940, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_89C940 },
-       { 0x11f6, 0x1401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Compex_RL2000 },
-       { 0x8e2e, 0x3000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_KTI_ET32P2 },
-       { 0x4a14, 0x5000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_NetVin_NV5000SC },
-       { 0x1106, 0x0926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Via_86C926 },
-       { 0x10bd, 0x0e34, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_SureCom_NE34 },
-       { 0x1050, 0x5a5a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_W89C940F },
-       { 0x12c3, 0x0058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80232 },
-       { 0x12c3, 0x5598, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80229 },
-       { 0x8c4a, 0x1980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_89C940_8c4a },
-       { 0, }
-};
-MODULE_DEVICE_TABLE(pci, ne2k_pci_tbl);
-
-
-/* ---- No user-serviceable parts below ---- */
-
-#define NE_BASE         (dev->base_addr)
-#define NE_CMD         0x00
-#define NE_DATAPORT    0x10    /* NatSemi-defined port window offset. */
-#define NE_RESET       0x1f    /* Issue a read to reset, a write to clear. */
-#define NE_IO_EXTENT   0x20
-
-#define NESM_START_PG  0x40    /* First page of TX buffer */
-#define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
-
-
-static int ne2k_pci_open(struct net_device *dev);
-static int ne2k_pci_close(struct net_device *dev);
-
-static void ne2k_pci_reset_8390(struct net_device *dev);
-static void ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                         int ring_page);
-static void ne2k_pci_block_input(struct net_device *dev, int count,
-                         struct sk_buff *skb, int ring_offset);
-static void ne2k_pci_block_output(struct net_device *dev, const int count,
-               const unsigned char *buf, const int start_page);
-static const struct ethtool_ops ne2k_pci_ethtool_ops;
-
-
-
-/* There is no room in the standard 8390 structure for extra info we need,
-   so we build a meta/outer-wrapper structure.. */
-struct ne2k_pci_card {
-       struct net_device *dev;
-       struct pci_dev *pci_dev;
-};
-
-
-
-/*
-  NEx000-clone boards have a Station Address (SA) PROM (SAPROM) in the packet
-  buffer memory space.  By-the-spec NE2000 clones have 0x57,0x57 in bytes
-  0x0e,0x0f of the SAPROM, while other supposed NE2000 clones must be
-  detected by their SA prefix.
-
-  Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
-  mode results in doubled values, which can be detected and compensated for.
-
-  The probe is also responsible for initializing the card and filling
-  in the 'dev' and 'ei_status' structures.
-*/
-
-static const struct net_device_ops ne2k_netdev_ops = {
-       .ndo_open               = ne2k_pci_open,
-       .ndo_stop               = ne2k_pci_close,
-       .ndo_start_xmit         = ei_start_xmit,
-       .ndo_tx_timeout         = ei_tx_timeout,
-       .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller = ei_poll,
-#endif
-};
-
-static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
-                                    const struct pci_device_id *ent)
-{
-       struct net_device *dev;
-       int i;
-       unsigned char SA_prom[32];
-       int start_page, stop_page;
-       int irq, reg0, chip_idx = ent->driver_data;
-       static unsigned int fnd_cnt;
-       long ioaddr;
-       int flags = pci_clone_list[chip_idx].flags;
-
-/* when built into the kernel, we only print version if device is found */
-#ifndef MODULE
-       static int printed_version;
-       if (!printed_version++)
-               printk(version);
-#endif
-
-       fnd_cnt++;
-
-       i = pci_enable_device (pdev);
-       if (i)
-               return i;
-
-       ioaddr = pci_resource_start (pdev, 0);
-       irq = pdev->irq;
-
-       if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_IO) == 0)) {
-               dev_err(&pdev->dev, "no I/O resource at PCI BAR #0\n");
-               return -ENODEV;
-       }
-
-       if (request_region (ioaddr, NE_IO_EXTENT, DRV_NAME) == NULL) {
-               dev_err(&pdev->dev, "I/O resource 0x%x @ 0x%lx busy\n",
-                       NE_IO_EXTENT, ioaddr);
-               return -EBUSY;
-       }
-
-       reg0 = inb(ioaddr);
-       if (reg0 == 0xFF)
-               goto err_out_free_res;
-
-       /* Do a preliminary verification that we have a 8390. */
-       {
-               int regd;
-               outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
-               regd = inb(ioaddr + 0x0d);
-               outb(0xff, ioaddr + 0x0d);
-               outb(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
-               inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
-               if (inb(ioaddr + EN0_COUNTER0) != 0) {
-                       outb(reg0, ioaddr);
-                       outb(regd, ioaddr + 0x0d);      /* Restore the old values. */
-                       goto err_out_free_res;
-               }
-       }
-
-       /* Allocate net_device, dev->priv; fill in 8390 specific dev fields. */
-       dev = alloc_ei_netdev();
-       if (!dev) {
-               dev_err(&pdev->dev, "cannot allocate ethernet device\n");
-               goto err_out_free_res;
-       }
-       dev->netdev_ops = &ne2k_netdev_ops;
-
-       SET_NETDEV_DEV(dev, &pdev->dev);
-
-       /* Reset card. Who knows what dain-bramaged state it was left in. */
-       {
-               unsigned long reset_start_time = jiffies;
-
-               outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
-
-               /* This looks like a horrible timing loop, but it should never take
-                  more than a few cycles.
-               */
-               while ((inb(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
-                       /* Limit wait: '2' avoids jiffy roll-over. */
-                       if (jiffies - reset_start_time > 2) {
-                               dev_err(&pdev->dev,
-                                       "Card failure (no reset ack).\n");
-                               goto err_out_free_netdev;
-                       }
-
-               outb(0xff, ioaddr + EN0_ISR);           /* Ack all intr. */
-       }
-
-       /* Read the 16 bytes of station address PROM.
-          We must first initialize registers, similar to NS8390_init(eifdev, 0).
-          We can't reliably read the SAPROM address without this.
-          (I learned the hard way!). */
-       {
-               struct {unsigned char value, offset; } program_seq[] = {
-                       {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
-                       {0x49,  EN0_DCFG},      /* Set word-wide access. */
-                       {0x00,  EN0_RCNTLO},    /* Clear the count regs. */
-                       {0x00,  EN0_RCNTHI},
-                       {0x00,  EN0_IMR},       /* Mask completion irq. */
-                       {0xFF,  EN0_ISR},
-                       {E8390_RXOFF, EN0_RXCR},        /* 0x20  Set to monitor */
-                       {E8390_TXOFF, EN0_TXCR},        /* 0x02  and loopback mode. */
-                       {32,    EN0_RCNTLO},
-                       {0x00,  EN0_RCNTHI},
-                       {0x00,  EN0_RSARLO},    /* DMA starting at 0x0000. */
-                       {0x00,  EN0_RSARHI},
-                       {E8390_RREAD+E8390_START, E8390_CMD},
-               };
-               for (i = 0; i < ARRAY_SIZE(program_seq); i++)
-                       outb(program_seq[i].value, ioaddr + program_seq[i].offset);
-
-       }
-
-       /* Note: all PCI cards have at least 16 bit access, so we don't have
-          to check for 8 bit cards.  Most cards permit 32 bit access. */
-       if (flags & ONLY_32BIT_IO) {
-               for (i = 0; i < 4 ; i++)
-                       ((u32 *)SA_prom)[i] = le32_to_cpu(inl(ioaddr + NE_DATAPORT));
-       } else
-               for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++)
-                       SA_prom[i] = inb(ioaddr + NE_DATAPORT);
-
-       /* We always set the 8390 registers for word mode. */
-       outb(0x49, ioaddr + EN0_DCFG);
-       start_page = NESM_START_PG;
-
-       stop_page = flags & STOP_PG_0x60 ? 0x60 : NESM_STOP_PG;
-
-       /* Set up the rest of the parameters. */
-       dev->irq = irq;
-       dev->base_addr = ioaddr;
-       pci_set_drvdata(pdev, dev);
-
-       ei_status.name = pci_clone_list[chip_idx].name;
-       ei_status.tx_start_page = start_page;
-       ei_status.stop_page = stop_page;
-       ei_status.word16 = 1;
-       ei_status.ne2k_flags = flags;
-       if (fnd_cnt < MAX_UNITS) {
-               if (full_duplex[fnd_cnt] > 0  ||  (options[fnd_cnt] & FORCE_FDX))
-                       ei_status.ne2k_flags |= FORCE_FDX;
-       }
-
-       ei_status.rx_start_page = start_page + TX_PAGES;
-#ifdef PACKETBUF_MEMSIZE
-       /* Allow the packet buffer size to be overridden by know-it-alls. */
-       ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
-#endif
-
-       ei_status.reset_8390 = &ne2k_pci_reset_8390;
-       ei_status.block_input = &ne2k_pci_block_input;
-       ei_status.block_output = &ne2k_pci_block_output;
-       ei_status.get_8390_hdr = &ne2k_pci_get_8390_hdr;
-       ei_status.priv = (unsigned long) pdev;
-
-       dev->ethtool_ops = &ne2k_pci_ethtool_ops;
-       NS8390_init(dev, 0);
-
-       memcpy(dev->dev_addr, SA_prom, dev->addr_len);
-       memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
-       i = register_netdev(dev);
-       if (i)
-               goto err_out_free_netdev;
-
-       printk("%s: %s found at %#lx, IRQ %d, %pM.\n",
-              dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq,
-              dev->dev_addr);
-
-       return 0;
-
-err_out_free_netdev:
-       free_netdev (dev);
-err_out_free_res:
-       release_region (ioaddr, NE_IO_EXTENT);
-       pci_set_drvdata (pdev, NULL);
-       return -ENODEV;
-
-}
-
-/*
- * Magic incantation sequence for full duplex on the supported cards.
- */
-static inline int set_realtek_fdx(struct net_device *dev)
-{
-       long ioaddr = dev->base_addr;
-
-       outb(0xC0 + E8390_NODMA, ioaddr + NE_CMD); /* Page 3 */
-       outb(0xC0, ioaddr + 0x01); /* Enable writes to CONFIG3 */
-       outb(0x40, ioaddr + 0x06); /* Enable full duplex */
-       outb(0x00, ioaddr + 0x01); /* Disable writes to CONFIG3 */
-       outb(E8390_PAGE0 + E8390_NODMA, ioaddr + NE_CMD); /* Page 0 */
-       return 0;
-}
-
-static inline int set_holtek_fdx(struct net_device *dev)
-{
-       long ioaddr = dev->base_addr;
-
-       outb(inb(ioaddr + 0x20) | 0x80, ioaddr + 0x20);
-       return 0;
-}
-
-static int ne2k_pci_set_fdx(struct net_device *dev)
-{
-       if (ei_status.ne2k_flags & REALTEK_FDX)
-               return set_realtek_fdx(dev);
-       else if (ei_status.ne2k_flags & HOLTEK_FDX)
-               return set_holtek_fdx(dev);
-
-       return -EOPNOTSUPP;
-}
-
-static int ne2k_pci_open(struct net_device *dev)
-{
-       int ret = request_irq(dev->irq, ei_interrupt, IRQF_SHARED, dev->name, dev);
-       if (ret)
-               return ret;
-
-       if (ei_status.ne2k_flags & FORCE_FDX)
-               ne2k_pci_set_fdx(dev);
-
-       ei_open(dev);
-       return 0;
-}
-
-static int ne2k_pci_close(struct net_device *dev)
-{
-       ei_close(dev);
-       free_irq(dev->irq, dev);
-       return 0;
-}
-
-/* Hard reset the card.  This used to pause for the same period that a
-   8390 reset command required, but that shouldn't be necessary. */
-static void ne2k_pci_reset_8390(struct net_device *dev)
-{
-       unsigned long reset_start_time = jiffies;
-
-       if (debug > 1) printk("%s: Resetting the 8390 t=%ld...",
-                                                 dev->name, jiffies);
-
-       outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
-       ei_status.txing = 0;
-       ei_status.dmaing = 0;
-
-       /* This check _should_not_ be necessary, omit eventually. */
-       while ((inb(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
-               if (jiffies - reset_start_time > 2) {
-                       printk("%s: ne2k_pci_reset_8390() did not complete.\n", dev->name);
-                       break;
-               }
-       outb(ENISR_RESET, NE_BASE + EN0_ISR);   /* Ack intr. */
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
-   we don't need to be concerned with ring wrap as the header will be at
-   the start of a page, so we optimize accordingly. */
-
-static void ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-
-       long nic_base = dev->base_addr;
-
-       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-       if (ei_status.dmaing) {
-               printk("%s: DMAing conflict in ne2k_pci_get_8390_hdr "
-                          "[DMAstat:%d][irqlock:%d].\n",
-                          dev->name, ei_status.dmaing, ei_status.irqlock);
-               return;
-       }
-
-       ei_status.dmaing |= 0x01;
-       outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-       outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
-       outb(0, nic_base + EN0_RCNTHI);
-       outb(0, nic_base + EN0_RSARLO);         /* On page boundary */
-       outb(ring_page, nic_base + EN0_RSARHI);
-       outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
-       if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
-               insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
-       } else {
-               *(u32*)hdr = le32_to_cpu(inl(NE_BASE + NE_DATAPORT));
-               le16_to_cpus(&hdr->count);
-       }
-
-       outb(ENISR_RDC, nic_base + EN0_ISR);    /* Ack intr. */
-       ei_status.dmaing &= ~0x01;
-}
-
-/* Block input and output, similar to the Crynwr packet driver.  If you
-   are porting to a new ethercard, look at the packet driver source for hints.
-   The NEx000 doesn't share the on-board packet memory -- you have to put
-   the packet out through the "remote DMA" dataport using outb. */
-
-static void ne2k_pci_block_input(struct net_device *dev, int count,
-                                struct sk_buff *skb, int ring_offset)
-{
-       long nic_base = dev->base_addr;
-       char *buf = skb->data;
-
-       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-       if (ei_status.dmaing) {
-               printk("%s: DMAing conflict in ne2k_pci_block_input "
-                          "[DMAstat:%d][irqlock:%d].\n",
-                          dev->name, ei_status.dmaing, ei_status.irqlock);
-               return;
-       }
-       ei_status.dmaing |= 0x01;
-       if (ei_status.ne2k_flags & ONLY_32BIT_IO)
-               count = (count + 3) & 0xFFFC;
-       outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-       outb(count & 0xff, nic_base + EN0_RCNTLO);
-       outb(count >> 8, nic_base + EN0_RCNTHI);
-       outb(ring_offset & 0xff, nic_base + EN0_RSARLO);
-       outb(ring_offset >> 8, nic_base + EN0_RSARHI);
-       outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
-       if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
-               insw(NE_BASE + NE_DATAPORT,buf,count>>1);
-               if (count & 0x01) {
-                       buf[count-1] = inb(NE_BASE + NE_DATAPORT);
-               }
-       } else {
-               insl(NE_BASE + NE_DATAPORT, buf, count>>2);
-               if (count & 3) {
-                       buf += count & ~3;
-                       if (count & 2) {
-                               __le16 *b = (__le16 *)buf;
-
-                               *b++ = cpu_to_le16(inw(NE_BASE + NE_DATAPORT));
-                               buf = (char *)b;
-                       }
-                       if (count & 1)
-                               *buf = inb(NE_BASE + NE_DATAPORT);
-               }
-       }
-
-       outb(ENISR_RDC, nic_base + EN0_ISR);    /* Ack intr. */
-       ei_status.dmaing &= ~0x01;
-}
-
-static void ne2k_pci_block_output(struct net_device *dev, int count,
-                                 const unsigned char *buf, const int start_page)
-{
-       long nic_base = NE_BASE;
-       unsigned long dma_start;
-
-       /* On little-endian it's always safe to round the count up for
-          word writes. */
-       if (ei_status.ne2k_flags & ONLY_32BIT_IO)
-               count = (count + 3) & 0xFFFC;
-       else
-               if (count & 0x01)
-                       count++;
-
-       /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-       if (ei_status.dmaing) {
-               printk("%s: DMAing conflict in ne2k_pci_block_output."
-                          "[DMAstat:%d][irqlock:%d]\n",
-                          dev->name, ei_status.dmaing, ei_status.irqlock);
-               return;
-       }
-       ei_status.dmaing |= 0x01;
-       /* We should already be in page 0, but to be safe... */
-       outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
-#ifdef NE8390_RW_BUGFIX
-       /* Handle the read-before-write bug the same way as the
-          Crynwr packet driver -- the NatSemi method doesn't work.
-          Actually this doesn't always work either, but if you have
-          problems with your NEx000 this is better than nothing! */
-       outb(0x42, nic_base + EN0_RCNTLO);
-       outb(0x00, nic_base + EN0_RCNTHI);
-       outb(0x42, nic_base + EN0_RSARLO);
-       outb(0x00, nic_base + EN0_RSARHI);
-       outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-#endif
-       outb(ENISR_RDC, nic_base + EN0_ISR);
-
-   /* Now the normal output. */
-       outb(count & 0xff, nic_base + EN0_RCNTLO);
-       outb(count >> 8,   nic_base + EN0_RCNTHI);
-       outb(0x00, nic_base + EN0_RSARLO);
-       outb(start_page, nic_base + EN0_RSARHI);
-       outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
-       if (ei_status.ne2k_flags & ONLY_16BIT_IO) {
-               outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
-       } else {
-               outsl(NE_BASE + NE_DATAPORT, buf, count>>2);
-               if (count & 3) {
-                       buf += count & ~3;
-                       if (count & 2) {
-                               __le16 *b = (__le16 *)buf;
-
-                               outw(le16_to_cpu(*b++), NE_BASE + NE_DATAPORT);
-                               buf = (char *)b;
-                       }
-               }
-       }
-
-       dma_start = jiffies;
-
-       while ((inb(nic_base + EN0_ISR) & ENISR_RDC) == 0)
-               if (jiffies - dma_start > 2) {                  /* Avoid clock roll-over. */
-                       printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
-                       ne2k_pci_reset_8390(dev);
-                       NS8390_init(dev,1);
-                       break;
-               }
-
-       outb(ENISR_RDC, nic_base + EN0_ISR);    /* Ack intr. */
-       ei_status.dmaing &= ~0x01;
-}
-
-static void ne2k_pci_get_drvinfo(struct net_device *dev,
-                                struct ethtool_drvinfo *info)
-{
-       struct ei_device *ei = netdev_priv(dev);
-       struct pci_dev *pci_dev = (struct pci_dev *) ei->priv;
-
-       strcpy(info->driver, DRV_NAME);
-       strcpy(info->version, DRV_VERSION);
-       strcpy(info->bus_info, pci_name(pci_dev));
-}
-
-static const struct ethtool_ops ne2k_pci_ethtool_ops = {
-       .get_drvinfo            = ne2k_pci_get_drvinfo,
-};
-
-static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
-{
-       struct net_device *dev = pci_get_drvdata(pdev);
-
-       BUG_ON(!dev);
-       unregister_netdev(dev);
-       release_region(dev->base_addr, NE_IO_EXTENT);
-       free_netdev(dev);
-       pci_disable_device(pdev);
-       pci_set_drvdata(pdev, NULL);
-}
-
-#ifdef CONFIG_PM
-static int ne2k_pci_suspend (struct pci_dev *pdev, pm_message_t state)
-{
-       struct net_device *dev = pci_get_drvdata (pdev);
-
-       netif_device_detach(dev);
-       pci_save_state(pdev);
-       pci_disable_device(pdev);
-       pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
-       return 0;
-}
-
-static int ne2k_pci_resume (struct pci_dev *pdev)
-{
-       struct net_device *dev = pci_get_drvdata (pdev);
-       int rc;
-
-       pci_set_power_state(pdev, 0);
-       pci_restore_state(pdev);
-
-       rc = pci_enable_device(pdev);
-       if (rc)
-               return rc;
-
-       NS8390_init(dev, 1);
-       netif_device_attach(dev);
-
-       return 0;
-}
-
-#endif /* CONFIG_PM */
-
-
-static struct pci_driver ne2k_driver = {
-       .name           = DRV_NAME,
-       .probe          = ne2k_pci_init_one,
-       .remove         = __devexit_p(ne2k_pci_remove_one),
-       .id_table       = ne2k_pci_tbl,
-#ifdef CONFIG_PM
-       .suspend        = ne2k_pci_suspend,
-       .resume         = ne2k_pci_resume,
-#endif /* CONFIG_PM */
-
-};
-
-
-static int __init ne2k_pci_init(void)
-{
-/* when a module, this is printed whether or not devices are found in probe */
-#ifdef MODULE
-       printk(version);
-#endif
-       return pci_register_driver(&ne2k_driver);
-}
-
-
-static void __exit ne2k_pci_cleanup(void)
-{
-       pci_unregister_driver (&ne2k_driver);
-}
-
-module_init(ne2k_pci_init);
-module_exit(ne2k_pci_cleanup);
diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c
deleted file mode 100644 (file)
index 243ed2a..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
-       ne3210.c
-
-       Linux driver for Novell NE3210 EISA Network Adapter
-
-       Copyright (C) 1998, Paul Gortmaker.
-
-       This software may be used and distributed according to the terms
-       of the GNU General Public License, incorporated herein by reference.
-
-       Information and Code Sources:
-
-       1) Based upon my other EISA 8390 drivers (lne390, es3210, smc-ultra32)
-       2) The existing myriad of other Linux 8390 drivers by Donald Becker.
-       3) Info for getting IRQ and sh-mem gleaned from the EISA cfg file
-
-       The NE3210 is an EISA shared memory NS8390 implementation.  Shared
-       memory address > 1MB should work with this driver.
-
-       Note that the .cfg file (3/11/93, v1.0) has AUI and BNC switched
-       around (or perhaps there are some defective/backwards cards ???)
-
-       This driver WILL NOT WORK FOR THE NE3200 - it is completely different
-       and does not use an 8390 at all.
-
-       Updated to EISA probing API 5/2003 by Marc Zyngier.
-*/
-
-#include <linux/module.h>
-#include <linux/eisa.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/mm.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include "8390.h"
-
-#define DRV_NAME "ne3210"
-
-static void ne3210_reset_8390(struct net_device *dev);
-
-static void ne3210_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
-static void ne3210_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset);
-static void ne3210_block_output(struct net_device *dev, int count, const unsigned char *buf, const int start_page);
-
-#define NE3210_START_PG                0x00    /* First page of TX buffer      */
-#define NE3210_STOP_PG         0x80    /* Last page +1 of RX ring      */
-
-#define NE3210_IO_EXTENT       0x20
-#define NE3210_SA_PROM         0x16    /* Start of e'net addr.         */
-#define NE3210_RESET_PORT      0xc84
-#define NE3210_NIC_OFFSET      0x00    /* Hello, the 8390 is *here*    */
-
-#define NE3210_ADDR0           0x00    /* 3 byte vendor prefix         */
-#define NE3210_ADDR1           0x00
-#define NE3210_ADDR2           0x1b
-
-#define NE3210_CFG1            0xc84   /* NB: 0xc84 is also "reset" port. */
-#define NE3210_CFG2            0xc90
-#define NE3210_CFG_EXTENT       (NE3210_CFG2 - NE3210_CFG1 + 1)
-
-/*
- *     You can OR any of the following bits together and assign it
- *     to NE3210_DEBUG to get verbose driver info during operation.
- *     Currently only the probe one is implemented.
- */
-
-#define NE3210_D_PROBE 0x01
-#define NE3210_D_RX_PKT        0x02
-#define NE3210_D_TX_PKT        0x04
-#define NE3210_D_IRQ   0x08
-
-#define NE3210_DEBUG   0x0
-
-static unsigned char irq_map[] __initdata = {15, 12, 11, 10, 9, 7, 5, 3};
-static unsigned int shmem_map[] __initdata = {0xff0, 0xfe0, 0xfff0, 0xd8, 0xffe0, 0xffc0, 0xd0, 0x0};
-static const char *ifmap[] __initdata = {"UTP", "?", "BNC", "AUI"};
-static int ifmap_val[] __initdata = {
-               IF_PORT_10BASET,
-               IF_PORT_UNKNOWN,
-               IF_PORT_10BASE2,
-               IF_PORT_AUI,
-};
-
-static int __init ne3210_eisa_probe (struct device *device)
-{
-       unsigned long ioaddr, phys_mem;
-       int i, retval, port_index;
-       struct eisa_device *edev = to_eisa_device (device);
-       struct net_device *dev;
-
-       /* Allocate dev->priv and fill in 8390 specific dev fields. */
-       if (!(dev = alloc_ei_netdev ())) {
-               printk ("ne3210.c: unable to allocate memory for dev!\n");
-               return -ENOMEM;
-       }
-
-       SET_NETDEV_DEV(dev, device);
-       dev_set_drvdata(device, dev);
-       ioaddr = edev->base_addr;
-
-       if (!request_region(ioaddr, NE3210_IO_EXTENT, DRV_NAME)) {
-               retval = -EBUSY;
-               goto out;
-       }
-
-       if (!request_region(ioaddr + NE3210_CFG1,
-                           NE3210_CFG_EXTENT, DRV_NAME)) {
-               retval = -EBUSY;
-               goto out1;
-       }
-
-#if NE3210_DEBUG & NE3210_D_PROBE
-       printk("ne3210-debug: probe at %#x, ID %s\n", ioaddr, edev->id.sig);
-       printk("ne3210-debug: config regs: %#x %#x\n",
-               inb(ioaddr + NE3210_CFG1), inb(ioaddr + NE3210_CFG2));
-#endif
-
-       port_index = inb(ioaddr + NE3210_CFG2) >> 6;
-       for(i = 0; i < ETHER_ADDR_LEN; i++)
-               dev->dev_addr[i] = inb(ioaddr + NE3210_SA_PROM + i);
-       printk("ne3210.c: NE3210 in EISA slot %d, media: %s, addr: %pM.\n",
-               edev->slot, ifmap[port_index], dev->dev_addr);
-
-       /* Snarf the interrupt now. CFG file has them all listed as `edge' with share=NO */
-       dev->irq = irq_map[(inb(ioaddr + NE3210_CFG2) >> 3) & 0x07];
-       printk("ne3210.c: using IRQ %d, ", dev->irq);
-
-       retval = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
-       if (retval) {
-               printk (" unable to get IRQ %d.\n", dev->irq);
-               goto out2;
-       }
-
-       phys_mem = shmem_map[inb(ioaddr + NE3210_CFG2) & 0x07] * 0x1000;
-
-       /*
-          BEWARE!! Some dain-bramaged EISA SCUs will allow you to put
-          the card mem within the region covered by `normal' RAM  !!!
-       */
-       if (phys_mem > 1024*1024) {     /* phys addr > 1MB */
-               if (phys_mem < virt_to_phys(high_memory)) {
-                       printk(KERN_CRIT "ne3210.c: Card RAM overlaps with normal memory!!!\n");
-                       printk(KERN_CRIT "ne3210.c: Use EISA SCU to set card memory below 1MB,\n");
-                       printk(KERN_CRIT "ne3210.c: or to an address above 0x%llx.\n",
-                               (u64)virt_to_phys(high_memory));
-                       printk(KERN_CRIT "ne3210.c: Driver NOT installed.\n");
-                       retval = -EINVAL;
-                       goto out3;
-               }
-       }
-
-       if (!request_mem_region (phys_mem, NE3210_STOP_PG*0x100, DRV_NAME)) {
-               printk ("ne3210.c: Unable to request shared memory at physical address %#lx\n",
-                       phys_mem);
-               goto out3;
-       }
-
-       printk("%dkB memory at physical address %#lx\n",
-              NE3210_STOP_PG/4, phys_mem);
-
-       ei_status.mem = ioremap(phys_mem, NE3210_STOP_PG*0x100);
-       if (!ei_status.mem) {
-               printk(KERN_ERR "ne3210.c: Unable to remap card memory !!\n");
-               printk(KERN_ERR "ne3210.c: Driver NOT installed.\n");
-               retval = -EAGAIN;
-               goto out4;
-       }
-       printk("ne3210.c: remapped %dkB card memory to virtual address %p\n",
-              NE3210_STOP_PG/4, ei_status.mem);
-       dev->mem_start = (unsigned long)ei_status.mem;
-       dev->mem_end = dev->mem_start + (NE3210_STOP_PG - NE3210_START_PG)*256;
-
-       /* The 8390 offset is zero for the NE3210 */
-       dev->base_addr = ioaddr;
-
-       ei_status.name = "NE3210";
-       ei_status.tx_start_page = NE3210_START_PG;
-       ei_status.rx_start_page = NE3210_START_PG + TX_PAGES;
-       ei_status.stop_page = NE3210_STOP_PG;
-       ei_status.word16 = 1;
-       ei_status.priv = phys_mem;
-
-       if (ei_debug > 0)
-               printk("ne3210 loaded.\n");
-
-       ei_status.reset_8390 = &ne3210_reset_8390;
-       ei_status.block_input = &ne3210_block_input;
-       ei_status.block_output = &ne3210_block_output;
-       ei_status.get_8390_hdr = &ne3210_get_8390_hdr;
-
-       dev->netdev_ops = &ei_netdev_ops;
-
-       dev->if_port = ifmap_val[port_index];
-
-       if ((retval = register_netdev (dev)))
-               goto out5;
-
-       NS8390_init(dev, 0);
-       return 0;
-
- out5:
-       iounmap(ei_status.mem);
- out4:
-       release_mem_region (phys_mem, NE3210_STOP_PG*0x100);
- out3:
-       free_irq (dev->irq, dev);
- out2:
-       release_region (ioaddr + NE3210_CFG1, NE3210_CFG_EXTENT);
- out1:
-       release_region (ioaddr, NE3210_IO_EXTENT);
- out:
-       free_netdev (dev);
-
-       return retval;
-}
-
-static int __devexit ne3210_eisa_remove (struct device *device)
-{
-       struct net_device  *dev    = dev_get_drvdata(device);
-       unsigned long       ioaddr = to_eisa_device (device)->base_addr;
-
-       unregister_netdev (dev);
-       iounmap(ei_status.mem);
-       release_mem_region (ei_status.priv, NE3210_STOP_PG*0x100);
-       free_irq (dev->irq, dev);
-       release_region (ioaddr + NE3210_CFG1, NE3210_CFG_EXTENT);
-       release_region (ioaddr, NE3210_IO_EXTENT);
-       free_netdev (dev);
-
-       return 0;
-}
-
-/*
- *     Reset by toggling the "Board Enable" bits (bit 2 and 0).
- */
-
-static void ne3210_reset_8390(struct net_device *dev)
-{
-       unsigned short ioaddr = dev->base_addr;
-
-       outb(0x04, ioaddr + NE3210_RESET_PORT);
-       if (ei_debug > 1) printk("%s: resetting the NE3210...", dev->name);
-
-       mdelay(2);
-
-       ei_status.txing = 0;
-       outb(0x01, ioaddr + NE3210_RESET_PORT);
-       if (ei_debug > 1) printk("reset done\n");
-}
-
-/*
- *     Note: In the following three functions is the implicit assumption
- *     that the associated memcpy will only use "rep; movsl" as long as
- *     we keep the counts as some multiple of doublewords. This is a
- *     requirement of the hardware, and also prevents us from using
- *     eth_io_copy_and_sum() since we can't guarantee it will limit
- *     itself to doubleword access.
- */
-
-/*
- *     Grab the 8390 specific header. Similar to the block_input routine, but
- *     we don't need to be concerned with ring wrap as the header will be at
- *     the start of a page, so we optimize accordingly. (A single doubleword.)
- */
-
-static void
-ne3210_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-       void __iomem *hdr_start = ei_status.mem + ((ring_page - NE3210_START_PG)<<8);
-       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
-       hdr->count = (hdr->count + 3) & ~3;     /* Round up allocation. */
-}
-
-/*
- *     Block input and output are easy on shared memory ethercards, the only
- *     complication is when the ring buffer wraps. The count will already
- *     be rounded up to a doubleword value via ne3210_get_8390_hdr() above.
- */
-
-static void ne3210_block_input(struct net_device *dev, int count, struct sk_buff *skb,
-                                                 int ring_offset)
-{
-       void __iomem *start = ei_status.mem + ring_offset - NE3210_START_PG*256;
-
-       if (ring_offset + count > NE3210_STOP_PG*256) {
-               /* Packet wraps over end of ring buffer. */
-               int semi_count = NE3210_STOP_PG*256 - ring_offset;
-               memcpy_fromio(skb->data, start, semi_count);
-               count -= semi_count;
-               memcpy_fromio(skb->data + semi_count,
-                               ei_status.mem + TX_PAGES*256, count);
-       } else {
-               /* Packet is in one chunk. */
-               memcpy_fromio(skb->data, start, count);
-       }
-}
-
-static void ne3210_block_output(struct net_device *dev, int count,
-                               const unsigned char *buf, int start_page)
-{
-       void __iomem *shmem = ei_status.mem + ((start_page - NE3210_START_PG)<<8);
-
-       count = (count + 3) & ~3;     /* Round up to doubleword */
-       memcpy_toio(shmem, buf, count);
-}
-
-static struct eisa_device_id ne3210_ids[] = {
-       { "EGL0101" },
-       { "NVL1801" },
-       { "" },
-};
-MODULE_DEVICE_TABLE(eisa, ne3210_ids);
-
-static struct eisa_driver ne3210_eisa_driver = {
-       .id_table = ne3210_ids,
-       .driver   = {
-               .name   = "ne3210",
-               .probe  = ne3210_eisa_probe,
-               .remove = __devexit_p (ne3210_eisa_remove),
-       },
-};
-
-MODULE_DESCRIPTION("NE3210 EISA Ethernet driver");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(eisa, ne3210_ids);
-
-static int ne3210_init(void)
-{
-       return eisa_driver_register (&ne3210_eisa_driver);
-}
-
-static void ne3210_cleanup(void)
-{
-       eisa_driver_unregister (&ne3210_eisa_driver);
-}
-
-module_init (ne3210_init);
-module_exit (ne3210_cleanup);
index e17ad95f66688c4ebfa892363972180bdf51c8a9..72aa25786a95a4a9e83e67e72f53de60919ac0b0 100644 (file)
@@ -31,16 +31,6 @@ config PCMCIA_FMVJ18X
          To compile this driver as a module, choose M here: the module will be
          called fmvj18x_cs.  If unsure, say N.
 
-config PCMCIA_PCNET
-       tristate "NE2000 compatible PCMCIA support"
-       select CRC32
-       help
-         Say Y here if you intend to attach an NE2000 compatible PCMCIA
-         (PC-card) Ethernet or Fast Ethernet card to your computer.
-
-         To compile this driver as a module, choose M here: the module will be
-         called pcnet_cs.  If unsure, say N.
-
 config PCMCIA_SMC91C92
        tristate "SMC 91Cxx PCMCIA support"
        select CRC32
@@ -61,17 +51,6 @@ config PCMCIA_XIRC2PS
          To compile this driver as a module, choose M here: the module will be
          called xirc2ps_cs.  If unsure, say N.
 
-config PCMCIA_AXNET
-       tristate "Asix AX88190 PCMCIA support"
-       ---help---
-         Say Y here if you intend to attach an Asix AX88190-based PCMCIA
-         (PC-card) Fast Ethernet card to your computer.  These cards are
-         nearly NE2000 compatible but need a separate driver due to a few
-         misfeatures.
-
-         To compile this driver as a module, choose M here: the module will be
-         called axnet_cs.  If unsure, say N.
-
 config ARCNET_COM20020_CS
        tristate "COM20020 ARCnet PCMCIA support"
        depends on ARCNET_COM20020
index 985f0ae37f8fcfdc2320f51f9aca01c762be4660..c2b8b44c7bb114f6ef599d7e9119bfa562c55836 100644 (file)
@@ -4,10 +4,8 @@
 
 # 16-bit client drivers
 obj-$(CONFIG_PCMCIA_FMVJ18X)   += fmvj18x_cs.o
-obj-$(CONFIG_PCMCIA_PCNET)     += pcnet_cs.o
 obj-$(CONFIG_PCMCIA_SMC91C92)  += smc91c92_cs.o
 obj-$(CONFIG_PCMCIA_XIRC2PS)   += xirc2ps_cs.o
 obj-$(CONFIG_ARCNET_COM20020_CS)+= com20020_cs.o
-obj-$(CONFIG_PCMCIA_AXNET)     += axnet_cs.o
 
 obj-$(CONFIG_PCMCIA_IBMTR)     += ibmtr_cs.o
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
deleted file mode 100644 (file)
index 9953db7..0000000
+++ /dev/null
@@ -1,1725 +0,0 @@
-/*======================================================================
-
-    A PCMCIA ethernet driver for Asix AX88190-based cards
-
-    The Asix AX88190 is a NS8390-derived chipset with a few nasty
-    idiosyncracies that make it very inconvenient to support with a
-    standard 8390 driver.  This driver is based on pcnet_cs, with the
-    tweaked 8390 code grafted on the end.  Much of what I did was to
-    clean up and update a similar driver supplied by Asix, which was
-    adapted by William Lee, william@asix.com.tw.
-
-    Copyright (C) 2001 David A. Hinds -- dahinds@users.sourceforge.net
-
-    axnet_cs.c 1.28 2002/06/29 06:27:37
-
-    The network driver code is based on Donald Becker's NE2000 code:
-
-    Written 1992,1993 by Donald Becker.
-    Copyright 1993 United States Government as represented by the
-    Director, National Security Agency.  This software may be used and
-    distributed according to the terms of the GNU General Public License,
-    incorporated herein by reference.
-    Donald Becker may be reached at becker@scyld.com
-
-======================================================================*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/crc32.h>
-#include <linux/mii.h>
-#include "../8390.h"
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ciscode.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/cisreg.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-
-#define AXNET_CMD      0x00
-#define AXNET_DATAPORT 0x10    /* NatSemi-defined port window offset. */
-#define AXNET_RESET    0x1f    /* Issue a read to reset, a write to clear. */
-#define AXNET_MII_EEP  0x14    /* Offset of MII access port */
-#define AXNET_TEST     0x15    /* Offset of TEST Register port */
-#define AXNET_GPIO     0x17    /* Offset of General Purpose Register Port */
-
-#define AXNET_START_PG 0x40    /* First page of TX buffer */
-#define AXNET_STOP_PG  0x80    /* Last page +1 of RX ring */
-
-#define AXNET_RDC_TIMEOUT 0x02 /* Max wait in jiffies for Tx RDC */
-
-#define IS_AX88190     0x0001
-#define IS_AX88790     0x0002
-
-/*====================================================================*/
-
-/* Module parameters */
-
-MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
-MODULE_DESCRIPTION("Asix AX88190 PCMCIA ethernet driver");
-MODULE_LICENSE("GPL");
-
-
-/*====================================================================*/
-
-static int axnet_config(struct pcmcia_device *link);
-static void axnet_release(struct pcmcia_device *link);
-static int axnet_open(struct net_device *dev);
-static int axnet_close(struct net_device *dev);
-static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static netdev_tx_t axnet_start_xmit(struct sk_buff *skb,
-                                         struct net_device *dev);
-static struct net_device_stats *get_stats(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-static void axnet_tx_timeout(struct net_device *dev);
-static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
-static void ei_watchdog(u_long arg);
-static void axnet_reset_8390(struct net_device *dev);
-
-static int mdio_read(unsigned int addr, int phy_id, int loc);
-static void mdio_write(unsigned int addr, int phy_id, int loc, int value);
-
-static void get_8390_hdr(struct net_device *,
-                        struct e8390_pkt_hdr *, int);
-static void block_input(struct net_device *dev, int count,
-                       struct sk_buff *skb, int ring_offset);
-static void block_output(struct net_device *dev, int count,
-                        const u_char *buf, const int start_page);
-
-static void axnet_detach(struct pcmcia_device *p_dev);
-
-static void AX88190_init(struct net_device *dev, int startp);
-static int ax_open(struct net_device *dev);
-static int ax_close(struct net_device *dev);
-static irqreturn_t ax_interrupt(int irq, void *dev_id);
-
-/*====================================================================*/
-
-typedef struct axnet_dev_t {
-       struct pcmcia_device    *p_dev;
-       caddr_t base;
-       struct timer_list       watchdog;
-       int     stale, fast_poll;
-       u_short link_status;
-       u_char  duplex_flag;
-       int     phy_id;
-       int     flags;
-       int     active_low;
-} axnet_dev_t;
-
-static inline axnet_dev_t *PRIV(struct net_device *dev)
-{
-       void *p = (char *)netdev_priv(dev) + sizeof(struct ei_device);
-       return p;
-}
-
-static const struct net_device_ops axnet_netdev_ops = {
-       .ndo_open               = axnet_open,
-       .ndo_stop               = axnet_close,
-       .ndo_do_ioctl           = axnet_ioctl,
-       .ndo_start_xmit         = axnet_start_xmit,
-       .ndo_tx_timeout         = axnet_tx_timeout,
-       .ndo_get_stats          = get_stats,
-       .ndo_set_multicast_list = set_multicast_list,
-       .ndo_change_mtu         = eth_change_mtu,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_validate_addr      = eth_validate_addr,
-};
-
-static int axnet_probe(struct pcmcia_device *link)
-{
-    axnet_dev_t *info;
-    struct net_device *dev;
-    struct ei_device *ei_local;
-
-    dev_dbg(&link->dev, "axnet_attach()\n");
-
-    dev = alloc_etherdev(sizeof(struct ei_device) + sizeof(axnet_dev_t));
-    if (!dev)
-       return -ENOMEM;
-
-    ei_local = netdev_priv(dev);
-    spin_lock_init(&ei_local->page_lock);
-
-    info = PRIV(dev);
-    info->p_dev = link;
-    link->priv = dev;
-    link->config_flags |= CONF_ENABLE_IRQ;
-
-    dev->netdev_ops = &axnet_netdev_ops;
-
-    dev->watchdog_timeo = TX_TIMEOUT;
-
-    return axnet_config(link);
-} /* axnet_attach */
-
-static void axnet_detach(struct pcmcia_device *link)
-{
-    struct net_device *dev = link->priv;
-
-    dev_dbg(&link->dev, "axnet_detach(0x%p)\n", link);
-
-    unregister_netdev(dev);
-
-    axnet_release(link);
-
-    free_netdev(dev);
-} /* axnet_detach */
-
-/*======================================================================
-
-    This probes for a card's hardware address by reading the PROM.
-
-======================================================================*/
-
-static int get_prom(struct pcmcia_device *link)
-{
-    struct net_device *dev = link->priv;
-    unsigned int ioaddr = dev->base_addr;
-    int i, j;
-
-    /* This is based on drivers/net/ne.c */
-    struct {
-       u_char value, offset;
-    } program_seq[] = {
-       {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
-       {0x01,  EN0_DCFG},      /* Set word-wide access. */
-       {0x00,  EN0_RCNTLO},    /* Clear the count regs. */
-       {0x00,  EN0_RCNTHI},
-       {0x00,  EN0_IMR},       /* Mask completion irq. */
-       {0xFF,  EN0_ISR},
-       {E8390_RXOFF|0x40, EN0_RXCR},   /* 0x60  Set to monitor */
-       {E8390_TXOFF, EN0_TXCR},        /* 0x02  and loopback mode. */
-       {0x10,  EN0_RCNTLO},
-       {0x00,  EN0_RCNTHI},
-       {0x00,  EN0_RSARLO},    /* DMA starting at 0x0400. */
-       {0x04,  EN0_RSARHI},
-       {E8390_RREAD+E8390_START, E8390_CMD},
-    };
-
-    /* Not much of a test, but the alternatives are messy */
-    if (link->config_base != 0x03c0)
-       return 0;
-
-    axnet_reset_8390(dev);
-    mdelay(10);
-
-    for (i = 0; i < ARRAY_SIZE(program_seq); i++)
-       outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
-
-    for (i = 0; i < 6; i += 2) {
-       j = inw(ioaddr + AXNET_DATAPORT);
-       dev->dev_addr[i] = j & 0xff;
-       dev->dev_addr[i+1] = j >> 8;
-    }
-    return 1;
-} /* get_prom */
-
-static int try_io_port(struct pcmcia_device *link)
-{
-    int j, ret;
-    link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-    link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
-    if (link->resource[0]->end == 32) {
-       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-       /* for master/slave multifunction cards */
-       if (link->resource[1]->end > 0)
-           link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-    } else {
-       /* This should be two 16-port windows */
-       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-       link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
-    }
-    if (link->resource[0]->start == 0) {
-       for (j = 0; j < 0x400; j += 0x20) {
-           link->resource[0]->start = j ^ 0x300;
-           link->resource[1]->start = (j ^ 0x300) + 0x10;
-           link->io_lines = 16;
-           ret = pcmcia_request_io(link);
-           if (ret == 0)
-                   return ret;
-       }
-       return ret;
-    } else {
-       return pcmcia_request_io(link);
-    }
-}
-
-static int axnet_configcheck(struct pcmcia_device *p_dev, void *priv_data)
-{
-       if (p_dev->config_index == 0)
-               return -EINVAL;
-
-       p_dev->config_index = 0x05;
-       if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
-               return -ENODEV;
-
-       return try_io_port(p_dev);
-}
-
-static int axnet_config(struct pcmcia_device *link)
-{
-    struct net_device *dev = link->priv;
-    axnet_dev_t *info = PRIV(dev);
-    int i, j, j2, ret;
-
-    dev_dbg(&link->dev, "axnet_config(0x%p)\n", link);
-
-    /* don't trust the CIS on this; Linksys got it wrong */
-    link->config_regs = 0x63;
-    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
-    ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
-    if (ret != 0)
-       goto failed;
-
-    if (!link->irq)
-           goto failed;
-
-    if (resource_size(link->resource[1]) == 8)
-       link->config_flags |= CONF_ENABLE_SPKR;
-    
-    ret = pcmcia_enable_device(link);
-    if (ret)
-           goto failed;
-
-    dev->irq = link->irq;
-    dev->base_addr = link->resource[0]->start;
-
-    if (!get_prom(link)) {
-       pr_notice("this is not an AX88190 card!\n");
-       pr_notice("use pcnet_cs instead.\n");
-       goto failed;
-    }
-
-    ei_status.name = "AX88190";
-    ei_status.word16 = 1;
-    ei_status.tx_start_page = AXNET_START_PG;
-    ei_status.rx_start_page = AXNET_START_PG + TX_PAGES;
-    ei_status.stop_page = AXNET_STOP_PG;
-    ei_status.reset_8390 = axnet_reset_8390;
-    ei_status.get_8390_hdr = get_8390_hdr;
-    ei_status.block_input = block_input;
-    ei_status.block_output = block_output;
-
-    if (inb(dev->base_addr + AXNET_TEST) != 0)
-       info->flags |= IS_AX88790;
-    else
-       info->flags |= IS_AX88190;
-
-    if (info->flags & IS_AX88790)
-       outb(0x10, dev->base_addr + AXNET_GPIO);  /* select Internal PHY */
-
-    info->active_low = 0;
-
-    for (i = 0; i < 32; i++) {
-       j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
-       j2 = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 2);
-       if (j == j2) continue;
-       if ((j != 0) && (j != 0xffff)) break;
-    }
-
-    if (i == 32) {
-       /* Maybe PHY is in power down mode. (PPD_SET = 1)
-          Bit 2 of CCSR is active low. */
-       pcmcia_write_config_byte(link, CISREG_CCSR, 0x04);
-       for (i = 0; i < 32; i++) {
-           j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
-           j2 = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 2);
-           if (j == j2) continue;
-           if ((j != 0) && (j != 0xffff)) {
-               info->active_low = 1;
-               break;
-           }
-       }
-    }
-
-    info->phy_id = (i < 32) ? i : -1;
-    SET_NETDEV_DEV(dev, &link->dev);
-
-    if (register_netdev(dev) != 0) {
-       pr_notice("register_netdev() failed\n");
-       goto failed;
-    }
-
-    netdev_info(dev, "Asix AX88%d90: io %#3lx, irq %d, hw_addr %pM\n",
-               ((info->flags & IS_AX88790) ? 7 : 1),
-               dev->base_addr, dev->irq, dev->dev_addr);
-    if (info->phy_id != -1) {
-       netdev_dbg(dev, "  MII transceiver at index %d, status %x\n",
-                  info->phy_id, j);
-    } else {
-       netdev_notice(dev, "  No MII transceivers found!\n");
-    }
-    return 0;
-
-failed:
-    axnet_release(link);
-    return -ENODEV;
-} /* axnet_config */
-
-static void axnet_release(struct pcmcia_device *link)
-{
-       pcmcia_disable_device(link);
-}
-
-static int axnet_suspend(struct pcmcia_device *link)
-{
-       struct net_device *dev = link->priv;
-
-       if (link->open)
-               netif_device_detach(dev);
-
-       return 0;
-}
-
-static int axnet_resume(struct pcmcia_device *link)
-{
-       struct net_device *dev = link->priv;
-       axnet_dev_t *info = PRIV(dev);
-
-       if (link->open) {
-               if (info->active_low == 1)
-                       pcmcia_write_config_byte(link, CISREG_CCSR, 0x04);
-
-               axnet_reset_8390(dev);
-               AX88190_init(dev, 1);
-               netif_device_attach(dev);
-       }
-
-       return 0;
-}
-
-
-/*======================================================================
-
-    MII interface support
-
-======================================================================*/
-
-#define MDIO_SHIFT_CLK         0x01
-#define MDIO_DATA_WRITE0       0x00
-#define MDIO_DATA_WRITE1       0x08
-#define MDIO_DATA_READ         0x04
-#define MDIO_MASK              0x0f
-#define MDIO_ENB_IN            0x02
-
-static void mdio_sync(unsigned int addr)
-{
-    int bits;
-    for (bits = 0; bits < 32; bits++) {
-       outb_p(MDIO_DATA_WRITE1, addr);
-       outb_p(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
-    }
-}
-
-static int mdio_read(unsigned int addr, int phy_id, int loc)
-{
-    u_int cmd = (0xf6<<10)|(phy_id<<5)|loc;
-    int i, retval = 0;
-
-    mdio_sync(addr);
-    for (i = 14; i >= 0; i--) {
-       int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
-       outb_p(dat, addr);
-       outb_p(dat | MDIO_SHIFT_CLK, addr);
-    }
-    for (i = 19; i > 0; i--) {
-       outb_p(MDIO_ENB_IN, addr);
-       retval = (retval << 1) | ((inb_p(addr) & MDIO_DATA_READ) != 0);
-       outb_p(MDIO_ENB_IN | MDIO_SHIFT_CLK, addr);
-    }
-    return (retval>>1) & 0xffff;
-}
-
-static void mdio_write(unsigned int addr, int phy_id, int loc, int value)
-{
-    u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
-    int i;
-
-    mdio_sync(addr);
-    for (i = 31; i >= 0; i--) {
-       int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
-       outb_p(dat, addr);
-       outb_p(dat | MDIO_SHIFT_CLK, addr);
-    }
-    for (i = 1; i >= 0; i--) {
-       outb_p(MDIO_ENB_IN, addr);
-       outb_p(MDIO_ENB_IN | MDIO_SHIFT_CLK, addr);
-    }
-}
-
-/*====================================================================*/
-
-static int axnet_open(struct net_device *dev)
-{
-    int ret;
-    axnet_dev_t *info = PRIV(dev);
-    struct pcmcia_device *link = info->p_dev;
-    unsigned int nic_base = dev->base_addr;
-    
-    dev_dbg(&link->dev, "axnet_open('%s')\n", dev->name);
-
-    if (!pcmcia_dev_present(link))
-       return -ENODEV;
-
-    outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */
-    ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
-    if (ret)
-           return ret;
-
-    link->open++;
-
-    info->link_status = 0x00;
-    init_timer(&info->watchdog);
-    info->watchdog.function = ei_watchdog;
-    info->watchdog.data = (u_long)dev;
-    info->watchdog.expires = jiffies + HZ;
-    add_timer(&info->watchdog);
-
-    return ax_open(dev);
-} /* axnet_open */
-
-/*====================================================================*/
-
-static int axnet_close(struct net_device *dev)
-{
-    axnet_dev_t *info = PRIV(dev);
-    struct pcmcia_device *link = info->p_dev;
-
-    dev_dbg(&link->dev, "axnet_close('%s')\n", dev->name);
-
-    ax_close(dev);
-    free_irq(dev->irq, dev);
-    
-    link->open--;
-    netif_stop_queue(dev);
-    del_timer_sync(&info->watchdog);
-
-    return 0;
-} /* axnet_close */
-
-/*======================================================================
-
-    Hard reset the card.  This used to pause for the same period that
-    a 8390 reset command required, but that shouldn't be necessary.
-
-======================================================================*/
-
-static void axnet_reset_8390(struct net_device *dev)
-{
-    unsigned int nic_base = dev->base_addr;
-    int i;
-
-    ei_status.txing = ei_status.dmaing = 0;
-
-    outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, nic_base + E8390_CMD);
-
-    outb(inb(nic_base + AXNET_RESET), nic_base + AXNET_RESET);
-
-    for (i = 0; i < 100; i++) {
-       if ((inb_p(nic_base+EN0_ISR) & ENISR_RESET) != 0)
-           break;
-       udelay(100);
-    }
-    outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
-    
-    if (i == 100)
-       netdev_err(dev, "axnet_reset_8390() did not complete\n");
-    
-} /* axnet_reset_8390 */
-
-/*====================================================================*/
-
-static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
-{
-    struct net_device *dev = dev_id;
-    PRIV(dev)->stale = 0;
-    return ax_interrupt(irq, dev_id);
-}
-
-static void ei_watchdog(u_long arg)
-{
-    struct net_device *dev = (struct net_device *)(arg);
-    axnet_dev_t *info = PRIV(dev);
-    unsigned int nic_base = dev->base_addr;
-    unsigned int mii_addr = nic_base + AXNET_MII_EEP;
-    u_short link;
-
-    if (!netif_device_present(dev)) goto reschedule;
-
-    /* Check for pending interrupt with expired latency timer: with
-       this, we can limp along even if the interrupt is blocked */
-    if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
-       if (!info->fast_poll)
-           netdev_info(dev, "interrupt(s) dropped!\n");
-       ei_irq_wrapper(dev->irq, dev);
-       info->fast_poll = HZ;
-    }
-    if (info->fast_poll) {
-       info->fast_poll--;
-       info->watchdog.expires = jiffies + 1;
-       add_timer(&info->watchdog);
-       return;
-    }
-
-    if (info->phy_id < 0)
-       goto reschedule;
-    link = mdio_read(mii_addr, info->phy_id, 1);
-    if (!link || (link == 0xffff)) {
-       netdev_info(dev, "MII is missing!\n");
-       info->phy_id = -1;
-       goto reschedule;
-    }
-
-    link &= 0x0004;
-    if (link != info->link_status) {
-       u_short p = mdio_read(mii_addr, info->phy_id, 5);
-       netdev_info(dev, "%s link beat\n", link ? "found" : "lost");
-       if (link) {
-           info->duplex_flag = (p & 0x0140) ? 0x80 : 0x00;
-           if (p)
-               netdev_info(dev, "autonegotiation complete: %dbaseT-%cD selected\n",
-                           (p & 0x0180) ? 100 : 10, (p & 0x0140) ? 'F' : 'H');
-           else
-               netdev_info(dev, "link partner did not autonegotiate\n");
-           AX88190_init(dev, 1);
-       }
-       info->link_status = link;
-    }
-
-reschedule:
-    info->watchdog.expires = jiffies + HZ;
-    add_timer(&info->watchdog);
-}
-
-/*====================================================================*/
-
-static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-    axnet_dev_t *info = PRIV(dev);
-    struct mii_ioctl_data *data = if_mii(rq);
-    unsigned int mii_addr = dev->base_addr + AXNET_MII_EEP;
-    switch (cmd) {
-    case SIOCGMIIPHY:
-       data->phy_id = info->phy_id;
-    case SIOCGMIIREG:          /* Read MII PHY register. */
-       data->val_out = mdio_read(mii_addr, data->phy_id, data->reg_num & 0x1f);
-       return 0;
-    case SIOCSMIIREG:          /* Write MII PHY register. */
-       mdio_write(mii_addr, data->phy_id, data->reg_num & 0x1f, data->val_in);
-       return 0;
-    }
-    return -EOPNOTSUPP;
-}
-
-/*====================================================================*/
-
-static void get_8390_hdr(struct net_device *dev,
-                        struct e8390_pkt_hdr *hdr,
-                        int ring_page)
-{
-    unsigned int nic_base = dev->base_addr;
-
-    outb_p(0, nic_base + EN0_RSARLO);          /* On page boundary */
-    outb_p(ring_page, nic_base + EN0_RSARHI);
-    outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD);
-
-    insw(nic_base + AXNET_DATAPORT, hdr,
-           sizeof(struct e8390_pkt_hdr)>>1);
-    /* Fix for big endian systems */
-    hdr->count = le16_to_cpu(hdr->count);
-
-}
-
-/*====================================================================*/
-
-static void block_input(struct net_device *dev, int count,
-                       struct sk_buff *skb, int ring_offset)
-{
-    unsigned int nic_base = dev->base_addr;
-    int xfer_count = count;
-    char *buf = skb->data;
-
-    if ((ei_debug > 4) && (count != 4))
-           pr_debug("%s: [bi=%d]\n", dev->name, count+4);
-    outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
-    outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
-    outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD);
-
-    insw(nic_base + AXNET_DATAPORT,buf,count>>1);
-    if (count & 0x01)
-       buf[count-1] = inb(nic_base + AXNET_DATAPORT), xfer_count++;
-
-}
-
-/*====================================================================*/
-
-static void block_output(struct net_device *dev, int count,
-                        const u_char *buf, const int start_page)
-{
-    unsigned int nic_base = dev->base_addr;
-
-    pr_debug("%s: [bo=%d]\n", dev->name, count);
-
-    /* Round the count up for word writes.  Do we need to do this?
-       What effect will an odd byte count have on the 8390?
-       I should check someday. */
-    if (count & 0x01)
-       count++;
-
-    outb_p(0x00, nic_base + EN0_RSARLO);
-    outb_p(start_page, nic_base + EN0_RSARHI);
-    outb_p(E8390_RWRITE+E8390_START, nic_base + AXNET_CMD);
-    outsw(nic_base + AXNET_DATAPORT, buf, count>>1);
-}
-
-static const struct pcmcia_device_id axnet_ids[] = {
-       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x016c, 0x0081),
-       PCMCIA_DEVICE_MANF_CARD(0x018a, 0x0301),
-       PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328),
-       PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0301),
-       PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0303),
-       PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0309),
-       PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1106),
-       PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab),
-       PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202), 
-       PCMCIA_DEVICE_MANF_CARD(0xffff, 0x1090),
-       PCMCIA_DEVICE_PROD_ID12("AmbiCom,Inc.", "Fast Ethernet PC Card(AMB8110)", 0x49b020a7, 0x119cc9fc),
-       PCMCIA_DEVICE_PROD_ID124("Fast Ethernet", "16-bit PC Card", "AX88190", 0xb4be14e3, 0x9a12eb6a, 0xab9be5ef),
-       PCMCIA_DEVICE_PROD_ID12("ASIX", "AX88190", 0x0959823b, 0xab9be5ef),
-       PCMCIA_DEVICE_PROD_ID12("Billionton", "LNA-100B", 0x552ab682, 0xbc3b87e1),
-       PCMCIA_DEVICE_PROD_ID12("CHEETAH ETHERCARD", "EN2228", 0x00fa7bc8, 0x00e990cc),
-       PCMCIA_DEVICE_PROD_ID12("CNet", "CNF301", 0xbc477dde, 0x78c5f40b),
-       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXD", 0x5261440f, 0x436768c5),
-       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEtherII PCC-TXD", 0x5261440f, 0x730df72e),
-       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXM", 0x5261440f, 0x3abbd061),
-       PCMCIA_DEVICE_PROD_ID12("Dynalink", "L100C16", 0x55632fd5, 0x66bc2a90),
-       PCMCIA_DEVICE_PROD_ID12("IO DATA", "ETXPCM", 0x547e66dc, 0x233adac2),
-       PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V3)", 0x0733cc81, 0x232019a8),
-       PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC3-TX", 0x481e0094, 0xf91af609),
-       PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA411", 0x9aa79dc3, 0x40fad875),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "100BASE", 0x281f1c5d, 0x7c2add04),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEtherCard", 0x281f1c5d, 0x7ef26116),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FEP501", 0x281f1c5d, 0x2e272058),
-       PCMCIA_DEVICE_PROD_ID14("Network Everywhere", "AX88190", 0x820a67b6,  0xab9be5ef),
-       PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, axnet_ids);
-
-static struct pcmcia_driver axnet_cs_driver = {
-       .owner          = THIS_MODULE,
-       .name           = "axnet_cs",
-       .probe          = axnet_probe,
-       .remove         = axnet_detach,
-       .id_table       = axnet_ids,
-       .suspend        = axnet_suspend,
-       .resume         = axnet_resume,
-};
-
-static int __init init_axnet_cs(void)
-{
-       return pcmcia_register_driver(&axnet_cs_driver);
-}
-
-static void __exit exit_axnet_cs(void)
-{
-       pcmcia_unregister_driver(&axnet_cs_driver);
-}
-
-module_init(init_axnet_cs);
-module_exit(exit_axnet_cs);
-
-/*====================================================================*/
-
-/* 8390.c: A general NS8390 ethernet driver core for linux. */
-/*
-       Written 1992-94 by Donald Becker.
-  
-       Copyright 1993 United States Government as represented by the
-       Director, National Security Agency.
-
-       This software may be used and distributed according to the terms
-       of the GNU General Public License, incorporated herein by reference.
-
-       The author may be reached as becker@scyld.com, or C/O
-       Scyld Computing Corporation
-       410 Severn Ave., Suite 210
-       Annapolis MD 21403
-
-  This is the chip-specific code for many 8390-based ethernet adaptors.
-  This is not a complete driver, it must be combined with board-specific
-  code such as ne.c, wd.c, 3c503.c, etc.
-
-  Seeing how at least eight drivers use this code, (not counting the
-  PCMCIA ones either) it is easy to break some card by what seems like
-  a simple innocent change. Please contact me or Donald if you think
-  you have found something that needs changing. -- PG
-
-  Changelog:
-
-  Paul Gortmaker       : remove set_bit lock, other cleanups.
-  Paul Gortmaker       : add ei_get_8390_hdr() so we can pass skb's to 
-                         ei_block_input() for eth_io_copy_and_sum().
-  Paul Gortmaker       : exchange static int ei_pingpong for a #define,
-                         also add better Tx error handling.
-  Paul Gortmaker       : rewrite Rx overrun handling as per NS specs.
-  Alexey Kuznetsov     : use the 8390's six bit hash multicast filter.
-  Paul Gortmaker       : tweak ANK's above multicast changes a bit.
-  Paul Gortmaker       : update packet statistics for v2.1.x
-  Alan Cox             : support arbitrary stupid port mappings on the
-                         68K Macintosh. Support >16bit I/O spaces
-  Paul Gortmaker       : add kmod support for auto-loading of the 8390
-                         module by all drivers that require it.
-  Alan Cox             : Spinlocking work, added 'BUG_83C690'
-  Paul Gortmaker       : Separate out Tx timeout code from Tx path.
-
-  Sources:
-  The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
-
-  */
-
-#include <linux/bitops.h>
-#include <asm/irq.h>
-#include <linux/fcntl.h>
-#include <linux/in.h>
-#include <linux/interrupt.h>
-
-#define BUG_83C690
-
-/* These are the operational function interfaces to board-specific
-   routines.
-       void reset_8390(struct net_device *dev)
-               Resets the board associated with DEV, including a hardware reset of
-               the 8390.  This is only called when there is a transmit timeout, and
-               it is always followed by 8390_init().
-       void block_output(struct net_device *dev, int count, const unsigned char *buf,
-                                         int start_page)
-               Write the COUNT bytes of BUF to the packet buffer at START_PAGE.  The
-               "page" value uses the 8390's 256-byte pages.
-       void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page)
-               Read the 4 byte, page aligned 8390 header. *If* there is a
-               subsequent read, it will be of the rest of the packet.
-       void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-               Read COUNT bytes from the packet buffer into the skb data area. Start 
-               reading from RING_OFFSET, the address as the 8390 sees it.  This will always
-               follow the read of the 8390 header. 
-*/
-#define ei_reset_8390 (ei_local->reset_8390)
-#define ei_block_output (ei_local->block_output)
-#define ei_block_input (ei_local->block_input)
-#define ei_get_8390_hdr (ei_local->get_8390_hdr)
-
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifndef ei_debug
-int ei_debug = 1;
-#endif
-
-/* Index to functions. */
-static void ei_tx_intr(struct net_device *dev);
-static void ei_tx_err(struct net_device *dev);
-static void ei_receive(struct net_device *dev);
-static void ei_rx_overrun(struct net_device *dev);
-
-/* Routines generic to NS8390-based boards. */
-static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
-                                                               int start_page);
-static void do_set_multicast_list(struct net_device *dev);
-
-/*
- *     SMP and the 8390 setup.
- *
- *     The 8390 isn't exactly designed to be multithreaded on RX/TX. There is
- *     a page register that controls bank and packet buffer access. We guard
- *     this with ei_local->page_lock. Nobody should assume or set the page other
- *     than zero when the lock is not held. Lock holders must restore page 0
- *     before unlocking. Even pure readers must take the lock to protect in 
- *     page 0.
- *
- *     To make life difficult the chip can also be very slow. We therefore can't
- *     just use spinlocks. For the longer lockups we disable the irq the device
- *     sits on and hold the lock. We must hold the lock because there is a dual
- *     processor case other than interrupts (get stats/set multicast list in
- *     parallel with each other and transmit).
- *
- *     Note: in theory we can just disable the irq on the card _but_ there is
- *     a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs"
- *     enter lock, take the queued irq. So we waddle instead of flying.
- *
- *     Finally by special arrangement for the purpose of being generally 
- *     annoying the transmit function is called bh atomic. That places
- *     restrictions on the user context callers as disable_irq won't save
- *     them.
- */
-/**
- * ax_open - Open/initialize the board.
- * @dev: network device to initialize
- *
- * This routine goes all-out, setting everything
- * up anew at each open, even though many of these registers should only
- * need to be set once at boot.
- */
-static int ax_open(struct net_device *dev)
-{
-       unsigned long flags;
-       struct ei_device *ei_local = netdev_priv(dev);
-
-       /*
-        *      Grab the page lock so we own the register set, then call
-        *      the init function.
-        */
-      
-       spin_lock_irqsave(&ei_local->page_lock, flags);
-       AX88190_init(dev, 1);
-       /* Set the flag before we drop the lock, That way the IRQ arrives
-          after its set and we get no silly warnings */
-       netif_start_queue(dev);
-       spin_unlock_irqrestore(&ei_local->page_lock, flags);
-       ei_local->irqlock = 0;
-       return 0;
-}
-
-#define dev_lock(dev) (((struct ei_device *)netdev_priv(dev))->page_lock)
-
-/**
- * ax_close - shut down network device
- * @dev: network device to close
- *
- * Opposite of ax_open(). Only used when "ifconfig <devname> down" is done.
- */
-static int ax_close(struct net_device *dev)
-{
-       unsigned long flags;
-
-       /*
-        *      Hold the page lock during close
-        */
-
-       spin_lock_irqsave(&dev_lock(dev), flags);
-       AX88190_init(dev, 0);
-       spin_unlock_irqrestore(&dev_lock(dev), flags);
-       netif_stop_queue(dev);
-       return 0;
-}
-
-/**
- * axnet_tx_timeout - handle transmit time out condition
- * @dev: network device which has apparently fallen asleep
- *
- * Called by kernel when device never acknowledges a transmit has
- * completed (or failed) - i.e. never posted a Tx related interrupt.
- */
-
-static void axnet_tx_timeout(struct net_device *dev)
-{
-       long e8390_base = dev->base_addr;
-       struct ei_device *ei_local = netdev_priv(dev);
-       int txsr, isr, tickssofar = jiffies - dev_trans_start(dev);
-       unsigned long flags;
-
-       dev->stats.tx_errors++;
-
-       spin_lock_irqsave(&ei_local->page_lock, flags);
-       txsr = inb(e8390_base+EN0_TSR);
-       isr = inb(e8390_base+EN0_ISR);
-       spin_unlock_irqrestore(&ei_local->page_lock, flags);
-
-       netdev_printk(KERN_DEBUG, dev,
-                     "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
-                     (txsr & ENTSR_ABT) ? "excess collisions." :
-                     (isr) ? "lost interrupt?" : "cable problem?",
-                     txsr, isr, tickssofar);
-
-       if (!isr && !dev->stats.tx_packets) 
-       {
-               /* The 8390 probably hasn't gotten on the cable yet. */
-               ei_local->interface_num ^= 1;   /* Try a different xcvr.  */
-       }
-
-       /* Ugly but a reset can be slow, yet must be protected */
-               
-       spin_lock_irqsave(&ei_local->page_lock, flags);
-               
-       /* Try to restart the card.  Perhaps the user has fixed something. */
-       ei_reset_8390(dev);
-       AX88190_init(dev, 1);
-               
-       spin_unlock_irqrestore(&ei_local->page_lock, flags);
-       netif_wake_queue(dev);
-}
-    
-/**
- * axnet_start_xmit - begin packet transmission
- * @skb: packet to be sent
- * @dev: network device to which packet is sent
- *
- * Sends a packet to an 8390 network device.
- */
-static netdev_tx_t axnet_start_xmit(struct sk_buff *skb,
-                                         struct net_device *dev)
-{
-       long e8390_base = dev->base_addr;
-       struct ei_device *ei_local = netdev_priv(dev);
-       int length, send_length, output_page;
-       unsigned long flags;
-       u8 packet[ETH_ZLEN];
-       
-       netif_stop_queue(dev);
-
-       length = skb->len;
-
-       /* Mask interrupts from the ethercard. 
-          SMP: We have to grab the lock here otherwise the IRQ handler
-          on another CPU can flip window and race the IRQ mask set. We end
-          up trashing the mcast filter not disabling irqs if we don't lock */
-          
-       spin_lock_irqsave(&ei_local->page_lock, flags);
-       outb_p(0x00, e8390_base + EN0_IMR);
-       
-       /*
-        *      Slow phase with lock held.
-        */
-        
-       ei_local->irqlock = 1;
-
-       send_length = max(length, ETH_ZLEN);
-
-       /*
-        * We have two Tx slots available for use. Find the first free
-        * slot, and then perform some sanity checks. With two Tx bufs,
-        * you get very close to transmitting back-to-back packets. With
-        * only one Tx buf, the transmitter sits idle while you reload the
-        * card, leaving a substantial gap between each transmitted packet.
-        */
-
-       if (ei_local->tx1 == 0) 
-       {
-               output_page = ei_local->tx_start_page;
-               ei_local->tx1 = send_length;
-               if (ei_debug  &&  ei_local->tx2 > 0)
-                       netdev_printk(KERN_DEBUG, dev,
-                                     "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
-                                     ei_local->tx2, ei_local->lasttx,
-                                     ei_local->txing);
-       }
-       else if (ei_local->tx2 == 0) 
-       {
-               output_page = ei_local->tx_start_page + TX_PAGES/2;
-               ei_local->tx2 = send_length;
-               if (ei_debug  &&  ei_local->tx1 > 0)
-                       netdev_printk(KERN_DEBUG, dev,
-                                     "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
-                                     ei_local->tx1, ei_local->lasttx,
-                                     ei_local->txing);
-       }
-       else
-       {       /* We should never get here. */
-               if (ei_debug)
-                       netdev_printk(KERN_DEBUG, dev,
-                                     "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
-                                     ei_local->tx1, ei_local->tx2,
-                                     ei_local->lasttx);
-               ei_local->irqlock = 0;
-               netif_stop_queue(dev);
-               outb_p(ENISR_ALL, e8390_base + EN0_IMR);
-               spin_unlock_irqrestore(&ei_local->page_lock, flags);
-               dev->stats.tx_errors++;
-               return NETDEV_TX_BUSY;
-       }
-
-       /*
-        * Okay, now upload the packet and trigger a send if the transmitter
-        * isn't already sending. If it is busy, the interrupt handler will
-        * trigger the send later, upon receiving a Tx done interrupt.
-        */
-
-       if (length == skb->len)
-               ei_block_output(dev, length, skb->data, output_page);
-       else {
-               memset(packet, 0, ETH_ZLEN);
-               skb_copy_from_linear_data(skb, packet, skb->len);
-               ei_block_output(dev, length, packet, output_page);
-       }
-       
-       if (! ei_local->txing) 
-       {
-               ei_local->txing = 1;
-               NS8390_trigger_send(dev, send_length, output_page);
-               dev->trans_start = jiffies;
-               if (output_page == ei_local->tx_start_page) 
-               {
-                       ei_local->tx1 = -1;
-                       ei_local->lasttx = -1;
-               }
-               else 
-               {
-                       ei_local->tx2 = -1;
-                       ei_local->lasttx = -2;
-               }
-       }
-       else ei_local->txqueue++;
-
-       if (ei_local->tx1  &&  ei_local->tx2)
-               netif_stop_queue(dev);
-       else
-               netif_start_queue(dev);
-
-       /* Turn 8390 interrupts back on. */
-       ei_local->irqlock = 0;
-       outb_p(ENISR_ALL, e8390_base + EN0_IMR);
-       
-       spin_unlock_irqrestore(&ei_local->page_lock, flags);
-
-       dev_kfree_skb (skb);
-       dev->stats.tx_bytes += send_length;
-    
-       return NETDEV_TX_OK;
-}
-
-/**
- * ax_interrupt - handle the interrupts from an 8390
- * @irq: interrupt number
- * @dev_id: a pointer to the net_device
- *
- * Handle the ether interface interrupts. We pull packets from
- * the 8390 via the card specific functions and fire them at the networking
- * stack. We also handle transmit completions and wake the transmit path if
- * necessary. We also update the counters and do other housekeeping as
- * needed.
- */
-
-static irqreturn_t ax_interrupt(int irq, void *dev_id)
-{
-       struct net_device *dev = dev_id;
-       long e8390_base;
-       int interrupts, nr_serviced = 0, i;
-       struct ei_device *ei_local;
-       int handled = 0;
-       unsigned long flags;
-
-       e8390_base = dev->base_addr;
-       ei_local = netdev_priv(dev);
-
-       /*
-        *      Protect the irq test too.
-        */
-        
-       spin_lock_irqsave(&ei_local->page_lock, flags);
-
-       if (ei_local->irqlock) {
-#if 1 /* This might just be an interrupt for a PCI device sharing this line */
-               const char *msg;
-               /* The "irqlock" check is only for testing. */
-               if (ei_local->irqlock)
-                       msg = "Interrupted while interrupts are masked!";
-               else
-                       msg = "Reentering the interrupt handler!";
-               netdev_info(dev, "%s, isr=%#2x imr=%#2x\n",
-                           msg,
-                           inb_p(e8390_base + EN0_ISR),
-                           inb_p(e8390_base + EN0_IMR));
-#endif
-               spin_unlock_irqrestore(&ei_local->page_lock, flags);
-               return IRQ_NONE;
-       }
-    
-       if (ei_debug > 3)
-               netdev_printk(KERN_DEBUG, dev, "interrupt(isr=%#2.2x)\n",
-                             inb_p(e8390_base + EN0_ISR));
-
-       outb_p(0x00, e8390_base + EN0_ISR);
-       ei_local->irqlock = 1;
-   
-       /* !!Assumption!! -- we stay in page 0.  Don't break this. */
-       while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0 &&
-              ++nr_serviced < MAX_SERVICE)
-       {
-               if (!netif_running(dev) || (interrupts == 0xff)) {
-                       if (ei_debug > 1)
-                               netdev_warn(dev,
-                                           "interrupt from stopped card\n");
-                       outb_p(interrupts, e8390_base + EN0_ISR);
-                       interrupts = 0;
-                       break;
-               }
-               handled = 1;
-
-               /* AX88190 bug fix. */
-               outb_p(interrupts, e8390_base + EN0_ISR);
-               for (i = 0; i < 10; i++) {
-                       if (!(inb(e8390_base + EN0_ISR) & interrupts))
-                               break;
-                       outb_p(0, e8390_base + EN0_ISR);
-                       outb_p(interrupts, e8390_base + EN0_ISR);
-               }
-               if (interrupts & ENISR_OVER) 
-                       ei_rx_overrun(dev);
-               else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) 
-               {
-                       /* Got a good (?) packet. */
-                       ei_receive(dev);
-               }
-               /* Push the next to-transmit packet through. */
-               if (interrupts & ENISR_TX)
-                       ei_tx_intr(dev);
-               else if (interrupts & ENISR_TX_ERR)
-                       ei_tx_err(dev);
-
-               if (interrupts & ENISR_COUNTERS) 
-               {
-                       dev->stats.rx_frame_errors += inb_p(e8390_base + EN0_COUNTER0);
-                       dev->stats.rx_crc_errors   += inb_p(e8390_base + EN0_COUNTER1);
-                       dev->stats.rx_missed_errors+= inb_p(e8390_base + EN0_COUNTER2);
-               }
-       }
-    
-       if (interrupts && ei_debug > 3) 
-       {
-               handled = 1;
-               if (nr_serviced >= MAX_SERVICE) 
-               {
-                       /* 0xFF is valid for a card removal */
-                       if(interrupts!=0xFF)
-                               netdev_warn(dev, "Too much work at interrupt, status %#2.2x\n",
-                                           interrupts);
-                       outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
-               } else {
-                       netdev_warn(dev, "unknown interrupt %#2x\n",
-                                   interrupts);
-                       outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
-               }
-       }
-
-       /* Turn 8390 interrupts back on. */
-       ei_local->irqlock = 0;
-       outb_p(ENISR_ALL, e8390_base + EN0_IMR);
-
-       spin_unlock_irqrestore(&ei_local->page_lock, flags);
-       return IRQ_RETVAL(handled);
-}
-
-/**
- * ei_tx_err - handle transmitter error
- * @dev: network device which threw the exception
- *
- * A transmitter error has happened. Most likely excess collisions (which
- * is a fairly normal condition). If the error is one where the Tx will
- * have been aborted, we try and send another one right away, instead of
- * letting the failed packet sit and collect dust in the Tx buffer. This
- * is a much better solution as it avoids kernel based Tx timeouts, and
- * an unnecessary card reset.
- *
- * Called with lock held.
- */
-
-static void ei_tx_err(struct net_device *dev)
-{
-       long e8390_base = dev->base_addr;
-       unsigned char txsr = inb_p(e8390_base+EN0_TSR);
-       unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
-
-#ifdef VERBOSE_ERROR_DUMP
-       netdev_printk(KERN_DEBUG, dev,
-                     "transmitter error (%#2x):", txsr);
-       if (txsr & ENTSR_ABT)
-               pr_cont(" excess-collisions");
-       if (txsr & ENTSR_ND)
-               pr_cont(" non-deferral");
-       if (txsr & ENTSR_CRS)
-               pr_cont(" lost-carrier");
-       if (txsr & ENTSR_FU)
-               pr_cont(" FIFO-underrun");
-       if (txsr & ENTSR_CDH)
-               pr_cont(" lost-heartbeat");
-       pr_cont("\n");
-#endif
-
-       if (tx_was_aborted)
-               ei_tx_intr(dev);
-       else 
-       {
-               dev->stats.tx_errors++;
-               if (txsr & ENTSR_CRS) dev->stats.tx_carrier_errors++;
-               if (txsr & ENTSR_CDH) dev->stats.tx_heartbeat_errors++;
-               if (txsr & ENTSR_OWC) dev->stats.tx_window_errors++;
-       }
-}
-
-/**
- * ei_tx_intr - transmit interrupt handler
- * @dev: network device for which tx intr is handled
- *
- * We have finished a transmit: check for errors and then trigger the next
- * packet to be sent. Called with lock held.
- */
-
-static void ei_tx_intr(struct net_device *dev)
-{
-       long e8390_base = dev->base_addr;
-       struct ei_device *ei_local = netdev_priv(dev);
-       int status = inb(e8390_base + EN0_TSR);
-    
-       /*
-        * There are two Tx buffers, see which one finished, and trigger
-        * the send of another one if it exists.
-        */
-       ei_local->txqueue--;
-
-       if (ei_local->tx1 < 0) 
-       {
-               if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
-                       netdev_err(dev, "%s: bogus last_tx_buffer %d, tx1=%d\n",
-                                  ei_local->name, ei_local->lasttx,
-                                  ei_local->tx1);
-               ei_local->tx1 = 0;
-               if (ei_local->tx2 > 0) 
-               {
-                       ei_local->txing = 1;
-                       NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
-                       dev->trans_start = jiffies;
-                       ei_local->tx2 = -1,
-                       ei_local->lasttx = 2;
-               }
-               else ei_local->lasttx = 20, ei_local->txing = 0;        
-       }
-       else if (ei_local->tx2 < 0) 
-       {
-               if (ei_local->lasttx != 2  &&  ei_local->lasttx != -2)
-                       netdev_info(dev, "%s: bogus last_tx_buffer %d, tx2=%d\n",
-                                   ei_local->name, ei_local->lasttx,
-                                   ei_local->tx2);
-               ei_local->tx2 = 0;
-               if (ei_local->tx1 > 0) 
-               {
-                       ei_local->txing = 1;
-                       NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
-                       dev->trans_start = jiffies;
-                       ei_local->tx1 = -1;
-                       ei_local->lasttx = 1;
-               }
-               else
-                       ei_local->lasttx = 10, ei_local->txing = 0;
-       }
-//     else
-//             netdev_warn(dev, "unexpected TX-done interrupt, lasttx=%d\n",
-//                         ei_local->lasttx);
-
-       /* Minimize Tx latency: update the statistics after we restart TXing. */
-       if (status & ENTSR_COL)
-               dev->stats.collisions++;
-       if (status & ENTSR_PTX)
-               dev->stats.tx_packets++;
-       else 
-       {
-               dev->stats.tx_errors++;
-               if (status & ENTSR_ABT) 
-               {
-                       dev->stats.tx_aborted_errors++;
-                       dev->stats.collisions += 16;
-               }
-               if (status & ENTSR_CRS) 
-                       dev->stats.tx_carrier_errors++;
-               if (status & ENTSR_FU) 
-                       dev->stats.tx_fifo_errors++;
-               if (status & ENTSR_CDH)
-                       dev->stats.tx_heartbeat_errors++;
-               if (status & ENTSR_OWC)
-                       dev->stats.tx_window_errors++;
-       }
-       netif_wake_queue(dev);
-}
-
-/**
- * ei_receive - receive some packets
- * @dev: network device with which receive will be run
- *
- * We have a good packet(s), get it/them out of the buffers. 
- * Called with lock held.
- */
-
-static void ei_receive(struct net_device *dev)
-{
-       long e8390_base = dev->base_addr;
-       struct ei_device *ei_local = netdev_priv(dev);
-       unsigned char rxing_page, this_frame, next_frame;
-       unsigned short current_offset;
-       int rx_pkt_count = 0;
-       struct e8390_pkt_hdr rx_frame;
-    
-       while (++rx_pkt_count < 10) 
-       {
-               int pkt_len, pkt_stat;
-               
-               /* Get the rx page (incoming packet pointer). */
-               rxing_page = inb_p(e8390_base + EN1_CURPAG -1);
-               
-               /* Remove one frame from the ring.  Boundary is always a page behind. */
-               this_frame = inb_p(e8390_base + EN0_BOUNDARY) + 1;
-               if (this_frame >= ei_local->stop_page)
-                       this_frame = ei_local->rx_start_page;
-               
-               /* Someday we'll omit the previous, iff we never get this message.
-                  (There is at least one clone claimed to have a problem.)  
-                  
-                  Keep quiet if it looks like a card removal. One problem here
-                  is that some clones crash in roughly the same way.
-                */
-               if (ei_debug > 0  &&  this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF))
-                   netdev_err(dev, "mismatched read page pointers %2x vs %2x\n",
-                              this_frame, ei_local->current_page);
-               
-               if (this_frame == rxing_page)   /* Read all the frames? */
-                       break;                          /* Done for now */
-               
-               current_offset = this_frame << 8;
-               ei_get_8390_hdr(dev, &rx_frame, this_frame);
-               
-               pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr);
-               pkt_stat = rx_frame.status;
-               
-               next_frame = this_frame + 1 + ((pkt_len+4)>>8);
-               
-               if (pkt_len < 60  ||  pkt_len > 1518) 
-               {
-                       if (ei_debug)
-                               netdev_printk(KERN_DEBUG, dev,
-                                             "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
-                                             rx_frame.count, rx_frame.status,
-                                             rx_frame.next);
-                       dev->stats.rx_errors++;
-                       dev->stats.rx_length_errors++;
-               }
-                else if ((pkt_stat & 0x0F) == ENRSR_RXOK) 
-               {
-                       struct sk_buff *skb;
-                       
-                       skb = dev_alloc_skb(pkt_len+2);
-                       if (skb == NULL) 
-                       {
-                               if (ei_debug > 1)
-                                       netdev_printk(KERN_DEBUG, dev,
-                                                     "Couldn't allocate a sk_buff of size %d\n",
-                                                     pkt_len);
-                               dev->stats.rx_dropped++;
-                               break;
-                       }
-                       else
-                       {
-                               skb_reserve(skb,2);     /* IP headers on 16 byte boundaries */
-                               skb_put(skb, pkt_len);  /* Make room */
-                               ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
-                               skb->protocol=eth_type_trans(skb,dev);
-                               netif_rx(skb);
-                               dev->stats.rx_packets++;
-                               dev->stats.rx_bytes += pkt_len;
-                               if (pkt_stat & ENRSR_PHY)
-                                       dev->stats.multicast++;
-                       }
-               } 
-               else 
-               {
-                       if (ei_debug)
-                               netdev_printk(KERN_DEBUG, dev,
-                                             "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
-                                             rx_frame.status, rx_frame.next,
-                                             rx_frame.count);
-                       dev->stats.rx_errors++;
-                       /* NB: The NIC counts CRC, frame and missed errors. */
-                       if (pkt_stat & ENRSR_FO)
-                               dev->stats.rx_fifo_errors++;
-               }
-               next_frame = rx_frame.next;
-               
-               /* This _should_ never happen: it's here for avoiding bad clones. */
-               if (next_frame >= ei_local->stop_page) {
-                       netdev_info(dev, "next frame inconsistency, %#2x\n",
-                                   next_frame);
-                       next_frame = ei_local->rx_start_page;
-               }
-               ei_local->current_page = next_frame;
-               outb_p(next_frame-1, e8390_base+EN0_BOUNDARY);
-       }
-}
-
-/**
- * ei_rx_overrun - handle receiver overrun
- * @dev: network device which threw exception
- *
- * We have a receiver overrun: we have to kick the 8390 to get it started
- * again. Problem is that you have to kick it exactly as NS prescribes in
- * the updated datasheets, or "the NIC may act in an unpredictable manner."
- * This includes causing "the NIC to defer indefinitely when it is stopped
- * on a busy network."  Ugh.
- * Called with lock held. Don't call this with the interrupts off or your
- * computer will hate you - it takes 10ms or so. 
- */
-
-static void ei_rx_overrun(struct net_device *dev)
-{
-       axnet_dev_t *info = PRIV(dev);
-       long e8390_base = dev->base_addr;
-       unsigned char was_txing, must_resend = 0;
-    
-       /*
-        * Record whether a Tx was in progress and then issue the
-        * stop command.
-        */
-       was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
-       outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
-    
-       if (ei_debug > 1)
-               netdev_printk(KERN_DEBUG, dev, "Receiver overrun\n");
-       dev->stats.rx_over_errors++;
-    
-       /* 
-        * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
-        * We wait at least 2ms.
-        */
-
-       mdelay(2);
-
-       /*
-        * Reset RBCR[01] back to zero as per magic incantation.
-        */
-       outb_p(0x00, e8390_base+EN0_RCNTLO);
-       outb_p(0x00, e8390_base+EN0_RCNTHI);
-
-       /*
-        * See if any Tx was interrupted or not. According to NS, this
-        * step is vital, and skipping it will cause no end of havoc.
-        */
-
-       if (was_txing)
-       { 
-               unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
-               if (!tx_completed)
-                       must_resend = 1;
-       }
-
-       /*
-        * Have to enter loopback mode and then restart the NIC before
-        * you are allowed to slurp packets up off the ring.
-        */
-       outb_p(E8390_TXOFF, e8390_base + EN0_TXCR);
-       outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
-
-       /*
-        * Clear the Rx ring of all the debris, and ack the interrupt.
-        */
-       ei_receive(dev);
-
-       /*
-        * Leave loopback mode, and resend any packet that got stopped.
-        */
-       outb_p(E8390_TXCONFIG | info->duplex_flag, e8390_base + EN0_TXCR); 
-       if (must_resend)
-               outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
-}
-
-/*
- *     Collect the stats. This is called unlocked and from several contexts.
- */
-static struct net_device_stats *get_stats(struct net_device *dev)
-{
-       long ioaddr = dev->base_addr;
-       struct ei_device *ei_local = netdev_priv(dev);
-       unsigned long flags;
-    
-       /* If the card is stopped, just return the present stats. */
-       if (!netif_running(dev))
-               return &dev->stats;
-
-       spin_lock_irqsave(&ei_local->page_lock,flags);
-       /* Read the counter registers, assuming we are in page 0. */
-       dev->stats.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0);
-       dev->stats.rx_crc_errors   += inb_p(ioaddr + EN0_COUNTER1);
-       dev->stats.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2);
-       spin_unlock_irqrestore(&ei_local->page_lock, flags);
-    
-       return &dev->stats;
-}
-
-/*
- * Form the 64 bit 8390 multicast table from the linked list of addresses
- * associated with this dev structure.
- */
-static inline void make_mc_bits(u8 *bits, struct net_device *dev)
-{
-       struct netdev_hw_addr *ha;
-       u32 crc;
-
-       netdev_for_each_mc_addr(ha, dev) {
-               crc = ether_crc(ETH_ALEN, ha->addr);
-               /* 
-                * The 8390 uses the 6 most significant bits of the
-                * CRC to index the multicast table.
-                */
-               bits[crc>>29] |= (1<<((crc>>26)&7));
-       }
-}
-
-/**
- * do_set_multicast_list - set/clear multicast filter
- * @dev: net device for which multicast filter is adjusted
- *
- *     Set or clear the multicast filter for this adaptor.
- *     Must be called with lock held. 
- */
-static void do_set_multicast_list(struct net_device *dev)
-{
-       long e8390_base = dev->base_addr;
-       int i;
-       struct ei_device *ei_local = netdev_priv(dev);
-
-       if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
-               memset(ei_local->mcfilter, 0, 8);
-               if (!netdev_mc_empty(dev))
-                       make_mc_bits(ei_local->mcfilter, dev);
-       } else {
-               /* set to accept-all */
-               memset(ei_local->mcfilter, 0xFF, 8);
-       }
-
-       outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
-       for(i = 0; i < 8; i++) 
-       {
-               outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
-       }
-       outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
-
-       if(dev->flags&IFF_PROMISC)
-               outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR);
-       else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev))
-               outb_p(E8390_RXCONFIG | 0x48, e8390_base + EN0_RXCR);
-       else
-               outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR);
-
-       outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
-}
-
-/*
- *     Called without lock held. This is invoked from user context and may
- *     be parallel to just about everything else. Its also fairly quick and
- *     not called too often. Must protect against both bh and irq users
- */
-
-static void set_multicast_list(struct net_device *dev)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&dev_lock(dev), flags);
-       do_set_multicast_list(dev);
-       spin_unlock_irqrestore(&dev_lock(dev), flags);
-}      
-
-/* This page of functions should be 8390 generic */
-/* Follow National Semi's recommendations for initializing the "NIC". */
-
-/**
- * AX88190_init - initialize 8390 hardware
- * @dev: network device to initialize
- * @startp: boolean.  non-zero value to initiate chip processing
- *
- *     Must be called with lock held.
- */
-
-static void AX88190_init(struct net_device *dev, int startp)
-{
-       axnet_dev_t *info = PRIV(dev);
-       long e8390_base = dev->base_addr;
-       struct ei_device *ei_local = netdev_priv(dev);
-       int i;
-       int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48;
-    
-       if(sizeof(struct e8390_pkt_hdr)!=4)
-               panic("8390.c: header struct mispacked\n");    
-       /* Follow National Semi's recommendations for initing the DP83902. */
-       outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */
-       outb_p(endcfg, e8390_base + EN0_DCFG);  /* 0x48 or 0x49 */
-       /* Clear the remote byte count registers. */
-       outb_p(0x00,  e8390_base + EN0_RCNTLO);
-       outb_p(0x00,  e8390_base + EN0_RCNTHI);
-       /* Set to monitor and loopback mode -- this is vital!. */
-       outb_p(E8390_RXOFF|0x40, e8390_base + EN0_RXCR); /* 0x60 */
-       outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
-       /* Set the transmit page and receive ring. */
-       outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
-       ei_local->tx1 = ei_local->tx2 = 0;
-       outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG);
-       outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY);       /* 3c503 says 0x3f,NS0x26*/
-       ei_local->current_page = ei_local->rx_start_page;               /* assert boundary+1 */
-       outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG);
-       /* Clear the pending interrupts and mask. */
-       outb_p(0xFF, e8390_base + EN0_ISR);
-       outb_p(0x00,  e8390_base + EN0_IMR);
-    
-       /* Copy the station address into the DS8390 registers. */
-
-       outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
-       for(i = 0; i < 6; i++) 
-       {
-               outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
-               if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
-                       netdev_err(dev, "Hw. address read/write mismap %d\n", i);
-       }
-
-       outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
-       outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
-
-       netif_start_queue(dev);
-       ei_local->tx1 = ei_local->tx2 = 0;
-       ei_local->txing = 0;
-
-       if (info->flags & IS_AX88790)   /* select Internal PHY */
-               outb(0x10, e8390_base + AXNET_GPIO);
-
-       if (startp) 
-       {
-               outb_p(0xff,  e8390_base + EN0_ISR);
-               outb_p(ENISR_ALL,  e8390_base + EN0_IMR);
-               outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
-               outb_p(E8390_TXCONFIG | info->duplex_flag,
-                      e8390_base + EN0_TXCR); /* xmit on. */
-               /* 3c503 TechMan says rxconfig only after the NIC is started. */
-               outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR); /* rx on, */
-               do_set_multicast_list(dev);     /* (re)load the mcast table */
-       }
-}
-
-/* Trigger a transmit start, assuming the length is valid. 
-   Always called with the page lock held */
-   
-static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
-                                                               int start_page)
-{
-       long e8390_base = dev->base_addr;
-       struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev);
-    
-       if (inb_p(e8390_base) & E8390_TRANS) 
-       {
-               netdev_warn(dev, "trigger_send() called with the transmitter busy\n");
-               return;
-       }
-       outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
-       outb_p(length >> 8, e8390_base + EN0_TCNTHI);
-       outb_p(start_page, e8390_base + EN0_TPSR);
-       outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD);
-}
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
deleted file mode 100644 (file)
index b4fd7c3..0000000
+++ /dev/null
@@ -1,1710 +0,0 @@
-/*======================================================================
-
-    A PCMCIA ethernet driver for NS8390-based cards
-
-    This driver supports the D-Link DE-650 and Linksys EthernetCard
-    cards, the newer D-Link and Linksys combo cards, Accton EN2212
-    cards, the RPTI EP400, and the PreMax PE-200 in non-shared-memory
-    mode, and the IBM Credit Card Adapter, the NE4100, the Thomas
-    Conrad ethernet card, and the Kingston KNE-PCM/x in shared-memory
-    mode.  It will also handle the Socket EA card in either mode.
-
-    Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
-
-    pcnet_cs.c 1.153 2003/11/09 18:53:09
-
-    The network driver code is based on Donald Becker's NE2000 code:
-
-    Written 1992,1993 by Donald Becker.
-    Copyright 1993 United States Government as represented by the
-    Director, National Security Agency.  This software may be used and
-    distributed according to the terms of the GNU General Public License,
-    incorporated herein by reference.
-    Donald Becker may be reached at becker@scyld.com
-
-    Based also on Keith Moore's changes to Don Becker's code, for IBM
-    CCAE support.  Drivers merged back together, and shared-memory
-    Socket EA support added, by Ken Raeburn, September 1995.
-
-======================================================================*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/log2.h>
-#include <linux/etherdevice.h>
-#include <linux/mii.h>
-#include "../8390.h"
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ciscode.h>
-#include <pcmcia/ds.h>
-#include <pcmcia/cisreg.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-
-#define PCNET_CMD      0x00
-#define PCNET_DATAPORT 0x10    /* NatSemi-defined port window offset. */
-#define PCNET_RESET    0x1f    /* Issue a read to reset, a write to clear. */
-#define PCNET_MISC     0x18    /* For IBM CCAE and Socket EA cards */
-
-#define PCNET_START_PG 0x40    /* First page of TX buffer */
-#define PCNET_STOP_PG  0x80    /* Last page +1 of RX ring */
-
-/* Socket EA cards have a larger packet buffer */
-#define SOCKET_START_PG        0x01
-#define SOCKET_STOP_PG 0xff
-
-#define PCNET_RDC_TIMEOUT (2*HZ/100)   /* Max wait in jiffies for Tx RDC */
-
-static const char *if_names[] = { "auto", "10baseT", "10base2"};
-
-
-/*====================================================================*/
-
-/* Module parameters */
-
-MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
-MODULE_DESCRIPTION("NE2000 compatible PCMCIA ethernet driver");
-MODULE_LICENSE("GPL");
-
-#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
-
-INT_MODULE_PARM(if_port,       1);     /* Transceiver type */
-INT_MODULE_PARM(use_big_buf,   1);     /* use 64K packet buffer? */
-INT_MODULE_PARM(mem_speed,     0);     /* shared mem speed, in ns */
-INT_MODULE_PARM(delay_output,  0);     /* pause after xmit? */
-INT_MODULE_PARM(delay_time,    4);     /* in usec */
-INT_MODULE_PARM(use_shmem,     -1);    /* use shared memory? */
-INT_MODULE_PARM(full_duplex,   0);     /* full duplex? */
-
-/* Ugh!  Let the user hardwire the hardware address for queer cards */
-static int hw_addr[6] = { 0, /* ... */ };
-module_param_array(hw_addr, int, NULL, 0);
-
-/*====================================================================*/
-
-static void mii_phy_probe(struct net_device *dev);
-static int pcnet_config(struct pcmcia_device *link);
-static void pcnet_release(struct pcmcia_device *link);
-static int pcnet_open(struct net_device *dev);
-static int pcnet_close(struct net_device *dev);
-static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
-static void ei_watchdog(u_long arg);
-static void pcnet_reset_8390(struct net_device *dev);
-static int set_config(struct net_device *dev, struct ifmap *map);
-static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
-                             int stop_pg, int cm_offset);
-static int setup_dma_config(struct pcmcia_device *link, int start_pg,
-                           int stop_pg);
-
-static void pcnet_detach(struct pcmcia_device *p_dev);
-
-/*====================================================================*/
-
-typedef struct hw_info_t {
-    u_int      offset;
-    u_char     a0, a1, a2;
-    u_int      flags;
-} hw_info_t;
-
-#define DELAY_OUTPUT   0x01
-#define HAS_MISC_REG   0x02
-#define USE_BIG_BUF    0x04
-#define HAS_IBM_MISC   0x08
-#define IS_DL10019     0x10
-#define IS_DL10022     0x20
-#define HAS_MII                0x40
-#define USE_SHMEM      0x80    /* autodetected */
-
-#define AM79C9XX_HOME_PHY      0x00006B90  /* HomePNA PHY */
-#define AM79C9XX_ETH_PHY       0x00006B70  /* 10baseT PHY */
-#define MII_PHYID_REV_MASK     0xfffffff0
-#define MII_PHYID_REG1         0x02
-#define MII_PHYID_REG2         0x03
-
-static hw_info_t hw_info[] = {
-    { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT },
-    { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 },
-    { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 },
-    { /* ASANTE FriendlyNet */ 0x4910, 0x00, 0x00, 0x94,
-      DELAY_OUTPUT | HAS_IBM_MISC },
-    { /* Danpex EN-6200P2 */ 0x0110, 0x00, 0x40, 0xc7, 0 },
-    { /* DataTrek NetCard */ 0x0ff0, 0x00, 0x20, 0xe8, 0 },
-    { /* Dayna CommuniCard E */ 0x0110, 0x00, 0x80, 0x19, 0 },
-    { /* D-Link DE-650 */ 0x0040, 0x00, 0x80, 0xc8, 0 },
-    { /* EP-210 Ethernet */ 0x0110, 0x00, 0x40, 0x33, 0 },
-    { /* EP4000 Ethernet */ 0x01c0, 0x00, 0x00, 0xb4, 0 },
-    { /* Epson EEN10B */ 0x0ff0, 0x00, 0x00, 0x48,
-      HAS_MISC_REG | HAS_IBM_MISC },
-    { /* ELECOM Laneed LD-CDWA */ 0xb8, 0x08, 0x00, 0x42, 0 },
-    { /* Hypertec Ethernet */ 0x01c0, 0x00, 0x40, 0x4c, 0 },
-    { /* IBM CCAE */ 0x0ff0, 0x08, 0x00, 0x5a,
-      HAS_MISC_REG | HAS_IBM_MISC },
-    { /* IBM CCAE */ 0x0ff0, 0x00, 0x04, 0xac,
-      HAS_MISC_REG | HAS_IBM_MISC },
-    { /* IBM CCAE */ 0x0ff0, 0x00, 0x06, 0x29,
-      HAS_MISC_REG | HAS_IBM_MISC },
-    { /* IBM FME */ 0x0374, 0x08, 0x00, 0x5a,
-      HAS_MISC_REG | HAS_IBM_MISC },
-    { /* IBM FME */ 0x0374, 0x00, 0x04, 0xac,
-      HAS_MISC_REG | HAS_IBM_MISC },
-    { /* Kansai KLA-PCM/T */ 0x0ff0, 0x00, 0x60, 0x87,
-      HAS_MISC_REG | HAS_IBM_MISC },
-    { /* NSC DP83903 */ 0x0374, 0x08, 0x00, 0x17,
-      HAS_MISC_REG | HAS_IBM_MISC },
-    { /* NSC DP83903 */ 0x0374, 0x00, 0xc0, 0xa8,
-      HAS_MISC_REG | HAS_IBM_MISC },
-    { /* NSC DP83903 */ 0x0374, 0x00, 0xa0, 0xb0,
-      HAS_MISC_REG | HAS_IBM_MISC },
-    { /* NSC DP83903 */ 0x0198, 0x00, 0x20, 0xe0,
-      HAS_MISC_REG | HAS_IBM_MISC },
-    { /* I-O DATA PCLA/T */ 0x0ff0, 0x00, 0xa0, 0xb0, 0 },
-    { /* Katron PE-520 */ 0x0110, 0x00, 0x40, 0xf6, 0 },
-    { /* Kingston KNE-PCM/x */ 0x0ff0, 0x00, 0xc0, 0xf0,
-      HAS_MISC_REG | HAS_IBM_MISC },
-    { /* Kingston KNE-PCM/x */ 0x0ff0, 0xe2, 0x0c, 0x0f,
-      HAS_MISC_REG | HAS_IBM_MISC },
-    { /* Kingston KNE-PC2 */ 0x0180, 0x00, 0xc0, 0xf0, 0 },
-    { /* Maxtech PCN2000 */ 0x5000, 0x00, 0x00, 0xe8, 0 },
-    { /* NDC Instant-Link */ 0x003a, 0x00, 0x80, 0xc6, 0 },
-    { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 },
-    { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65,
-      HAS_MISC_REG | HAS_IBM_MISC },
-    { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45,
-      HAS_MISC_REG | HAS_IBM_MISC },
-    { /* PreMax PE-200 */ 0x07f0, 0x00, 0x20, 0xe0, 0 },
-    { /* RPTI EP400 */ 0x0110, 0x00, 0x40, 0x95, 0 },
-    { /* SCM Ethernet */ 0x0ff0, 0x00, 0x20, 0xcb, 0 },
-    { /* Socket EA */ 0x4000, 0x00, 0xc0, 0x1b,
-      DELAY_OUTPUT | HAS_MISC_REG | USE_BIG_BUF },
-    { /* Socket LP-E CF+ */ 0x01c0, 0x00, 0xc0, 0x1b, 0 },
-    { /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 },
-    { /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 },
-    { /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 },
-    { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 }
-};
-
-#define NR_INFO                ARRAY_SIZE(hw_info)
-
-static hw_info_t default_info = { 0, 0, 0, 0, 0 };
-static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII };
-static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII };
-
-typedef struct pcnet_dev_t {
-       struct pcmcia_device    *p_dev;
-    u_int              flags;
-    void               __iomem *base;
-    struct timer_list  watchdog;
-    int                        stale, fast_poll;
-    u_char             phy_id;
-    u_char             eth_phy, pna_phy;
-    u_short            link_status;
-    u_long             mii_reset;
-} pcnet_dev_t;
-
-static inline pcnet_dev_t *PRIV(struct net_device *dev)
-{
-       char *p = netdev_priv(dev);
-       return (pcnet_dev_t *)(p + sizeof(struct ei_device));
-}
-
-static const struct net_device_ops pcnet_netdev_ops = {
-       .ndo_open               = pcnet_open,
-       .ndo_stop               = pcnet_close,
-       .ndo_set_config         = set_config,
-       .ndo_start_xmit         = ei_start_xmit,
-       .ndo_get_stats          = ei_get_stats,
-       .ndo_do_ioctl           = ei_ioctl,
-       .ndo_set_multicast_list = ei_set_multicast_list,
-       .ndo_tx_timeout         = ei_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_validate_addr      = eth_validate_addr,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = ei_poll,
-#endif
-};
-
-static int pcnet_probe(struct pcmcia_device *link)
-{
-    pcnet_dev_t *info;
-    struct net_device *dev;
-
-    dev_dbg(&link->dev, "pcnet_attach()\n");
-
-    /* Create new ethernet device */
-    dev = __alloc_ei_netdev(sizeof(pcnet_dev_t));
-    if (!dev) return -ENOMEM;
-    info = PRIV(dev);
-    info->p_dev = link;
-    link->priv = dev;
-
-    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
-
-    dev->netdev_ops = &pcnet_netdev_ops;
-
-    return pcnet_config(link);
-} /* pcnet_attach */
-
-static void pcnet_detach(struct pcmcia_device *link)
-{
-       struct net_device *dev = link->priv;
-
-       dev_dbg(&link->dev, "pcnet_detach\n");
-
-       unregister_netdev(dev);
-
-       pcnet_release(link);
-
-       free_netdev(dev);
-} /* pcnet_detach */
-
-/*======================================================================
-
-    This probes for a card's hardware address, for card types that
-    encode this information in their CIS.
-
-======================================================================*/
-
-static hw_info_t *get_hwinfo(struct pcmcia_device *link)
-{
-    struct net_device *dev = link->priv;
-    u_char __iomem *base, *virt;
-    int i, j;
-
-    /* Allocate a small memory window */
-    link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-    link->resource[2]->start = 0; link->resource[2]->end = 0;
-    i = pcmcia_request_window(link, link->resource[2], 0);
-    if (i != 0)
-       return NULL;
-
-    virt = ioremap(link->resource[2]->start,
-           resource_size(link->resource[2]));
-    for (i = 0; i < NR_INFO; i++) {
-       pcmcia_map_mem_page(link, link->resource[2],
-               hw_info[i].offset & ~(resource_size(link->resource[2])-1));
-       base = &virt[hw_info[i].offset & (resource_size(link->resource[2])-1)];
-       if ((readb(base+0) == hw_info[i].a0) &&
-           (readb(base+2) == hw_info[i].a1) &&
-           (readb(base+4) == hw_info[i].a2)) {
-               for (j = 0; j < 6; j++)
-                   dev->dev_addr[j] = readb(base + (j<<1));
-               break;
-       }
-    }
-
-    iounmap(virt);
-    j = pcmcia_release_window(link, link->resource[2]);
-    return (i < NR_INFO) ? hw_info+i : NULL;
-} /* get_hwinfo */
-
-/*======================================================================
-
-    This probes for a card's hardware address by reading the PROM.
-    It checks the address against a list of known types, then falls
-    back to a simple NE2000 clone signature check.
-
-======================================================================*/
-
-static hw_info_t *get_prom(struct pcmcia_device *link)
-{
-    struct net_device *dev = link->priv;
-    unsigned int ioaddr = dev->base_addr;
-    u_char prom[32];
-    int i, j;
-
-    /* This is lifted straight from drivers/net/ne.c */
-    struct {
-       u_char value, offset;
-    } program_seq[] = {
-       {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
-       {0x48,  EN0_DCFG},      /* Set byte-wide (0x48) access. */
-       {0x00,  EN0_RCNTLO},    /* Clear the count regs. */
-       {0x00,  EN0_RCNTHI},
-       {0x00,  EN0_IMR},       /* Mask completion irq. */
-       {0xFF,  EN0_ISR},
-       {E8390_RXOFF, EN0_RXCR},        /* 0x20  Set to monitor */
-       {E8390_TXOFF, EN0_TXCR},        /* 0x02  and loopback mode. */
-       {32,    EN0_RCNTLO},
-       {0x00,  EN0_RCNTHI},
-       {0x00,  EN0_RSARLO},    /* DMA starting at 0x0000. */
-       {0x00,  EN0_RSARHI},
-       {E8390_RREAD+E8390_START, E8390_CMD},
-    };
-
-    pcnet_reset_8390(dev);
-    mdelay(10);
-
-    for (i = 0; i < ARRAY_SIZE(program_seq); i++)
-       outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
-
-    for (i = 0; i < 32; i++)
-       prom[i] = inb(ioaddr + PCNET_DATAPORT);
-    for (i = 0; i < NR_INFO; i++) {
-       if ((prom[0] == hw_info[i].a0) &&
-           (prom[2] == hw_info[i].a1) &&
-           (prom[4] == hw_info[i].a2))
-           break;
-    }
-    if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) {
-       for (j = 0; j < 6; j++)
-           dev->dev_addr[j] = prom[j<<1];
-       return (i < NR_INFO) ? hw_info+i : &default_info;
-    }
-    return NULL;
-} /* get_prom */
-
-/*======================================================================
-
-    For DL10019 based cards, like the Linksys EtherFast
-
-======================================================================*/
-
-static hw_info_t *get_dl10019(struct pcmcia_device *link)
-{
-    struct net_device *dev = link->priv;
-    int i;
-    u_char sum;
-
-    for (sum = 0, i = 0x14; i < 0x1c; i++)
-       sum += inb_p(dev->base_addr + i);
-    if (sum != 0xff)
-       return NULL;
-    for (i = 0; i < 6; i++)
-       dev->dev_addr[i] = inb_p(dev->base_addr + 0x14 + i);
-    i = inb(dev->base_addr + 0x1f);
-    return ((i == 0x91)||(i == 0x99)) ? &dl10022_info : &dl10019_info;
-}
-
-/*======================================================================
-
-    For Asix AX88190 based cards
-
-======================================================================*/
-
-static hw_info_t *get_ax88190(struct pcmcia_device *link)
-{
-    struct net_device *dev = link->priv;
-    unsigned int ioaddr = dev->base_addr;
-    int i, j;
-
-    /* Not much of a test, but the alternatives are messy */
-    if (link->config_base != 0x03c0)
-       return NULL;
-
-    outb_p(0x01, ioaddr + EN0_DCFG);   /* Set word-wide access. */
-    outb_p(0x00, ioaddr + EN0_RSARLO); /* DMA starting at 0x0400. */
-    outb_p(0x04, ioaddr + EN0_RSARHI);
-    outb_p(E8390_RREAD+E8390_START, ioaddr + E8390_CMD);
-
-    for (i = 0; i < 6; i += 2) {
-       j = inw(ioaddr + PCNET_DATAPORT);
-       dev->dev_addr[i] = j & 0xff;
-       dev->dev_addr[i+1] = j >> 8;
-    }
-    return NULL;
-}
-
-/*======================================================================
-
-    This should be totally unnecessary... but when we can't figure
-    out the hardware address any other way, we'll let the user hard
-    wire it when the module is initialized.
-
-======================================================================*/
-
-static hw_info_t *get_hwired(struct pcmcia_device *link)
-{
-    struct net_device *dev = link->priv;
-    int i;
-
-    for (i = 0; i < 6; i++)
-       if (hw_addr[i] != 0) break;
-    if (i == 6)
-       return NULL;
-
-    for (i = 0; i < 6; i++)
-       dev->dev_addr[i] = hw_addr[i];
-
-    return &default_info;
-} /* get_hwired */
-
-static int try_io_port(struct pcmcia_device *link)
-{
-    int j, ret;
-    link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-    link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
-    if (link->resource[0]->end == 32) {
-       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-       if (link->resource[1]->end > 0) {
-           /* for master/slave multifunction cards */
-           link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-       }
-    } else {
-       /* This should be two 16-port windows */
-       link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
-       link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
-    }
-    if (link->resource[0]->start == 0) {
-       for (j = 0; j < 0x400; j += 0x20) {
-           link->resource[0]->start = j ^ 0x300;
-           link->resource[1]->start = (j ^ 0x300) + 0x10;
-           link->io_lines = 16;
-           ret = pcmcia_request_io(link);
-           if (ret == 0)
-                   return ret;
-       }
-       return ret;
-    } else {
-       return pcmcia_request_io(link);
-    }
-}
-
-static int pcnet_confcheck(struct pcmcia_device *p_dev, void *priv_data)
-{
-       int *priv = priv_data;
-       int try = (*priv & 0x1);
-
-       *priv &= (p_dev->resource[2]->end >= 0x4000) ? 0x10 : ~0x10;
-
-       if (p_dev->config_index == 0)
-               return -EINVAL;
-
-       if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
-               return -EINVAL;
-
-       if (try)
-               p_dev->io_lines = 16;
-       return try_io_port(p_dev);
-}
-
-static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
-                                  int *has_shmem, int try)
-{
-       struct net_device *dev = link->priv;
-       hw_info_t *local_hw_info;
-       pcnet_dev_t *info = PRIV(dev);
-       int priv = try;
-       int ret;
-
-       ret = pcmcia_loop_config(link, pcnet_confcheck, &priv);
-       if (ret) {
-               dev_warn(&link->dev, "no useable port range found\n");
-               return NULL;
-       }
-       *has_shmem = (priv & 0x10);
-
-       if (!link->irq)
-               return NULL;
-
-       if (resource_size(link->resource[1]) == 8)
-               link->config_flags |= CONF_ENABLE_SPKR;
-
-       if ((link->manf_id == MANFID_IBM) &&
-           (link->card_id == PRODID_IBM_HOME_AND_AWAY))
-               link->config_index |= 0x10;
-
-       ret = pcmcia_enable_device(link);
-       if (ret)
-               return NULL;
-
-       dev->irq = link->irq;
-       dev->base_addr = link->resource[0]->start;
-
-       if (info->flags & HAS_MISC_REG) {
-               if ((if_port == 1) || (if_port == 2))
-                       dev->if_port = if_port;
-               else
-                       dev_notice(&link->dev, "invalid if_port requested\n");
-       } else
-               dev->if_port = 0;
-
-       if ((link->config_base == 0x03c0) &&
-           (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) {
-               dev_info(&link->dev,
-                       "this is an AX88190 card - use axnet_cs instead.\n");
-               return NULL;
-       }
-
-       local_hw_info = get_hwinfo(link);
-       if (!local_hw_info)
-               local_hw_info = get_prom(link);
-       if (!local_hw_info)
-               local_hw_info = get_dl10019(link);
-       if (!local_hw_info)
-               local_hw_info = get_ax88190(link);
-       if (!local_hw_info)
-               local_hw_info = get_hwired(link);
-
-       return local_hw_info;
-}
-
-static int pcnet_config(struct pcmcia_device *link)
-{
-    struct net_device *dev = link->priv;
-    pcnet_dev_t *info = PRIV(dev);
-    int start_pg, stop_pg, cm_offset;
-    int has_shmem = 0;
-    hw_info_t *local_hw_info;
-
-    dev_dbg(&link->dev, "pcnet_config\n");
-
-    local_hw_info = pcnet_try_config(link, &has_shmem, 0);
-    if (!local_hw_info) {
-           /* check whether forcing io_lines to 16 helps... */
-           pcmcia_disable_device(link);
-           local_hw_info = pcnet_try_config(link, &has_shmem, 1);
-           if (local_hw_info == NULL) {
-                   dev_notice(&link->dev, "unable to read hardware net"
-                           " address for io base %#3lx\n", dev->base_addr);
-                   goto failed;
-           }
-    }
-
-    info->flags = local_hw_info->flags;
-    /* Check for user overrides */
-    info->flags |= (delay_output) ? DELAY_OUTPUT : 0;
-    if ((link->manf_id == MANFID_SOCKET) &&
-       ((link->card_id == PRODID_SOCKET_LPE) ||
-        (link->card_id == PRODID_SOCKET_LPE_CF) ||
-        (link->card_id == PRODID_SOCKET_EIO)))
-       info->flags &= ~USE_BIG_BUF;
-    if (!use_big_buf)
-       info->flags &= ~USE_BIG_BUF;
-
-    if (info->flags & USE_BIG_BUF) {
-       start_pg = SOCKET_START_PG;
-       stop_pg = SOCKET_STOP_PG;
-       cm_offset = 0x10000;
-    } else {
-       start_pg = PCNET_START_PG;
-       stop_pg = PCNET_STOP_PG;
-       cm_offset = 0;
-    }
-
-    /* has_shmem is ignored if use_shmem != -1 */
-    if ((use_shmem == 0) || (!has_shmem && (use_shmem == -1)) ||
-       (setup_shmem_window(link, start_pg, stop_pg, cm_offset) != 0))
-       setup_dma_config(link, start_pg, stop_pg);
-
-    ei_status.name = "NE2000";
-    ei_status.word16 = 1;
-    ei_status.reset_8390 = pcnet_reset_8390;
-
-    if (info->flags & (IS_DL10019|IS_DL10022))
-       mii_phy_probe(dev);
-
-    SET_NETDEV_DEV(dev, &link->dev);
-
-    if (register_netdev(dev) != 0) {
-       pr_notice("register_netdev() failed\n");
-       goto failed;
-    }
-
-    if (info->flags & (IS_DL10019|IS_DL10022)) {
-       u_char id = inb(dev->base_addr + 0x1a);
-       netdev_info(dev, "NE2000 (DL100%d rev %02x): ",
-              (info->flags & IS_DL10022) ? 22 : 19, id);
-       if (info->pna_phy)
-           pr_cont("PNA, ");
-    } else {
-       netdev_info(dev, "NE2000 Compatible: ");
-    }
-    pr_cont("io %#3lx, irq %d,", dev->base_addr, dev->irq);
-    if (info->flags & USE_SHMEM)
-       pr_cont(" mem %#5lx,", dev->mem_start);
-    if (info->flags & HAS_MISC_REG)
-       pr_cont(" %s xcvr,", if_names[dev->if_port]);
-    pr_cont(" hw_addr %pM\n", dev->dev_addr);
-    return 0;
-
-failed:
-    pcnet_release(link);
-    return -ENODEV;
-} /* pcnet_config */
-
-static void pcnet_release(struct pcmcia_device *link)
-{
-       pcnet_dev_t *info = PRIV(link->priv);
-
-       dev_dbg(&link->dev, "pcnet_release\n");
-
-       if (info->flags & USE_SHMEM)
-               iounmap(info->base);
-
-       pcmcia_disable_device(link);
-}
-
-static int pcnet_suspend(struct pcmcia_device *link)
-{
-       struct net_device *dev = link->priv;
-
-       if (link->open)
-               netif_device_detach(dev);
-
-       return 0;
-}
-
-static int pcnet_resume(struct pcmcia_device *link)
-{
-       struct net_device *dev = link->priv;
-
-       if (link->open) {
-               pcnet_reset_8390(dev);
-               NS8390_init(dev, 1);
-               netif_device_attach(dev);
-       }
-
-       return 0;
-}
-
-
-/*======================================================================
-
-    MII interface support for DL10019 and DL10022 based cards
-
-    On the DL10019, the MII IO direction bit is 0x10; on the DL10022
-    it is 0x20.  Setting both bits seems to work on both card types.
-
-======================================================================*/
-
-#define DLINK_GPIO             0x1c
-#define DLINK_DIAG             0x1d
-#define DLINK_EEPROM           0x1e
-
-#define MDIO_SHIFT_CLK         0x80
-#define MDIO_DATA_OUT          0x40
-#define MDIO_DIR_WRITE         0x30
-#define MDIO_DATA_WRITE0       (MDIO_DIR_WRITE)
-#define MDIO_DATA_WRITE1       (MDIO_DIR_WRITE | MDIO_DATA_OUT)
-#define MDIO_DATA_READ         0x10
-#define MDIO_MASK              0x0f
-
-static void mdio_sync(unsigned int addr)
-{
-    int bits, mask = inb(addr) & MDIO_MASK;
-    for (bits = 0; bits < 32; bits++) {
-       outb(mask | MDIO_DATA_WRITE1, addr);
-       outb(mask | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
-    }
-}
-
-static int mdio_read(unsigned int addr, int phy_id, int loc)
-{
-    u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
-    int i, retval = 0, mask = inb(addr) & MDIO_MASK;
-
-    mdio_sync(addr);
-    for (i = 13; i >= 0; i--) {
-       int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
-       outb(mask | dat, addr);
-       outb(mask | dat | MDIO_SHIFT_CLK, addr);
-    }
-    for (i = 19; i > 0; i--) {
-       outb(mask, addr);
-       retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0);
-       outb(mask | MDIO_SHIFT_CLK, addr);
-    }
-    return (retval>>1) & 0xffff;
-}
-
-static void mdio_write(unsigned int addr, int phy_id, int loc, int value)
-{
-    u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
-    int i, mask = inb(addr) & MDIO_MASK;
-
-    mdio_sync(addr);
-    for (i = 31; i >= 0; i--) {
-       int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
-       outb(mask | dat, addr);
-       outb(mask | dat | MDIO_SHIFT_CLK, addr);
-    }
-    for (i = 1; i >= 0; i--) {
-       outb(mask, addr);
-       outb(mask | MDIO_SHIFT_CLK, addr);
-    }
-}
-
-/*======================================================================
-
-    EEPROM access routines for DL10019 and DL10022 based cards
-
-======================================================================*/
-
-#define EE_EEP         0x40
-#define EE_ASIC                0x10
-#define EE_CS          0x08
-#define EE_CK          0x04
-#define EE_DO          0x02
-#define EE_DI          0x01
-#define EE_ADOT                0x01    /* DataOut for ASIC */
-#define EE_READ_CMD    0x06
-
-#define DL19FDUPLX     0x0400  /* DL10019 Full duplex mode */
-
-static int read_eeprom(unsigned int ioaddr, int location)
-{
-    int i, retval = 0;
-    unsigned int ee_addr = ioaddr + DLINK_EEPROM;
-    int read_cmd = location | (EE_READ_CMD << 8);
-
-    outb(0, ee_addr);
-    outb(EE_EEP|EE_CS, ee_addr);
-
-    /* Shift the read command bits out. */
-    for (i = 10; i >= 0; i--) {
-       short dataval = (read_cmd & (1 << i)) ? EE_DO : 0;
-       outb_p(EE_EEP|EE_CS|dataval, ee_addr);
-       outb_p(EE_EEP|EE_CS|dataval|EE_CK, ee_addr);
-    }
-    outb(EE_EEP|EE_CS, ee_addr);
-
-    for (i = 16; i > 0; i--) {
-       outb_p(EE_EEP|EE_CS | EE_CK, ee_addr);
-       retval = (retval << 1) | ((inb(ee_addr) & EE_DI) ? 1 : 0);
-       outb_p(EE_EEP|EE_CS, ee_addr);
-    }
-
-    /* Terminate the EEPROM access. */
-    outb(0, ee_addr);
-    return retval;
-}
-
-/*
-    The internal ASIC registers can be changed by EEPROM READ access
-    with EE_ASIC bit set.
-    In ASIC mode, EE_ADOT is used to output the data to the ASIC.
-*/
-
-static void write_asic(unsigned int ioaddr, int location, short asic_data)
-{
-       int i;
-       unsigned int ee_addr = ioaddr + DLINK_EEPROM;
-       short dataval;
-       int read_cmd = location | (EE_READ_CMD << 8);
-
-       asic_data |= read_eeprom(ioaddr, location);
-
-       outb(0, ee_addr);
-       outb(EE_ASIC|EE_CS|EE_DI, ee_addr);
-
-       read_cmd = read_cmd >> 1;
-
-       /* Shift the read command bits out. */
-       for (i = 9; i >= 0; i--) {
-               dataval = (read_cmd & (1 << i)) ? EE_DO : 0;
-               outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr);
-               outb_p(EE_ASIC|EE_CS|EE_DI|dataval|EE_CK, ee_addr);
-               outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr);
-       }
-       // sync
-       outb(EE_ASIC|EE_CS, ee_addr);
-       outb(EE_ASIC|EE_CS|EE_CK, ee_addr);
-       outb(EE_ASIC|EE_CS, ee_addr);
-
-       for (i = 15; i >= 0; i--) {
-               dataval = (asic_data & (1 << i)) ? EE_ADOT : 0;
-               outb_p(EE_ASIC|EE_CS|dataval, ee_addr);
-               outb_p(EE_ASIC|EE_CS|dataval|EE_CK, ee_addr);
-               outb_p(EE_ASIC|EE_CS|dataval, ee_addr);
-       }
-
-       /* Terminate the ASIC access. */
-       outb(EE_ASIC|EE_DI, ee_addr);
-       outb(EE_ASIC|EE_DI| EE_CK, ee_addr);
-       outb(EE_ASIC|EE_DI, ee_addr);
-
-       outb(0, ee_addr);
-}
-
-/*====================================================================*/
-
-static void set_misc_reg(struct net_device *dev)
-{
-    unsigned int nic_base = dev->base_addr;
-    pcnet_dev_t *info = PRIV(dev);
-    u_char tmp;
-
-    if (info->flags & HAS_MISC_REG) {
-       tmp = inb_p(nic_base + PCNET_MISC) & ~3;
-       if (dev->if_port == 2)
-           tmp |= 1;
-       if (info->flags & USE_BIG_BUF)
-           tmp |= 2;
-       if (info->flags & HAS_IBM_MISC)
-           tmp |= 8;
-       outb_p(tmp, nic_base + PCNET_MISC);
-    }
-    if (info->flags & IS_DL10022) {
-       if (info->flags & HAS_MII) {
-           /* Advertise 100F, 100H, 10F, 10H */
-           mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1);
-           /* Restart MII autonegotiation */
-           mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000);
-           mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200);
-           info->mii_reset = jiffies;
-       } else {
-           outb(full_duplex ? 4 : 0, nic_base + DLINK_DIAG);
-       }
-    } else if (info->flags & IS_DL10019) {
-       /* Advertise 100F, 100H, 10F, 10H */
-       mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1);
-       /* Restart MII autonegotiation */
-       mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000);
-       mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200);
-    }
-}
-
-/*====================================================================*/
-
-static void mii_phy_probe(struct net_device *dev)
-{
-    pcnet_dev_t *info = PRIV(dev);
-    unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
-    int i;
-    u_int tmp, phyid;
-
-    for (i = 31; i >= 0; i--) {
-       tmp = mdio_read(mii_addr, i, 1);
-       if ((tmp == 0) || (tmp == 0xffff))
-           continue;
-       tmp = mdio_read(mii_addr, i, MII_PHYID_REG1);
-       phyid = tmp << 16;
-       phyid |= mdio_read(mii_addr, i, MII_PHYID_REG2);
-       phyid &= MII_PHYID_REV_MASK;
-       netdev_dbg(dev, "MII at %d is 0x%08x\n", i, phyid);
-       if (phyid == AM79C9XX_HOME_PHY) {
-           info->pna_phy = i;
-       } else if (phyid != AM79C9XX_ETH_PHY) {
-           info->eth_phy = i;
-       }
-    }
-}
-
-static int pcnet_open(struct net_device *dev)
-{
-    int ret;
-    pcnet_dev_t *info = PRIV(dev);
-    struct pcmcia_device *link = info->p_dev;
-    unsigned int nic_base = dev->base_addr;
-
-    dev_dbg(&link->dev, "pcnet_open('%s')\n", dev->name);
-
-    if (!pcmcia_dev_present(link))
-       return -ENODEV;
-
-    set_misc_reg(dev);
-
-    outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */
-    ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev->name, dev);
-    if (ret)
-           return ret;
-
-    link->open++;
-
-    info->phy_id = info->eth_phy;
-    info->link_status = 0x00;
-    init_timer(&info->watchdog);
-    info->watchdog.function = ei_watchdog;
-    info->watchdog.data = (u_long)dev;
-    info->watchdog.expires = jiffies + HZ;
-    add_timer(&info->watchdog);
-
-    return ei_open(dev);
-} /* pcnet_open */
-
-/*====================================================================*/
-
-static int pcnet_close(struct net_device *dev)
-{
-    pcnet_dev_t *info = PRIV(dev);
-    struct pcmcia_device *link = info->p_dev;
-
-    dev_dbg(&link->dev, "pcnet_close('%s')\n", dev->name);
-
-    ei_close(dev);
-    free_irq(dev->irq, dev);
-
-    link->open--;
-    netif_stop_queue(dev);
-    del_timer_sync(&info->watchdog);
-
-    return 0;
-} /* pcnet_close */
-
-/*======================================================================
-
-    Hard reset the card.  This used to pause for the same period that
-    a 8390 reset command required, but that shouldn't be necessary.
-
-======================================================================*/
-
-static void pcnet_reset_8390(struct net_device *dev)
-{
-    unsigned int nic_base = dev->base_addr;
-    int i;
-
-    ei_status.txing = ei_status.dmaing = 0;
-
-    outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, nic_base + E8390_CMD);
-
-    outb(inb(nic_base + PCNET_RESET), nic_base + PCNET_RESET);
-
-    for (i = 0; i < 100; i++) {
-       if ((inb_p(nic_base+EN0_ISR) & ENISR_RESET) != 0)
-           break;
-       udelay(100);
-    }
-    outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
-
-    if (i == 100)
-       netdev_err(dev, "pcnet_reset_8390() did not complete.\n");
-
-    set_misc_reg(dev);
-
-} /* pcnet_reset_8390 */
-
-/*====================================================================*/
-
-static int set_config(struct net_device *dev, struct ifmap *map)
-{
-    pcnet_dev_t *info = PRIV(dev);
-    if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
-       if (!(info->flags & HAS_MISC_REG))
-           return -EOPNOTSUPP;
-       else if ((map->port < 1) || (map->port > 2))
-           return -EINVAL;
-       dev->if_port = map->port;
-       netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]);
-       NS8390_init(dev, 1);
-    }
-    return 0;
-}
-
-/*====================================================================*/
-
-static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
-{
-    struct net_device *dev = dev_id;
-    pcnet_dev_t *info;
-    irqreturn_t ret = ei_interrupt(irq, dev_id);
-
-    if (ret == IRQ_HANDLED) {
-           info = PRIV(dev);
-           info->stale = 0;
-    }
-    return ret;
-}
-
-static void ei_watchdog(u_long arg)
-{
-    struct net_device *dev = (struct net_device *)arg;
-    pcnet_dev_t *info = PRIV(dev);
-    unsigned int nic_base = dev->base_addr;
-    unsigned int mii_addr = nic_base + DLINK_GPIO;
-    u_short link;
-
-    if (!netif_device_present(dev)) goto reschedule;
-
-    /* Check for pending interrupt with expired latency timer: with
-       this, we can limp along even if the interrupt is blocked */
-    if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
-       if (!info->fast_poll)
-           netdev_info(dev, "interrupt(s) dropped!\n");
-       ei_irq_wrapper(dev->irq, dev);
-       info->fast_poll = HZ;
-    }
-    if (info->fast_poll) {
-       info->fast_poll--;
-       info->watchdog.expires = jiffies + 1;
-       add_timer(&info->watchdog);
-       return;
-    }
-
-    if (!(info->flags & HAS_MII))
-       goto reschedule;
-
-    mdio_read(mii_addr, info->phy_id, 1);
-    link = mdio_read(mii_addr, info->phy_id, 1);
-    if (!link || (link == 0xffff)) {
-       if (info->eth_phy) {
-           info->phy_id = info->eth_phy = 0;
-       } else {
-           netdev_info(dev, "MII is missing!\n");
-           info->flags &= ~HAS_MII;
-       }
-       goto reschedule;
-    }
-
-    link &= 0x0004;
-    if (link != info->link_status) {
-       u_short p = mdio_read(mii_addr, info->phy_id, 5);
-       netdev_info(dev, "%s link beat\n", link ? "found" : "lost");
-       if (link && (info->flags & IS_DL10022)) {
-           /* Disable collision detection on full duplex links */
-           outb((p & 0x0140) ? 4 : 0, nic_base + DLINK_DIAG);
-       } else if (link && (info->flags & IS_DL10019)) {
-           /* Disable collision detection on full duplex links */
-           write_asic(dev->base_addr, 4, (p & 0x140) ? DL19FDUPLX : 0);
-       }
-       if (link) {
-           if (info->phy_id == info->eth_phy) {
-               if (p)
-                   netdev_info(dev, "autonegotiation complete: "
-                          "%sbaseT-%cD selected\n",
-                          ((p & 0x0180) ? "100" : "10"),
-                          ((p & 0x0140) ? 'F' : 'H'));
-               else
-                   netdev_info(dev, "link partner did not autonegotiate\n");
-           }
-           NS8390_init(dev, 1);
-       }
-       info->link_status = link;
-    }
-    if (info->pna_phy && time_after(jiffies, info->mii_reset + 6*HZ)) {
-       link = mdio_read(mii_addr, info->eth_phy, 1) & 0x0004;
-       if (((info->phy_id == info->pna_phy) && link) ||
-           ((info->phy_id != info->pna_phy) && !link)) {
-           /* isolate this MII and try flipping to the other one */
-           mdio_write(mii_addr, info->phy_id, 0, 0x0400);
-           info->phy_id ^= info->pna_phy ^ info->eth_phy;
-           netdev_info(dev, "switched to %s transceiver\n",
-                  (info->phy_id == info->eth_phy) ? "ethernet" : "PNA");
-           mdio_write(mii_addr, info->phy_id, 0,
-                      (info->phy_id == info->eth_phy) ? 0x1000 : 0);
-           info->link_status = 0;
-           info->mii_reset = jiffies;
-       }
-    }
-
-reschedule:
-    info->watchdog.expires = jiffies + HZ;
-    add_timer(&info->watchdog);
-}
-
-/*====================================================================*/
-
-
-static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-    pcnet_dev_t *info = PRIV(dev);
-    struct mii_ioctl_data *data = if_mii(rq);
-    unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
-
-    if (!(info->flags & (IS_DL10019|IS_DL10022)))
-       return -EINVAL;
-
-    switch (cmd) {
-    case SIOCGMIIPHY:
-       data->phy_id = info->phy_id;
-    case SIOCGMIIREG:          /* Read MII PHY register. */
-       data->val_out = mdio_read(mii_addr, data->phy_id, data->reg_num & 0x1f);
-       return 0;
-    case SIOCSMIIREG:          /* Write MII PHY register. */
-       mdio_write(mii_addr, data->phy_id, data->reg_num & 0x1f, data->val_in);
-       return 0;
-    }
-    return -EOPNOTSUPP;
-}
-
-/*====================================================================*/
-
-static void dma_get_8390_hdr(struct net_device *dev,
-                            struct e8390_pkt_hdr *hdr,
-                            int ring_page)
-{
-    unsigned int nic_base = dev->base_addr;
-
-    if (ei_status.dmaing) {
-       netdev_notice(dev, "DMAing conflict in dma_block_input."
-              "[DMAstat:%1x][irqlock:%1x]\n",
-              ei_status.dmaing, ei_status.irqlock);
-       return;
-    }
-
-    ei_status.dmaing |= 0x01;
-    outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD);
-    outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
-    outb_p(0, nic_base + EN0_RCNTHI);
-    outb_p(0, nic_base + EN0_RSARLO);          /* On page boundary */
-    outb_p(ring_page, nic_base + EN0_RSARHI);
-    outb_p(E8390_RREAD+E8390_START, nic_base + PCNET_CMD);
-
-    insw(nic_base + PCNET_DATAPORT, hdr,
-           sizeof(struct e8390_pkt_hdr)>>1);
-    /* Fix for big endian systems */
-    hdr->count = le16_to_cpu(hdr->count);
-
-    outb_p(ENISR_RDC, nic_base + EN0_ISR);     /* Ack intr. */
-    ei_status.dmaing &= ~0x01;
-}
-
-/*====================================================================*/
-
-static void dma_block_input(struct net_device *dev, int count,
-                           struct sk_buff *skb, int ring_offset)
-{
-    unsigned int nic_base = dev->base_addr;
-    int xfer_count = count;
-    char *buf = skb->data;
-
-    if ((ei_debug > 4) && (count != 4))
-       netdev_dbg(dev, "[bi=%d]\n", count+4);
-    if (ei_status.dmaing) {
-       netdev_notice(dev, "DMAing conflict in dma_block_input."
-              "[DMAstat:%1x][irqlock:%1x]\n",
-              ei_status.dmaing, ei_status.irqlock);
-       return;
-    }
-    ei_status.dmaing |= 0x01;
-    outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD);
-    outb_p(count & 0xff, nic_base + EN0_RCNTLO);
-    outb_p(count >> 8, nic_base + EN0_RCNTHI);
-    outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
-    outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
-    outb_p(E8390_RREAD+E8390_START, nic_base + PCNET_CMD);
-
-    insw(nic_base + PCNET_DATAPORT,buf,count>>1);
-    if (count & 0x01)
-       buf[count-1] = inb(nic_base + PCNET_DATAPORT), xfer_count++;
-
-    /* This was for the ALPHA version only, but enough people have been
-       encountering problems that it is still here. */
-#ifdef PCMCIA_DEBUG
-    if (ei_debug > 4) {                /* DMA termination address check... */
-       int addr, tries = 20;
-       do {
-           /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
-              -- it's broken for Rx on some cards! */
-           int high = inb_p(nic_base + EN0_RSARHI);
-           int low = inb_p(nic_base + EN0_RSARLO);
-           addr = (high << 8) + low;
-           if (((ring_offset + xfer_count) & 0xff) == (addr & 0xff))
-               break;
-       } while (--tries > 0);
-       if (tries <= 0)
-           netdev_notice(dev, "RX transfer address mismatch,"
-                  "%#4.4x (expected) vs. %#4.4x (actual).\n",
-                  ring_offset + xfer_count, addr);
-    }
-#endif
-    outb_p(ENISR_RDC, nic_base + EN0_ISR);     /* Ack intr. */
-    ei_status.dmaing &= ~0x01;
-} /* dma_block_input */
-
-/*====================================================================*/
-
-static void dma_block_output(struct net_device *dev, int count,
-                            const u_char *buf, const int start_page)
-{
-    unsigned int nic_base = dev->base_addr;
-    pcnet_dev_t *info = PRIV(dev);
-#ifdef PCMCIA_DEBUG
-    int retries = 0;
-#endif
-    u_long dma_start;
-
-#ifdef PCMCIA_DEBUG
-    if (ei_debug > 4)
-       netdev_dbg(dev, "[bo=%d]\n", count);
-#endif
-
-    /* Round the count up for word writes.  Do we need to do this?
-       What effect will an odd byte count have on the 8390?
-       I should check someday. */
-    if (count & 0x01)
-       count++;
-    if (ei_status.dmaing) {
-       netdev_notice(dev, "DMAing conflict in dma_block_output."
-              "[DMAstat:%1x][irqlock:%1x]\n",
-              ei_status.dmaing, ei_status.irqlock);
-       return;
-    }
-    ei_status.dmaing |= 0x01;
-    /* We should already be in page 0, but to be safe... */
-    outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base+PCNET_CMD);
-
-#ifdef PCMCIA_DEBUG
-  retry:
-#endif
-
-    outb_p(ENISR_RDC, nic_base + EN0_ISR);
-
-    /* Now the normal output. */
-    outb_p(count & 0xff, nic_base + EN0_RCNTLO);
-    outb_p(count >> 8,   nic_base + EN0_RCNTHI);
-    outb_p(0x00, nic_base + EN0_RSARLO);
-    outb_p(start_page, nic_base + EN0_RSARHI);
-
-    outb_p(E8390_RWRITE+E8390_START, nic_base + PCNET_CMD);
-    outsw(nic_base + PCNET_DATAPORT, buf, count>>1);
-
-    dma_start = jiffies;
-
-#ifdef PCMCIA_DEBUG
-    /* This was for the ALPHA version only, but enough people have been
-       encountering problems that it is still here. */
-    if (ei_debug > 4) {        /* DMA termination address check... */
-       int addr, tries = 20;
-       do {
-           int high = inb_p(nic_base + EN0_RSARHI);
-           int low = inb_p(nic_base + EN0_RSARLO);
-           addr = (high << 8) + low;
-           if ((start_page << 8) + count == addr)
-               break;
-       } while (--tries > 0);
-       if (tries <= 0) {
-           netdev_notice(dev, "Tx packet transfer address mismatch,"
-                  "%#4.4x (expected) vs. %#4.4x (actual).\n",
-                  (start_page << 8) + count, addr);
-           if (retries++ == 0)
-               goto retry;
-       }
-    }
-#endif
-
-    while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
-       if (time_after(jiffies, dma_start + PCNET_RDC_TIMEOUT)) {
-           netdev_notice(dev, "timeout waiting for Tx RDC.\n");
-           pcnet_reset_8390(dev);
-           NS8390_init(dev, 1);
-           break;
-       }
-
-    outb_p(ENISR_RDC, nic_base + EN0_ISR);     /* Ack intr. */
-    if (info->flags & DELAY_OUTPUT)
-       udelay((long)delay_time);
-    ei_status.dmaing &= ~0x01;
-}
-
-/*====================================================================*/
-
-static int setup_dma_config(struct pcmcia_device *link, int start_pg,
-                           int stop_pg)
-{
-    struct net_device *dev = link->priv;
-
-    ei_status.tx_start_page = start_pg;
-    ei_status.rx_start_page = start_pg + TX_PAGES;
-    ei_status.stop_page = stop_pg;
-
-    /* set up block i/o functions */
-    ei_status.get_8390_hdr = dma_get_8390_hdr;
-    ei_status.block_input = dma_block_input;
-    ei_status.block_output = dma_block_output;
-
-    return 0;
-}
-
-/*====================================================================*/
-
-static void copyin(void *dest, void __iomem *src, int c)
-{
-    u_short *d = dest;
-    u_short __iomem *s = src;
-    int odd;
-
-    if (c <= 0)
-       return;
-    odd = (c & 1); c >>= 1;
-
-    if (c) {
-       do { *d++ = __raw_readw(s++); } while (--c);
-    }
-    /* get last byte by fetching a word and masking */
-    if (odd)
-       *((u_char *)d) = readw(s) & 0xff;
-}
-
-static void copyout(void __iomem *dest, const void *src, int c)
-{
-    u_short __iomem *d = dest;
-    const u_short *s = src;
-    int odd;
-
-    if (c <= 0)
-       return;
-    odd = (c & 1); c >>= 1;
-
-    if (c) {
-       do { __raw_writew(*s++, d++); } while (--c);
-    }
-    /* copy last byte doing a read-modify-write */
-    if (odd)
-       writew((readw(d) & 0xff00) | *(u_char *)s, d);
-}
-
-/*====================================================================*/
-
-static void shmem_get_8390_hdr(struct net_device *dev,
-                              struct e8390_pkt_hdr *hdr,
-                              int ring_page)
-{
-    void __iomem *xfer_start = ei_status.mem + (TX_PAGES<<8)
-                               + (ring_page << 8)
-                               - (ei_status.rx_start_page << 8);
-
-    copyin(hdr, xfer_start, sizeof(struct e8390_pkt_hdr));
-    /* Fix for big endian systems */
-    hdr->count = le16_to_cpu(hdr->count);
-}
-
-/*====================================================================*/
-
-static void shmem_block_input(struct net_device *dev, int count,
-                             struct sk_buff *skb, int ring_offset)
-{
-    void __iomem *base = ei_status.mem;
-    unsigned long offset = (TX_PAGES<<8) + ring_offset
-                               - (ei_status.rx_start_page << 8);
-    char *buf = skb->data;
-
-    if (offset + count > ei_status.priv) {
-       /* We must wrap the input move. */
-       int semi_count = ei_status.priv - offset;
-       copyin(buf, base + offset, semi_count);
-       buf += semi_count;
-       offset = TX_PAGES<<8;
-       count -= semi_count;
-    }
-    copyin(buf, base + offset, count);
-}
-
-/*====================================================================*/
-
-static void shmem_block_output(struct net_device *dev, int count,
-                              const u_char *buf, const int start_page)
-{
-    void __iomem *shmem = ei_status.mem + (start_page << 8);
-    shmem -= ei_status.tx_start_page << 8;
-    copyout(shmem, buf, count);
-}
-
-/*====================================================================*/
-
-static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
-                             int stop_pg, int cm_offset)
-{
-    struct net_device *dev = link->priv;
-    pcnet_dev_t *info = PRIV(dev);
-    int i, window_size, offset, ret;
-
-    window_size = (stop_pg - start_pg) << 8;
-    if (window_size > 32 * 1024)
-       window_size = 32 * 1024;
-
-    /* Make sure it's a power of two.  */
-    window_size = roundup_pow_of_two(window_size);
-
-    /* Allocate a memory window */
-    link->resource[3]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
-    link->resource[3]->flags |= WIN_USE_WAIT;
-    link->resource[3]->start = 0; link->resource[3]->end = window_size;
-    ret = pcmcia_request_window(link, link->resource[3], mem_speed);
-    if (ret)
-           goto failed;
-
-    offset = (start_pg << 8) + cm_offset;
-    offset -= offset % window_size;
-    ret = pcmcia_map_mem_page(link, link->resource[3], offset);
-    if (ret)
-           goto failed;
-
-    /* Try scribbling on the buffer */
-    info->base = ioremap(link->resource[3]->start,
-                       resource_size(link->resource[3]));
-    for (i = 0; i < (TX_PAGES<<8); i += 2)
-       __raw_writew((i>>1), info->base+offset+i);
-    udelay(100);
-    for (i = 0; i < (TX_PAGES<<8); i += 2)
-       if (__raw_readw(info->base+offset+i) != (i>>1)) break;
-    pcnet_reset_8390(dev);
-    if (i != (TX_PAGES<<8)) {
-       iounmap(info->base);
-       pcmcia_release_window(link, link->resource[3]);
-       info->base = NULL;
-       goto failed;
-    }
-
-    ei_status.mem = info->base + offset;
-    ei_status.priv = resource_size(link->resource[3]);
-    dev->mem_start = (u_long)ei_status.mem;
-    dev->mem_end = dev->mem_start + resource_size(link->resource[3]);
-
-    ei_status.tx_start_page = start_pg;
-    ei_status.rx_start_page = start_pg + TX_PAGES;
-    ei_status.stop_page = start_pg + (
-           (resource_size(link->resource[3]) - offset) >> 8);
-
-    /* set up block i/o functions */
-    ei_status.get_8390_hdr = shmem_get_8390_hdr;
-    ei_status.block_input = shmem_block_input;
-    ei_status.block_output = shmem_block_output;
-
-    info->flags |= USE_SHMEM;
-    return 0;
-
-failed:
-    return 1;
-}
-
-/*====================================================================*/
-
-static const struct pcmcia_device_id pcnet_ids[] = {
-       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0057, 0x0021),
-       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0104, 0x000a),
-       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0xea15),
-       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0x3341),
-       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0xc0ab),
-       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x021b, 0x0101),
-       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x08a1, 0xc0ab),
-       PCMCIA_PFC_DEVICE_PROD_ID12(0, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
-       PCMCIA_PFC_DEVICE_PROD_ID12(0, "ATKK", "LM33-PCM-T", 0xba9eb7e2, 0x077c174e),
-       PCMCIA_PFC_DEVICE_PROD_ID12(0, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
-       PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
-       PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
-       PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
-       PCMCIA_PFC_DEVICE_PROD_ID12(0, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
-       PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
-       PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
-       PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card       ", 0xb569a6e5, 0x5bd4ff2c),
-       PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3),
-       PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15),
-       PCMCIA_MFC_DEVICE_PROD_ID123(0, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f),
-       PCMCIA_MFC_DEVICE_PROD_ID2(0, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
-       PCMCIA_DEVICE_MANF_CARD(0x0057, 0x1004),
-       PCMCIA_DEVICE_MANF_CARD(0x0104, 0x000d),
-       PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0075),
-       PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0145),
-       PCMCIA_DEVICE_MANF_CARD(0x0149, 0x0230),
-       PCMCIA_DEVICE_MANF_CARD(0x0149, 0x4530),
-       PCMCIA_DEVICE_MANF_CARD(0x0149, 0xc1ab),
-       PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0110),
-       PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x8041),
-       PCMCIA_DEVICE_MANF_CARD(0x0213, 0x2452),
-       PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0300),
-       PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0307),
-       PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030a),
-       PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103),
-       PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121),
-       PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941),
-       PCMCIA_DEVICE_PROD_ID1234("Socket", "CF 10/100 Ethernet Card", "Revision B", "05/11/06", 0xb38bcc2e, 0x4de88352, 0xeaca6c8d, 0x7e57c22e),
-       PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b),
-       PCMCIA_DEVICE_PROD_ID123("CNet  ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b),
-       PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e),
-       PCMCIA_DEVICE_PROD_ID123("Edimax Technology Inc.", "PCMCIA", "Ethernet Card", 0x738a0019, 0x281f1c5d, 0x5e9d92c0),
-       PCMCIA_DEVICE_PROD_ID123("EFA   ", "EFA207", "ETHERNET", 0x3d294be4, 0xeb9aab6c, 0x3ff7175b),
-       PCMCIA_DEVICE_PROD_ID123("I-O DATA", "PCLA", "ETHERNET", 0x1d55d7ec, 0xe4c64d34, 0x3ff7175b),
-       PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCLATE", "ETHERNET", 0x547e66dc, 0x6b260753, 0x3ff7175b),
-       PCMCIA_DEVICE_PROD_ID123("KingMax Technology Inc.", "EN10-T2", "PCMCIA Ethernet Card", 0x932b7189, 0x699e4436, 0x6f6652e0),
-       PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2216", 0x281f1c5d, 0xd4cd2f20, 0xb87add82),
-       PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2620", 0x281f1c5d, 0xd4cd2f20, 0x7d3d83a8),
-       PCMCIA_DEVICE_PROD_ID1("2412LAN", 0x67f236ab),
-       PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2212", 0xdfc6b5b2, 0xcb112a11),
-       PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2216-PCMCIA-ETHERNET", 0xdfc6b5b2, 0x5542bfff),
-       PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA100-PCM-T V2 100/10M LAN PC Card", 0xbb7fbdd7, 0xcd91cc68),
-       PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA100-PCM V2", 0x36634a66, 0xc6d05997),
-       PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA-PCM_V2", 0xbb7fBdd7, 0x28e299f8),
-       PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA-PCM V3", 0x36634a66, 0x62241d96),
-       PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8010", 0x5070a7f9, 0x82f96e96),
-       PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8610", 0x5070a7f9, 0x86741224),
-       PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002", 0x93b15570, 0x75ec3efb),
-       PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002T", 0x93b15570, 0x461c5247),
-       PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8010", 0x93b15570, 0x82f96e96),
-       PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet", 0x578ba6e7, 0x0a9888c1),
-       PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet 10/100", 0x578ba6e7, 0x939fedbd),
-       PCMCIA_DEVICE_PROD_ID12("AROWANA", "PCMCIA Ethernet LAN Card", 0x313adbc8, 0x08d9f190),
-       PCMCIA_DEVICE_PROD_ID12("ASANTE", "FriendlyNet PC Card", 0x3a7ade0f, 0x41c64504),
-       PCMCIA_DEVICE_PROD_ID12("Billionton", "LNT-10TB", 0x552ab682, 0xeeb1ba6a),
-       PCMCIA_DEVICE_PROD_ID12("CF", "10Base-Ethernet", 0x44ebf863, 0x93ae4d79),
-       PCMCIA_DEVICE_PROD_ID12("CNet", "CN40BC Ethernet", 0xbc477dde, 0xfba775a7),
-       PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "BASEline PCMCIA 10 MBit Ethernetadapter", 0xfa2e424d, 0xe9190d8a),
-       PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "FASTline PCMCIA 10/100 Fast-Ethernet", 0xfa2e424d, 0x3953d9b9),
-       PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722),
-       PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2),
-       PCMCIA_DEVICE_PROD_ID12("corega", "Ether CF-TD", 0x0a21501a, 0x6589340a),
-       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether CF-TD LAN Card", 0x5261440f, 0x8797663b),
-       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd),
-       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d),
-       PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d),
-       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa),
-       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-TD", 0x5261440f, 0x47d5ca83),
-       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9),
-       PCMCIA_DEVICE_PROD_ID12("Corega,K.K.", "Ethernet LAN Card", 0x110d26d9, 0x9fd2f0a2),
-       PCMCIA_DEVICE_PROD_ID12("corega,K.K.", "Ethernet LAN Card", 0x9791a90e, 0x9fd2f0a2),
-       PCMCIA_DEVICE_PROD_ID12("corega K.K.", "(CG-LAPCCTXD)", 0x5261440f, 0x73ec0d88),
-       PCMCIA_DEVICE_PROD_ID12("CouplerlessPCMCIA", "100BASE", 0xee5af0ad, 0x7c2add04),
-       PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-010", 0x77008979, 0x9d8d445d),
-       PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-110E 10/100M LAN Card", 0x77008979, 0xfd184814),
-       PCMCIA_DEVICE_PROD_ID12("DataTrek.", "NetCard ", 0x5cd66d9d, 0x84697ce0),
-       PCMCIA_DEVICE_PROD_ID12("Dayna Communications, Inc.", "CommuniCard E", 0x0c629325, 0xb4e7dbaf),
-       PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100", 0x697403d8, 0xe160b995),
-       PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100 Dongless", 0x697403d8, 0xa6d3b233),
-       PCMCIA_DEVICE_PROD_ID12("DIGITAL", "DEPCM-XX", 0x69616cb3, 0xe600e76e),
-       PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-650", 0x1a424a1c, 0xf28c8398),
-       PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660", 0x1a424a1c, 0xd9a1d05b),
-       PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660+", 0x1a424a1c, 0x50dcd0ec),
-       PCMCIA_DEVICE_PROD_ID12("D-Link", "DFE-650", 0x1a424a1c, 0x0f0073f9),
-       PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 PC Card", 0x725b842d, 0xf1efee84),
-       PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 Port Attached PC Card", 0x725b842d, 0x2db1f8e9),
-       PCMCIA_DEVICE_PROD_ID12("Dynalink", "L10BC", 0x55632fd5, 0xdc65f2b1),
-       PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10BC", 0x6a26d1cf, 0xdc65f2b1),
-       PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10C", 0x6a26d1cf, 0xc4f84efb),
-       PCMCIA_DEVICE_PROD_ID12("E-CARD", "E-CARD", 0x6701da11, 0x6701da11),
-       PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet 10BaseT card", 0x53c864c6, 0xedd059f6),
-       PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet Combo card", 0x53c864c6, 0x929c486c),
-       PCMCIA_DEVICE_PROD_ID12("Ethernet", "Adapter", 0x00b2e941, 0x4b0d829e),
-       PCMCIA_DEVICE_PROD_ID12("Ethernet Adapter", "E2000 PCMCIA Ethernet", 0x96767301, 0x71fbbc61),
-       PCMCIA_DEVICE_PROD_ID12("Ethernet PCMCIA adapter", "EP-210", 0x8dd86181, 0xf2b52517),
-       PCMCIA_DEVICE_PROD_ID12("Fast Ethernet", "Adapter", 0xb4be14e3, 0x4b0d829e),
-       PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2000", 0x2a151fac, 0xf00555cb),
-       PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2220", 0x2a151fac, 0xc1b7e327),
-       PCMCIA_DEVICE_PROD_ID12("GVC", "NIC-2000p", 0x76e171bd, 0x6eb1c947),
-       PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "Ethernet", 0xe3736c88, 0x00b2e941),
-       PCMCIA_DEVICE_PROD_ID12("IC-CARD", "IC-CARD", 0x60cb09a6, 0x60cb09a6),
-       PCMCIA_DEVICE_PROD_ID12("IC-CARD+", "IC-CARD+", 0x93693494, 0x93693494),
-       PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCETTX", 0x547e66dc, 0x6fc5459b),
-       PCMCIA_DEVICE_PROD_ID12("iPort", "10/100 Ethernet Card", 0x56c538d2, 0x11b0ffc0),
-       PCMCIA_DEVICE_PROD_ID12("KANSAI ELECTRIC CO.,LTD", "KLA-PCM/T", 0xb18dc3b4, 0xcc51a956),
-       PCMCIA_DEVICE_PROD_ID12("KENTRONICS", "KEP-230", 0xaf8144c9, 0x868f6616),
-       PCMCIA_DEVICE_PROD_ID12("KCI", "PE520 PCMCIA Ethernet Adapter", 0xa89b87d3, 0x1eb88e64),
-       PCMCIA_DEVICE_PROD_ID12("KINGMAX", "EN10T2T", 0x7bcb459a, 0xa5c81fa5),
-       PCMCIA_DEVICE_PROD_ID12("Kingston", "KNE-PC2", 0x1128e633, 0xce2a89b3),
-       PCMCIA_DEVICE_PROD_ID12("Kingston Technology Corp.", "EtheRx PC Card Ethernet Adapter", 0x313c7be3, 0x0afb54a2),
-       PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-10/100CD", 0x1b7827b2, 0xcda71d1c),
-       PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDF", 0x1b7827b2, 0xfec71e40),
-       PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDL/T", 0x1b7827b2, 0x79fba4f7),
-       PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDS", 0x1b7827b2, 0x931afaab),
-       PCMCIA_DEVICE_PROD_ID12("LEMEL", "LM-N89TX PRO", 0xbbefb52f, 0xd2897a97),
-       PCMCIA_DEVICE_PROD_ID12("Linksys", "Combo PCMCIA EthernetCard (EC2T)", 0x0733cc81, 0x32ee8c78),
-       PCMCIA_DEVICE_PROD_ID12("LINKSYS", "E-CARD", 0xf7cb0b07, 0x6701da11),
-       PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 Integrated PC Card (PCM100)", 0x0733cc81, 0x453c3f9d),
-       PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100)", 0x0733cc81, 0x66c5a389),
-       PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V2)", 0x0733cc81, 0x3a3b28e9),
-       PCMCIA_DEVICE_PROD_ID12("Linksys", "HomeLink Phoneline + 10/100 Network PC Card (PCM100H1)", 0x733cc81, 0x7a3e5c3a),
-       PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TX", 0x88fcdeda, 0x6d772737),
-       PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TE", 0x88fcdeda, 0x0e714bee),
-       PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN20T", 0x88fcdeda, 0x81090922),
-       PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN10TE", 0x88fcdeda, 0xc1e2521c),
-       PCMCIA_DEVICE_PROD_ID12("LONGSHINE", "PCMCIA Ethernet Card", 0xf866b0b0, 0x6f6652e0),
-       PCMCIA_DEVICE_PROD_ID12("MACNICA", "ME1-JEIDA", 0x20841b68, 0xaf8a3578),
-       PCMCIA_DEVICE_PROD_ID12("Macsense", "MPC-10", 0xd830297f, 0xd265c307),
-       PCMCIA_DEVICE_PROD_ID12("Matsushita Electric Industrial Co.,LTD.", "CF-VEL211", 0x44445376, 0x8ded41d4),
-       PCMCIA_DEVICE_PROD_ID12("MAXTECH", "PCN2000", 0x78d64bc0, 0xca0ca4b8),
-       PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-T", 0x481e0094, 0xa2eb0cf3),
-       PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-TX", 0x481e0094, 0x41a6916c),
-       PCMCIA_DEVICE_PROD_ID12("Microcom C.E.", "Travel Card LAN 10/100", 0x4b91cec7, 0xe70220d6),
-       PCMCIA_DEVICE_PROD_ID12("Microdyne", "NE4200", 0x2e6da59b, 0x0478e472),
-       PCMCIA_DEVICE_PROD_ID12("MIDORI ELEC.", "LT-PCMT", 0x648d55c1, 0xbde526c7),
-       PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover 4100", 0x36e1191f, 0x60c229b9),
-       PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover NE4100", 0x36e1191f, 0xa6617ec8),
-       PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J12", 0x18df0ba0, 0xbc912d76),
-       PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA410TX", 0x9aa79dc3, 0x60e5bc0e),
-       PCMCIA_DEVICE_PROD_ID12("Network Everywhere", "Fast Ethernet 10/100 PC Card", 0x820a67b6, 0x31ed1a5f),
-       PCMCIA_DEVICE_PROD_ID12("NextCom K.K.", "Next Hawk", 0xaedaec74, 0xad050ef1),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100Mbps Ethernet Card", 0x281f1c5d, 0x6e41773b),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet", 0x281f1c5d, 0x00b2e941),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET", 0x281f1c5d, 0x3ff7175b),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet 10BaseT Card", 0x281f1c5d, 0x4de2f6c8),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Card", 0x281f1c5d, 0x5e9d92c0),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Combo card", 0x281f1c5d, 0x929c486c),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET V1.0", 0x281f1c5d, 0x4d8817c8),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEthernet", 0x281f1c5d, 0xfe871eeb),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast-Ethernet", 0x281f1c5d, 0x45f1f3b4),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FAST ETHERNET CARD", 0x281f1c5d, 0xec5dbca7),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA LAN", "Ethernet", 0x7500e246, 0x00b2e941),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "LNT-10TN", 0x281f1c5d, 0xe707f641),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "UE2212", 0x281f1c5d, 0xbf17199b),
-       PCMCIA_DEVICE_PROD_ID12("PCMCIA", "    Ethernet NE2000 Compatible", 0x281f1c5d, 0x42d5d7e1),
-       PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10baseT 3.3V", 0xebf91155, 0x30074c80),
-       PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50),
-       PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110),
-       PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941),
-       PCMCIA_DEVICE_PROD_ID12("RIOS Systems Co.", "PC CARD3 ETHERNET", 0x7dd33481, 0x10b41826),
-       PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df),
-       PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0),
-       PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd),
-       PCMCIA_DEVICE_PROD_ID12("RPTI LTD.", "EP400", 0xc53ac515, 0x81e39388),
-       PCMCIA_DEVICE_PROD_ID12("SCM", "Ethernet Combo card", 0xbdc3b102, 0x929c486c),
-       PCMCIA_DEVICE_PROD_ID12("Seiko Epson Corp.", "Ethernet", 0x09928730, 0x00b2e941),
-       PCMCIA_DEVICE_PROD_ID12("SMC", "EZCard-10-PCMCIA", 0xc4f8b18b, 0xfb21d265),
-       PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision D", 0xc70a4760, 0x2ade483e),
-       PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision E", 0xc70a4760, 0x5dd978a8),
-       PCMCIA_DEVICE_PROD_ID12("TDK", "LAK-CD031 for PCMCIA", 0x1eae9475, 0x0ed386fa),
-       PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE450T", 0x466b05f0, 0x8b74bc4f),
-       PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE550T", 0x466b05f0, 0x33c8db2a),
-       PCMCIA_DEVICE_PROD_ID13("Hypertec",  "EP401", 0x8787bec7, 0xf6e4a31e),
-       PCMCIA_DEVICE_PROD_ID13("KingMax Technology Inc.", "Ethernet Card", 0x932b7189, 0x5e9d92c0),
-       PCMCIA_DEVICE_PROD_ID13("LONGSHINE", "EP401", 0xf866b0b0, 0xf6e4a31e),
-       PCMCIA_DEVICE_PROD_ID13("Xircom", "CFE-10", 0x2e3ee845, 0x22a49f89),
-       PCMCIA_DEVICE_PROD_ID1("CyQ've 10 Base-T LAN CARD", 0x94faf360),
-       PCMCIA_DEVICE_PROD_ID1("EP-210 PCMCIA LAN CARD.", 0x8850b4de),
-       PCMCIA_DEVICE_PROD_ID1("ETHER-C16", 0x06a8514f),
-       PCMCIA_DEVICE_PROD_ID1("NE2000 Compatible", 0x75b8ad5a),
-       PCMCIA_DEVICE_PROD_ID2("EN-6200P2", 0xa996d078),
-       /* too generic! */
-       /* PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100 Ethernet Card", 0x281f1c5d, 0x11b0ffc0), */
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
-       PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
-       PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
-       PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
-       PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID12("Allied Telesis,K.K", "Ethernet LAN Card", 0x2ad62f3c, 0x9fd2f0a2, "cis/LA-PCM.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "cis/PE520.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "cis/NE2K.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID12("PMX   ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "cis/PE-200.cis"),
-       PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "cis/tamarack.cis"),
-       PCMCIA_DEVICE_PROD_ID12("Ethernet", "CF Size PC Card", 0x00b2e941, 0x43ac239b),
-       PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0",
-               0xb4be14e3, 0x43ac239b, 0x0877b627),
-       PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, pcnet_ids);
-MODULE_FIRMWARE("cis/PCMLM28.cis");
-MODULE_FIRMWARE("cis/DP83903.cis");
-MODULE_FIRMWARE("cis/LA-PCM.cis");
-MODULE_FIRMWARE("cis/PE520.cis");
-MODULE_FIRMWARE("cis/NE2K.cis");
-MODULE_FIRMWARE("cis/PE-200.cis");
-MODULE_FIRMWARE("cis/tamarack.cis");
-
-static struct pcmcia_driver pcnet_driver = {
-       .name           = "pcnet_cs",
-       .probe          = pcnet_probe,
-       .remove         = pcnet_detach,
-       .owner          = THIS_MODULE,
-       .id_table       = pcnet_ids,
-       .suspend        = pcnet_suspend,
-       .resume         = pcnet_resume,
-};
-
-static int __init init_pcnet_cs(void)
-{
-    return pcmcia_register_driver(&pcnet_driver);
-}
-
-static void __exit exit_pcnet_cs(void)
-{
-    pcmcia_unregister_driver(&pcnet_driver);
-}
-
-module_init(init_pcnet_cs);
-module_exit(exit_pcnet_cs);
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
deleted file mode 100644 (file)
index 34934fb..0000000
+++ /dev/null
@@ -1,576 +0,0 @@
-/* smc-mca.c: A SMC Ultra ethernet driver for linux. */
-/*
-    Most of this driver, except for ultramca_probe is nearly
-    verbatim from smc-ultra.c by Donald Becker. The rest is
-    written and copyright 1996 by David Weis, weisd3458@uni.edu
-
-    This is a driver for the SMC Ultra and SMC EtherEZ ethercards.
-
-    This driver uses the cards in the 8390-compatible, shared memory mode.
-    Most of the run-time complexity is handled by the generic code in
-    8390.c.
-
-    This driver enables the shared memory only when doing the actual data
-    transfers to avoid a bug in early version of the card that corrupted
-    data transferred by a AHA1542.
-
-    This driver does not support the programmed-I/O data transfer mode of
-    the EtherEZ.  That support (if available) is smc-ez.c.  Nor does it
-    use the non-8390-compatible "Altego" mode. (No support currently planned.)
-
-    Changelog:
-
-    Paul Gortmaker      : multiple card support for module users.
-    David Weis          : Micro Channel-ized it.
-    Tom Sightler        : Added support for IBM PS/2 Ethernet Adapter/A
-    Christopher Turcksin : Changed MCA-probe so that multiple adapters are
-                          found correctly (Jul 16, 1997)
-    Chris Beauregard    : Tried to merge the two changes above (Dec 15, 1997)
-    Tom Sightler        : Fixed minor detection bug caused by above merge
-    Tom Sightler        : Added support for three more Western Digital
-                          MCA-adapters
-    Tom Sightler        : Added support for 2.2.x mca_find_unused_adapter
-    Hartmut Schmidt     : - Modified parameter detection to handle each
-                            card differently depending on a switch-list
-                          - 'card_ver' removed from the adapter list
-                          - Some minor bug fixes
-*/
-
-#include <linux/mca.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include "8390.h"
-
-#define DRV_NAME "smc-mca"
-
-static int ultramca_open(struct net_device *dev);
-static void ultramca_reset_8390(struct net_device *dev);
-static void ultramca_get_8390_hdr(struct net_device *dev,
-                                  struct e8390_pkt_hdr *hdr,
-                                  int ring_page);
-static void ultramca_block_input(struct net_device *dev, int count,
-                                 struct sk_buff *skb,
-                                 int ring_offset);
-static void ultramca_block_output(struct net_device *dev, int count,
-                                  const unsigned char *buf,
-                                  const int start_page);
-static int ultramca_close_card(struct net_device *dev);
-
-#define START_PG        0x00    /* First page of TX buffer */
-
-#define ULTRA_CMDREG 0      /* Offset to ASIC command register. */
-#define ULTRA_RESET  0x80   /* Board reset, in ULTRA_CMDREG. */
-#define ULTRA_MEMENB 0x40   /* Enable the shared memory. */
-#define ULTRA_NIC_OFFSET 16 /* NIC register offset from the base_addr. */
-#define ULTRA_IO_EXTENT 32
-#define EN0_ERWCNT      0x08  /* Early receive warning count. */
-
-#define _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A            0
-#define _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A            1
-#define _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A              2
-#define _6fc1_WD_Starcard_PLUS_A_WD8003ST_A                            3
-#define _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A                        4
-#define _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A        5
-#define _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A        6
-#define _efe5_IBM_PS2_Adapter_A_for_Ethernet                           7
-
-struct smc_mca_adapters_t {
-       unsigned int id;
-       char *name;
-};
-
-#define MAX_ULTRAMCA_CARDS 4   /* Max number of Ultra cards per module */
-
-static int ultra_io[MAX_ULTRAMCA_CARDS];
-static int ultra_irq[MAX_ULTRAMCA_CARDS];
-MODULE_LICENSE("GPL");
-
-module_param_array(ultra_io, int, NULL, 0);
-module_param_array(ultra_irq, int, NULL, 0);
-MODULE_PARM_DESC(ultra_io, "SMC Ultra/EtherEZ MCA I/O base address(es)");
-MODULE_PARM_DESC(ultra_irq, "SMC Ultra/EtherEZ MCA IRQ number(s)");
-
-static const struct {
-  unsigned int base_addr;
-} addr_table[] = {
-    { 0x0800 },
-    { 0x1800 },
-    { 0x2800 },
-    { 0x3800 },
-    { 0x4800 },
-    { 0x5800 },
-    { 0x6800 },
-    { 0x7800 },
-    { 0x8800 },
-    { 0x9800 },
-    { 0xa800 },
-    { 0xb800 },
-    { 0xc800 },
-    { 0xd800 },
-    { 0xe800 },
-    { 0xf800 }
-};
-
-#define MEM_MASK 64
-
-static const struct {
-  unsigned char mem_index;
-  unsigned long mem_start;
-  unsigned char num_pages;
-} mem_table[] = {
-    { 16, 0x0c0000, 40 },
-    { 18, 0x0c4000, 40 },
-    { 20, 0x0c8000, 40 },
-    { 22, 0x0cc000, 40 },
-    { 24, 0x0d0000, 40 },
-    { 26, 0x0d4000, 40 },
-    { 28, 0x0d8000, 40 },
-    { 30, 0x0dc000, 40 },
-    {144, 0xfc0000, 40 },
-    {148, 0xfc8000, 40 },
-    {154, 0xfd0000, 40 },
-    {156, 0xfd8000, 40 },
-    {  0, 0x0c0000, 20 },
-    {  1, 0x0c2000, 20 },
-    {  2, 0x0c4000, 20 },
-    {  3, 0x0c6000, 20 }
-};
-
-#define IRQ_MASK 243
-static const struct {
-   unsigned char new_irq;
-   unsigned char old_irq;
-} irq_table[] = {
-   {  3,  3 },
-   {  4,  4 },
-   { 10, 10 },
-   { 14, 15 }
-};
-
-static short smc_mca_adapter_ids[] __initdata = {
-       0x61c8,
-       0x61c9,
-       0x6fc0,
-       0x6fc1,
-       0x6fc2,
-       0xefd4,
-       0xefd5,
-       0xefe5,
-       0x0000
-};
-
-static char *smc_mca_adapter_names[] __initdata = {
-       "SMC Ethercard PLUS Elite/A BNC/AUI (WD8013EP/A)",
-       "SMC Ethercard PLUS Elite/A UTP/AUI (WD8013WP/A)",
-       "WD Ethercard PLUS/A (WD8003E/A or WD8003ET/A)",
-       "WD Starcard PLUS/A (WD8003ST/A)",
-       "WD Ethercard PLUS 10T/A (WD8003W/A)",
-       "IBM PS/2 Adapter/A for Ethernet UTP/AUI (WD8013WP/A)",
-       "IBM PS/2 Adapter/A for Ethernet BNC/AUI (WD8013EP/A)",
-       "IBM PS/2 Adapter/A for Ethernet",
-       NULL
-};
-
-static int ultra_found = 0;
-
-
-static const struct net_device_ops ultramca_netdev_ops = {
-       .ndo_open               = ultramca_open,
-       .ndo_stop               = ultramca_close_card,
-
-       .ndo_start_xmit         = ei_start_xmit,
-       .ndo_tx_timeout         = ei_tx_timeout,
-       .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = ei_poll,
-#endif
-};
-
-static int __init ultramca_probe(struct device *gen_dev)
-{
-       unsigned short ioaddr;
-       struct net_device *dev;
-       unsigned char reg4, num_pages;
-       struct mca_device *mca_dev = to_mca_device(gen_dev);
-       char slot = mca_dev->slot;
-       unsigned char pos2 = 0xff, pos3 = 0xff, pos4 = 0xff, pos5 = 0xff;
-       int i, rc;
-       int adapter = mca_dev->index;
-       int tbase = 0;
-       int tirq = 0;
-       int base_addr = ultra_io[ultra_found];
-       int irq = ultra_irq[ultra_found];
-
-       if (base_addr || irq) {
-               printk(KERN_INFO "Probing for SMC MCA adapter");
-               if (base_addr) {
-                       printk(KERN_INFO " at I/O address 0x%04x%c",
-                              base_addr, irq ? ' ' : '\n');
-               }
-               if (irq) {
-                       printk(KERN_INFO "using irq %d\n", irq);
-               }
-       }
-
-       tirq = 0;
-       tbase = 0;
-
-       /* If we're trying to match a specificied irq or io address,
-        * we'll reject the adapter found unless it's the one we're
-        * looking for */
-
-       pos2 = mca_device_read_stored_pos(mca_dev, 2); /* io_addr */
-       pos3 = mca_device_read_stored_pos(mca_dev, 3); /* shared mem */
-       pos4 = mca_device_read_stored_pos(mca_dev, 4); /* ROM bios addr range */
-       pos5 = mca_device_read_stored_pos(mca_dev, 5); /* irq, media and RIPL */
-
-       /* Test the following conditions:
-        * - If an irq parameter is supplied, compare it
-        *   with the irq of the adapter we found
-        * - If a base_addr paramater is given, compare it
-        *   with the base_addr of the adapter we found
-        * - Check that the irq and the base_addr of the
-        *   adapter we found is not already in use by
-        *   this driver
-        */
-
-       switch (mca_dev->index) {
-       case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A:
-       case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A:
-       case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A:
-       case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A:
-               {
-                       tbase = addr_table[(pos2 & 0xf0) >> 4].base_addr;
-                       tirq  = irq_table[(pos5 & 0xc) >> 2].new_irq;
-                       break;
-               }
-       case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A:
-       case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A:
-       case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
-       case _efe5_IBM_PS2_Adapter_A_for_Ethernet:
-               {
-                       tbase = ((pos2 & 0x0fe) * 0x10);
-                       tirq  = irq_table[(pos5 & 3)].old_irq;
-                       break;
-               }
-       }
-
-       if(!tirq || !tbase ||
-          (irq && irq != tirq) ||
-          (base_addr && tbase != base_addr))
-               /* FIXME: we're trying to force the ordering of the
-                * devices here, there should be a way of getting this
-                * to happen */
-               return -ENXIO;
-
-        /* Adapter found. */
-       dev  = alloc_ei_netdev();
-       if(!dev)
-               return -ENODEV;
-
-       SET_NETDEV_DEV(dev, gen_dev);
-       mca_device_set_name(mca_dev, smc_mca_adapter_names[adapter]);
-       mca_device_set_claim(mca_dev, 1);
-
-       printk(KERN_INFO "smc_mca: %s found in slot %d\n",
-                      smc_mca_adapter_names[adapter], slot + 1);
-
-       ultra_found++;
-
-       dev->base_addr = ioaddr = mca_device_transform_ioport(mca_dev, tbase);
-       dev->irq       = mca_device_transform_irq(mca_dev, tirq);
-       dev->mem_start = 0;
-       num_pages      = 40;
-
-       switch (adapter) {      /* card-# in const array above [hs] */
-               case _61c8_SMC_Ethercard_PLUS_Elite_A_BNC_AUI_WD8013EP_A:
-               case _61c9_SMC_Ethercard_PLUS_Elite_A_UTP_AUI_WD8013EP_A:
-               {
-                       for (i = 0; i < 16; i++) { /* taking 16 counts
-                                                   * up to 15 [hs] */
-                               if (mem_table[i].mem_index == (pos3 & ~MEM_MASK)) {
-                                       dev->mem_start = (unsigned long)
-                                         mca_device_transform_memory(mca_dev, (void *)mem_table[i].mem_start);
-                                       num_pages = mem_table[i].num_pages;
-                               }
-                       }
-                       break;
-               }
-               case _6fc0_WD_Ethercard_PLUS_A_WD8003E_A_OR_WD8003ET_A:
-               case _6fc1_WD_Starcard_PLUS_A_WD8003ST_A:
-               case _6fc2_WD_Ethercard_PLUS_10T_A_WD8003W_A:
-               case _efe5_IBM_PS2_Adapter_A_for_Ethernet:
-               {
-                       dev->mem_start = (unsigned long)
-                         mca_device_transform_memory(mca_dev, (void *)((pos3 & 0xfc) * 0x1000));
-                       num_pages = 0x40;
-                       break;
-               }
-               case _efd4_IBM_PS2_Adapter_A_for_Ethernet_UTP_AUI_WD8013WP_A:
-               case _efd5_IBM_PS2_Adapter_A_for_Ethernet_BNC_AUI_WD8013WP_A:
-               {
-                       /* courtesy of gamera@quartz.ocn.ne.jp, pos3 indicates
-                        * the index of the 0x2000 step.
-                        * beware different number of pages [hs]
-                        */
-                       dev->mem_start = (unsigned long)
-                         mca_device_transform_memory(mca_dev, (void *)(0xc0000 + (0x2000 * (pos3 & 0xf))));
-                       num_pages = 0x20 + (2 * (pos3 & 0x10));
-                       break;
-               }
-       }
-
-       /* sanity check, shouldn't happen */
-       if (dev->mem_start == 0) {
-               rc = -ENODEV;
-               goto err_unclaim;
-       }
-
-       if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME)) {
-               rc = -ENODEV;
-               goto err_unclaim;
-       }
-
-       reg4 = inb(ioaddr + 4) & 0x7f;
-       outb(reg4, ioaddr + 4);
-
-       for (i = 0; i < 6; i++)
-               dev->dev_addr[i] = inb(ioaddr + 8 + i);
-
-       printk(KERN_INFO "smc_mca[%d]: Parameters: %#3x, %pM",
-              slot + 1, ioaddr, dev->dev_addr);
-
-       /* Switch from the station address to the alternate register set
-        * and read the useful registers there.
-        */
-
-       outb(0x80 | reg4, ioaddr + 4);
-
-       /* Enable FINE16 mode to avoid BIOS ROM width mismatches @ reboot.
-        */
-
-       outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
-
-       /* Switch back to the station address register set so that
-        * the MS-DOS driver can find the card after a warm boot.
-        */
-
-       outb(reg4, ioaddr + 4);
-
-       dev_set_drvdata(gen_dev, dev);
-
-       /* The 8390 isn't at the base address, so fake the offset
-        */
-
-       dev->base_addr = ioaddr + ULTRA_NIC_OFFSET;
-
-       ei_status.name = "SMC Ultra MCA";
-       ei_status.word16 = 1;
-       ei_status.tx_start_page = START_PG;
-       ei_status.rx_start_page = START_PG + TX_PAGES;
-       ei_status.stop_page = num_pages;
-
-       ei_status.mem = ioremap(dev->mem_start, (ei_status.stop_page - START_PG) * 256);
-       if (!ei_status.mem) {
-               rc = -ENOMEM;
-               goto err_release_region;
-       }
-
-       dev->mem_end = dev->mem_start + (ei_status.stop_page - START_PG) * 256;
-
-       printk(", IRQ %d memory %#lx-%#lx.\n",
-       dev->irq, dev->mem_start, dev->mem_end - 1);
-
-       ei_status.reset_8390 = &ultramca_reset_8390;
-       ei_status.block_input = &ultramca_block_input;
-       ei_status.block_output = &ultramca_block_output;
-       ei_status.get_8390_hdr = &ultramca_get_8390_hdr;
-
-       ei_status.priv = slot;
-
-       dev->netdev_ops = &ultramca_netdev_ops;
-
-       NS8390_init(dev, 0);
-
-       rc = register_netdev(dev);
-       if (rc)
-               goto err_unmap;
-
-       return 0;
-
-err_unmap:
-       iounmap(ei_status.mem);
-err_release_region:
-       release_region(ioaddr, ULTRA_IO_EXTENT);
-err_unclaim:
-       mca_device_set_claim(mca_dev, 0);
-       free_netdev(dev);
-       return rc;
-}
-
-static int ultramca_open(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
-       int retval;
-
-       if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev)))
-               return retval;
-
-       outb(ULTRA_MEMENB, ioaddr); /* Enable memory */
-       outb(0x80, ioaddr + 5);     /* ??? */
-       outb(0x01, ioaddr + 6);     /* Enable interrupts and memory. */
-       outb(0x04, ioaddr + 5);     /* ??? */
-
-       /* Set the early receive warning level in window 0 high enough not
-        * to receive ERW interrupts.
-        */
-
-       /* outb_p(E8390_NODMA + E8390_PAGE0, dev->base_addr);
-        * outb(0xff, dev->base_addr + EN0_ERWCNT);
-        */
-
-       ei_open(dev);
-       return 0;
-}
-
-static void ultramca_reset_8390(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
-
-       outb(ULTRA_RESET, ioaddr);
-       if (ei_debug > 1)
-               printk("resetting Ultra, t=%ld...", jiffies);
-       ei_status.txing = 0;
-
-       outb(0x80, ioaddr + 5);     /* ??? */
-       outb(0x01, ioaddr + 6);     /* Enable interrupts and memory. */
-
-       if (ei_debug > 1)
-               printk("reset done\n");
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
- * we don't need to be concerned with ring wrap as the header will be at
- * the start of a page, so we optimize accordingly.
- */
-
-static void ultramca_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-       void __iomem *hdr_start = ei_status.mem + ((ring_page - START_PG) << 8);
-
-#ifdef notdef
-       /* Officially this is what we are doing, but the readl() is faster */
-       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
-#else
-       ((unsigned int*)hdr)[0] = readl(hdr_start);
-#endif
-}
-
-/* Block input and output are easy on shared memory ethercards, the only
- * complication is when the ring buffer wraps.
- */
-
-static void ultramca_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-       void __iomem *xfer_start = ei_status.mem + ring_offset - START_PG * 256;
-
-       if (ring_offset + count > ei_status.stop_page * 256) {
-               /* We must wrap the input move. */
-               int semi_count = ei_status.stop_page * 256 - ring_offset;
-               memcpy_fromio(skb->data, xfer_start, semi_count);
-               count -= semi_count;
-               memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
-       } else {
-               memcpy_fromio(skb->data, xfer_start, count);
-       }
-
-}
-
-static void ultramca_block_output(struct net_device *dev, int count, const unsigned char *buf,
-                int start_page)
-{
-       void __iomem *shmem = ei_status.mem + ((start_page - START_PG) << 8);
-
-       memcpy_toio(shmem, buf, count);
-}
-
-static int ultramca_close_card(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
-
-       netif_stop_queue(dev);
-
-       if (ei_debug > 1)
-               printk("%s: Shutting down ethercard.\n", dev->name);
-
-       outb(0x00, ioaddr + 6);     /* Disable interrupts. */
-       free_irq(dev->irq, dev);
-
-       NS8390_init(dev, 0);
-       /* We should someday disable shared memory and change to 8-bit mode
-         * "just in case"...
-        */
-
-       return 0;
-}
-
-static int ultramca_remove(struct device *gen_dev)
-{
-       struct mca_device *mca_dev = to_mca_device(gen_dev);
-       struct net_device *dev = dev_get_drvdata(gen_dev);
-
-       if (dev) {
-               /* NB: ultra_close_card() does free_irq */
-               int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
-
-               unregister_netdev(dev);
-               mca_device_set_claim(mca_dev, 0);
-               release_region(ioaddr, ULTRA_IO_EXTENT);
-               iounmap(ei_status.mem);
-               free_netdev(dev);
-       }
-       return 0;
-}
-
-
-static struct mca_driver ultra_driver = {
-       .id_table = smc_mca_adapter_ids,
-       .driver = {
-               .name = "smc-mca",
-               .bus = &mca_bus_type,
-               .probe = ultramca_probe,
-               .remove = ultramca_remove,
-       }
-};
-
-static int __init ultramca_init_module(void)
-{
-       if(!MCA_bus)
-               return -ENXIO;
-
-       mca_register_driver(&ultra_driver);
-
-       return ultra_found ? 0 : -ENXIO;
-}
-
-static void __exit ultramca_cleanup_module(void)
-{
-       mca_unregister_driver(&ultra_driver);
-}
-module_init(ultramca_init_module);
-module_exit(ultramca_cleanup_module);
-
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
deleted file mode 100644 (file)
index ba44ede..0000000
+++ /dev/null
@@ -1,622 +0,0 @@
-/* smc-ultra.c: A SMC Ultra ethernet driver for linux. */
-/*
-       This is a driver for the SMC Ultra and SMC EtherEZ ISA ethercards.
-
-       Written 1993-1998 by Donald Becker.
-
-       Copyright 1993 United States Government as represented by the
-       Director, National Security Agency.
-
-       This software may be used and distributed according to the terms
-       of the GNU General Public License, incorporated herein by reference.
-
-       The author may be reached as becker@scyld.com, or C/O
-       Scyld Computing Corporation
-       410 Severn Ave., Suite 210
-       Annapolis MD 21403
-
-       This driver uses the cards in the 8390-compatible mode.
-       Most of the run-time complexity is handled by the generic code in
-       8390.c.  The code in this file is responsible for
-
-               ultra_probe()           Detecting and initializing the card.
-               ultra_probe1()
-               ultra_probe_isapnp()
-
-               ultra_open()            The card-specific details of starting, stopping
-               ultra_reset_8390()      and resetting the 8390 NIC core.
-               ultra_close()
-
-               ultra_block_input()             Routines for reading and writing blocks of
-               ultra_block_output()    packet buffer memory.
-               ultra_pio_input()
-               ultra_pio_output()
-
-       This driver enables the shared memory only when doing the actual data
-       transfers to avoid a bug in early version of the card that corrupted
-       data transferred by a AHA1542.
-
-       This driver now supports the programmed-I/O (PIO) data transfer mode of
-       the EtherEZ. It does not use the non-8390-compatible "Altego" mode.
-       That support (if available) is in smc-ez.c.
-
-       Changelog:
-
-       Paul Gortmaker  : multiple card support for module users.
-       Donald Becker   : 4/17/96 PIO support, minor potential problems avoided.
-       Donald Becker   : 6/6/96 correctly set auto-wrap bit.
-       Alexander Sotirov : 1/20/01 Added support for ISAPnP cards
-
-       Note about the ISA PnP support:
-
-       This driver can not autoprobe for more than one SMC EtherEZ PnP card.
-       You have to configure the second card manually through the /proc/isapnp
-       interface and then load the module with an explicit io=0x___ option.
-*/
-
-static const char version[] =
-       "smc-ultra.c:v2.02 2/3/98 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/isapnp.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-
-#include "8390.h"
-
-#define DRV_NAME "smc-ultra"
-
-/* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int ultra_portlist[] __initdata =
-{0x200, 0x220, 0x240, 0x280, 0x300, 0x340, 0x380, 0};
-
-static int ultra_probe1(struct net_device *dev, int ioaddr);
-
-#ifdef __ISAPNP__
-static int ultra_probe_isapnp(struct net_device *dev);
-#endif
-
-static int ultra_open(struct net_device *dev);
-static void ultra_reset_8390(struct net_device *dev);
-static void ultra_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                                               int ring_page);
-static void ultra_block_input(struct net_device *dev, int count,
-                                                 struct sk_buff *skb, int ring_offset);
-static void ultra_block_output(struct net_device *dev, int count,
-                                                       const unsigned char *buf, const int start_page);
-static void ultra_pio_get_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                                               int ring_page);
-static void ultra_pio_input(struct net_device *dev, int count,
-                                                 struct sk_buff *skb, int ring_offset);
-static void ultra_pio_output(struct net_device *dev, int count,
-                                                        const unsigned char *buf, const int start_page);
-static int ultra_close_card(struct net_device *dev);
-
-#ifdef __ISAPNP__
-static struct isapnp_device_id ultra_device_ids[] __initdata = {
-        {       ISAPNP_VENDOR('S','M','C'), ISAPNP_FUNCTION(0x8416),
-                ISAPNP_VENDOR('S','M','C'), ISAPNP_FUNCTION(0x8416),
-                (long) "SMC EtherEZ (8416)" },
-        { }    /* terminate list */
-};
-
-MODULE_DEVICE_TABLE(isapnp, ultra_device_ids);
-#endif
-
-
-#define START_PG               0x00    /* First page of TX buffer */
-
-#define ULTRA_CMDREG   0               /* Offset to ASIC command register. */
-#define         ULTRA_RESET    0x80    /* Board reset, in ULTRA_CMDREG. */
-#define         ULTRA_MEMENB   0x40    /* Enable the shared memory. */
-#define IOPD   0x02                    /* I/O Pipe Data (16 bits), PIO operation. */
-#define IOPA   0x07                    /* I/O Pipe Address for PIO operation. */
-#define ULTRA_NIC_OFFSET  16   /* NIC register offset from the base_addr. */
-#define ULTRA_IO_EXTENT 32
-#define EN0_ERWCNT             0x08    /* Early receive warning count. */
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void ultra_poll(struct net_device *dev)
-{
-       disable_irq(dev->irq);
-       ei_interrupt(dev->irq, dev);
-       enable_irq(dev->irq);
-}
-#endif
-/*     Probe for the Ultra.  This looks like a 8013 with the station
-       address PROM at I/O ports <base>+8 to <base>+13, with a checksum
-       following.
-*/
-
-static int __init do_ultra_probe(struct net_device *dev)
-{
-       int i;
-       int base_addr = dev->base_addr;
-       int irq = dev->irq;
-
-       if (base_addr > 0x1ff)          /* Check a single specified location. */
-               return ultra_probe1(dev, base_addr);
-       else if (base_addr != 0)        /* Don't probe at all. */
-               return -ENXIO;
-
-#ifdef __ISAPNP__
-       /* Look for any installed ISAPnP cards */
-       if (isapnp_present() && (ultra_probe_isapnp(dev) == 0))
-               return 0;
-#endif
-
-       for (i = 0; ultra_portlist[i]; i++) {
-               dev->irq = irq;
-               if (ultra_probe1(dev, ultra_portlist[i]) == 0)
-                       return 0;
-       }
-
-       return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init ultra_probe(int unit)
-{
-       struct net_device *dev = alloc_ei_netdev();
-       int err;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       sprintf(dev->name, "eth%d", unit);
-       netdev_boot_setup_check(dev);
-
-       err = do_ultra_probe(dev);
-       if (err)
-               goto out;
-       return dev;
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-#endif
-
-static const struct net_device_ops ultra_netdev_ops = {
-       .ndo_open               = ultra_open,
-       .ndo_stop               = ultra_close_card,
-
-       .ndo_start_xmit         = ei_start_xmit,
-       .ndo_tx_timeout         = ei_tx_timeout,
-       .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = ultra_poll,
-#endif
-};
-
-static int __init ultra_probe1(struct net_device *dev, int ioaddr)
-{
-       int i, retval;
-       int checksum = 0;
-       const char *model_name;
-       unsigned char eeprom_irq = 0;
-       static unsigned version_printed;
-       /* Values from various config regs. */
-       unsigned char num_pages, irqreg, addr, piomode;
-       unsigned char idreg = inb(ioaddr + 7);
-       unsigned char reg4 = inb(ioaddr + 4) & 0x7f;
-
-       if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME))
-               return -EBUSY;
-
-       /* Check the ID nibble. */
-       if ((idreg & 0xF0) != 0x20                      /* SMC Ultra */
-               && (idreg & 0xF0) != 0x40) {            /* SMC EtherEZ */
-               retval = -ENODEV;
-               goto out;
-       }
-
-       /* Select the station address register set. */
-       outb(reg4, ioaddr + 4);
-
-       for (i = 0; i < 8; i++)
-               checksum += inb(ioaddr + 8 + i);
-       if ((checksum & 0xff) != 0xFF) {
-               retval = -ENODEV;
-               goto out;
-       }
-
-       if (ei_debug  &&  version_printed++ == 0)
-               printk(version);
-
-       model_name = (idreg & 0xF0) == 0x20 ? "SMC Ultra" : "SMC EtherEZ";
-
-       for (i = 0; i < 6; i++)
-               dev->dev_addr[i] = inb(ioaddr + 8 + i);
-
-       printk("%s: %s at %#3x, %pM", dev->name, model_name,
-              ioaddr, dev->dev_addr);
-
-       /* Switch from the station address to the alternate register set and
-          read the useful registers there. */
-       outb(0x80 | reg4, ioaddr + 4);
-
-       /* Enabled FINE16 mode to avoid BIOS ROM width mismatches @ reboot. */
-       outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
-       piomode = inb(ioaddr + 0x8);
-       addr = inb(ioaddr + 0xb);
-       irqreg = inb(ioaddr + 0xd);
-
-       /* Switch back to the station address register set so that the MS-DOS driver
-          can find the card after a warm boot. */
-       outb(reg4, ioaddr + 4);
-
-       if (dev->irq < 2) {
-               unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15};
-               int irq;
-
-               /* The IRQ bits are split. */
-               irq = irqmap[((irqreg & 0x40) >> 4) + ((irqreg & 0x0c) >> 2)];
-
-               if (irq == 0) {
-                       printk(", failed to detect IRQ line.\n");
-                       retval =  -EAGAIN;
-                       goto out;
-               }
-               dev->irq = irq;
-               eeprom_irq = 1;
-       }
-
-       /* The 8390 isn't at the base address, so fake the offset */
-       dev->base_addr = ioaddr+ULTRA_NIC_OFFSET;
-
-       {
-               static const int addr_tbl[4] = {
-                       0x0C0000, 0x0E0000, 0xFC0000, 0xFE0000
-               };
-               static const short num_pages_tbl[4] = {
-                       0x20, 0x40, 0x80, 0xff
-               };
-
-               dev->mem_start = ((addr & 0x0f) << 13) + addr_tbl[(addr >> 6) & 3] ;
-               num_pages = num_pages_tbl[(addr >> 4) & 3];
-       }
-
-       ei_status.name = model_name;
-       ei_status.word16 = 1;
-       ei_status.tx_start_page = START_PG;
-       ei_status.rx_start_page = START_PG + TX_PAGES;
-       ei_status.stop_page = num_pages;
-
-       ei_status.mem = ioremap(dev->mem_start, (ei_status.stop_page - START_PG)*256);
-       if (!ei_status.mem) {
-               printk(", failed to ioremap.\n");
-               retval =  -ENOMEM;
-               goto out;
-       }
-
-       dev->mem_end = dev->mem_start + (ei_status.stop_page - START_PG)*256;
-
-       if (piomode) {
-               printk(",%s IRQ %d programmed-I/O mode.\n",
-                          eeprom_irq ? "EEPROM" : "assigned ", dev->irq);
-               ei_status.block_input = &ultra_pio_input;
-               ei_status.block_output = &ultra_pio_output;
-               ei_status.get_8390_hdr = &ultra_pio_get_hdr;
-       } else {
-               printk(",%s IRQ %d memory %#lx-%#lx.\n", eeprom_irq ? "" : "assigned ",
-                          dev->irq, dev->mem_start, dev->mem_end-1);
-               ei_status.block_input = &ultra_block_input;
-               ei_status.block_output = &ultra_block_output;
-               ei_status.get_8390_hdr = &ultra_get_8390_hdr;
-       }
-       ei_status.reset_8390 = &ultra_reset_8390;
-
-       dev->netdev_ops = &ultra_netdev_ops;
-       NS8390_init(dev, 0);
-
-       retval = register_netdev(dev);
-       if (retval)
-               goto out;
-       return 0;
-out:
-       release_region(ioaddr, ULTRA_IO_EXTENT);
-       return retval;
-}
-
-#ifdef __ISAPNP__
-static int __init ultra_probe_isapnp(struct net_device *dev)
-{
-        int i;
-
-        for (i = 0; ultra_device_ids[i].vendor != 0; i++) {
-               struct pnp_dev *idev = NULL;
-
-                while ((idev = pnp_find_dev(NULL,
-                                            ultra_device_ids[i].vendor,
-                                            ultra_device_ids[i].function,
-                                            idev))) {
-                        /* Avoid already found cards from previous calls */
-                        if (pnp_device_attach(idev) < 0)
-                               continue;
-                        if (pnp_activate_dev(idev) < 0) {
-                              __again:
-                               pnp_device_detach(idev);
-                               continue;
-                        }
-                       /* if no io and irq, search for next */
-                       if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0))
-                               goto __again;
-                        /* found it */
-                       dev->base_addr = pnp_port_start(idev, 0);
-                       dev->irq = pnp_irq(idev, 0);
-                        printk(KERN_INFO "smc-ultra.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
-                                (char *) ultra_device_ids[i].driver_data,
-                                dev->base_addr, dev->irq);
-                        if (ultra_probe1(dev, dev->base_addr) != 0) {      /* Shouldn't happen. */
-                                printk(KERN_ERR "smc-ultra.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr);
-                                pnp_device_detach(idev);
-                               return -ENXIO;
-                        }
-                        ei_status.priv = (unsigned long)idev;
-                        break;
-                }
-                if (!idev)
-                        continue;
-                return 0;
-        }
-
-        return -ENODEV;
-}
-#endif
-
-static int
-ultra_open(struct net_device *dev)
-{
-       int retval;
-       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
-       unsigned char irq2reg[] = {0, 0, 0x04, 0x08, 0, 0x0C, 0, 0x40,
-                                  0, 0x04, 0x44, 0x48, 0, 0, 0, 0x4C, };
-
-       retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev);
-       if (retval)
-               return retval;
-
-       outb(0x00, ioaddr);     /* Disable shared memory for safety. */
-       outb(0x80, ioaddr + 5);
-       /* Set the IRQ line. */
-       outb(inb(ioaddr + 4) | 0x80, ioaddr + 4);
-       outb((inb(ioaddr + 13) & ~0x4C) | irq2reg[dev->irq], ioaddr + 13);
-       outb(inb(ioaddr + 4) & 0x7f, ioaddr + 4);
-
-       if (ei_status.block_input == &ultra_pio_input) {
-               outb(0x11, ioaddr + 6);         /* Enable interrupts and PIO. */
-               outb(0x01, ioaddr + 0x19);      /* Enable ring read auto-wrap. */
-       } else
-               outb(0x01, ioaddr + 6);         /* Enable interrupts and memory. */
-       /* Set the early receive warning level in window 0 high enough not
-          to receive ERW interrupts. */
-       outb_p(E8390_NODMA+E8390_PAGE0, dev->base_addr);
-       outb(0xff, dev->base_addr + EN0_ERWCNT);
-       ei_open(dev);
-       return 0;
-}
-
-static void
-ultra_reset_8390(struct net_device *dev)
-{
-       int cmd_port = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC base addr */
-
-       outb(ULTRA_RESET, cmd_port);
-       if (ei_debug > 1) printk("resetting Ultra, t=%ld...", jiffies);
-       ei_status.txing = 0;
-
-       outb(0x00, cmd_port);   /* Disable shared memory for safety. */
-       outb(0x80, cmd_port + 5);
-       if (ei_status.block_input == &ultra_pio_input)
-               outb(0x11, cmd_port + 6);               /* Enable interrupts and PIO. */
-       else
-               outb(0x01, cmd_port + 6);               /* Enable interrupts and memory. */
-
-       if (ei_debug > 1) printk("reset done\n");
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
-   we don't need to be concerned with ring wrap as the header will be at
-   the start of a page, so we optimize accordingly. */
-
-static void
-ultra_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-       void __iomem *hdr_start = ei_status.mem + ((ring_page - START_PG)<<8);
-
-       outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);  /* shmem on */
-#ifdef __BIG_ENDIAN
-       /* Officially this is what we are doing, but the readl() is faster */
-       /* unfortunately it isn't endian aware of the struct               */
-       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
-       hdr->count = le16_to_cpu(hdr->count);
-#else
-       ((unsigned int*)hdr)[0] = readl(hdr_start);
-#endif
-       outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem off */
-}
-
-/* Block input and output are easy on shared memory ethercards, the only
-   complication is when the ring buffer wraps. */
-
-static void
-ultra_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-       void __iomem *xfer_start = ei_status.mem + ring_offset - (START_PG<<8);
-
-       /* Enable shared memory. */
-       outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
-
-       if (ring_offset + count > ei_status.stop_page*256) {
-               /* We must wrap the input move. */
-               int semi_count = ei_status.stop_page*256 - ring_offset;
-               memcpy_fromio(skb->data, xfer_start, semi_count);
-               count -= semi_count;
-               memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
-       } else {
-               memcpy_fromio(skb->data, xfer_start, count);
-       }
-
-       outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET);  /* Disable memory. */
-}
-
-static void
-ultra_block_output(struct net_device *dev, int count, const unsigned char *buf,
-                               int start_page)
-{
-       void __iomem *shmem = ei_status.mem + ((start_page - START_PG)<<8);
-
-       /* Enable shared memory. */
-       outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
-
-       memcpy_toio(shmem, buf, count);
-
-       outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */
-}
-
-/* The identical operations for programmed I/O cards.
-   The PIO model is trivial to use: the 16 bit start address is written
-   byte-sequentially to IOPA, with no intervening I/O operations, and the
-   data is read or written to the IOPD data port.
-   The only potential complication is that the address register is shared
-   and must be always be rewritten between each read/write direction change.
-   This is no problem for us, as the 8390 code ensures that we are single
-   threaded. */
-static void ultra_pio_get_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                                               int ring_page)
-{
-       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
-       outb(0x00, ioaddr + IOPA);      /* Set the address, LSB first. */
-       outb(ring_page, ioaddr + IOPA);
-       insw(ioaddr + IOPD, hdr, sizeof(struct e8390_pkt_hdr)>>1);
-}
-
-static void ultra_pio_input(struct net_device *dev, int count,
-                                                 struct sk_buff *skb, int ring_offset)
-{
-       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
-    char *buf = skb->data;
-
-       /* For now set the address again, although it should already be correct. */
-       outb(ring_offset, ioaddr + IOPA);       /* Set the address, LSB first. */
-       outb(ring_offset >> 8, ioaddr + IOPA);
-       /* We know skbuffs are padded to at least word alignment. */
-       insw(ioaddr + IOPD, buf, (count+1)>>1);
-}
-
-static void ultra_pio_output(struct net_device *dev, int count,
-                                                       const unsigned char *buf, const int start_page)
-{
-       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */
-       outb(0x00, ioaddr + IOPA);      /* Set the address, LSB first. */
-       outb(start_page, ioaddr + IOPA);
-       /* An extra odd byte is OK here as well. */
-       outsw(ioaddr + IOPD, buf, (count+1)>>1);
-}
-
-static int
-ultra_close_card(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* CMDREG */
-
-       netif_stop_queue(dev);
-
-       if (ei_debug > 1)
-               printk("%s: Shutting down ethercard.\n", dev->name);
-
-       outb(0x00, ioaddr + 6);         /* Disable interrupts. */
-       free_irq(dev->irq, dev);
-
-       NS8390_init(dev, 0);
-
-       /* We should someday disable shared memory and change to 8-bit mode
-          "just in case"... */
-
-       return 0;
-}
-
-
-#ifdef MODULE
-#define MAX_ULTRA_CARDS        4       /* Max number of Ultra cards per module */
-static struct net_device *dev_ultra[MAX_ULTRA_CARDS];
-static int io[MAX_ULTRA_CARDS];
-static int irq[MAX_ULTRA_CARDS];
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
-MODULE_DESCRIPTION("SMC Ultra/EtherEZ ISA/PnP Ethernet driver");
-MODULE_LICENSE("GPL");
-
-/* This is set up so that only a single autoprobe takes place per call.
-ISA device autoprobes on a running machine are not recommended. */
-int __init
-init_module(void)
-{
-       struct net_device *dev;
-       int this_dev, found = 0;
-
-       for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) {
-               if (io[this_dev] == 0)  {
-                       if (this_dev != 0) break; /* only autoprobe 1st one */
-                       printk(KERN_NOTICE "smc-ultra.c: Presently autoprobing (not recommended) for a single card.\n");
-               }
-               dev = alloc_ei_netdev();
-               if (!dev)
-                       break;
-               dev->irq = irq[this_dev];
-               dev->base_addr = io[this_dev];
-               if (do_ultra_probe(dev) == 0) {
-                       dev_ultra[found++] = dev;
-                       continue;
-               }
-               free_netdev(dev);
-               printk(KERN_WARNING "smc-ultra.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]);
-               break;
-       }
-       if (found)
-               return 0;
-       return -ENXIO;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-       /* NB: ultra_close_card() does free_irq */
-#ifdef __ISAPNP__
-       struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
-       if (idev)
-               pnp_device_detach(idev);
-#endif
-       release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT);
-       iounmap(ei_status.mem);
-}
-
-void __exit
-cleanup_module(void)
-{
-       int this_dev;
-
-       for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) {
-               struct net_device *dev = dev_ultra[this_dev];
-               if (dev) {
-                       unregister_netdev(dev);
-                       cleanup_card(dev);
-                       free_netdev(dev);
-               }
-       }
-}
-#endif /* MODULE */
diff --git a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c
deleted file mode 100644 (file)
index e459c3b..0000000
+++ /dev/null
@@ -1,464 +0,0 @@
-/*     smc-ultra32.c: An SMC Ultra32 EISA ethernet driver for linux.
-
-Sources:
-
-       This driver is based on (cloned from) the ISA SMC Ultra driver
-       written by Donald Becker. Modifications to support the EISA
-       version of the card by Paul Gortmaker and Leonard N. Zubkoff.
-
-       This software may be used and distributed according to the terms
-       of the GNU General Public License, incorporated herein by reference.
-
-Theory of Operation:
-
-       The SMC Ultra32C card uses the SMC 83c790 chip which is also
-       found on the ISA SMC Ultra cards. It has a shared memory mode of
-       operation that makes it similar to the ISA version of the card.
-       The main difference is that the EISA card has 32KB of RAM, but
-       only an 8KB window into that memory. The EISA card also can be
-       set for a bus-mastering mode of operation via the ECU, but that
-       is not (and probably will never be) supported by this driver.
-       The ECU should be run to enable shared memory and to disable the
-       bus-mastering feature for use with linux.
-
-       By programming the 8390 to use only 8KB RAM, the modifications
-       to the ISA driver can be limited to the probe and initialization
-       code. This allows easy integration of EISA support into the ISA
-       driver. However, the driver development kit from SMC provided the
-       register information for sliding the 8KB window, and hence the 8390
-       is programmed to use the full 32KB RAM.
-
-       Unfortunately this required code changes outside the probe/init
-       routines, and thus we decided to separate the EISA driver from
-       the ISA one. In this way, ISA users don't end up with a larger
-       driver due to the EISA code, and EISA users don't end up with a
-       larger driver due to the ISA EtherEZ PIO code. The driver is
-       similar to the 3c503/16 driver, in that the window must be set
-       back to the 1st 8KB of space for access to the two 8390 Tx slots.
-
-       In testing, using only 8KB RAM (3 Tx / 5 Rx) didn't appear to
-       be a limiting factor, since the EISA bus could get packets off
-       the card fast enough, but having the use of lots of RAM as Rx
-       space is extra insurance if interrupt latencies become excessive.
-
-*/
-
-static const char *version = "smc-ultra32.c: 06/97 v1.00\n";
-
-
-#include <linux/module.h>
-#include <linux/eisa.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include "8390.h"
-
-#define DRV_NAME "smc-ultra32"
-
-static int ultra32_probe1(struct net_device *dev, int ioaddr);
-static int ultra32_open(struct net_device *dev);
-static void ultra32_reset_8390(struct net_device *dev);
-static void ultra32_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                                int ring_page);
-static void ultra32_block_input(struct net_device *dev, int count,
-                               struct sk_buff *skb, int ring_offset);
-static void ultra32_block_output(struct net_device *dev, int count,
-                                const unsigned char *buf,
-                                const int start_page);
-static int ultra32_close(struct net_device *dev);
-
-#define ULTRA32_CMDREG 0       /* Offset to ASIC command register. */
-#define         ULTRA32_RESET  0x80    /* Board reset, in ULTRA32_CMDREG. */
-#define         ULTRA32_MEMENB 0x40    /* Enable the shared memory. */
-#define ULTRA32_NIC_OFFSET 16  /* NIC register offset from the base_addr. */
-#define ULTRA32_IO_EXTENT 32
-#define EN0_ERWCNT             0x08    /* Early receive warning count. */
-
-/*
- * Defines that apply only to the Ultra32 EISA card. Note that
- * "smc" = 10011 01101 00011 = 0x4da3, and hence !smc8010.cfg translates
- * into an EISA ID of 0x1080A34D
- */
-#define ULTRA32_BASE   0xca0
-#define ULTRA32_ID     0x1080a34d
-#define ULTRA32_IDPORT (-0x20) /* 0xc80 */
-/* Config regs 1->7 from the EISA !SMC8010.CFG file. */
-#define ULTRA32_CFG1   0x04    /* 0xca4 */
-#define ULTRA32_CFG2   0x05    /* 0xca5 */
-#define ULTRA32_CFG3   (-0x18) /* 0xc88 */
-#define ULTRA32_CFG4   (-0x17) /* 0xc89 */
-#define ULTRA32_CFG5   (-0x16) /* 0xc8a */
-#define ULTRA32_CFG6   (-0x15) /* 0xc8b */
-#define ULTRA32_CFG7   0x0d    /* 0xcad */
-
-static void cleanup_card(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET;
-       /* NB: ultra32_close_card() does free_irq */
-       release_region(ioaddr, ULTRA32_IO_EXTENT);
-       iounmap(ei_status.mem);
-}
-
-/*     Probe for the Ultra32.  This looks like a 8013 with the station
-       address PROM at I/O ports <base>+8 to <base>+13, with a checksum
-       following.
-*/
-
-struct net_device * __init ultra32_probe(int unit)
-{
-       struct net_device *dev;
-       int base;
-       int irq;
-       int err = -ENODEV;
-
-       if (!EISA_bus)
-               return ERR_PTR(-ENODEV);
-
-       dev = alloc_ei_netdev();
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       if (unit >= 0) {
-               sprintf(dev->name, "eth%d", unit);
-               netdev_boot_setup_check(dev);
-       }
-
-       irq = dev->irq;
-
-       /* EISA spec allows for up to 16 slots, but 8 is typical. */
-       for (base = 0x1000 + ULTRA32_BASE; base < 0x9000; base += 0x1000) {
-               if (ultra32_probe1(dev, base) == 0)
-                       break;
-               dev->irq = irq;
-       }
-       if (base >= 0x9000)
-               goto out;
-       err = register_netdev(dev);
-       if (err)
-               goto out1;
-       return dev;
-out1:
-       cleanup_card(dev);
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-
-
-static const struct net_device_ops ultra32_netdev_ops = {
-       .ndo_open               = ultra32_open,
-       .ndo_stop               = ultra32_close,
-       .ndo_start_xmit         = ei_start_xmit,
-       .ndo_tx_timeout         = ei_tx_timeout,
-       .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = ei_poll,
-#endif
-};
-
-static int __init ultra32_probe1(struct net_device *dev, int ioaddr)
-{
-       int i, edge, media, retval;
-       int checksum = 0;
-       const char *model_name;
-       static unsigned version_printed;
-       /* Values from various config regs. */
-       unsigned char idreg;
-       unsigned char reg4;
-       const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"};
-
-       if (!request_region(ioaddr, ULTRA32_IO_EXTENT, DRV_NAME))
-               return -EBUSY;
-
-       if (inb(ioaddr + ULTRA32_IDPORT) == 0xff ||
-           inl(ioaddr + ULTRA32_IDPORT) != ULTRA32_ID) {
-               retval = -ENODEV;
-               goto out;
-       }
-
-       media = inb(ioaddr + ULTRA32_CFG7) & 0x03;
-       edge = inb(ioaddr + ULTRA32_CFG5) & 0x08;
-       printk("SMC Ultra32 in EISA Slot %d, Media: %s, %s IRQs.\n",
-               ioaddr >> 12, ifmap[media],
-               (edge ? "Edge Triggered" : "Level Sensitive"));
-
-       idreg = inb(ioaddr + 7);
-       reg4 = inb(ioaddr + 4) & 0x7f;
-
-       /* Check the ID nibble. */
-       if ((idreg & 0xf0) != 0x20) {                   /* SMC Ultra */
-               retval = -ENODEV;
-               goto out;
-       }
-
-       /* Select the station address register set. */
-       outb(reg4, ioaddr + 4);
-
-       for (i = 0; i < 8; i++)
-               checksum += inb(ioaddr + 8 + i);
-       if ((checksum & 0xff) != 0xff) {
-               retval = -ENODEV;
-               goto out;
-       }
-
-       if (ei_debug  &&  version_printed++ == 0)
-               printk(version);
-
-       model_name = "SMC Ultra32";
-
-       for (i = 0; i < 6; i++)
-               dev->dev_addr[i] = inb(ioaddr + 8 + i);
-
-       printk("%s: %s at 0x%X, %pM",
-              dev->name, model_name, ioaddr, dev->dev_addr);
-
-       /* Switch from the station address to the alternate register set and
-          read the useful registers there. */
-       outb(0x80 | reg4, ioaddr + 4);
-
-       /* Enable FINE16 mode to avoid BIOS ROM width mismatches @ reboot. */
-       outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c);
-
-       /* Reset RAM addr. */
-       outb(0x00, ioaddr + 0x0b);
-
-       /* Switch back to the station address register set so that the
-          MS-DOS driver can find the card after a warm boot. */
-       outb(reg4, ioaddr + 4);
-
-       if ((inb(ioaddr + ULTRA32_CFG5) & 0x40) == 0) {
-               printk("\nsmc-ultra32: Card RAM is disabled!  "
-                      "Run EISA config utility.\n");
-               retval = -ENODEV;
-               goto out;
-       }
-       if ((inb(ioaddr + ULTRA32_CFG2) & 0x04) == 0)
-               printk("\nsmc-ultra32: Ignoring Bus-Master enable bit.  "
-                      "Run EISA config utility.\n");
-
-       if (dev->irq < 2) {
-               unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15};
-               int irq = irqmap[inb(ioaddr + ULTRA32_CFG5) & 0x07];
-               if (irq == 0) {
-                       printk(", failed to detect IRQ line.\n");
-                       retval = -EAGAIN;
-                       goto out;
-               }
-               dev->irq = irq;
-       }
-
-       /* The 8390 isn't at the base address, so fake the offset */
-       dev->base_addr = ioaddr + ULTRA32_NIC_OFFSET;
-
-       /* Save RAM address in the unused reg0 to avoid excess inb's. */
-       ei_status.reg0 = inb(ioaddr + ULTRA32_CFG3) & 0xfc;
-
-       dev->mem_start =  0xc0000 + ((ei_status.reg0 & 0x7c) << 11);
-
-       ei_status.name = model_name;
-       ei_status.word16 = 1;
-       ei_status.tx_start_page = 0;
-       ei_status.rx_start_page = TX_PAGES;
-       /* All Ultra32 cards have 32KB memory with an 8KB window. */
-       ei_status.stop_page = 128;
-
-       ei_status.mem = ioremap(dev->mem_start, 0x2000);
-       if (!ei_status.mem) {
-               printk(", failed to ioremap.\n");
-               retval = -ENOMEM;
-               goto out;
-       }
-       dev->mem_end = dev->mem_start + 0x1fff;
-
-       printk(", IRQ %d, 32KB memory, 8KB window at 0x%lx-0x%lx.\n",
-              dev->irq, dev->mem_start, dev->mem_end);
-       ei_status.block_input = &ultra32_block_input;
-       ei_status.block_output = &ultra32_block_output;
-       ei_status.get_8390_hdr = &ultra32_get_8390_hdr;
-       ei_status.reset_8390 = &ultra32_reset_8390;
-
-       dev->netdev_ops = &ultra32_netdev_ops;
-       NS8390_init(dev, 0);
-
-       return 0;
-out:
-       release_region(ioaddr, ULTRA32_IO_EXTENT);
-       return retval;
-}
-
-static int ultra32_open(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* ASIC addr */
-       int irq_flags = (inb(ioaddr + ULTRA32_CFG5) & 0x08) ? 0 : IRQF_SHARED;
-       int retval;
-
-       retval = request_irq(dev->irq, ei_interrupt, irq_flags, dev->name, dev);
-       if (retval)
-               return retval;
-
-       outb(ULTRA32_MEMENB, ioaddr); /* Enable Shared Memory. */
-       outb(0x80, ioaddr + ULTRA32_CFG6); /* Enable Interrupts. */
-       outb(0x84, ioaddr + 5); /* Enable MEM16 & Disable Bus Master. */
-       outb(0x01, ioaddr + 6); /* Enable Interrupts. */
-       /* Set the early receive warning level in window 0 high enough not
-          to receive ERW interrupts. */
-       outb_p(E8390_NODMA+E8390_PAGE0, dev->base_addr);
-       outb(0xff, dev->base_addr + EN0_ERWCNT);
-       ei_open(dev);
-       return 0;
-}
-
-static int ultra32_close(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* CMDREG */
-
-       netif_stop_queue(dev);
-
-       if (ei_debug > 1)
-               printk("%s: Shutting down ethercard.\n", dev->name);
-
-       outb(0x00, ioaddr + ULTRA32_CFG6); /* Disable Interrupts. */
-       outb(0x00, ioaddr + 6);         /* Disable interrupts. */
-       free_irq(dev->irq, dev);
-
-       NS8390_init(dev, 0);
-
-       return 0;
-}
-
-static void ultra32_reset_8390(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* ASIC base addr */
-
-       outb(ULTRA32_RESET, ioaddr);
-       if (ei_debug > 1) printk("resetting Ultra32, t=%ld...", jiffies);
-       ei_status.txing = 0;
-
-       outb(ULTRA32_MEMENB, ioaddr); /* Enable Shared Memory. */
-       outb(0x80, ioaddr + ULTRA32_CFG6); /* Enable Interrupts. */
-       outb(0x84, ioaddr + 5); /* Enable MEM16 & Disable Bus Master. */
-       outb(0x01, ioaddr + 6); /* Enable Interrupts. */
-       if (ei_debug > 1) printk("reset done\n");
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
-   we don't need to be concerned with ring wrap as the header will be at
-   the start of a page, so we optimize accordingly. */
-
-static void ultra32_get_8390_hdr(struct net_device *dev,
-                                struct e8390_pkt_hdr *hdr,
-                                int ring_page)
-{
-       void __iomem *hdr_start = ei_status.mem + ((ring_page & 0x1f) << 8);
-       unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3;
-
-       /* Select correct 8KB Window. */
-       outb(ei_status.reg0 | ((ring_page & 0x60) >> 5), RamReg);
-
-#ifdef __BIG_ENDIAN
-       /* Officially this is what we are doing, but the readl() is faster */
-       /* unfortunately it isn't endian aware of the struct               */
-       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
-       hdr->count = le16_to_cpu(hdr->count);
-#else
-       ((unsigned int*)hdr)[0] = readl(hdr_start);
-#endif
-}
-
-/* Block input and output are easy on shared memory ethercards, the only
-   complication is when the ring buffer wraps, or in this case, when a
-   packet spans an 8KB boundary. Note that the current 8KB segment is
-   already set by the get_8390_hdr routine. */
-
-static void ultra32_block_input(struct net_device *dev,
-                               int count,
-                               struct sk_buff *skb,
-                               int ring_offset)
-{
-       void __iomem *xfer_start = ei_status.mem + (ring_offset & 0x1fff);
-       unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3;
-
-       if ((ring_offset & ~0x1fff) != ((ring_offset + count - 1) & ~0x1fff)) {
-               int semi_count = 8192 - (ring_offset & 0x1FFF);
-               memcpy_fromio(skb->data, xfer_start, semi_count);
-               count -= semi_count;
-               if (ring_offset < 96*256) {
-                       /* Select next 8KB Window. */
-                       ring_offset += semi_count;
-                       outb(ei_status.reg0 | ((ring_offset & 0x6000) >> 13), RamReg);
-                       memcpy_fromio(skb->data + semi_count, ei_status.mem, count);
-               } else {
-                       /* Select first 8KB Window. */
-                       outb(ei_status.reg0, RamReg);
-                       memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
-               }
-       } else {
-               memcpy_fromio(skb->data, xfer_start, count);
-       }
-}
-
-static void ultra32_block_output(struct net_device *dev,
-                                int count,
-                                const unsigned char *buf,
-                                int start_page)
-{
-       void __iomem *xfer_start = ei_status.mem + (start_page<<8);
-       unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3;
-
-       /* Select first 8KB Window. */
-       outb(ei_status.reg0, RamReg);
-
-       memcpy_toio(xfer_start, buf, count);
-}
-
-#ifdef MODULE
-#define MAX_ULTRA32_CARDS   4  /* Max number of Ultra cards per module */
-static struct net_device *dev_ultra[MAX_ULTRA32_CARDS];
-
-MODULE_DESCRIPTION("SMC Ultra32 EISA ethernet driver");
-MODULE_LICENSE("GPL");
-
-int __init init_module(void)
-{
-       int this_dev, found = 0;
-
-       for (this_dev = 0; this_dev < MAX_ULTRA32_CARDS; this_dev++) {
-               struct net_device *dev = ultra32_probe(-1);
-               if (IS_ERR(dev))
-                       break;
-               dev_ultra[found++] = dev;
-       }
-       if (found)
-               return 0;
-       printk(KERN_WARNING "smc-ultra32.c: No SMC Ultra32 found.\n");
-       return -ENXIO;
-}
-
-void __exit cleanup_module(void)
-{
-       int this_dev;
-
-       for (this_dev = 0; this_dev < MAX_ULTRA32_CARDS; this_dev++) {
-               struct net_device *dev = dev_ultra[this_dev];
-               if (dev) {
-                       unregister_netdev(dev);
-                       cleanup_card(dev);
-                       free_netdev(dev);
-               }
-       }
-}
-#endif /* MODULE */
-
diff --git a/drivers/net/stnic.c b/drivers/net/stnic.c
deleted file mode 100644 (file)
index d85f0a8..0000000
+++ /dev/null
@@ -1,294 +0,0 @@
-/* stnic.c : A SH7750 specific part of driver for NS DP83902A ST-NIC.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1999 kaz Kojima
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <mach-se/mach/se.h>
-#include <asm/machvec.h>
-#ifdef CONFIG_SH_STANDARD_BIOS
-#include <asm/sh_bios.h>
-#endif
-
-#include "8390.h"
-
-#define DRV_NAME "stnic"
-
-#define byte   unsigned char
-#define half   unsigned short
-#define word   unsigned int
-#define vbyte  volatile unsigned char
-#define vhalf  volatile unsigned short
-#define vword  volatile unsigned int
-
-#define STNIC_RUN      0x01    /* 1 == Run, 0 == reset. */
-
-#define START_PG       0       /* First page of TX buffer */
-#define STOP_PG                128     /* Last page +1 of RX ring */
-
-/* Alias */
-#define STNIC_CR       E8390_CMD
-#define PG0_RSAR0      EN0_RSARLO
-#define PG0_RSAR1      EN0_RSARHI
-#define PG0_RBCR0      EN0_RCNTLO
-#define PG0_RBCR1      EN0_RCNTHI
-
-#define CR_RRD         E8390_RREAD
-#define CR_RWR         E8390_RWRITE
-#define CR_PG0         E8390_PAGE0
-#define CR_STA         E8390_START
-#define CR_RDMA                E8390_NODMA
-
-/* FIXME! YOU MUST SET YOUR OWN ETHER ADDRESS.  */
-static byte stnic_eadr[6] =
-{0x00, 0xc0, 0x6e, 0x00, 0x00, 0x07};
-
-static struct net_device *stnic_dev;
-
-static void stnic_reset (struct net_device *dev);
-static void stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                          int ring_page);
-static void stnic_block_input (struct net_device *dev, int count,
-                              struct sk_buff *skb , int ring_offset);
-static void stnic_block_output (struct net_device *dev, int count,
-                               const unsigned char *buf, int start_page);
-
-static void stnic_init (struct net_device *dev);
-
-/* SH7750 specific read/write io. */
-static inline void
-STNIC_DELAY (void)
-{
-  vword trash;
-  trash = *(vword *) 0xa0000000;
-  trash = *(vword *) 0xa0000000;
-  trash = *(vword *) 0xa0000000;
-}
-
-static inline byte
-STNIC_READ (int reg)
-{
-  byte val;
-
-  val = (*(vhalf *) (PA_83902 + ((reg) << 1)) >> 8) & 0xff;
-  STNIC_DELAY ();
-  return val;
-}
-
-static inline void
-STNIC_WRITE (int reg, byte val)
-{
-  *(vhalf *) (PA_83902 + ((reg) << 1)) = ((half) (val) << 8);
-  STNIC_DELAY ();
-}
-
-static int __init stnic_probe(void)
-{
-  struct net_device *dev;
-  int i, err;
-
-  /* If we are not running on a SolutionEngine, give up now */
-  if (! MACH_SE)
-    return -ENODEV;
-
-  /* New style probing API */
-  dev = alloc_ei_netdev();
-  if (!dev)
-       return -ENOMEM;
-
-#ifdef CONFIG_SH_STANDARD_BIOS
-  sh_bios_get_node_addr (stnic_eadr);
-#endif
-  for (i = 0; i < ETHER_ADDR_LEN; i++)
-    dev->dev_addr[i] = stnic_eadr[i];
-
-  /* Set the base address to point to the NIC, not the "real" base! */
-  dev->base_addr = 0x1000;
-  dev->irq = IRQ_STNIC;
-  dev->netdev_ops = &ei_netdev_ops;
-
-  /* Snarf the interrupt now.  There's no point in waiting since we cannot
-     share and the board will usually be enabled. */
-  err = request_irq (dev->irq, ei_interrupt, 0, DRV_NAME, dev);
-  if (err)  {
-      printk (KERN_EMERG " unable to get IRQ %d.\n", dev->irq);
-      free_netdev(dev);
-      return err;
-    }
-
-  ei_status.name = dev->name;
-  ei_status.word16 = 1;
-#ifdef __LITTLE_ENDIAN__
-  ei_status.bigendian = 0;
-#else
-  ei_status.bigendian = 1;
-#endif
-  ei_status.tx_start_page = START_PG;
-  ei_status.rx_start_page = START_PG + TX_PAGES;
-  ei_status.stop_page = STOP_PG;
-
-  ei_status.reset_8390 = &stnic_reset;
-  ei_status.get_8390_hdr = &stnic_get_hdr;
-  ei_status.block_input = &stnic_block_input;
-  ei_status.block_output = &stnic_block_output;
-
-  stnic_init (dev);
-
-  err = register_netdev(dev);
-  if (err) {
-    free_irq(dev->irq, dev);
-    free_netdev(dev);
-    return err;
-  }
-  stnic_dev = dev;
-
-  printk (KERN_INFO "NS ST-NIC 83902A\n");
-
-  return 0;
-}
-
-static void
-stnic_reset (struct net_device *dev)
-{
-  *(vhalf *) PA_83902_RST = 0;
-  udelay (5);
-  if (ei_debug > 1)
-    printk (KERN_WARNING "8390 reset done (%ld).\n", jiffies);
-  *(vhalf *) PA_83902_RST = ~0;
-  udelay (5);
-}
-
-static void
-stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
-              int ring_page)
-{
-  half buf[2];
-
-  STNIC_WRITE (PG0_RSAR0, 0);
-  STNIC_WRITE (PG0_RSAR1, ring_page);
-  STNIC_WRITE (PG0_RBCR0, 4);
-  STNIC_WRITE (PG0_RBCR1, 0);
-  STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
-
-  buf[0] = *(vhalf *) PA_83902_IF;
-  STNIC_DELAY ();
-  buf[1] = *(vhalf *) PA_83902_IF;
-  STNIC_DELAY ();
-  hdr->next = buf[0] >> 8;
-  hdr->status = buf[0] & 0xff;
-#ifdef __LITTLE_ENDIAN__
-  hdr->count = buf[1];
-#else
-  hdr->count = ((buf[1] >> 8) & 0xff) | (buf[1] << 8);
-#endif
-
-  if (ei_debug > 1)
-    printk (KERN_DEBUG "ring %x status %02x next %02x count %04x.\n",
-           ring_page, hdr->status, hdr->next, hdr->count);
-
-  STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
-}
-
-/* Block input and output, similar to the Crynwr packet driver. If you are
-   porting to a new ethercard look at the packet driver source for hints.
-   The HP LAN doesn't use shared memory -- we put the packet
-   out through the "remote DMA" dataport. */
-
-static void
-stnic_block_input (struct net_device *dev, int length, struct sk_buff *skb,
-                  int offset)
-{
-  char *buf = skb->data;
-  half val;
-
-  STNIC_WRITE (PG0_RSAR0, offset & 0xff);
-  STNIC_WRITE (PG0_RSAR1, offset >> 8);
-  STNIC_WRITE (PG0_RBCR0, length & 0xff);
-  STNIC_WRITE (PG0_RBCR1, length >> 8);
-  STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
-
-  if (length & 1)
-    length++;
-
-  while (length > 0)
-    {
-      val = *(vhalf *) PA_83902_IF;
-#ifdef __LITTLE_ENDIAN__
-      *buf++ = val & 0xff;
-      *buf++ = val >> 8;
-#else
-      *buf++ = val >> 8;
-      *buf++ = val & 0xff;
-#endif
-      STNIC_DELAY ();
-      length -= sizeof (half);
-    }
-
-  STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
-}
-
-static void
-stnic_block_output (struct net_device *dev, int length,
-                   const unsigned char *buf, int output_page)
-{
-  STNIC_WRITE (PG0_RBCR0, 1);  /* Write non-zero value */
-  STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
-  STNIC_DELAY ();
-
-  STNIC_WRITE (PG0_RBCR0, length & 0xff);
-  STNIC_WRITE (PG0_RBCR1, length >> 8);
-  STNIC_WRITE (PG0_RSAR0, 0);
-  STNIC_WRITE (PG0_RSAR1, output_page);
-  STNIC_WRITE (STNIC_CR, CR_RWR | CR_PG0 | CR_STA);
-
-  if (length & 1)
-    length++;
-
-  while (length > 0)
-    {
-#ifdef __LITTLE_ENDIAN__
-      *(vhalf *) PA_83902_IF = ((half) buf[1] << 8) | buf[0];
-#else
-      *(vhalf *) PA_83902_IF = ((half) buf[0] << 8) | buf[1];
-#endif
-      STNIC_DELAY ();
-      buf += sizeof (half);
-      length -= sizeof (half);
-    }
-
-  STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
-}
-
-/* This function resets the STNIC if something screws up.  */
-static void
-stnic_init (struct net_device *dev)
-{
-  stnic_reset (dev);
-  NS8390_init (dev, 0);
-}
-
-static void __exit stnic_cleanup(void)
-{
-       unregister_netdev(stnic_dev);
-       free_irq(stnic_dev->irq, stnic_dev);
-       free_netdev(stnic_dev);
-}
-
-module_init(stnic_probe);
-module_exit(stnic_cleanup);
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
deleted file mode 100644 (file)
index 8831a33..0000000
+++ /dev/null
@@ -1,567 +0,0 @@
-/* wd.c: A WD80x3 ethernet driver for linux. */
-/*
-       Written 1993-94 by Donald Becker.
-
-       Copyright 1993 United States Government as represented by the
-       Director, National Security Agency.
-
-       This software may be used and distributed according to the terms
-       of the GNU General Public License, incorporated herein by reference.
-
-       The author may be reached as becker@scyld.com, or C/O
-       Scyld Computing Corporation
-       410 Severn Ave., Suite 210
-       Annapolis MD 21403
-
-       This is a driver for WD8003 and WD8013 "compatible" ethercards.
-
-       Thanks to Russ Nelson (nelson@crnwyr.com) for loaning me a WD8013.
-
-       Changelog:
-
-       Paul Gortmaker  : multiple card support for module users, support
-                         for non-standard memory sizes.
-
-
-*/
-
-static const char version[] =
-       "wd.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-
-#include "8390.h"
-
-#define DRV_NAME "wd"
-
-/* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int wd_portlist[] __initdata =
-{0x300, 0x280, 0x380, 0x240, 0};
-
-static int wd_probe1(struct net_device *dev, int ioaddr);
-
-static int wd_open(struct net_device *dev);
-static void wd_reset_8390(struct net_device *dev);
-static void wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
-                                               int ring_page);
-static void wd_block_input(struct net_device *dev, int count,
-                                                 struct sk_buff *skb, int ring_offset);
-static void wd_block_output(struct net_device *dev, int count,
-                                                       const unsigned char *buf, int start_page);
-static int wd_close(struct net_device *dev);
-
-
-#define WD_START_PG            0x00    /* First page of TX buffer */
-#define WD03_STOP_PG   0x20    /* Last page +1 of RX ring */
-#define WD13_STOP_PG   0x40    /* Last page +1 of RX ring */
-
-#define WD_CMDREG              0               /* Offset to ASIC command register. */
-#define         WD_RESET               0x80    /* Board reset, in WD_CMDREG. */
-#define         WD_MEMENB              0x40    /* Enable the shared memory. */
-#define WD_CMDREG5             5               /* Offset to 16-bit-only ASIC register 5. */
-#define         ISA16                  0x80    /* Enable 16 bit access from the ISA bus. */
-#define         NIC16                  0x40    /* Enable 16 bit access from the 8390. */
-#define WD_NIC_OFFSET  16              /* Offset to the 8390 from the base_addr. */
-#define WD_IO_EXTENT   32
-
-
-/*     Probe for the WD8003 and WD8013.  These cards have the station
-       address PROM at I/O ports <base>+8 to <base>+13, with a checksum
-       following. A Soundblaster can have the same checksum as an WDethercard,
-       so we have an extra exclusionary check for it.
-
-       The wd_probe1() routine initializes the card and fills the
-       station address field. */
-
-static int __init do_wd_probe(struct net_device *dev)
-{
-       int i;
-       struct resource *r;
-       int base_addr = dev->base_addr;
-       int irq = dev->irq;
-       int mem_start = dev->mem_start;
-       int mem_end = dev->mem_end;
-
-       if (base_addr > 0x1ff) {        /* Check a user specified location. */
-               r = request_region(base_addr, WD_IO_EXTENT, "wd-probe");
-               if ( r == NULL)
-                       return -EBUSY;
-               i = wd_probe1(dev, base_addr);
-               if (i != 0)
-                       release_region(base_addr, WD_IO_EXTENT);
-               else
-                       r->name = dev->name;
-               return i;
-       }
-       else if (base_addr != 0)        /* Don't probe at all. */
-               return -ENXIO;
-
-       for (i = 0; wd_portlist[i]; i++) {
-               int ioaddr = wd_portlist[i];
-               r = request_region(ioaddr, WD_IO_EXTENT, "wd-probe");
-               if (r == NULL)
-                       continue;
-               if (wd_probe1(dev, ioaddr) == 0) {
-                       r->name = dev->name;
-                       return 0;
-               }
-               release_region(ioaddr, WD_IO_EXTENT);
-               dev->irq = irq;
-               dev->mem_start = mem_start;
-               dev->mem_end = mem_end;
-       }
-
-       return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init wd_probe(int unit)
-{
-       struct net_device *dev = alloc_ei_netdev();
-       int err;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       sprintf(dev->name, "eth%d", unit);
-       netdev_boot_setup_check(dev);
-
-       err = do_wd_probe(dev);
-       if (err)
-               goto out;
-       return dev;
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-#endif
-
-static const struct net_device_ops wd_netdev_ops = {
-       .ndo_open               = wd_open,
-       .ndo_stop               = wd_close,
-       .ndo_start_xmit         = ei_start_xmit,
-       .ndo_tx_timeout         = ei_tx_timeout,
-       .ndo_get_stats          = ei_get_stats,
-       .ndo_set_multicast_list = ei_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = ei_poll,
-#endif
-};
-
-static int __init wd_probe1(struct net_device *dev, int ioaddr)
-{
-       int i;
-       int err;
-       int checksum = 0;
-       int ancient = 0;                        /* An old card without config registers. */
-       int word16 = 0;                         /* 0 = 8 bit, 1 = 16 bit */
-       const char *model_name;
-       static unsigned version_printed;
-
-       for (i = 0; i < 8; i++)
-               checksum += inb(ioaddr + 8 + i);
-       if (inb(ioaddr + 8) == 0xff     /* Extra check to avoid soundcard. */
-               || inb(ioaddr + 9) == 0xff
-               || (checksum & 0xff) != 0xFF)
-               return -ENODEV;
-
-       /* Check for semi-valid mem_start/end values if supplied. */
-       if ((dev->mem_start % 0x2000) || (dev->mem_end % 0x2000)) {
-               printk(KERN_WARNING "wd.c: user supplied mem_start or mem_end not on 8kB boundary - ignored.\n");
-               dev->mem_start = 0;
-               dev->mem_end = 0;
-       }
-
-       if (ei_debug  &&  version_printed++ == 0)
-               printk(version);
-
-       for (i = 0; i < 6; i++)
-               dev->dev_addr[i] = inb(ioaddr + 8 + i);
-
-       printk("%s: WD80x3 at %#3x, %pM",
-              dev->name, ioaddr, dev->dev_addr);
-
-       /* The following PureData probe code was contributed by
-          Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata does software
-          configuration differently from others so we have to check for them.
-          This detects an 8 bit, 16 bit or dumb (Toshiba, jumpered) card.
-          */
-       if (inb(ioaddr+0) == 'P' && inb(ioaddr+1) == 'D') {
-               unsigned char reg5 = inb(ioaddr+5);
-
-               switch (inb(ioaddr+2)) {
-               case 0x03: word16 = 0; model_name = "PDI8023-8";        break;
-               case 0x05: word16 = 0; model_name = "PDUC8023"; break;
-               case 0x0a: word16 = 1; model_name = "PDI8023-16"; break;
-                       /* Either 0x01 (dumb) or they've released a new version. */
-               default:         word16 = 0; model_name = "PDI8023";    break;
-               }
-               dev->mem_start = ((reg5 & 0x1c) + 0xc0) << 12;
-               dev->irq = (reg5 & 0xe0) == 0xe0 ? 10 : (reg5 >> 5) + 1;
-       } else {                                                                /* End of PureData probe */
-               /* This method of checking for a 16-bit board is borrowed from the
-                  we.c driver.  A simpler method is just to look in ASIC reg. 0x03.
-                  I'm comparing the two method in alpha test to make certain they
-                  return the same result. */
-               /* Check for the old 8 bit board - it has register 0/8 aliasing.
-                  Do NOT check i>=6 here -- it hangs the old 8003 boards! */
-               for (i = 0; i < 6; i++)
-                       if (inb(ioaddr+i) != inb(ioaddr+8+i))
-                               break;
-               if (i >= 6) {
-                       ancient = 1;
-                       model_name = "WD8003-old";
-                       word16 = 0;
-               } else {
-                       int tmp = inb(ioaddr+1); /* fiddle with 16bit bit */
-                       outb( tmp ^ 0x01, ioaddr+1 ); /* attempt to clear 16bit bit */
-                       if (((inb( ioaddr+1) & 0x01) == 0x01) /* A 16 bit card */
-                               && (tmp & 0x01) == 0x01 ) {                             /* In a 16 slot. */
-                               int asic_reg5 = inb(ioaddr+WD_CMDREG5);
-                               /* Magic to set ASIC to word-wide mode. */
-                               outb( NIC16 | (asic_reg5&0x1f), ioaddr+WD_CMDREG5);
-                               outb(tmp, ioaddr+1);
-                               model_name = "WD8013";
-                               word16 = 1;             /* We have a 16bit board here! */
-                       } else {
-                               model_name = "WD8003";
-                               word16 = 0;
-                       }
-                       outb(tmp, ioaddr+1);                    /* Restore original reg1 value. */
-               }
-#ifndef final_version
-               if ( !ancient && (inb(ioaddr+1) & 0x01) != (word16 & 0x01))
-                       printk("\nWD80?3: Bus width conflict, %d (probe) != %d (reg report).",
-                                  word16 ? 16 : 8, (inb(ioaddr+1) & 0x01) ? 16 : 8);
-#endif
-       }
-
-#if defined(WD_SHMEM) && WD_SHMEM > 0x80000
-       /* Allow a compile-time override.        */
-       dev->mem_start = WD_SHMEM;
-#else
-       if (dev->mem_start == 0) {
-               /* Sanity and old 8003 check */
-               int reg0 = inb(ioaddr);
-               if (reg0 == 0xff || reg0 == 0) {
-                       /* Future plan: this could check a few likely locations first. */
-                       dev->mem_start = 0xd0000;
-                       printk(" assigning address %#lx", dev->mem_start);
-               } else {
-                       int high_addr_bits = inb(ioaddr+WD_CMDREG5) & 0x1f;
-                       /* Some boards don't have the register 5 -- it returns 0xff. */
-                       if (high_addr_bits == 0x1f || word16 == 0)
-                               high_addr_bits = 0x01;
-                       dev->mem_start = ((reg0&0x3f) << 13) + (high_addr_bits << 19);
-               }
-       }
-#endif
-
-       /* The 8390 isn't at the base address -- the ASIC regs are there! */
-       dev->base_addr = ioaddr+WD_NIC_OFFSET;
-
-       if (dev->irq < 2) {
-               static const int irqmap[] = {9, 3, 5, 7, 10, 11, 15, 4};
-               int reg1 = inb(ioaddr+1);
-               int reg4 = inb(ioaddr+4);
-               if (ancient || reg1 == 0xff) {  /* Ack!! No way to read the IRQ! */
-                       short nic_addr = ioaddr+WD_NIC_OFFSET;
-                       unsigned long irq_mask;
-
-                       /* We have an old-style ethercard that doesn't report its IRQ
-                          line.  Do autoirq to find the IRQ line. Note that this IS NOT
-                          a reliable way to trigger an interrupt. */
-                       outb_p(E8390_NODMA + E8390_STOP, nic_addr);
-                       outb(0x00, nic_addr+EN0_IMR);   /* Disable all intrs. */
-
-                       irq_mask = probe_irq_on();
-                       outb_p(0xff, nic_addr + EN0_IMR);       /* Enable all interrupts. */
-                       outb_p(0x00, nic_addr + EN0_RCNTLO);
-                       outb_p(0x00, nic_addr + EN0_RCNTHI);
-                       outb(E8390_RREAD+E8390_START, nic_addr); /* Trigger it... */
-                       mdelay(20);
-                       dev->irq = probe_irq_off(irq_mask);
-
-                       outb_p(0x00, nic_addr+EN0_IMR); /* Mask all intrs. again. */
-
-                       if (ei_debug > 2)
-                               printk(" autoirq is %d", dev->irq);
-                       if (dev->irq < 2)
-                               dev->irq = word16 ? 10 : 5;
-               } else
-                       dev->irq = irqmap[((reg4 >> 5) & 0x03) + (reg1 & 0x04)];
-       } else if (dev->irq == 2)               /* Fixup bogosity: IRQ2 is really IRQ9 */
-               dev->irq = 9;
-
-       /* Snarf the interrupt now.  There's no point in waiting since we cannot
-          share and the board will usually be enabled. */
-       i = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
-       if (i) {
-               printk (" unable to get IRQ %d.\n", dev->irq);
-               return i;
-       }
-
-       /* OK, were are certain this is going to work.  Setup the device. */
-       ei_status.name = model_name;
-       ei_status.word16 = word16;
-       ei_status.tx_start_page = WD_START_PG;
-       ei_status.rx_start_page = WD_START_PG + TX_PAGES;
-
-       /* Don't map in the shared memory until the board is actually opened. */
-
-       /* Some cards (eg WD8003EBT) can be jumpered for more (32k!) memory. */
-       if (dev->mem_end != 0) {
-               ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
-               ei_status.priv = dev->mem_end - dev->mem_start;
-       } else {
-               ei_status.stop_page = word16 ? WD13_STOP_PG : WD03_STOP_PG;
-               dev->mem_end = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256;
-               ei_status.priv = (ei_status.stop_page - WD_START_PG)*256;
-       }
-
-       ei_status.mem = ioremap(dev->mem_start, ei_status.priv);
-       if (!ei_status.mem) {
-               free_irq(dev->irq, dev);
-               return -ENOMEM;
-       }
-
-       printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
-                  model_name, dev->irq, dev->mem_start, dev->mem_end-1);
-
-       ei_status.reset_8390 = wd_reset_8390;
-       ei_status.block_input = wd_block_input;
-       ei_status.block_output = wd_block_output;
-       ei_status.get_8390_hdr = wd_get_8390_hdr;
-
-       dev->netdev_ops = &wd_netdev_ops;
-       NS8390_init(dev, 0);
-
-#if 1
-       /* Enable interrupt generation on softconfig cards -- M.U */
-       /* .. but possibly potentially unsafe - Donald */
-       if (inb(ioaddr+14) & 0x20)
-               outb(inb(ioaddr+4)|0x80, ioaddr+4);
-#endif
-
-       err = register_netdev(dev);
-       if (err) {
-               free_irq(dev->irq, dev);
-               iounmap(ei_status.mem);
-       }
-       return err;
-}
-
-static int
-wd_open(struct net_device *dev)
-{
-  int ioaddr = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
-
-  /* Map in the shared memory. Always set register 0 last to remain
-        compatible with very old boards. */
-  ei_status.reg0 = ((dev->mem_start>>13) & 0x3f) | WD_MEMENB;
-  ei_status.reg5 = ((dev->mem_start>>19) & 0x1f) | NIC16;
-
-  if (ei_status.word16)
-         outb(ei_status.reg5, ioaddr+WD_CMDREG5);
-  outb(ei_status.reg0, ioaddr); /* WD_CMDREG */
-
-  return ei_open(dev);
-}
-
-static void
-wd_reset_8390(struct net_device *dev)
-{
-       int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
-
-       outb(WD_RESET, wd_cmd_port);
-       if (ei_debug > 1) printk("resetting the WD80x3 t=%lu...", jiffies);
-       ei_status.txing = 0;
-
-       /* Set up the ASIC registers, just in case something changed them. */
-       outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmd_port);
-       if (ei_status.word16)
-               outb(NIC16 | ((dev->mem_start>>19) & 0x1f), wd_cmd_port+WD_CMDREG5);
-
-       if (ei_debug > 1) printk("reset done\n");
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
-   we don't need to be concerned with ring wrap as the header will be at
-   the start of a page, so we optimize accordingly. */
-
-static void
-wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
-{
-
-       int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
-       void __iomem *hdr_start = ei_status.mem + ((ring_page - WD_START_PG)<<8);
-
-       /* We'll always get a 4 byte header read followed by a packet read, so
-          we enable 16 bit mode before the header, and disable after the body. */
-       if (ei_status.word16)
-               outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
-
-#ifdef __BIG_ENDIAN
-       /* Officially this is what we are doing, but the readl() is faster */
-       /* unfortunately it isn't endian aware of the struct               */
-       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
-       hdr->count = le16_to_cpu(hdr->count);
-#else
-       ((unsigned int*)hdr)[0] = readl(hdr_start);
-#endif
-}
-
-/* Block input and output are easy on shared memory ethercards, and trivial
-   on the Western digital card where there is no choice of how to do it.
-   The only complications are that the ring buffer wraps, and need to map
-   switch between 8- and 16-bit modes. */
-
-static void
-wd_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
-{
-       int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
-       unsigned long offset = ring_offset - (WD_START_PG<<8);
-       void __iomem *xfer_start = ei_status.mem + offset;
-
-       if (offset + count > ei_status.priv) {
-               /* We must wrap the input move. */
-               int semi_count = ei_status.priv - offset;
-               memcpy_fromio(skb->data, xfer_start, semi_count);
-               count -= semi_count;
-               memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
-       } else {
-               /* Packet is in one chunk -- we can copy + cksum. */
-               memcpy_fromio(skb->data, xfer_start, count);
-       }
-
-       /* Turn off 16 bit access so that reboot works.  ISA brain-damage */
-       if (ei_status.word16)
-               outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
-}
-
-static void
-wd_block_output(struct net_device *dev, int count, const unsigned char *buf,
-                               int start_page)
-{
-       int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
-       void __iomem *shmem = ei_status.mem + ((start_page - WD_START_PG)<<8);
-
-
-       if (ei_status.word16) {
-               /* Turn on and off 16 bit access so that reboot works. */
-               outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
-               memcpy_toio(shmem, buf, count);
-               outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
-       } else
-               memcpy_toio(shmem, buf, count);
-}
-
-
-static int
-wd_close(struct net_device *dev)
-{
-       int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
-
-       if (ei_debug > 1)
-               printk("%s: Shutting down ethercard.\n", dev->name);
-       ei_close(dev);
-
-       /* Change from 16-bit to 8-bit shared memory so reboot works. */
-       if (ei_status.word16)
-               outb(ei_status.reg5, wd_cmdreg + WD_CMDREG5 );
-
-       /* And disable the shared memory. */
-       outb(ei_status.reg0 & ~WD_MEMENB, wd_cmdreg);
-
-       return 0;
-}
-
-
-#ifdef MODULE
-#define MAX_WD_CARDS   4       /* Max number of wd cards per module */
-static struct net_device *dev_wd[MAX_WD_CARDS];
-static int io[MAX_WD_CARDS];
-static int irq[MAX_WD_CARDS];
-static int mem[MAX_WD_CARDS];
-static int mem_end[MAX_WD_CARDS];      /* for non std. mem size */
-
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(mem, int, NULL, 0);
-module_param_array(mem_end, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es)");
-MODULE_PARM_DESC(irq, "IRQ number(s) (ignored for PureData boards)");
-MODULE_PARM_DESC(mem, "memory base address(es)(ignored for PureData boards)");
-MODULE_PARM_DESC(mem_end, "memory end address(es)");
-MODULE_DESCRIPTION("ISA Western Digital wd8003/wd8013 ; SMC Elite, Elite16 ethernet driver");
-MODULE_LICENSE("GPL");
-
-/* This is set up so that only a single autoprobe takes place per call.
-ISA device autoprobes on a running machine are not recommended. */
-
-int __init init_module(void)
-{
-       struct net_device *dev;
-       int this_dev, found = 0;
-
-       for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
-               if (io[this_dev] == 0)  {
-                       if (this_dev != 0) break; /* only autoprobe 1st one */
-                       printk(KERN_NOTICE "wd.c: Presently autoprobing (not recommended) for a single card.\n");
-               }
-               dev = alloc_ei_netdev();
-               if (!dev)
-                       break;
-               dev->irq = irq[this_dev];
-               dev->base_addr = io[this_dev];
-               dev->mem_start = mem[this_dev];
-               dev->mem_end = mem_end[this_dev];
-               if (do_wd_probe(dev) == 0) {
-                       dev_wd[found++] = dev;
-                       continue;
-               }
-               free_netdev(dev);
-               printk(KERN_WARNING "wd.c: No wd80x3 card found (i/o = 0x%x).\n", io[this_dev]);
-               break;
-       }
-       if (found)
-               return 0;
-       return -ENXIO;
-}
-
-static void cleanup_card(struct net_device *dev)
-{
-       free_irq(dev->irq, dev);
-       release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT);
-       iounmap(ei_status.mem);
-}
-
-void __exit
-cleanup_module(void)
-{
-       int this_dev;
-
-       for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
-               struct net_device *dev = dev_wd[this_dev];
-               if (dev) {
-                       unregister_netdev(dev);
-                       cleanup_card(dev);
-                       free_netdev(dev);
-               }
-       }
-}
-#endif /* MODULE */
diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c
deleted file mode 100644 (file)
index 15e7751..0000000
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- *  Amiga Linux/m68k and Linux/PPC Zorro NS8390 Ethernet Driver
- *
- *  (C) Copyright 1998-2000 by some Elitist 680x0 Users(TM)
- *
- *  ---------------------------------------------------------------------------
- *
- *  This program is based on all the other NE2000 drivers for Linux
- *
- *  ---------------------------------------------------------------------------
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of the Linux
- *  distribution for more details.
- *
- *  ---------------------------------------------------------------------------
- *
- *  The Ariadne II and X-Surf are Zorro-II boards containing Realtek RTL8019AS
- *  Ethernet Controllers.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/zorro.h>
-#include <linux/jiffies.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-
-#define EI_SHIFT(x)            (ei_local->reg_offset[x])
-#define ei_inb(port)           in_8(port)
-#define ei_outb(val, port)     out_8(port, val)
-#define ei_inb_p(port)         in_8(port)
-#define ei_outb_p(val, port)   out_8(port, val)
-
-static const char version[] =
-       "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#include "lib8390.c"
-
-#define DRV_NAME       "zorro8390"
-
-#define NE_BASE                (dev->base_addr)
-#define NE_CMD         (0x00 * 2)
-#define NE_DATAPORT    (0x10 * 2)      /* NatSemi-defined port window offset */
-#define NE_RESET       (0x1f * 2)      /* Issue a read to reset,
-                                        * a write to clear. */
-#define NE_IO_EXTENT   (0x20 * 2)
-
-#define NE_EN0_ISR     (0x07 * 2)
-#define NE_EN0_DCFG    (0x0e * 2)
-
-#define NE_EN0_RSARLO  (0x08 * 2)
-#define NE_EN0_RSARHI  (0x09 * 2)
-#define NE_EN0_RCNTLO  (0x0a * 2)
-#define NE_EN0_RXCR    (0x0c * 2)
-#define NE_EN0_TXCR    (0x0d * 2)
-#define NE_EN0_RCNTHI  (0x0b * 2)
-#define NE_EN0_IMR     (0x0f * 2)
-
-#define NESM_START_PG  0x40    /* First page of TX buffer */
-#define NESM_STOP_PG   0x80    /* Last page +1 of RX ring */
-
-#define WORDSWAP(a)    ((((a) >> 8) & 0xff) | ((a) << 8))
-
-static struct card_info {
-       zorro_id id;
-       const char *name;
-       unsigned int offset;
-} cards[] __devinitdata = {
-       { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 },
-       { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 },
-};
-
-/* Hard reset the card.  This used to pause for the same period that a
- * 8390 reset command required, but that shouldn't be necessary.
- */
-static void zorro8390_reset_8390(struct net_device *dev)
-{
-       unsigned long reset_start_time = jiffies;
-
-       if (ei_debug > 1)
-               netdev_dbg(dev, "resetting - t=%ld...\n", jiffies);
-
-       z_writeb(z_readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
-
-       ei_status.txing = 0;
-       ei_status.dmaing = 0;
-
-       /* This check _should_not_ be necessary, omit eventually. */
-       while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RESET) == 0)
-               if (time_after(jiffies, reset_start_time + 2 * HZ / 100)) {
-                       netdev_warn(dev, "%s: did not complete\n", __func__);
-                       break;
-               }
-       z_writeb(ENISR_RESET, NE_BASE + NE_EN0_ISR);    /* Ack intr */
-}
-
-/* Grab the 8390 specific header. Similar to the block_input routine, but
- * we don't need to be concerned with ring wrap as the header will be at
- * the start of a page, so we optimize accordingly.
- */
-static void zorro8390_get_8390_hdr(struct net_device *dev,
-                                  struct e8390_pkt_hdr *hdr, int ring_page)
-{
-       int nic_base = dev->base_addr;
-       int cnt;
-       short *ptrs;
-
-       /* This *shouldn't* happen.
-        * If it does, it's the last thing you'll see
-        */
-       if (ei_status.dmaing) {
-               netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
-                          __func__, ei_status.dmaing, ei_status.irqlock);
-               return;
-       }
-
-       ei_status.dmaing |= 0x01;
-       z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
-       z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
-       z_writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
-       z_writeb(0, nic_base + NE_EN0_RCNTHI);
-       z_writeb(0, nic_base + NE_EN0_RSARLO);          /* On page boundary */
-       z_writeb(ring_page, nic_base + NE_EN0_RSARHI);
-       z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
-       ptrs = (short *)hdr;
-       for (cnt = 0; cnt < sizeof(struct e8390_pkt_hdr) >> 1; cnt++)
-               *ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
-
-       z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);     /* Ack intr */
-
-       hdr->count = WORDSWAP(hdr->count);
-
-       ei_status.dmaing &= ~0x01;
-}
-
-/* Block input and output, similar to the Crynwr packet driver.
- * If you are porting to a new ethercard, look at the packet driver source
- * for hints. The NEx000 doesn't share the on-board packet memory --
- * you have to put the packet out through the "remote DMA" dataport
- * using z_writeb.
- */
-static void zorro8390_block_input(struct net_device *dev, int count,
-                                 struct sk_buff *skb, int ring_offset)
-{
-       int nic_base = dev->base_addr;
-       char *buf = skb->data;
-       short *ptrs;
-       int cnt;
-
-       /* This *shouldn't* happen.
-        * If it does, it's the last thing you'll see
-        */
-       if (ei_status.dmaing) {
-               netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
-                          __func__, ei_status.dmaing, ei_status.irqlock);
-               return;
-       }
-       ei_status.dmaing |= 0x01;
-       z_writeb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
-       z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
-       z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
-       z_writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
-       z_writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
-       z_writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
-       z_writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-       ptrs = (short *)buf;
-       for (cnt = 0; cnt < count >> 1; cnt++)
-               *ptrs++ = z_readw(NE_BASE + NE_DATAPORT);
-       if (count & 0x01)
-               buf[count - 1] = z_readb(NE_BASE + NE_DATAPORT);
-
-       z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);     /* Ack intr */
-       ei_status.dmaing &= ~0x01;
-}
-
-static void zorro8390_block_output(struct net_device *dev, int count,
-                                  const unsigned char *buf,
-                                  const int start_page)
-{
-       int nic_base = NE_BASE;
-       unsigned long dma_start;
-       short *ptrs;
-       int cnt;
-
-       /* Round the count up for word writes.  Do we need to do this?
-        * What effect will an odd byte count have on the 8390?
-        * I should check someday.
-        */
-       if (count & 0x01)
-               count++;
-
-       /* This *shouldn't* happen.
-        * If it does, it's the last thing you'll see
-        */
-       if (ei_status.dmaing) {
-               netdev_err(dev, "%s: DMAing conflict [DMAstat:%d][irqlock:%d]\n",
-                          __func__, ei_status.dmaing, ei_status.irqlock);
-               return;
-       }
-       ei_status.dmaing |= 0x01;
-       /* We should already be in page 0, but to be safe... */
-       z_writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
-
-       z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
-
-       /* Now the normal output. */
-       z_writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
-       z_writeb(count >> 8,   nic_base + NE_EN0_RCNTHI);
-       z_writeb(0x00, nic_base + NE_EN0_RSARLO);
-       z_writeb(start_page, nic_base + NE_EN0_RSARHI);
-
-       z_writeb(E8390_RWRITE + E8390_START, nic_base + NE_CMD);
-       ptrs = (short *)buf;
-       for (cnt = 0; cnt < count >> 1; cnt++)
-               z_writew(*ptrs++, NE_BASE + NE_DATAPORT);
-
-       dma_start = jiffies;
-
-       while ((z_readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
-               if (time_after(jiffies, dma_start + 2 * HZ / 100)) {
-                                       /* 20ms */
-                       netdev_err(dev, "timeout waiting for Tx RDC\n");
-                       zorro8390_reset_8390(dev);
-                       __NS8390_init(dev, 1);
-                       break;
-               }
-
-       z_writeb(ENISR_RDC, nic_base + NE_EN0_ISR);     /* Ack intr */
-       ei_status.dmaing &= ~0x01;
-}
-
-static int zorro8390_open(struct net_device *dev)
-{
-       __ei_open(dev);
-       return 0;
-}
-
-static int zorro8390_close(struct net_device *dev)
-{
-       if (ei_debug > 1)
-               netdev_dbg(dev, "Shutting down ethercard\n");
-       __ei_close(dev);
-       return 0;
-}
-
-static void __devexit zorro8390_remove_one(struct zorro_dev *z)
-{
-       struct net_device *dev = zorro_get_drvdata(z);
-
-       unregister_netdev(dev);
-       free_irq(IRQ_AMIGA_PORTS, dev);
-       release_mem_region(ZTWO_PADDR(dev->base_addr), NE_IO_EXTENT * 2);
-       free_netdev(dev);
-}
-
-static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = {
-       { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, },
-       { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
-       { 0 }
-};
-MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl);
-
-static const struct net_device_ops zorro8390_netdev_ops = {
-       .ndo_open               = zorro8390_open,
-       .ndo_stop               = zorro8390_close,
-       .ndo_start_xmit         = __ei_start_xmit,
-       .ndo_tx_timeout         = __ei_tx_timeout,
-       .ndo_get_stats          = __ei_get_stats,
-       .ndo_set_multicast_list = __ei_set_multicast_list,
-       .ndo_validate_addr      = eth_validate_addr,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_change_mtu         = eth_change_mtu,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       .ndo_poll_controller    = __ei_poll,
-#endif
-};
-
-static int __devinit zorro8390_init(struct net_device *dev,
-                                   unsigned long board, const char *name,
-                                   unsigned long ioaddr)
-{
-       int i;
-       int err;
-       unsigned char SA_prom[32];
-       int start_page, stop_page;
-       static u32 zorro8390_offsets[16] = {
-               0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
-               0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
-       };
-
-       /* Reset card. Who knows what dain-bramaged state it was left in. */
-       {
-               unsigned long reset_start_time = jiffies;
-
-               z_writeb(z_readb(ioaddr + NE_RESET), ioaddr + NE_RESET);
-
-               while ((z_readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
-                       if (time_after(jiffies,
-                                      reset_start_time + 2 * HZ / 100)) {
-                               netdev_warn(dev, "not found (no reset ack)\n");
-                               return -ENODEV;
-                       }
-
-               z_writeb(0xff, ioaddr + NE_EN0_ISR);    /* Ack all intr. */
-       }
-
-       /* Read the 16 bytes of station address PROM.
-        * We must first initialize registers,
-        * similar to NS8390_init(eifdev, 0).
-        * We can't reliably read the SAPROM address without this.
-        * (I learned the hard way!).
-        */
-       {
-               static const struct {
-                       u32 value;
-                       u32 offset;
-               } program_seq[] = {
-                       {E8390_NODMA + E8390_PAGE0 + E8390_STOP, NE_CMD},
-                                               /* Select page 0 */
-                       {0x48,  NE_EN0_DCFG},   /* 0x48: Set byte-wide access */
-                       {0x00,  NE_EN0_RCNTLO}, /* Clear the count regs */
-                       {0x00,  NE_EN0_RCNTHI},
-                       {0x00,  NE_EN0_IMR},    /* Mask completion irq */
-                       {0xFF,  NE_EN0_ISR},
-                       {E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */
-                       {E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode */
-                       {32,    NE_EN0_RCNTLO},
-                       {0x00,  NE_EN0_RCNTHI},
-                       {0x00,  NE_EN0_RSARLO}, /* DMA starting at 0x0000 */
-                       {0x00,  NE_EN0_RSARHI},
-                       {E8390_RREAD + E8390_START, NE_CMD},
-               };
-               for (i = 0; i < ARRAY_SIZE(program_seq); i++)
-                       z_writeb(program_seq[i].value,
-                                ioaddr + program_seq[i].offset);
-       }
-       for (i = 0; i < 16; i++) {
-               SA_prom[i] = z_readb(ioaddr + NE_DATAPORT);
-               (void)z_readb(ioaddr + NE_DATAPORT);
-       }
-
-       /* We must set the 8390 for word mode. */
-       z_writeb(0x49, ioaddr + NE_EN0_DCFG);
-       start_page = NESM_START_PG;
-       stop_page = NESM_STOP_PG;
-
-       dev->base_addr = ioaddr;
-       dev->irq = IRQ_AMIGA_PORTS;
-
-       /* Install the Interrupt handler */
-       i = request_irq(IRQ_AMIGA_PORTS, __ei_interrupt,
-                       IRQF_SHARED, DRV_NAME, dev);
-       if (i)
-               return i;
-
-       for (i = 0; i < ETHER_ADDR_LEN; i++)
-               dev->dev_addr[i] = SA_prom[i];
-
-       pr_debug("Found ethernet address: %pM\n", dev->dev_addr);
-
-       ei_status.name = name;
-       ei_status.tx_start_page = start_page;
-       ei_status.stop_page = stop_page;
-       ei_status.word16 = 1;
-
-       ei_status.rx_start_page = start_page + TX_PAGES;
-
-       ei_status.reset_8390 = zorro8390_reset_8390;
-       ei_status.block_input = zorro8390_block_input;
-       ei_status.block_output = zorro8390_block_output;
-       ei_status.get_8390_hdr = zorro8390_get_8390_hdr;
-       ei_status.reg_offset = zorro8390_offsets;
-
-       dev->netdev_ops = &zorro8390_netdev_ops;
-       __NS8390_init(dev, 0);
-       err = register_netdev(dev);
-       if (err) {
-               free_irq(IRQ_AMIGA_PORTS, dev);
-               return err;
-       }
-
-       netdev_info(dev, "%s at 0x%08lx, Ethernet Address %pM\n",
-                   name, board, dev->dev_addr);
-
-       return 0;
-}
-
-static int __devinit zorro8390_init_one(struct zorro_dev *z,
-                                       const struct zorro_device_id *ent)
-{
-       struct net_device *dev;
-       unsigned long board, ioaddr;
-       int err, i;
-
-       for (i = ARRAY_SIZE(cards) - 1; i >= 0; i--)
-               if (z->id == cards[i].id)
-                       break;
-       if (i < 0)
-               return -ENODEV;
-
-       board = z->resource.start;
-       ioaddr = board + cards[i].offset;
-       dev = ____alloc_ei_netdev(0);
-       if (!dev)
-               return -ENOMEM;
-       if (!request_mem_region(ioaddr, NE_IO_EXTENT * 2, DRV_NAME)) {
-               free_netdev(dev);
-               return -EBUSY;
-       }
-       err = zorro8390_init(dev, board, cards[i].name, ZTWO_VADDR(ioaddr));
-       if (err) {
-               release_mem_region(ioaddr, NE_IO_EXTENT * 2);
-               free_netdev(dev);
-               return err;
-       }
-       zorro_set_drvdata(z, dev);
-       return 0;
-}
-
-static struct zorro_driver zorro8390_driver = {
-       .name           = "zorro8390",
-       .id_table       = zorro8390_zorro_tbl,
-       .probe          = zorro8390_init_one,
-       .remove         = __devexit_p(zorro8390_remove_one),
-};
-
-static int __init zorro8390_init_module(void)
-{
-       return zorro_register_driver(&zorro8390_driver);
-}
-
-static void __exit zorro8390_cleanup_module(void)
-{
-       zorro_unregister_driver(&zorro8390_driver);
-}
-
-module_init(zorro8390_init_module);
-module_exit(zorro8390_cleanup_module);
-
-MODULE_LICENSE("GPL");