eth16i: Move the Allied Telesis/Fujitsu drivers
authorJeff Kirsher <jeffrey.t.kirsher@intel.com>
Sat, 11 Jun 2011 08:13:22 +0000 (01:13 -0700)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Fri, 12 Aug 2011 07:22:08 +0000 (00:22 -0700)
Move the Allied Telesis/Fujitsu drivers into drivers/net/ethernet/fujitsu/
and make the necessary Kconfig and Makefile changes.

CC: Shingo Fujimoto <shingo@flab.fujitsu.co.jp>
CC: Yutaka Tamiya <tamy@flab.fujitsu.co.jp>
CC: Rene Schmit <rene@bss.lu>
CC: Mika Kuoppala <miku@iki.fi>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
15 files changed:
MAINTAINERS
drivers/net/Kconfig
drivers/net/Makefile
drivers/net/at1700.c [deleted file]
drivers/net/eth16i.c [deleted file]
drivers/net/ethernet/Kconfig
drivers/net/ethernet/Makefile
drivers/net/ethernet/fujitsu/Kconfig [new file with mode: 0644]
drivers/net/ethernet/fujitsu/Makefile [new file with mode: 0644]
drivers/net/ethernet/fujitsu/at1700.c [new file with mode: 0644]
drivers/net/ethernet/fujitsu/eth16i.c [new file with mode: 0644]
drivers/net/ethernet/fujitsu/fmvj18x_cs.c [new file with mode: 0644]
drivers/net/pcmcia/Kconfig
drivers/net/pcmcia/Makefile
drivers/net/pcmcia/fmvj18x_cs.c [deleted file]

index 51d9281a30355f58a78bedcb133cf900b2cce448..5b2ad6c8cac11a99426f8f96f31b2a33a04c91f1 100644 (file)
@@ -2525,7 +2525,7 @@ F:        net/bridge/
 ETHERTEAM 16I DRIVER
 M:     Mika Kuoppala <miku@iki.fi>
 S:     Maintained
-F:     drivers/net/eth16i.c
+F:     drivers/net/ethernet/fujitsu/eth16i.c
 
 EXT2 FILE SYSTEM
 M:     Jan Kara <jack@suse.cz>
index c1e491add8f998940fbf6dc175f55209a4cf5c63..27f97b4e83b18a9fd418edfe5669b4fd4e72761d 100644 (file)
@@ -428,18 +428,6 @@ config DNET
          To compile this driver as a module, choose M here: the module
          will be called dnet.
 
-config AT1700
-       tristate "AT1700/1720 support (EXPERIMENTAL)"
-       depends on (ISA || MCA_LEGACY) && 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 at1700.
-
 config HP100
        tristate "HP 10/100VG PCLAN (ISA, EISA, PCI) support"
        depends on ISA || EISA || PCI
@@ -451,34 +439,6 @@ config HP100
          To compile this driver as a module, choose M here. The module
          will be called hp100.
 
-config NET_ISA
-       bool "Other ISA cards"
-       depends on ISA
-       ---help---
-         If your network (Ethernet) card hasn't been mentioned yet and its
-         bus system (that's the way the cards talks to the other components
-         of your computer) is ISA (as opposed to EISA, VLB or PCI), say Y.
-         Make sure you know the name of your card. Read the Ethernet-HOWTO,
-         available from <http://www.tldp.org/docs.html#howto>.
-
-         If unsure, say Y.
-
-         Note that the answer to this question doesn't directly affect the
-         kernel: saying N will just cause the configurator to skip all
-         the remaining ISA network card questions. If you say Y, you will be
-         asked for your specific card in the following questions.
-
-config ETH16I
-       tristate "ICL EtherTeam 16i/32 support"
-       depends on NET_ISA
-       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 eth16i.
-
 config NET_PCI
        bool "EISA, VLB, PCI and on board controllers"
        depends on ISA || EISA || PCI
index 7e1128fd62bdcd8ebf304a583e9aae9addfc9d73..07cad1a79456eefcda3f7e4f509df4411d8c5b52 100644 (file)
@@ -96,10 +96,7 @@ obj-$(CONFIG_IFB) += ifb.o
 obj-$(CONFIG_MACVLAN) += macvlan.o
 obj-$(CONFIG_MACVTAP) += macvtap.o
 obj-$(CONFIG_DEFXX) += defxx.o
-obj-$(CONFIG_AT1700) += at1700.o
 obj-$(CONFIG_CPMAC) += cpmac.o
-
-obj-$(CONFIG_ETH16I) += eth16i.o
 obj-$(CONFIG_EQUALIZER) += eql.o
 obj-$(CONFIG_KORINA) += korina.o
 obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
deleted file mode 100644 (file)
index 65a78f9..0000000
+++ /dev/null
@@ -1,900 +0,0 @@
-/* at1700.c: A network device driver for  the Allied Telesis AT1700.
-
-       Written 1993-98 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 device driver for the Allied Telesis AT1700, and
-        Fujitsu FMV-181/182/181A/182A/183/184/183A/184A, which are
-       straight-forward Fujitsu MB86965 implementations.
-
-       Modification for Fujitsu FMV-18X cards is done by Yutaka Tamiya
-       (tamy@flab.fujitsu.co.jp).
-
-  Sources:
-    The Fujitsu MB86965 datasheet.
-
-       After the initial version of this driver was written Gerry Sawkins of
-       ATI provided their EEPROM configuration code header file.
-    Thanks to NIIBE Yutaka <gniibe@mri.co.jp> for bug fixes.
-
-    MCA bus (AT1720) support by Rene Schmit <rene@bss.lu>
-
-  Bugs:
-       The MB86965 has a design flaw that makes all probes unreliable.  Not
-       only is it difficult to detect, it also moves around in I/O space in
-       response to inb()s from other device probes!
-*/
-
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/mca-legacy.h>
-#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/skbuff.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/crc32.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-static char version[] __initdata =
-       "at1700.c:v1.16 9/11/06  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
-#define DRV_NAME "at1700"
-
-/* Tunable parameters. */
-
-/* When to switch from the 64-entry multicast filter to Rx-all-multicast. */
-#define MC_FILTERBREAK 64
-
-/* These unusual address orders are used to verify the CONFIG register. */
-
-static int fmv18x_probe_list[] __initdata = {
-       0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0
-};
-
-/*
- *     ISA
- */
-
-static unsigned at1700_probe_list[] __initdata = {
-       0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
-};
-
-/*
- *     MCA
- */
-#ifdef CONFIG_MCA_LEGACY
-static int at1700_ioaddr_pattern[] __initdata = {
-       0x00, 0x04, 0x01, 0x05, 0x02, 0x06, 0x03, 0x07
-};
-
-static int at1700_mca_probe_list[] __initdata = {
-       0x400, 0x1400, 0x2400, 0x3400, 0x4400, 0x5400, 0x6400, 0x7400, 0
-};
-
-static int at1700_irq_pattern[] __initdata = {
-       0x00, 0x00, 0x00, 0x30, 0x70, 0xb0, 0x00, 0x00,
-       0x00, 0xf0, 0x34, 0x74, 0xb4, 0x00, 0x00, 0xf4, 0x00
-};
-#endif
-
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifndef NET_DEBUG
-#define NET_DEBUG 1
-#endif
-static unsigned int net_debug = NET_DEBUG;
-
-typedef unsigned char uchar;
-
-/* Information that need to be kept for each board. */
-struct net_local {
-       spinlock_t lock;
-       unsigned char mc_filter[8];
-       uint jumpered:1;                        /* Set iff the board has jumper config. */
-       uint tx_started:1;                      /* Packets are on the Tx queue. */
-       uint tx_queue_ready:1;                  /* Tx queue is ready to be sent. */
-       uint rx_started:1;                      /* Packets are Rxing. */
-       uchar tx_queue;                         /* Number of packet on the Tx queue. */
-       char mca_slot;                          /* -1 means ISA */
-       ushort tx_queue_len;                    /* Current length of the Tx queue. */
-};
-
-
-/* Offsets from the base address. */
-#define STATUS                 0
-#define TX_STATUS              0
-#define RX_STATUS              1
-#define TX_INTR                        2               /* Bit-mapped interrupt enable registers. */
-#define RX_INTR                        3
-#define TX_MODE                        4
-#define RX_MODE                        5
-#define CONFIG_0               6               /* Misc. configuration settings. */
-#define CONFIG_1               7
-/* Run-time register bank 2 definitions. */
-#define DATAPORT               8               /* Word-wide DMA or programmed-I/O dataport. */
-#define TX_START               10
-#define COL16CNTL              11              /* Control Reg for 16 collisions */
-#define MODE13                 13
-#define RX_CTRL                        14
-/* Configuration registers only on the '865A/B chips. */
-#define EEPROM_Ctrl    16
-#define EEPROM_Data    17
-#define CARDSTATUS     16                      /* FMV-18x Card Status */
-#define CARDSTATUS1    17                      /* FMV-18x Card Status */
-#define IOCONFIG               18              /* Either read the jumper, or move the I/O. */
-#define IOCONFIG1              19
-#define        SAPROM                  20              /* The station address PROM, if no EEPROM. */
-#define MODE24                 24
-#define RESET                  31              /* Write to reset some parts of the chip. */
-#define AT1700_IO_EXTENT       32
-#define PORT_OFFSET(o) (o)
-
-
-#define TX_TIMEOUT             (HZ/10)
-
-
-/* Index to functions, as function prototypes. */
-
-static int at1700_probe1(struct net_device *dev, int ioaddr);
-static int read_eeprom(long ioaddr, int location);
-static int net_open(struct net_device *dev);
-static netdev_tx_t net_send_packet(struct sk_buff *skb,
-                                  struct net_device *dev);
-static irqreturn_t net_interrupt(int irq, void *dev_id);
-static void net_rx(struct net_device *dev);
-static int net_close(struct net_device *dev);
-static void set_rx_mode(struct net_device *dev);
-static void net_tx_timeout (struct net_device *dev);
-
-
-#ifdef CONFIG_MCA_LEGACY
-struct at1720_mca_adapters_struct {
-       char* name;
-       int id;
-};
-/* rEnE : maybe there are others I don't know off... */
-
-static struct at1720_mca_adapters_struct at1720_mca_adapters[] __initdata = {
-       { "Allied Telesys AT1720AT",    0x6410 },
-       { "Allied Telesys AT1720BT",    0x6413 },
-       { "Allied Telesys AT1720T",     0x6416 },
-       { NULL, 0 },
-};
-#endif
-
-/* Check for a network adaptor of this type, and return '0' iff one exists.
-   If dev->base_addr == 0, probe all likely locations.
-   If dev->base_addr == 1, always return failure.
-   If dev->base_addr == 2, allocate space for the device and return success
-   (detachable devices only).
-   */
-
-static int io = 0x260;
-
-static int irq;
-
-static void cleanup_card(struct net_device *dev)
-{
-#ifdef CONFIG_MCA_LEGACY
-       struct net_local *lp = netdev_priv(dev);
-       if (lp->mca_slot >= 0)
-               mca_mark_as_unused(lp->mca_slot);
-#endif
-       free_irq(dev->irq, NULL);
-       release_region(dev->base_addr, AT1700_IO_EXTENT);
-}
-
-struct net_device * __init at1700_probe(int unit)
-{
-       struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
-       unsigned *port;
-       int err = 0;
-
-       if (!dev)
-               return ERR_PTR(-ENODEV);
-
-       if (unit >= 0) {
-               sprintf(dev->name, "eth%d", unit);
-               netdev_boot_setup_check(dev);
-               io = dev->base_addr;
-               irq = dev->irq;
-       } else {
-               dev->base_addr = io;
-               dev->irq = irq;
-       }
-
-       if (io > 0x1ff) {       /* Check a single specified location. */
-               err = at1700_probe1(dev, io);
-       } else if (io != 0) {   /* Don't probe at all. */
-               err = -ENXIO;
-       } else {
-               for (port = at1700_probe_list; *port; port++) {
-                       if (at1700_probe1(dev, *port) == 0)
-                               break;
-                       dev->irq = irq;
-               }
-               if (!*port)
-                       err = -ENODEV;
-       }
-       if (err)
-               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 at1700_netdev_ops = {
-       .ndo_open               = net_open,
-       .ndo_stop               = net_close,
-       .ndo_start_xmit         = net_send_packet,
-       .ndo_set_multicast_list = set_rx_mode,
-       .ndo_tx_timeout         = net_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_validate_addr      = eth_validate_addr,
-};
-
-/* The Fujitsu datasheet suggests that the NIC be probed for by checking its
-   "signature", the default bit pattern after a reset.  This *doesn't* work --
-   there is no way to reset the bus interface without a complete power-cycle!
-
-   It turns out that ATI came to the same conclusion I did: the only thing
-   that can be done is checking a few bits and then diving right into an
-   EEPROM read. */
-
-static int __init at1700_probe1(struct net_device *dev, int ioaddr)
-{
-       static const char fmv_irqmap[4] = {3, 7, 10, 15};
-       static const char fmv_irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
-       static const char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
-       unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0;
-       int slot, ret = -ENODEV;
-       struct net_local *lp = netdev_priv(dev);
-
-       if (!request_region(ioaddr, AT1700_IO_EXTENT, DRV_NAME))
-               return -EBUSY;
-
-       /* Resetting the chip doesn't reset the ISA interface, so don't bother.
-          That means we have to be careful with the register values we probe
-          for.
-        */
-#ifdef notdef
-       printk("at1700 probe at %#x, eeprom is %4.4x %4.4x %4.4x ctrl %4.4x.\n",
-                  ioaddr, read_eeprom(ioaddr, 4), read_eeprom(ioaddr, 5),
-                  read_eeprom(ioaddr, 6), inw(ioaddr + EEPROM_Ctrl));
-#endif
-
-#ifdef CONFIG_MCA_LEGACY
-       /* rEnE (rene@bss.lu): got this from 3c509 driver source , adapted for AT1720 */
-
-    /* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch, heavily
-       modified by Chris Beauregard (cpbeaure@csclub.uwaterloo.ca)
-       to support standard MCA probing. */
-
-       /* redone for multi-card detection by ZP Gu (zpg@castle.net) */
-       /* now works as a module */
-
-       if (MCA_bus) {
-               int j;
-               int l_i;
-               u_char pos3, pos4;
-
-               for (j = 0; at1720_mca_adapters[j].name != NULL; j ++) {
-                       slot = 0;
-                       while (slot != MCA_NOTFOUND) {
-
-                               slot = mca_find_unused_adapter( at1720_mca_adapters[j].id, slot );
-                               if (slot == MCA_NOTFOUND) break;
-
-                               /* if we get this far, an adapter has been detected and is
-                               enabled */
-
-                               pos3 = mca_read_stored_pos( slot, 3 );
-                               pos4 = mca_read_stored_pos( slot, 4 );
-
-                               for (l_i = 0; l_i < 8; l_i++)
-                                       if (( pos3 & 0x07) == at1700_ioaddr_pattern[l_i])
-                                               break;
-                               ioaddr = at1700_mca_probe_list[l_i];
-
-                               for (irq = 0; irq < 0x10; irq++)
-                                       if (((((pos4>>4) & 0x0f) | (pos3 & 0xf0)) & 0xff) == at1700_irq_pattern[irq])
-                                               break;
-
-                                       /* probing for a card at a particular IO/IRQ */
-                               if ((dev->irq && dev->irq != irq) ||
-                                   (dev->base_addr && dev->base_addr != ioaddr)) {
-                                       slot++;         /* probing next slot */
-                                       continue;
-                               }
-
-                               dev->irq = irq;
-
-                               /* claim the slot */
-                               mca_set_adapter_name( slot, at1720_mca_adapters[j].name );
-                               mca_mark_as_used(slot);
-
-                               goto found;
-                       }
-               }
-               /* if we get here, we didn't find an MCA adapter - try ISA */
-       }
-#endif
-       slot = -1;
-       /* We must check for the EEPROM-config boards first, else accessing
-          IOCONFIG0 will move the board! */
-       if (at1700_probe_list[inb(ioaddr + IOCONFIG1) & 0x07] == ioaddr &&
-           read_eeprom(ioaddr, 4) == 0x0000 &&
-           (read_eeprom(ioaddr, 5) & 0xff00) == 0xF400)
-               is_at1700 = 1;
-       else if (inb(ioaddr + SAPROM    ) == 0x00 &&
-                inb(ioaddr + SAPROM + 1) == 0x00 &&
-                inb(ioaddr + SAPROM + 2) == 0x0e)
-               is_fmv18x = 1;
-       else {
-               goto err_out;
-       }
-
-#ifdef CONFIG_MCA_LEGACY
-found:
-#endif
-
-               /* Reset the internal state machines. */
-       outb(0, ioaddr + RESET);
-
-       if (is_at1700) {
-               irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04)
-                                                  | (read_eeprom(ioaddr, 0)>>14)];
-       } else {
-               /* Check PnP mode for FMV-183/184/183A/184A. */
-               /* This PnP routine is very poor. IO and IRQ should be known. */
-               if (inb(ioaddr + CARDSTATUS1) & 0x20) {
-                       irq = dev->irq;
-                       for (i = 0; i < 8; i++) {
-                               if (irq == fmv_irqmap_pnp[i])
-                                       break;
-                       }
-                       if (i == 8) {
-                               goto err_mca;
-                       }
-               } else {
-                       if (fmv18x_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr)
-                               goto err_mca;
-                       irq = fmv_irqmap[(inb(ioaddr + IOCONFIG)>>6) & 0x03];
-               }
-       }
-
-       printk("%s: %s found at %#3x, IRQ %d, address ", dev->name,
-                  is_at1700 ? "AT1700" : "FMV-18X", ioaddr, irq);
-
-       dev->base_addr = ioaddr;
-       dev->irq = irq;
-
-       if (is_at1700) {
-               for(i = 0; i < 3; i++) {
-                       unsigned short eeprom_val = read_eeprom(ioaddr, 4+i);
-                       ((unsigned short *)dev->dev_addr)[i] = ntohs(eeprom_val);
-               }
-       } else {
-               for(i = 0; i < 6; i++) {
-                       unsigned char val = inb(ioaddr + SAPROM + i);
-                       dev->dev_addr[i] = val;
-               }
-       }
-       printk("%pM", dev->dev_addr);
-
-       /* The EEPROM word 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
-          rather than 150 ohm shielded twisted pair compensation.
-          0x0000 == auto-sense the interface
-          0x0800 == use TP interface
-          0x1800 == use coax interface
-          */
-       {
-               const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2"};
-               if (is_at1700) {
-                       ushort setup_value = read_eeprom(ioaddr, 12);
-                       dev->if_port = setup_value >> 8;
-               } else {
-                       ushort setup_value = inb(ioaddr + CARDSTATUS);
-                       switch (setup_value & 0x07) {
-                       case 0x01: /* 10base5 */
-                       case 0x02: /* 10base2 */
-                               dev->if_port = 0x18; break;
-                       case 0x04: /* 10baseT */
-                               dev->if_port = 0x08; break;
-                       default:   /* auto-sense */
-                               dev->if_port = 0x00; break;
-                       }
-               }
-               printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);
-       }
-
-       /* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit
-          bus access, two 4K Tx queues, and disabled Tx and Rx. */
-       outb(0xda, ioaddr + CONFIG_0);
-
-       /* Set the station address in bank zero. */
-       outb(0x00, ioaddr + CONFIG_1);
-       for (i = 0; i < 6; i++)
-               outb(dev->dev_addr[i], ioaddr + PORT_OFFSET(8 + i));
-
-       /* Switch to bank 1 and set the multicast table to accept none. */
-       outb(0x04, ioaddr + CONFIG_1);
-       for (i = 0; i < 8; i++)
-               outb(0x00, ioaddr + PORT_OFFSET(8 + i));
-
-
-       /* Switch to bank 2 */
-       /* Lock our I/O address, and set manual processing mode for 16 collisions. */
-       outb(0x08, ioaddr + CONFIG_1);
-       outb(dev->if_port, ioaddr + MODE13);
-       outb(0x00, ioaddr + COL16CNTL);
-
-       if (net_debug)
-               printk(version);
-
-       dev->netdev_ops = &at1700_netdev_ops;
-       dev->watchdog_timeo = TX_TIMEOUT;
-
-       spin_lock_init(&lp->lock);
-
-       lp->jumpered = is_fmv18x;
-       lp->mca_slot = slot;
-       /* Snarf the interrupt vector now. */
-       ret = request_irq(irq, net_interrupt, 0, DRV_NAME, dev);
-       if (ret) {
-               printk(KERN_ERR "AT1700 at %#3x is unusable due to a "
-                      "conflict on IRQ %d.\n",
-                      ioaddr, irq);
-               goto err_mca;
-       }
-
-       return 0;
-
-err_mca:
-#ifdef CONFIG_MCA_LEGACY
-       if (slot >= 0)
-               mca_mark_as_unused(slot);
-#endif
-err_out:
-       release_region(ioaddr, AT1700_IO_EXTENT);
-       return ret;
-}
-
-
-/*  EEPROM_Ctrl bits. */
-#define EE_SHIFT_CLK   0x40    /* EEPROM shift clock, in reg. 16. */
-#define EE_CS                  0x20    /* EEPROM chip select, in reg. 16. */
-#define EE_DATA_WRITE  0x80    /* EEPROM chip data in, in reg. 17. */
-#define EE_DATA_READ   0x80    /* EEPROM chip data out, in reg. 17. */
-
-/* The EEPROM commands include the alway-set leading bit. */
-#define EE_WRITE_CMD   (5 << 6)
-#define EE_READ_CMD            (6 << 6)
-#define EE_ERASE_CMD   (7 << 6)
-
-static int __init read_eeprom(long ioaddr, int location)
-{
-       int i;
-       unsigned short retval = 0;
-       long ee_addr = ioaddr + EEPROM_Ctrl;
-       long ee_daddr = ioaddr + EEPROM_Data;
-       int read_cmd = location | EE_READ_CMD;
-
-       /* Shift the read command bits out. */
-       for (i = 9; i >= 0; i--) {
-               short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
-               outb(EE_CS, ee_addr);
-               outb(dataval, ee_daddr);
-               outb(EE_CS | EE_SHIFT_CLK, ee_addr);    /* EEPROM clock tick. */
-       }
-       outb(EE_DATA_WRITE, ee_daddr);
-       for (i = 16; i > 0; i--) {
-               outb(EE_CS, ee_addr);
-               outb(EE_CS | EE_SHIFT_CLK, ee_addr);
-               retval = (retval << 1) | ((inb(ee_daddr) & EE_DATA_READ) ? 1 : 0);
-       }
-
-       /* Terminate the EEPROM access. */
-       outb(EE_CS, ee_addr);
-       outb(EE_SHIFT_CLK, ee_addr);
-       outb(0, ee_addr);
-       return retval;
-}
-
-
-
-static int net_open(struct net_device *dev)
-{
-       struct net_local *lp = netdev_priv(dev);
-       int ioaddr = dev->base_addr;
-
-       /* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit
-          bus access, and two 4K Tx queues. */
-       outb(0x5a, ioaddr + CONFIG_0);
-
-       /* Powerup, switch to register bank 2, and enable the Rx and Tx. */
-       outb(0xe8, ioaddr + CONFIG_1);
-
-       lp->tx_started = 0;
-       lp->tx_queue_ready = 1;
-       lp->rx_started = 0;
-       lp->tx_queue = 0;
-       lp->tx_queue_len = 0;
-
-       /* Turn on hardware Tx and Rx interrupts. */
-       outb(0x82, ioaddr + TX_INTR);
-       outb(0x81, ioaddr + RX_INTR);
-
-       /* Enable the IRQ on boards of fmv18x it is feasible. */
-       if (lp->jumpered) {
-               outb(0x80, ioaddr + IOCONFIG1);
-       }
-
-       netif_start_queue(dev);
-       return 0;
-}
-
-static void net_tx_timeout (struct net_device *dev)
-{
-       struct net_local *lp = netdev_priv(dev);
-       int ioaddr = dev->base_addr;
-
-       printk ("%s: transmit timed out with status %04x, %s?\n", dev->name,
-               inw (ioaddr + STATUS), inb (ioaddr + TX_STATUS) & 0x80
-               ? "IRQ conflict" : "network cable problem");
-       printk ("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
-        dev->name, inw(ioaddr + TX_STATUS), inw(ioaddr + TX_INTR), inw(ioaddr + TX_MODE),
-               inw(ioaddr + CONFIG_0), inw(ioaddr + DATAPORT), inw(ioaddr + TX_START),
-               inw(ioaddr + MODE13 - 1), inw(ioaddr + RX_CTRL));
-       dev->stats.tx_errors++;
-       /* ToDo: We should try to restart the adaptor... */
-       outw(0xffff, ioaddr + MODE24);
-       outw (0xffff, ioaddr + TX_STATUS);
-       outb (0x5a, ioaddr + CONFIG_0);
-       outb (0xe8, ioaddr + CONFIG_1);
-       outw (0x8182, ioaddr + TX_INTR);
-       outb (0x00, ioaddr + TX_START);
-       outb (0x03, ioaddr + COL16CNTL);
-
-       dev->trans_start = jiffies; /* prevent tx timeout */
-
-       lp->tx_started = 0;
-       lp->tx_queue_ready = 1;
-       lp->rx_started = 0;
-       lp->tx_queue = 0;
-       lp->tx_queue_len = 0;
-
-       netif_wake_queue(dev);
-}
-
-
-static netdev_tx_t net_send_packet (struct sk_buff *skb,
-                                   struct net_device *dev)
-{
-       struct net_local *lp = netdev_priv(dev);
-       int ioaddr = dev->base_addr;
-       short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-       short len = skb->len;
-       unsigned char *buf = skb->data;
-       static u8 pad[ETH_ZLEN];
-
-       netif_stop_queue (dev);
-
-       /* We may not start transmitting unless we finish transferring
-          a packet into the Tx queue. During executing the following
-          codes we possibly catch a Tx interrupt. Thus we flag off
-          tx_queue_ready, so that we prevent the interrupt routine
-          (net_interrupt) to start transmitting. */
-       lp->tx_queue_ready = 0;
-       {
-               outw (length, ioaddr + DATAPORT);
-               /* Packet data */
-               outsw (ioaddr + DATAPORT, buf, len >> 1);
-               /* Check for dribble byte */
-               if (len & 1) {
-                       outw(skb->data[skb->len-1], ioaddr + DATAPORT);
-                       len++;
-               }
-               /* Check for packet padding */
-               if (length != skb->len)
-                       outsw(ioaddr + DATAPORT, pad, (length - len + 1) >> 1);
-
-               lp->tx_queue++;
-               lp->tx_queue_len += length + 2;
-       }
-       lp->tx_queue_ready = 1;
-
-       if (lp->tx_started == 0) {
-               /* If the Tx is idle, always trigger a transmit. */
-               outb (0x80 | lp->tx_queue, ioaddr + TX_START);
-               lp->tx_queue = 0;
-               lp->tx_queue_len = 0;
-               lp->tx_started = 1;
-               netif_start_queue (dev);
-       } else if (lp->tx_queue_len < 4096 - 1502)
-               /* Yes, there is room for one more packet. */
-               netif_start_queue (dev);
-       dev_kfree_skb (skb);
-
-       return NETDEV_TX_OK;
-}
-
-/* The typical workload of the driver:
-   Handle the network interface interrupts. */
-static irqreturn_t net_interrupt(int irq, void *dev_id)
-{
-       struct net_device *dev = dev_id;
-       struct net_local *lp;
-       int ioaddr, status;
-       int handled = 0;
-
-       if (dev == NULL) {
-               printk ("at1700_interrupt(): irq %d for unknown device.\n", irq);
-               return IRQ_NONE;
-       }
-
-       ioaddr = dev->base_addr;
-       lp = netdev_priv(dev);
-
-       spin_lock (&lp->lock);
-
-       status = inw(ioaddr + TX_STATUS);
-       outw(status, ioaddr + TX_STATUS);
-
-       if (net_debug > 4)
-               printk("%s: Interrupt with status %04x.\n", dev->name, status);
-       if (lp->rx_started == 0 &&
-           (status & 0xff00 || (inb(ioaddr + RX_MODE) & 0x40) == 0)) {
-               /* Got a packet(s).
-                  We cannot execute net_rx more than once at the same time for
-                  the same device. During executing net_rx, we possibly catch a
-                  Tx interrupt. Thus we flag on rx_started, so that we prevent
-                  the interrupt routine (net_interrupt) to dive into net_rx
-                  again. */
-               handled = 1;
-               lp->rx_started = 1;
-               outb(0x00, ioaddr + RX_INTR);   /* Disable RX intr. */
-               net_rx(dev);
-               outb(0x81, ioaddr + RX_INTR);   /* Enable  RX intr. */
-               lp->rx_started = 0;
-       }
-       if (status & 0x00ff) {
-               handled = 1;
-               if (status & 0x02) {
-                       /* More than 16 collisions occurred */
-                       if (net_debug > 4)
-                               printk("%s: 16 Collision occur during Txing.\n", dev->name);
-                       /* Cancel sending a packet. */
-                       outb(0x03, ioaddr + COL16CNTL);
-                       dev->stats.collisions++;
-               }
-               if (status & 0x82) {
-                       dev->stats.tx_packets++;
-                       /* The Tx queue has any packets and is not being
-                          transferred a packet from the host, start
-                          transmitting. */
-                       if (lp->tx_queue && lp->tx_queue_ready) {
-                               outb(0x80 | lp->tx_queue, ioaddr + TX_START);
-                               lp->tx_queue = 0;
-                               lp->tx_queue_len = 0;
-                               dev->trans_start = jiffies;
-                               netif_wake_queue (dev);
-                       } else {
-                               lp->tx_started = 0;
-                               netif_wake_queue (dev);
-                       }
-               }
-       }
-
-       spin_unlock (&lp->lock);
-       return IRQ_RETVAL(handled);
-}
-
-/* We have a good packet(s), get it/them out of the buffers. */
-static void
-net_rx(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr;
-       int boguscount = 5;
-
-       while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {
-               ushort status = inw(ioaddr + DATAPORT);
-               ushort pkt_len = inw(ioaddr + DATAPORT);
-
-               if (net_debug > 4)
-                       printk("%s: Rxing packet mode %02x status %04x.\n",
-                                  dev->name, inb(ioaddr + RX_MODE), status);
-#ifndef final_version
-               if (status == 0) {
-                       outb(0x05, ioaddr + RX_CTRL);
-                       break;
-               }
-#endif
-
-               if ((status & 0xF0) != 0x20) {  /* There was an error. */
-                       dev->stats.rx_errors++;
-                       if (status & 0x08) dev->stats.rx_length_errors++;
-                       if (status & 0x04) dev->stats.rx_frame_errors++;
-                       if (status & 0x02) dev->stats.rx_crc_errors++;
-                       if (status & 0x01) dev->stats.rx_over_errors++;
-               } else {
-                       /* Malloc up new buffer. */
-                       struct sk_buff *skb;
-
-                       if (pkt_len > 1550) {
-                               printk("%s: The AT1700 claimed a very large packet, size %d.\n",
-                                          dev->name, pkt_len);
-                               /* Prime the FIFO and then flush the packet. */
-                               inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT);
-                               outb(0x05, ioaddr + RX_CTRL);
-                               dev->stats.rx_errors++;
-                               break;
-                       }
-                       skb = dev_alloc_skb(pkt_len+3);
-                       if (skb == NULL) {
-                               printk("%s: Memory squeeze, dropping packet (len %d).\n",
-                                          dev->name, pkt_len);
-                               /* Prime the FIFO and then flush the packet. */
-                               inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT);
-                               outb(0x05, ioaddr + RX_CTRL);
-                               dev->stats.rx_dropped++;
-                               break;
-                       }
-                       skb_reserve(skb,2);
-
-                       insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
-                       skb->protocol=eth_type_trans(skb, dev);
-                       netif_rx(skb);
-                       dev->stats.rx_packets++;
-                       dev->stats.rx_bytes += pkt_len;
-               }
-               if (--boguscount <= 0)
-                       break;
-       }
-
-       /* If any worth-while packets have been received, dev_rint()
-          has done a mark_bh(NET_BH) for us and will work on them
-          when we get to the bottom-half routine. */
-       {
-               int i;
-               for (i = 0; i < 20; i++) {
-                       if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
-                               break;
-                       inw(ioaddr + DATAPORT);                         /* dummy status read */
-                       outb(0x05, ioaddr + RX_CTRL);
-               }
-
-               if (net_debug > 5)
-                       printk("%s: Exint Rx packet with mode %02x after %d ticks.\n",
-                                  dev->name, inb(ioaddr + RX_MODE), i);
-       }
-}
-
-/* The inverse routine to net_open(). */
-static int net_close(struct net_device *dev)
-{
-       struct net_local *lp = netdev_priv(dev);
-       int ioaddr = dev->base_addr;
-
-       netif_stop_queue(dev);
-
-       /* Set configuration register 0 to disable Tx and Rx. */
-       outb(0xda, ioaddr + CONFIG_0);
-
-       /* No statistic counters on the chip to update. */
-
-       /* Disable the IRQ on boards of fmv18x where it is feasible. */
-       if (lp->jumpered)
-               outb(0x00, ioaddr + IOCONFIG1);
-
-       /* Power-down the chip.  Green, green, green! */
-       outb(0x00, ioaddr + CONFIG_1);
-       return 0;
-}
-
-/*
-  Set the multicast/promiscuous mode for this adaptor.
-*/
-
-static void
-set_rx_mode(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr;
-       struct net_local *lp = netdev_priv(dev);
-       unsigned char mc_filter[8];              /* Multicast hash filter */
-       unsigned long flags;
-
-       if (dev->flags & IFF_PROMISC) {
-               memset(mc_filter, 0xff, sizeof(mc_filter));
-               outb(3, ioaddr + RX_MODE);      /* Enable promiscuous mode */
-       } else if (netdev_mc_count(dev) > MC_FILTERBREAK ||
-                          (dev->flags & IFF_ALLMULTI)) {
-               /* Too many to filter perfectly -- accept all multicasts. */
-               memset(mc_filter, 0xff, sizeof(mc_filter));
-               outb(2, ioaddr + RX_MODE);      /* Use normal mode. */
-       } else if (netdev_mc_empty(dev)) {
-               memset(mc_filter, 0x00, sizeof(mc_filter));
-               outb(1, ioaddr + RX_MODE);      /* Ignore almost all multicasts. */
-       } else {
-               struct netdev_hw_addr *ha;
-
-               memset(mc_filter, 0, sizeof(mc_filter));
-               netdev_for_each_mc_addr(ha, dev) {
-                       unsigned int bit =
-                               ether_crc_le(ETH_ALEN, ha->addr) >> 26;
-                       mc_filter[bit >> 3] |= (1 << bit);
-               }
-               outb(0x02, ioaddr + RX_MODE);   /* Use normal mode. */
-       }
-
-       spin_lock_irqsave (&lp->lock, flags);
-       if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) {
-               int i;
-               int saved_bank = inw(ioaddr + CONFIG_0);
-               /* Switch to bank 1 and set the multicast table. */
-               outw((saved_bank & ~0x0C00) | 0x0480, ioaddr + CONFIG_0);
-               for (i = 0; i < 8; i++)
-                       outb(mc_filter[i], ioaddr + PORT_OFFSET(8 + i));
-               memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter));
-               outw(saved_bank, ioaddr + CONFIG_0);
-       }
-       spin_unlock_irqrestore (&lp->lock, flags);
-}
-
-#ifdef MODULE
-static struct net_device *dev_at1700;
-
-module_param(io, int, 0);
-module_param(irq, int, 0);
-module_param(net_debug, int, 0);
-MODULE_PARM_DESC(io, "AT1700/FMV18X I/O base address");
-MODULE_PARM_DESC(irq, "AT1700/FMV18X IRQ number");
-MODULE_PARM_DESC(net_debug, "AT1700/FMV18X debug level (0-6)");
-
-static int __init at1700_module_init(void)
-{
-       if (io == 0)
-               printk("at1700: You should not use auto-probing with insmod!\n");
-       dev_at1700 = at1700_probe(-1);
-       if (IS_ERR(dev_at1700))
-               return PTR_ERR(dev_at1700);
-       return 0;
-}
-
-static void __exit at1700_module_exit(void)
-{
-       unregister_netdev(dev_at1700);
-       cleanup_card(dev_at1700);
-       free_netdev(dev_at1700);
-}
-module_init(at1700_module_init);
-module_exit(at1700_module_exit);
-#endif /* MODULE */
-MODULE_LICENSE("GPL");
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
deleted file mode 100644 (file)
index 12d28e9..0000000
+++ /dev/null
@@ -1,1484 +0,0 @@
-/* eth16i.c An ICL EtherTeam 16i and 32 EISA ethernet driver for Linux
-
-   Written 1994-1999 by Mika Kuoppala
-
-   Copyright (C) 1994-1999 by Mika Kuoppala
-   Based on skeleton.c and heavily on at1700.c by Donald Becker
-
-   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 miku@iki.fi
-
-   This driver supports following cards :
-       - ICL EtherTeam 16i
-       - ICL EtherTeam 32 EISA
-         (Uses true 32 bit transfers rather than 16i compatibility mode)
-
-   Example Module usage:
-        insmod eth16i.o io=0x2a0 mediatype=bnc
-
-       mediatype can be one of the following: bnc,tp,dix,auto,eprom
-
-       'auto' will try to autoprobe mediatype.
-       'eprom' will use whatever type defined in eprom.
-
-   I have benchmarked driver with PII/300Mhz as a ftp client
-   and 486/33Mhz as a ftp server. Top speed was 1128.37 kilobytes/sec.
-
-   Sources:
-     - skeleton.c  a sample network driver core for linux,
-       written by Donald Becker <becker@scyld.com>
-     - at1700.c a driver for Allied Telesis AT1700, written
-       by Donald Becker.
-     - e16iSRV.asm a Netware 3.X Server Driver for ICL EtherTeam16i
-       written by Markku Viima
-     - The Fujitsu MB86965 databook.
-
-   Author thanks following persons due to their valueble assistance:
-        Markku Viima (ICL)
-       Ari Valve (ICL)
-       Donald Becker
-       Kurt Huwig <kurt@huwig.de>
-
-   Revision history:
-
-   Version     Date            Description
-
-   0.01         15.12-94        Initial version (card detection)
-   0.02         23.01-95        Interrupt is now hooked correctly
-   0.03         01.02-95        Rewrote initialization part
-   0.04         07.02-95        Base skeleton done...
-                                Made a few changes to signature checking
-                                to make it a bit reliable.
-                                - fixed bug in tx_buf mapping
-                                - fixed bug in initialization (DLC_EN
-                                  wasn't enabled when initialization
-                                  was done.)
-   0.05         08.02-95        If there were more than one packet to send,
-                                transmit was jammed due to invalid
-                                register write...now fixed
-   0.06         19.02-95        Rewrote interrupt handling
-   0.07         13.04-95        Wrote EEPROM read routines
-                                Card configuration now set according to
-                                data read from EEPROM
-   0.08         23.06-95        Wrote part that tries to probe used interface
-                                port if AUTO is selected
-
-   0.09         01.09-95        Added module support
-
-   0.10         04.09-95        Fixed receive packet allocation to work
-                                with kernels > 1.3.x
-
-   0.20                20.09-95        Added support for EtherTeam32 EISA
-
-   0.21         17.10-95        Removed the unnecessary extern
-                               init_etherdev() declaration. Some
-                               other cleanups.
-
-   0.22                22.02-96        Receive buffer was not flushed
-                               correctly when faulty packet was
-                               received. Now fixed.
-
-   0.23                26.02-96        Made resetting the adapter
-                               more reliable.
-
-   0.24                27.02-96        Rewrote faulty packet handling in eth16i_rx
-
-   0.25                22.05-96        kfree() was missing from cleanup_module.
-
-   0.26                11.06-96        Sometimes card was not found by
-                               check_signature(). Now made more reliable.
-
-   0.27                23.06-96        Oops. 16 consecutive collisions halted
-                               adapter. Now will try to retransmit
-                               MAX_COL_16 times before finally giving up.
-
-   0.28                28.10-97        Added dev_id parameter (NULL) for free_irq
-
-   0.29         29.10-97        Multiple card support for module users
-
-   0.30         30.10-97        Fixed irq allocation bug.
-                                (request_irq moved from probe to open)
-
-   0.30a        21.08-98        Card detection made more relaxed. Driver
-                                had problems with some TCP/IP-PROM boots
-                               to find the card. Suggested by
-                               Kurt Huwig <kurt@huwig.de>
-
-   0.31         28.08-98        Media interface port can now be selected
-                                with module parameters or kernel
-                               boot parameters.
-
-   0.32         31.08-98        IRQ was never freed if open/close
-                                pair wasn't called. Now fixed.
-
-   0.33         10.09-98        When eth16i_open() was called after
-                                eth16i_close() chip never recovered.
-                               Now more shallow reset is made on
-                               close.
-
-   0.34         29.06-99       Fixed one bad #ifdef.
-                               Changed ioaddr -> io for consistency
-
-   0.35         01.07-99        transmit,-receive bytes were never
-                                updated in stats.
-
-   Bugs:
-       In some cases the media interface autoprobing code doesn't find
-       the correct interface type. In this case you can
-       manually choose the interface type in DOS with E16IC.EXE which is
-       configuration software for EtherTeam16i and EtherTeam32 cards.
-       This is also true for IRQ setting. You cannot use module
-       parameter to configure IRQ of the card (yet).
-
-   To do:
-       - Real multicast support
-       - Rewrite the media interface autoprobing code. Its _horrible_ !
-       - Possibly merge all the MB86965 specific code to external
-         module for use by eth16.c and Donald's at1700.c
-       - IRQ configuration with module parameter. I will do
-         this when i will get enough info about setting
-         irq without configuration utility.
-*/
-
-static char *version =
-    "eth16i.c: v0.35 01-Jul-1999 Mika Kuoppala (miku@iki.fi)\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/spinlock.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-#include <linux/jiffies.h>
-#include <linux/io.h>
-
-#include <asm/system.h>
-#include <asm/dma.h>
-
-
-
-/* Few macros */
-#define BITSET(ioaddr, bnum)   ((outb(((inb(ioaddr)) | (bnum)), ioaddr)))
-#define BITCLR(ioaddr, bnum)   ((outb(((inb(ioaddr)) & (~(bnum))), ioaddr)))
-
-/* This is the I/O address space for Etherteam 16i adapter. */
-#define ETH16I_IO_EXTENT       32
-
-/* Ticks before deciding that transmit has timed out */
-#define TX_TIMEOUT             (400*HZ/1000)
-
-/* Maximum loop count when receiving packets */
-#define MAX_RX_LOOP            20
-
-/* Some interrupt masks */
-#define ETH16I_INTR_ON        0xef8a       /* Higher is receive mask */
-#define ETH16I_INTR_OFF               0x0000
-
-/* Buffers header status byte meanings */
-#define PKT_GOOD               BIT(5)
-#define PKT_GOOD_RMT           BIT(4)
-#define PKT_SHORT              BIT(3)
-#define PKT_ALIGN_ERR          BIT(2)
-#define PKT_CRC_ERR            BIT(1)
-#define PKT_RX_BUF_OVERFLOW    BIT(0)
-
-/* Transmit status register (DLCR0) */
-#define TX_STATUS_REG          0
-#define TX_DONE                BIT(7)
-#define NET_BUSY               BIT(6)
-#define TX_PKT_RCD             BIT(5)
-#define CR_LOST                BIT(4)
-#define TX_JABBER_ERR         BIT(3)
-#define COLLISION              BIT(2)
-#define COLLISIONS_16          BIT(1)
-
-/* Receive status register (DLCR1) */
-#define RX_STATUS_REG          1
-#define RX_PKT                 BIT(7)  /* Packet received */
-#define BUS_RD_ERR             BIT(6)
-#define SHORT_PKT_ERR          BIT(3)
-#define ALIGN_ERR              BIT(2)
-#define CRC_ERR                BIT(1)
-#define RX_BUF_OVERFLOW        BIT(0)
-
-/* Transmit Interrupt Enable Register (DLCR2) */
-#define TX_INTR_REG            2
-#define TX_INTR_DONE           BIT(7)
-#define TX_INTR_COL            BIT(2)
-#define TX_INTR_16_COL         BIT(1)
-
-/* Receive Interrupt Enable Register (DLCR3) */
-#define RX_INTR_REG            3
-#define RX_INTR_RECEIVE        BIT(7)
-#define RX_INTR_SHORT_PKT      BIT(3)
-#define RX_INTR_CRC_ERR        BIT(1)
-#define RX_INTR_BUF_OVERFLOW   BIT(0)
-
-/* Transmit Mode Register (DLCR4) */
-#define TRANSMIT_MODE_REG      4
-#define LOOPBACK_CONTROL       BIT(1)
-#define CONTROL_OUTPUT         BIT(2)
-
-/* Receive Mode Register (DLCR5) */
-#define RECEIVE_MODE_REG       5
-#define RX_BUFFER_EMPTY        BIT(6)
-#define ACCEPT_BAD_PACKETS     BIT(5)
-#define RECEIVE_SHORT_ADDR     BIT(4)
-#define ACCEPT_SHORT_PACKETS   BIT(3)
-#define REMOTE_RESET           BIT(2)
-
-#define ADDRESS_FILTER_MODE    BIT(1) | BIT(0)
-#define REJECT_ALL             0
-#define ACCEPT_ALL             3
-#define MODE_1                 1            /* NODE ID, BC, MC, 2-24th bit */
-#define MODE_2                 2            /* NODE ID, BC, MC, Hash Table */
-
-/* Configuration Register 0 (DLCR6) */
-#define CONFIG_REG_0           6
-#define DLC_EN                 BIT(7)
-#define SRAM_CYCLE_TIME_100NS  BIT(6)
-#define SYSTEM_BUS_WIDTH_8     BIT(5)       /* 1 = 8bit, 0 = 16bit */
-#define BUFFER_WIDTH_8         BIT(4)       /* 1 = 8bit, 0 = 16bit */
-#define TBS1                   BIT(3)
-#define TBS0                   BIT(2)
-#define SRAM_BS1               BIT(1)       /* 00=8kb,  01=16kb  */
-#define SRAM_BS0               BIT(0)       /* 10=32kb, 11=64kb  */
-
-#ifndef ETH16I_TX_BUF_SIZE                   /* 0 = 2kb, 1 = 4kb  */
-#define ETH16I_TX_BUF_SIZE     3             /* 2 = 8kb, 3 = 16kb */
-#endif
-#define TX_BUF_1x2048          0
-#define TX_BUF_2x2048          1
-#define TX_BUF_2x4098          2
-#define TX_BUF_2x8192          3
-
-/* Configuration Register 1 (DLCR7) */
-#define CONFIG_REG_1           7
-#define POWERUP                BIT(5)
-
-/* Transmit start register */
-#define TRANSMIT_START_REG     10
-#define TRANSMIT_START_RB      2
-#define TX_START               BIT(7)       /* Rest of register bit indicate*/
-                                            /* number of packets in tx buffer*/
-/* Node ID registers (DLCR8-13) */
-#define NODE_ID_0              8
-#define NODE_ID_RB             0
-
-/* Hash Table registers (HT8-15) */
-#define HASH_TABLE_0           8
-#define HASH_TABLE_RB          1
-
-/* Buffer memory ports */
-#define BUFFER_MEM_PORT_LB     8
-#define DATAPORT               BUFFER_MEM_PORT_LB
-#define BUFFER_MEM_PORT_HB     9
-
-/* 16 Collision control register (BMPR11) */
-#define COL_16_REG             11
-#define HALT_ON_16             0x00
-#define RETRANS_AND_HALT_ON_16 0x02
-
-/* Maximum number of attempts to send after 16 concecutive collisions */
-#define MAX_COL_16            10
-
-/* DMA Burst and Transceiver Mode Register (BMPR13) */
-#define TRANSCEIVER_MODE_REG   13
-#define TRANSCEIVER_MODE_RB    2
-#define IO_BASE_UNLOCK        BIT(7)
-#define LOWER_SQUELCH_TRESH    BIT(6)
-#define LINK_TEST_DISABLE      BIT(5)
-#define AUI_SELECT             BIT(4)
-#define DIS_AUTO_PORT_SEL      BIT(3)
-
-/* Filter Self Receive Register (BMPR14)  */
-#define FILTER_SELF_RX_REG     14
-#define SKIP_RX_PACKET         BIT(2)
-#define FILTER_SELF_RECEIVE    BIT(0)
-
-/* EEPROM Control Register (BMPR 16) */
-#define EEPROM_CTRL_REG        16
-
-/* EEPROM Data Register (BMPR 17) */
-#define EEPROM_DATA_REG        17
-
-/* NMC93CSx6 EEPROM Control Bits */
-#define CS_0                   0x00
-#define CS_1                   0x20
-#define SK_0                   0x00
-#define SK_1                   0x40
-#define DI_0                   0x00
-#define DI_1                   0x80
-
-/* NMC93CSx6 EEPROM Instructions */
-#define EEPROM_READ            0x80
-
-/* NMC93CSx6 EEPROM Addresses */
-#define E_NODEID_0             0x02
-#define E_NODEID_1             0x03
-#define E_NODEID_2             0x04
-#define E_PORT_SELECT          0x14
-  #define E_PORT_BNC           0x00
-  #define E_PORT_DIX           0x01
-  #define E_PORT_TP            0x02
-  #define E_PORT_AUTO          0x03
-  #define E_PORT_FROM_EPROM    0x04
-#define E_PRODUCT_CFG          0x30
-
-
-/* Macro to slow down io between EEPROM clock transitions */
-#define eeprom_slow_io() do { int _i = 40; while(--_i > 0) { inb(0x80); }}while(0)
-
-/* Jumperless Configuration Register (BMPR19) */
-#define JUMPERLESS_CONFIG      19
-
-/* ID ROM registers, writing to them also resets some parts of chip */
-#define ID_ROM_0               24
-#define ID_ROM_7               31
-#define RESET                  ID_ROM_0
-
-/* This is the I/O address list to be probed when seeking the card */
-static unsigned int eth16i_portlist[] __initdata = {
-       0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
-};
-
-static unsigned int eth32i_portlist[] __initdata = {
-       0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000,
-       0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0
-};
-
-/* This is the Interrupt lookup table for Eth16i card */
-static unsigned int eth16i_irqmap[] __initdata = { 9, 10, 5, 15, 0 };
-#define NUM_OF_ISA_IRQS    4
-
-/* This is the Interrupt lookup table for Eth32i card */
-static unsigned int eth32i_irqmap[] __initdata = { 3, 5, 7, 9, 10, 11, 12, 15, 0 };
-#define EISA_IRQ_REG   0xc89
-#define NUM_OF_EISA_IRQS   8
-
-static unsigned int eth16i_tx_buf_map[] = { 2048, 2048, 4096, 8192 };
-
-/* Use 0 for production, 1 for verification, >2 for debug */
-#ifndef ETH16I_DEBUG
-#define ETH16I_DEBUG 0
-#endif
-static unsigned int eth16i_debug = ETH16I_DEBUG;
-
-/* Information for each board */
-
-struct eth16i_local {
-       unsigned char     tx_started;
-       unsigned char     tx_buf_busy;
-       unsigned short    tx_queue;  /* Number of packets in transmit buffer */
-       unsigned short    tx_queue_len;
-       unsigned int      tx_buf_size;
-       unsigned long     open_time;
-       unsigned long     tx_buffered_packets;
-       unsigned long     tx_buffered_bytes;
-       unsigned long     col_16;
-       spinlock_t        lock;
-};
-
-/* Function prototypes */
-
-static int     eth16i_probe1(struct net_device *dev, int ioaddr);
-static int     eth16i_check_signature(int ioaddr);
-static int     eth16i_probe_port(int ioaddr);
-static void    eth16i_set_port(int ioaddr, int porttype);
-static int     eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l);
-static int     eth16i_receive_probe_packet(int ioaddr);
-static int     eth16i_get_irq(int ioaddr);
-static int     eth16i_read_eeprom(int ioaddr, int offset);
-static int     eth16i_read_eeprom_word(int ioaddr);
-static void    eth16i_eeprom_cmd(int ioaddr, unsigned char command);
-static int     eth16i_open(struct net_device *dev);
-static int     eth16i_close(struct net_device *dev);
-static netdev_tx_t eth16i_tx(struct sk_buff *skb, struct net_device *dev);
-static void    eth16i_rx(struct net_device *dev);
-static void    eth16i_timeout(struct net_device *dev);
-static irqreturn_t eth16i_interrupt(int irq, void *dev_id);
-static void    eth16i_reset(struct net_device *dev);
-static void    eth16i_timeout(struct net_device *dev);
-static void    eth16i_skip_packet(struct net_device *dev);
-static void    eth16i_multicast(struct net_device *dev);
-static void    eth16i_select_regbank(unsigned char regbank, int ioaddr);
-static void    eth16i_initialize(struct net_device *dev, int boot);
-
-#if 0
-static int     eth16i_set_irq(struct net_device *dev);
-#endif
-
-#ifdef MODULE
-static ushort  eth16i_parse_mediatype(const char* s);
-#endif
-
-static char cardname[] __initdata = "ICL EtherTeam 16i/32";
-
-static int __init do_eth16i_probe(struct net_device *dev)
-{
-       int i;
-       int ioaddr;
-       int base_addr = dev->base_addr;
-
-       if(eth16i_debug > 4)
-               printk(KERN_DEBUG "Probing started for %s\n", cardname);
-
-       if(base_addr > 0x1ff)           /* Check only single location */
-               return eth16i_probe1(dev, base_addr);
-       else if(base_addr != 0)         /* Don't probe at all */
-               return -ENXIO;
-
-       /* Seek card from the ISA io address space */
-       for(i = 0; (ioaddr = eth16i_portlist[i]) ; i++)
-               if(eth16i_probe1(dev, ioaddr) == 0)
-                       return 0;
-
-       /* Seek card from the EISA io address space */
-       for(i = 0; (ioaddr = eth32i_portlist[i]) ; i++)
-               if(eth16i_probe1(dev, ioaddr) == 0)
-                       return 0;
-
-       return -ENODEV;
-}
-
-#ifndef MODULE
-struct net_device * __init eth16i_probe(int unit)
-{
-       struct net_device *dev = alloc_etherdev(sizeof(struct eth16i_local));
-       int err;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       sprintf(dev->name, "eth%d", unit);
-       netdev_boot_setup_check(dev);
-
-       err = do_eth16i_probe(dev);
-       if (err)
-               goto out;
-       return dev;
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-#endif
-
-static const struct net_device_ops eth16i_netdev_ops = {
-       .ndo_open               = eth16i_open,
-       .ndo_stop               = eth16i_close,
-       .ndo_start_xmit         = eth16i_tx,
-       .ndo_set_multicast_list = eth16i_multicast,
-       .ndo_tx_timeout         = eth16i_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_validate_addr      = eth_validate_addr,
-};
-
-static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
-{
-       struct eth16i_local *lp = netdev_priv(dev);
-       static unsigned version_printed;
-       int retval;
-
-       /* Let's grab the region */
-       if (!request_region(ioaddr, ETH16I_IO_EXTENT, cardname))
-               return -EBUSY;
-
-       /*
-         The MB86985 chip has on register which holds information in which
-         io address the chip lies. First read this register and compare
-         it to our current io address and if match then this could
-         be our chip.
-         */
-
-       if(ioaddr < 0x1000) {
-               if(eth16i_portlist[(inb(ioaddr + JUMPERLESS_CONFIG) & 0x07)]
-                  != ioaddr) {
-                       retval = -ENODEV;
-                       goto out;
-               }
-       }
-
-       /* Now we will go a bit deeper and try to find the chip's signature */
-
-       if(eth16i_check_signature(ioaddr) != 0) {
-               retval = -ENODEV;
-               goto out;
-       }
-
-       /*
-          Now it seems that we have found a ethernet chip in this particular
-          ioaddr. The MB86985 chip has this feature, that when you read a
-          certain register it will increase it's io base address to next
-          configurable slot. Now when we have found the chip, first thing is
-          to make sure that the chip's ioaddr will hold still here.
-          */
-
-       eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
-       outb(0x00, ioaddr + TRANSCEIVER_MODE_REG);
-
-       outb(0x00, ioaddr + RESET);             /* Reset some parts of chip */
-       BITSET(ioaddr + CONFIG_REG_0, BIT(7));  /* Disable the data link */
-
-       if( (eth16i_debug & version_printed++) == 0)
-               printk(KERN_INFO "%s", version);
-
-       dev->base_addr = ioaddr;
-       dev->irq = eth16i_get_irq(ioaddr);
-
-       /* Try to obtain interrupt vector */
-
-       if ((retval = request_irq(dev->irq, (void *)&eth16i_interrupt, 0, cardname, dev))) {
-               printk(KERN_WARNING "%s at %#3x, but is unusable due to conflicting IRQ %d.\n",
-                      cardname, ioaddr, dev->irq);
-               goto out;
-       }
-
-       printk(KERN_INFO "%s: %s at %#3x, IRQ %d, ",
-              dev->name, cardname, ioaddr, dev->irq);
-
-
-       /* Now we will have to lock the chip's io address */
-       eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
-       outb(0x38, ioaddr + TRANSCEIVER_MODE_REG);
-
-       eth16i_initialize(dev, 1); /* Initialize rest of the chip's registers */
-
-       /* Now let's same some energy by shutting down the chip ;) */
-       BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
-
-       /* Initialize the device structure */
-       dev->netdev_ops         = &eth16i_netdev_ops;
-       dev->watchdog_timeo     = TX_TIMEOUT;
-       spin_lock_init(&lp->lock);
-
-       retval = register_netdev(dev);
-       if (retval)
-               goto out1;
-       return 0;
-out1:
-       free_irq(dev->irq, dev);
-out:
-       release_region(ioaddr, ETH16I_IO_EXTENT);
-       return retval;
-}
-
-
-static void eth16i_initialize(struct net_device *dev, int boot)
-{
-       int ioaddr = dev->base_addr;
-       int i, node_w = 0;
-       unsigned char node_byte = 0;
-
-       /* Setup station address */
-       eth16i_select_regbank(NODE_ID_RB, ioaddr);
-       for(i = 0 ; i < 3 ; i++) {
-               unsigned short node_val = eth16i_read_eeprom(ioaddr, E_NODEID_0 + i);
-               ((unsigned short *)dev->dev_addr)[i] = ntohs(node_val);
-       }
-
-       for(i = 0; i < 6; i++) {
-               outb( ((unsigned char *)dev->dev_addr)[i], ioaddr + NODE_ID_0 + i);
-               if(boot) {
-                       printk("%02x", inb(ioaddr + NODE_ID_0 + i));
-                       if(i != 5)
-                               printk(":");
-               }
-       }
-
-       /* Now we will set multicast addresses to accept none */
-       eth16i_select_regbank(HASH_TABLE_RB, ioaddr);
-       for(i = 0; i < 8; i++)
-               outb(0x00, ioaddr + HASH_TABLE_0 + i);
-
-       /*
-         Now let's disable the transmitter and receiver, set the buffer ram
-         cycle time, bus width and buffer data path width. Also we shall
-         set transmit buffer size and total buffer size.
-         */
-
-       eth16i_select_regbank(2, ioaddr);
-
-       node_byte = 0;
-       node_w = eth16i_read_eeprom(ioaddr, E_PRODUCT_CFG);
-
-       if( (node_w & 0xFF00) == 0x0800)
-               node_byte |= BUFFER_WIDTH_8;
-
-       node_byte |= SRAM_BS1;
-
-       if( (node_w & 0x00FF) == 64)
-               node_byte |= SRAM_BS0;
-
-       node_byte |= DLC_EN | SRAM_CYCLE_TIME_100NS | (ETH16I_TX_BUF_SIZE << 2);
-
-       outb(node_byte, ioaddr + CONFIG_REG_0);
-
-       /* We shall halt the transmitting, if 16 collisions are detected */
-       outb(HALT_ON_16, ioaddr + COL_16_REG);
-
-#ifdef MODULE
-       /* if_port already set by init_module() */
-#else
-       dev->if_port = (dev->mem_start < E_PORT_FROM_EPROM) ?
-               dev->mem_start : E_PORT_FROM_EPROM;
-#endif
-
-       /* Set interface port type */
-       if(boot) {
-               static const char * const porttype[] = {
-                       "BNC", "DIX", "TP", "AUTO", "FROM_EPROM"
-               };
-
-               switch(dev->if_port)
-               {
-
-               case E_PORT_FROM_EPROM:
-                       dev->if_port = eth16i_read_eeprom(ioaddr, E_PORT_SELECT);
-                       break;
-
-               case E_PORT_AUTO:
-                       dev->if_port = eth16i_probe_port(ioaddr);
-                       break;
-
-               case E_PORT_BNC:
-               case E_PORT_TP:
-               case E_PORT_DIX:
-                       break;
-               }
-
-               printk(" %s interface.\n", porttype[dev->if_port]);
-
-               eth16i_set_port(ioaddr, dev->if_port);
-       }
-
-       /* Set Receive Mode to normal operation */
-       outb(MODE_2, ioaddr + RECEIVE_MODE_REG);
-}
-
-static int eth16i_probe_port(int ioaddr)
-{
-       int i;
-       int retcode;
-       unsigned char dummy_packet[64];
-
-       /* Powerup the chip */
-       outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
-
-       BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
-
-       eth16i_select_regbank(NODE_ID_RB, ioaddr);
-
-       for(i = 0; i < 6; i++) {
-               dummy_packet[i] = inb(ioaddr + NODE_ID_0 + i);
-               dummy_packet[i+6] = inb(ioaddr + NODE_ID_0 + i);
-       }
-
-       dummy_packet[12] = 0x00;
-       dummy_packet[13] = 0x04;
-       memset(dummy_packet + 14, 0, sizeof(dummy_packet) - 14);
-
-       eth16i_select_regbank(2, ioaddr);
-
-       for(i = 0; i < 3; i++) {
-               BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
-               BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
-               eth16i_set_port(ioaddr, i);
-
-               if(eth16i_debug > 1)
-                       printk(KERN_DEBUG "Set port number %d\n", i);
-
-               retcode = eth16i_send_probe_packet(ioaddr, dummy_packet, 64);
-               if(retcode == 0) {
-                       retcode = eth16i_receive_probe_packet(ioaddr);
-                       if(retcode != -1) {
-                               if(eth16i_debug > 1)
-                                       printk(KERN_DEBUG "Eth16i interface port found at %d\n", i);
-                               return i;
-                       }
-               }
-               else {
-                       if(eth16i_debug > 1)
-                               printk(KERN_DEBUG "TRANSMIT_DONE timeout when probing interface port\n");
-               }
-       }
-
-       if( eth16i_debug > 1)
-               printk(KERN_DEBUG "Using default port\n");
-
-       return E_PORT_BNC;
-}
-
-static void eth16i_set_port(int ioaddr, int porttype)
-{
-       unsigned short temp = 0;
-
-       eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
-       outb(LOOPBACK_CONTROL, ioaddr + TRANSMIT_MODE_REG);
-
-       temp |= DIS_AUTO_PORT_SEL;
-
-       switch(porttype) {
-
-       case E_PORT_BNC :
-               temp |= AUI_SELECT;
-               break;
-
-       case E_PORT_TP :
-               break;
-
-       case E_PORT_DIX :
-               temp |= AUI_SELECT;
-               BITSET(ioaddr + TRANSMIT_MODE_REG, CONTROL_OUTPUT);
-               break;
-       }
-
-       outb(temp, ioaddr + TRANSCEIVER_MODE_REG);
-
-       if(eth16i_debug > 1) {
-               printk(KERN_DEBUG "TRANSMIT_MODE_REG = %x\n", inb(ioaddr + TRANSMIT_MODE_REG));
-               printk(KERN_DEBUG "TRANSCEIVER_MODE_REG = %x\n",
-                      inb(ioaddr+TRANSCEIVER_MODE_REG));
-       }
-}
-
-static int eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l)
-{
-       unsigned long starttime;
-
-       outb(0xff, ioaddr + TX_STATUS_REG);
-
-       outw(l, ioaddr + DATAPORT);
-       outsw(ioaddr + DATAPORT, (unsigned short *)b, (l + 1) >> 1);
-
-       starttime = jiffies;
-       outb(TX_START | 1, ioaddr + TRANSMIT_START_REG);
-
-       while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0) {
-               if( time_after(jiffies, starttime + TX_TIMEOUT)) {
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-static int eth16i_receive_probe_packet(int ioaddr)
-{
-       unsigned long starttime;
-
-       starttime = jiffies;
-
-       while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0) {
-               if( time_after(jiffies, starttime + TX_TIMEOUT)) {
-
-                       if(eth16i_debug > 1)
-                               printk(KERN_DEBUG "Timeout occurred waiting transmit packet received\n");
-                       starttime = jiffies;
-                       while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) {
-                               if( time_after(jiffies, starttime + TX_TIMEOUT)) {
-                                       if(eth16i_debug > 1)
-                                               printk(KERN_DEBUG "Timeout occurred waiting receive packet\n");
-                                       return -1;
-                               }
-                       }
-
-                       if(eth16i_debug > 1)
-                               printk(KERN_DEBUG "RECEIVE_PACKET\n");
-                       return 0; /* Found receive packet */
-               }
-       }
-
-       if(eth16i_debug > 1) {
-               printk(KERN_DEBUG "TRANSMIT_PACKET_RECEIVED %x\n", inb(ioaddr + TX_STATUS_REG));
-               printk(KERN_DEBUG "RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG));
-       }
-
-       return 0; /* Return success */
-}
-
-#if 0
-static int eth16i_set_irq(struct net_device* dev)
-{
-       const int ioaddr = dev->base_addr;
-       const int irq = dev->irq;
-       int i = 0;
-
-       if(ioaddr < 0x1000) {
-               while(eth16i_irqmap[i] && eth16i_irqmap[i] != irq)
-                       i++;
-
-               if(i < NUM_OF_ISA_IRQS) {
-                       u8 cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
-                       cbyte = (cbyte & 0x3F) | (i << 6);
-                       outb(cbyte, ioaddr + JUMPERLESS_CONFIG);
-                       return 0;
-               }
-       }
-       else {
-               printk(KERN_NOTICE "%s: EISA Interrupt cannot be set. Use EISA Configuration utility.\n", dev->name);
-       }
-
-       return -1;
-
-}
-#endif
-
-static int __init eth16i_get_irq(int ioaddr)
-{
-       unsigned char cbyte;
-
-       if( ioaddr < 0x1000) {
-               cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
-               return eth16i_irqmap[((cbyte & 0xC0) >> 6)];
-       } else {  /* Oh..the card is EISA so method getting IRQ different */
-               unsigned short index = 0;
-               cbyte = inb(ioaddr + EISA_IRQ_REG);
-               while( (cbyte & 0x01) == 0) {
-                       cbyte = cbyte >> 1;
-                       index++;
-               }
-               return eth32i_irqmap[index];
-       }
-}
-
-static int __init eth16i_check_signature(int ioaddr)
-{
-       int i;
-       unsigned char creg[4] = { 0 };
-
-       for(i = 0; i < 4 ; i++) {
-
-               creg[i] = inb(ioaddr + TRANSMIT_MODE_REG + i);
-
-               if(eth16i_debug > 1)
-                       printk("eth16i: read signature byte %x at %x\n",
-                              creg[i],
-                              ioaddr + TRANSMIT_MODE_REG + i);
-       }
-
-       creg[0] &= 0x0F;      /* Mask collision cnr */
-       creg[2] &= 0x7F;      /* Mask DCLEN bit */
-
-#if 0
-       /*
-          This was removed because the card was sometimes left to state
-          from which it couldn't be find anymore. If there is need
-          to more strict check still this have to be fixed.
-          */
-       if( ! ((creg[0] == 0x06) && (creg[1] == 0x41)) ) {
-               if(creg[1] != 0x42)
-                       return -1;
-       }
-#endif
-
-       if( !((creg[2] == 0x36) && (creg[3] == 0xE0)) ) {
-               creg[2] &= 0x40;
-               creg[3] &= 0x03;
-
-               if( !((creg[2] == 0x40) && (creg[3] == 0x00)) )
-                       return -1;
-       }
-
-       if(eth16i_read_eeprom(ioaddr, E_NODEID_0) != 0)
-               return -1;
-
-       if((eth16i_read_eeprom(ioaddr, E_NODEID_1) & 0xFF00) != 0x4B00)
-               return -1;
-
-       return 0;
-}
-
-static int eth16i_read_eeprom(int ioaddr, int offset)
-{
-       int data = 0;
-
-       eth16i_eeprom_cmd(ioaddr, EEPROM_READ | offset);
-       outb(CS_1, ioaddr + EEPROM_CTRL_REG);
-       data = eth16i_read_eeprom_word(ioaddr);
-       outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
-
-       return data;
-}
-
-static int eth16i_read_eeprom_word(int ioaddr)
-{
-       int i;
-       int data = 0;
-
-       for(i = 16; i > 0; i--) {
-               outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
-               eeprom_slow_io();
-               outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
-               eeprom_slow_io();
-               data = (data << 1) |
-                       ((inb(ioaddr + EEPROM_DATA_REG) & DI_1) ? 1 : 0);
-
-               eeprom_slow_io();
-       }
-
-       return data;
-}
-
-static void eth16i_eeprom_cmd(int ioaddr, unsigned char command)
-{
-       int i;
-
-       outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
-       outb(DI_0, ioaddr + EEPROM_DATA_REG);
-       outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
-       outb(DI_1, ioaddr + EEPROM_DATA_REG);
-       outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
-
-       for(i = 7; i >= 0; i--) {
-               short cmd = ( (command & (1 << i)) ? DI_1 : DI_0 );
-               outb(cmd, ioaddr + EEPROM_DATA_REG);
-               outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
-               eeprom_slow_io();
-               outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
-               eeprom_slow_io();
-       }
-}
-
-static int eth16i_open(struct net_device *dev)
-{
-       struct eth16i_local *lp = netdev_priv(dev);
-       int ioaddr = dev->base_addr;
-
-       /* Powerup the chip */
-       outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
-
-       /* Initialize the chip */
-       eth16i_initialize(dev, 0);
-
-       /* Set the transmit buffer size */
-       lp->tx_buf_size = eth16i_tx_buf_map[ETH16I_TX_BUF_SIZE & 0x03];
-
-       if(eth16i_debug > 0)
-               printk(KERN_DEBUG "%s: transmit buffer size %d\n",
-                      dev->name, lp->tx_buf_size);
-
-       /* Now enable Transmitter and Receiver sections */
-       BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
-
-       /* Now switch to register bank 2, for run time operation */
-       eth16i_select_regbank(2, ioaddr);
-
-       lp->open_time = jiffies;
-       lp->tx_started = 0;
-       lp->tx_queue = 0;
-       lp->tx_queue_len = 0;
-
-       /* Turn on interrupts*/
-       outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-
-       netif_start_queue(dev);
-       return 0;
-}
-
-static int eth16i_close(struct net_device *dev)
-{
-       struct eth16i_local *lp = netdev_priv(dev);
-       int ioaddr = dev->base_addr;
-
-       eth16i_reset(dev);
-
-       /* Turn off interrupts*/
-       outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
-
-       netif_stop_queue(dev);
-
-       lp->open_time = 0;
-
-       /* Disable transmit and receive */
-       BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
-
-       /* Reset the chip */
-       /* outb(0xff, ioaddr + RESET); */
-       /* outw(0xffff, ioaddr + TX_STATUS_REG);    */
-
-       outb(0x00, ioaddr + CONFIG_REG_1);
-
-       return 0;
-}
-
-static void eth16i_timeout(struct net_device *dev)
-{
-       struct eth16i_local *lp = netdev_priv(dev);
-       int ioaddr = dev->base_addr;
-       /*
-          If we get here, some higher level has decided that
-          we are broken. There should really be a "kick me"
-          function call instead.
-          */
-
-       outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
-       printk(KERN_WARNING "%s: transmit timed out with status %04x, %s ?\n",
-              dev->name,
-       inw(ioaddr + TX_STATUS_REG),  (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ?
-                      "IRQ conflict" : "network cable problem");
-
-       dev->trans_start = jiffies; /* prevent tx timeout */
-
-       /* Let's dump all registers */
-       if(eth16i_debug > 0) {
-               printk(KERN_DEBUG "%s: timeout: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
-                      dev->name, inb(ioaddr + 0),
-                      inb(ioaddr + 1), inb(ioaddr + 2),
-                      inb(ioaddr + 3), inb(ioaddr + 4),
-                      inb(ioaddr + 5),
-                      inb(ioaddr + 6), inb(ioaddr + 7));
-
-               printk(KERN_DEBUG "%s: transmit start reg: %02x. collision reg %02x\n",
-                      dev->name, inb(ioaddr + TRANSMIT_START_REG),
-                      inb(ioaddr + COL_16_REG));
-                       printk(KERN_DEBUG "lp->tx_queue = %d\n", lp->tx_queue);
-               printk(KERN_DEBUG "lp->tx_queue_len = %d\n", lp->tx_queue_len);
-               printk(KERN_DEBUG "lp->tx_started = %d\n", lp->tx_started);
-       }
-       dev->stats.tx_errors++;
-       eth16i_reset(dev);
-       dev->trans_start = jiffies; /* prevent tx timeout */
-       outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-       netif_wake_queue(dev);
-}
-
-static netdev_tx_t eth16i_tx(struct sk_buff *skb, struct net_device *dev)
-{
-       struct eth16i_local *lp = netdev_priv(dev);
-       int ioaddr = dev->base_addr;
-       int status = 0;
-       ushort length = skb->len;
-       unsigned char *buf;
-       unsigned long flags;
-
-       if (length < ETH_ZLEN) {
-               if (skb_padto(skb, ETH_ZLEN))
-                       return NETDEV_TX_OK;
-               length = ETH_ZLEN;
-       }
-       buf = skb->data;
-
-       netif_stop_queue(dev);
-
-       /* Turn off TX interrupts */
-       outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
-
-       /* We would be better doing the disable_irq tricks the 3c509 does,
-          that would make this suck a lot less */
-
-       spin_lock_irqsave(&lp->lock, flags);
-
-       if( (length + 2) > (lp->tx_buf_size - lp->tx_queue_len)) {
-               if(eth16i_debug > 0)
-                       printk(KERN_WARNING "%s: Transmit buffer full.\n", dev->name);
-       }
-       else {
-               outw(length, ioaddr + DATAPORT);
-
-               if( ioaddr < 0x1000 )
-                       outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
-               else {
-                       unsigned char frag = length % 4;
-                       outsl(ioaddr + DATAPORT, buf, length >> 2);
-                       if( frag != 0 ) {
-                               outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
-                               if( frag == 3 )
-                                       outsw(ioaddr + DATAPORT,
-                                             (buf + (length & 0xFFFC) + 2), 1);
-                       }
-               }
-               lp->tx_buffered_packets++;
-               lp->tx_buffered_bytes = length;
-               lp->tx_queue++;
-               lp->tx_queue_len += length + 2;
-       }
-       lp->tx_buf_busy = 0;
-
-       if(lp->tx_started == 0) {
-               /* If the transmitter is idle..always trigger a transmit */
-               outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
-               lp->tx_queue = 0;
-               lp->tx_queue_len = 0;
-               lp->tx_started = 1;
-               netif_wake_queue(dev);
-       }
-       else if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
-               /* There is still more room for one more packet in tx buffer */
-               netif_wake_queue(dev);
-       }
-
-       spin_unlock_irqrestore(&lp->lock, flags);
-
-       outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-       /* Turn TX interrupts back on */
-       /* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */
-       status = 0;
-       dev_kfree_skb(skb);
-       return NETDEV_TX_OK;
-}
-
-static void eth16i_rx(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr;
-       int boguscount = MAX_RX_LOOP;
-
-       /* Loop until all packets have been read */
-       while( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) {
-
-               /* Read status byte from receive buffer */
-               ushort status = inw(ioaddr + DATAPORT);
-
-               /* Get the size of the packet from receive buffer */
-               ushort pkt_len = inw(ioaddr + DATAPORT);
-
-               if(eth16i_debug > 4)
-                       printk(KERN_DEBUG "%s: Receiving packet mode %02x status %04x.\n",
-                              dev->name,
-                              inb(ioaddr + RECEIVE_MODE_REG), status);
-
-               if( !(status & PKT_GOOD) ) {
-                       dev->stats.rx_errors++;
-
-                       if( (pkt_len < ETH_ZLEN) || (pkt_len > ETH_FRAME_LEN) ) {
-                               dev->stats.rx_length_errors++;
-                               eth16i_reset(dev);
-                               return;
-                       }
-                       else {
-                               eth16i_skip_packet(dev);
-                               dev->stats.rx_dropped++;
-                       }
-               }
-               else {   /* Ok so now we should have a good packet */
-                       struct sk_buff *skb;
-
-                       skb = dev_alloc_skb(pkt_len + 3);
-                       if( skb == NULL ) {
-                               printk(KERN_WARNING "%s: Could'n allocate memory for packet (len %d)\n",
-                                      dev->name, pkt_len);
-                               eth16i_skip_packet(dev);
-                               dev->stats.rx_dropped++;
-                               break;
-                       }
-
-                       skb_reserve(skb,2);
-
-                       /*
-                          Now let's get the packet out of buffer.
-                          size is (pkt_len + 1) >> 1, cause we are now reading words
-                          and it have to be even aligned.
-                          */
-
-                       if(ioaddr < 0x1000)
-                               insw(ioaddr + DATAPORT, skb_put(skb, pkt_len),
-                                    (pkt_len + 1) >> 1);
-                       else {
-                               unsigned char *buf = skb_put(skb, pkt_len);
-                               unsigned char frag = pkt_len % 4;
-
-                               insl(ioaddr + DATAPORT, buf, pkt_len >> 2);
-
-                               if(frag != 0) {
-                                       unsigned short rest[2];
-                                       rest[0] = inw( ioaddr + DATAPORT );
-                                       if(frag == 3)
-                                               rest[1] = inw( ioaddr + DATAPORT );
-
-                                       memcpy(buf + (pkt_len & 0xfffc), (char *)rest, frag);
-                               }
-                       }
-
-                       skb->protocol=eth_type_trans(skb, dev);
-
-                       if( eth16i_debug > 5 ) {
-                               int i;
-                               printk(KERN_DEBUG "%s: Received packet of length %d.\n",
-                                      dev->name, pkt_len);
-                               for(i = 0; i < 14; i++)
-                                       printk(KERN_DEBUG " %02x", skb->data[i]);
-                               printk(KERN_DEBUG ".\n");
-                       }
-                       netif_rx(skb);
-                       dev->stats.rx_packets++;
-                       dev->stats.rx_bytes += pkt_len;
-
-               } /* else */
-
-               if(--boguscount <= 0)
-                       break;
-
-       } /* while */
-}
-
-static irqreturn_t eth16i_interrupt(int irq, void *dev_id)
-{
-       struct net_device *dev = dev_id;
-       struct eth16i_local *lp;
-       int ioaddr = 0, status;
-       int handled = 0;
-
-       ioaddr = dev->base_addr;
-       lp = netdev_priv(dev);
-
-       /* Turn off all interrupts from adapter */
-       outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
-
-       /* eth16i_tx won't be called */
-       spin_lock(&lp->lock);
-
-       status = inw(ioaddr + TX_STATUS_REG);      /* Get the status */
-       outw(status, ioaddr + TX_STATUS_REG);      /* Clear status bits */
-
-       if (status)
-               handled = 1;
-
-       if(eth16i_debug > 3)
-               printk(KERN_DEBUG "%s: Interrupt with status %04x.\n", dev->name, status);
-
-       if( status & 0x7f00 ) {
-
-               dev->stats.rx_errors++;
-
-               if(status & (BUS_RD_ERR << 8) )
-                       printk(KERN_WARNING "%s: Bus read error.\n",dev->name);
-               if(status & (SHORT_PKT_ERR << 8) )   dev->stats.rx_length_errors++;
-               if(status & (ALIGN_ERR << 8) )       dev->stats.rx_frame_errors++;
-               if(status & (CRC_ERR << 8) )        dev->stats.rx_crc_errors++;
-               if(status & (RX_BUF_OVERFLOW << 8) ) dev->stats.rx_over_errors++;
-       }
-       if( status & 0x001a) {
-
-               dev->stats.tx_errors++;
-
-               if(status & CR_LOST) dev->stats.tx_carrier_errors++;
-               if(status & TX_JABBER_ERR) dev->stats.tx_window_errors++;
-
-#if 0
-               if(status & COLLISION) {
-                       dev->stats.collisions +=
-                               ((inb(ioaddr+TRANSMIT_MODE_REG) & 0xF0) >> 4);
-               }
-#endif
-               if(status & COLLISIONS_16) {
-                       if(lp->col_16 < MAX_COL_16) {
-                               lp->col_16++;
-                               dev->stats.collisions++;
-                               /* Resume transmitting, skip failed packet */
-                               outb(0x02, ioaddr + COL_16_REG);
-                       }
-                       else {
-                               printk(KERN_WARNING "%s: bailing out due to many consecutive 16-in-a-row collisions. Network cable problem?\n", dev->name);
-                       }
-               }
-       }
-
-       if( status & 0x00ff ) {          /* Let's check the transmit status reg */
-
-               if(status & TX_DONE) {         /* The transmit has been done */
-                       dev->stats.tx_packets = lp->tx_buffered_packets;
-                       dev->stats.tx_bytes += lp->tx_buffered_bytes;
-                       lp->col_16 = 0;
-
-                       if(lp->tx_queue) {           /* Is there still packets ? */
-                               /* There was packet(s) so start transmitting and write also
-                                  how many packets there is to be sended */
-                               outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
-                               lp->tx_queue = 0;
-                               lp->tx_queue_len = 0;
-                               lp->tx_started = 1;
-                       }
-                       else {
-                               lp->tx_started = 0;
-                       }
-                       netif_wake_queue(dev);
-               }
-       }
-
-       if( ( status & 0x8000 ) ||
-           ( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) ) {
-               eth16i_rx(dev);  /* We have packet in receive buffer */
-       }
-
-       /* Turn interrupts back on */
-       outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-
-       if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
-               /* There is still more room for one more packet in tx buffer */
-               netif_wake_queue(dev);
-       }
-
-       spin_unlock(&lp->lock);
-
-       return IRQ_RETVAL(handled);
-}
-
-static void eth16i_skip_packet(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr;
-
-       inw(ioaddr + DATAPORT);
-       inw(ioaddr + DATAPORT);
-       inw(ioaddr + DATAPORT);
-
-       outb(SKIP_RX_PACKET, ioaddr + FILTER_SELF_RX_REG);
-       while( inb( ioaddr + FILTER_SELF_RX_REG ) != 0);
-}
-
-static void eth16i_reset(struct net_device *dev)
-{
-       struct eth16i_local *lp = netdev_priv(dev);
-       int ioaddr = dev->base_addr;
-
-       if(eth16i_debug > 1)
-               printk(KERN_DEBUG "%s: Resetting device.\n", dev->name);
-
-       BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
-       outw(0xffff, ioaddr + TX_STATUS_REG);
-       eth16i_select_regbank(2, ioaddr);
-
-       lp->tx_started = 0;
-       lp->tx_buf_busy = 0;
-       lp->tx_queue = 0;
-       lp->tx_queue_len = 0;
-       BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
-}
-
-static void eth16i_multicast(struct net_device *dev)
-{
-       int ioaddr = dev->base_addr;
-
-       if (!netdev_mc_empty(dev) || dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
-       {
-               outb(3, ioaddr + RECEIVE_MODE_REG);
-       } else {
-               outb(2, ioaddr + RECEIVE_MODE_REG);
-       }
-}
-
-static void eth16i_select_regbank(unsigned char banknbr, int ioaddr)
-{
-       unsigned char data;
-
-       data = inb(ioaddr + CONFIG_REG_1);
-       outb( ((data & 0xF3) | ( (banknbr & 0x03) << 2)), ioaddr + CONFIG_REG_1);
-}
-
-#ifdef MODULE
-
-static ushort eth16i_parse_mediatype(const char* s)
-{
-       if(!s)
-               return E_PORT_FROM_EPROM;
-
-        if (!strncmp(s, "bnc", 3))
-               return E_PORT_BNC;
-        else if (!strncmp(s, "tp", 2))
-                return E_PORT_TP;
-        else if (!strncmp(s, "dix", 3))
-                return E_PORT_DIX;
-        else if (!strncmp(s, "auto", 4))
-               return E_PORT_AUTO;
-       else
-               return E_PORT_FROM_EPROM;
-}
-
-#define MAX_ETH16I_CARDS 4  /* Max number of Eth16i cards per module */
-
-static struct net_device *dev_eth16i[MAX_ETH16I_CARDS];
-static int io[MAX_ETH16I_CARDS];
-#if 0
-static int irq[MAX_ETH16I_CARDS];
-#endif
-static char* mediatype[MAX_ETH16I_CARDS];
-static int debug = -1;
-
-MODULE_AUTHOR("Mika Kuoppala <miku@iki.fi>");
-MODULE_DESCRIPTION("ICL EtherTeam 16i/32 driver");
-MODULE_LICENSE("GPL");
-
-
-module_param_array(io, int, NULL, 0);
-MODULE_PARM_DESC(io, "eth16i I/O base address(es)");
-
-#if 0
-module_param_array(irq, int, NULL, 0);
-MODULE_PARM_DESC(irq, "eth16i interrupt request number");
-#endif
-
-module_param_array(mediatype, charp, NULL, 0);
-MODULE_PARM_DESC(mediatype, "eth16i media type of interface(s) (bnc,tp,dix,auto,eprom)");
-
-module_param(debug, int, 0);
-MODULE_PARM_DESC(debug, "eth16i debug level (0-6)");
-
-int __init init_module(void)
-{
-       int this_dev, found = 0;
-       struct net_device *dev;
-
-       for (this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++) {
-               dev = alloc_etherdev(sizeof(struct eth16i_local));
-               if (!dev)
-                       break;
-
-               dev->base_addr = io[this_dev];
-
-               if(debug != -1)
-                       eth16i_debug = debug;
-
-               if(eth16i_debug > 1)
-                       printk(KERN_NOTICE "eth16i(%d): interface type %s\n", this_dev, mediatype[this_dev] ? mediatype[this_dev] : "none" );
-
-               dev->if_port = eth16i_parse_mediatype(mediatype[this_dev]);
-
-               if(io[this_dev] == 0) {
-                       if (this_dev != 0) { /* Only autoprobe 1st one */
-                               free_netdev(dev);
-                               break;
-                       }
-
-                       printk(KERN_NOTICE "eth16i.c: Presently autoprobing (not recommended) for a single card.\n");
-               }
-
-               if (do_eth16i_probe(dev) == 0) {
-                       dev_eth16i[found++] = dev;
-                       continue;
-               }
-               printk(KERN_WARNING "eth16i.c No Eth16i card found (i/o = 0x%x).\n",
-                      io[this_dev]);
-               free_netdev(dev);
-               break;
-       }
-       if (found)
-               return 0;
-       return -ENXIO;
-}
-
-void __exit cleanup_module(void)
-{
-       int this_dev;
-
-       for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++) {
-               struct net_device *dev = dev_eth16i[this_dev];
-
-               if (netdev_priv(dev)) {
-                       unregister_netdev(dev);
-                       free_irq(dev->irq, dev);
-                       release_region(dev->base_addr, ETH16I_IO_EXTENT);
-                       free_netdev(dev);
-               }
-       }
-}
-#endif /* MODULE */
index bdc0df873daf636761f281d6c7fdf6886a93d286..d3aff7456baef85f51cec72838beb9b6d7be7239 100644 (file)
@@ -24,6 +24,7 @@ source "drivers/net/ethernet/dlink/Kconfig"
 source "drivers/net/ethernet/emulex/Kconfig"
 source "drivers/net/ethernet/neterion/Kconfig"
 source "drivers/net/ethernet/faraday/Kconfig"
+source "drivers/net/ethernet/fujitsu/Kconfig"
 source "drivers/net/ethernet/ibm/Kconfig"
 source "drivers/net/ethernet/intel/Kconfig"
 source "drivers/net/ethernet/i825xx/Kconfig"
index ac60ac9026bb895d7037726a809b7c319b5d4e34..b098c5e1fa2c00b380efe116e2b92dc385d1aa4b 100644 (file)
@@ -16,6 +16,7 @@ obj-$(CONFIG_NET_VENDOR_DLINK) += dlink/
 obj-$(CONFIG_NET_VENDOR_EMULEX) += emulex/
 obj-$(CONFIG_NET_VENDOR_EXAR) += neterion/
 obj-$(CONFIG_NET_VENDOR_FARADAY) += faraday/
+obj-$(CONFIG_NET_VENDOR_FUJITSU) += fujitsu/
 obj-$(CONFIG_NET_VENDOR_IBM) += ibm/
 obj-$(CONFIG_NET_VENDOR_INTEL) += intel/
 obj-$(CONFIG_NET_VENDOR_I825XX) += i825xx/
diff --git a/drivers/net/ethernet/fujitsu/Kconfig b/drivers/net/ethernet/fujitsu/Kconfig
new file mode 100644 (file)
index 0000000..2cd968e
--- /dev/null
@@ -0,0 +1,53 @@
+#
+# Fujitsu Network device configuration
+#
+
+config NET_VENDOR_FUJITSU
+       bool "Fujitsu devices"
+       depends on ISA || PCMCIA || ((ISA || MCA_LEGACY) && 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
+         the questions about Fujitsu cards. If you say Y, you will be asked for
+         your specific card in the following questions.
+
+if NET_VENDOR_FUJITSU
+
+config AT1700
+       tristate "AT1700/1720 support (EXPERIMENTAL)"
+       depends on (ISA || MCA_LEGACY) && 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 at1700.
+
+config PCMCIA_FMVJ18X
+       tristate "Fujitsu FMV-J18x PCMCIA support"
+       depends on PCMCIA
+       select CRC32
+       ---help---
+         Say Y here if you intend to attach a Fujitsu FMV-J18x or compatible
+         PCMCIA (PC-card) Ethernet card to your computer.
+
+         To compile this driver as a module, choose M here: the module will be
+         called fmvj18x_cs.  If unsure, say N.
+
+config ETH16I
+       tristate "ICL EtherTeam 16i/32 support"
+       depends on ISA
+       ---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 eth16i.
+
+endif # NET_VENDOR_FUJITSU
diff --git a/drivers/net/ethernet/fujitsu/Makefile b/drivers/net/ethernet/fujitsu/Makefile
new file mode 100644 (file)
index 0000000..2730ae6
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for the Fujitsu network device drivers.
+#
+
+obj-$(CONFIG_AT1700) += at1700.o
+obj-$(CONFIG_ETH16I) += eth16i.o
+obj-$(CONFIG_PCMCIA_FMVJ18X) += fmvj18x_cs.o
diff --git a/drivers/net/ethernet/fujitsu/at1700.c b/drivers/net/ethernet/fujitsu/at1700.c
new file mode 100644 (file)
index 0000000..65a78f9
--- /dev/null
@@ -0,0 +1,900 @@
+/* at1700.c: A network device driver for  the Allied Telesis AT1700.
+
+       Written 1993-98 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 device driver for the Allied Telesis AT1700, and
+        Fujitsu FMV-181/182/181A/182A/183/184/183A/184A, which are
+       straight-forward Fujitsu MB86965 implementations.
+
+       Modification for Fujitsu FMV-18X cards is done by Yutaka Tamiya
+       (tamy@flab.fujitsu.co.jp).
+
+  Sources:
+    The Fujitsu MB86965 datasheet.
+
+       After the initial version of this driver was written Gerry Sawkins of
+       ATI provided their EEPROM configuration code header file.
+    Thanks to NIIBE Yutaka <gniibe@mri.co.jp> for bug fixes.
+
+    MCA bus (AT1720) support by Rene Schmit <rene@bss.lu>
+
+  Bugs:
+       The MB86965 has a design flaw that makes all probes unreliable.  Not
+       only is it difficult to detect, it also moves around in I/O space in
+       response to inb()s from other device probes!
+*/
+
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/mca-legacy.h>
+#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/skbuff.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/crc32.h>
+#include <linux/bitops.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
+static char version[] __initdata =
+       "at1700.c:v1.16 9/11/06  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
+#define DRV_NAME "at1700"
+
+/* Tunable parameters. */
+
+/* When to switch from the 64-entry multicast filter to Rx-all-multicast. */
+#define MC_FILTERBREAK 64
+
+/* These unusual address orders are used to verify the CONFIG register. */
+
+static int fmv18x_probe_list[] __initdata = {
+       0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0
+};
+
+/*
+ *     ISA
+ */
+
+static unsigned at1700_probe_list[] __initdata = {
+       0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
+};
+
+/*
+ *     MCA
+ */
+#ifdef CONFIG_MCA_LEGACY
+static int at1700_ioaddr_pattern[] __initdata = {
+       0x00, 0x04, 0x01, 0x05, 0x02, 0x06, 0x03, 0x07
+};
+
+static int at1700_mca_probe_list[] __initdata = {
+       0x400, 0x1400, 0x2400, 0x3400, 0x4400, 0x5400, 0x6400, 0x7400, 0
+};
+
+static int at1700_irq_pattern[] __initdata = {
+       0x00, 0x00, 0x00, 0x30, 0x70, 0xb0, 0x00, 0x00,
+       0x00, 0xf0, 0x34, 0x74, 0xb4, 0x00, 0x00, 0xf4, 0x00
+};
+#endif
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifndef NET_DEBUG
+#define NET_DEBUG 1
+#endif
+static unsigned int net_debug = NET_DEBUG;
+
+typedef unsigned char uchar;
+
+/* Information that need to be kept for each board. */
+struct net_local {
+       spinlock_t lock;
+       unsigned char mc_filter[8];
+       uint jumpered:1;                        /* Set iff the board has jumper config. */
+       uint tx_started:1;                      /* Packets are on the Tx queue. */
+       uint tx_queue_ready:1;                  /* Tx queue is ready to be sent. */
+       uint rx_started:1;                      /* Packets are Rxing. */
+       uchar tx_queue;                         /* Number of packet on the Tx queue. */
+       char mca_slot;                          /* -1 means ISA */
+       ushort tx_queue_len;                    /* Current length of the Tx queue. */
+};
+
+
+/* Offsets from the base address. */
+#define STATUS                 0
+#define TX_STATUS              0
+#define RX_STATUS              1
+#define TX_INTR                        2               /* Bit-mapped interrupt enable registers. */
+#define RX_INTR                        3
+#define TX_MODE                        4
+#define RX_MODE                        5
+#define CONFIG_0               6               /* Misc. configuration settings. */
+#define CONFIG_1               7
+/* Run-time register bank 2 definitions. */
+#define DATAPORT               8               /* Word-wide DMA or programmed-I/O dataport. */
+#define TX_START               10
+#define COL16CNTL              11              /* Control Reg for 16 collisions */
+#define MODE13                 13
+#define RX_CTRL                        14
+/* Configuration registers only on the '865A/B chips. */
+#define EEPROM_Ctrl    16
+#define EEPROM_Data    17
+#define CARDSTATUS     16                      /* FMV-18x Card Status */
+#define CARDSTATUS1    17                      /* FMV-18x Card Status */
+#define IOCONFIG               18              /* Either read the jumper, or move the I/O. */
+#define IOCONFIG1              19
+#define        SAPROM                  20              /* The station address PROM, if no EEPROM. */
+#define MODE24                 24
+#define RESET                  31              /* Write to reset some parts of the chip. */
+#define AT1700_IO_EXTENT       32
+#define PORT_OFFSET(o) (o)
+
+
+#define TX_TIMEOUT             (HZ/10)
+
+
+/* Index to functions, as function prototypes. */
+
+static int at1700_probe1(struct net_device *dev, int ioaddr);
+static int read_eeprom(long ioaddr, int location);
+static int net_open(struct net_device *dev);
+static netdev_tx_t net_send_packet(struct sk_buff *skb,
+                                  struct net_device *dev);
+static irqreturn_t net_interrupt(int irq, void *dev_id);
+static void net_rx(struct net_device *dev);
+static int net_close(struct net_device *dev);
+static void set_rx_mode(struct net_device *dev);
+static void net_tx_timeout (struct net_device *dev);
+
+
+#ifdef CONFIG_MCA_LEGACY
+struct at1720_mca_adapters_struct {
+       char* name;
+       int id;
+};
+/* rEnE : maybe there are others I don't know off... */
+
+static struct at1720_mca_adapters_struct at1720_mca_adapters[] __initdata = {
+       { "Allied Telesys AT1720AT",    0x6410 },
+       { "Allied Telesys AT1720BT",    0x6413 },
+       { "Allied Telesys AT1720T",     0x6416 },
+       { NULL, 0 },
+};
+#endif
+
+/* Check for a network adaptor of this type, and return '0' iff one exists.
+   If dev->base_addr == 0, probe all likely locations.
+   If dev->base_addr == 1, always return failure.
+   If dev->base_addr == 2, allocate space for the device and return success
+   (detachable devices only).
+   */
+
+static int io = 0x260;
+
+static int irq;
+
+static void cleanup_card(struct net_device *dev)
+{
+#ifdef CONFIG_MCA_LEGACY
+       struct net_local *lp = netdev_priv(dev);
+       if (lp->mca_slot >= 0)
+               mca_mark_as_unused(lp->mca_slot);
+#endif
+       free_irq(dev->irq, NULL);
+       release_region(dev->base_addr, AT1700_IO_EXTENT);
+}
+
+struct net_device * __init at1700_probe(int unit)
+{
+       struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
+       unsigned *port;
+       int err = 0;
+
+       if (!dev)
+               return ERR_PTR(-ENODEV);
+
+       if (unit >= 0) {
+               sprintf(dev->name, "eth%d", unit);
+               netdev_boot_setup_check(dev);
+               io = dev->base_addr;
+               irq = dev->irq;
+       } else {
+               dev->base_addr = io;
+               dev->irq = irq;
+       }
+
+       if (io > 0x1ff) {       /* Check a single specified location. */
+               err = at1700_probe1(dev, io);
+       } else if (io != 0) {   /* Don't probe at all. */
+               err = -ENXIO;
+       } else {
+               for (port = at1700_probe_list; *port; port++) {
+                       if (at1700_probe1(dev, *port) == 0)
+                               break;
+                       dev->irq = irq;
+               }
+               if (!*port)
+                       err = -ENODEV;
+       }
+       if (err)
+               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 at1700_netdev_ops = {
+       .ndo_open               = net_open,
+       .ndo_stop               = net_close,
+       .ndo_start_xmit         = net_send_packet,
+       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_tx_timeout         = net_tx_timeout,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
+/* The Fujitsu datasheet suggests that the NIC be probed for by checking its
+   "signature", the default bit pattern after a reset.  This *doesn't* work --
+   there is no way to reset the bus interface without a complete power-cycle!
+
+   It turns out that ATI came to the same conclusion I did: the only thing
+   that can be done is checking a few bits and then diving right into an
+   EEPROM read. */
+
+static int __init at1700_probe1(struct net_device *dev, int ioaddr)
+{
+       static const char fmv_irqmap[4] = {3, 7, 10, 15};
+       static const char fmv_irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
+       static const char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
+       unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0;
+       int slot, ret = -ENODEV;
+       struct net_local *lp = netdev_priv(dev);
+
+       if (!request_region(ioaddr, AT1700_IO_EXTENT, DRV_NAME))
+               return -EBUSY;
+
+       /* Resetting the chip doesn't reset the ISA interface, so don't bother.
+          That means we have to be careful with the register values we probe
+          for.
+        */
+#ifdef notdef
+       printk("at1700 probe at %#x, eeprom is %4.4x %4.4x %4.4x ctrl %4.4x.\n",
+                  ioaddr, read_eeprom(ioaddr, 4), read_eeprom(ioaddr, 5),
+                  read_eeprom(ioaddr, 6), inw(ioaddr + EEPROM_Ctrl));
+#endif
+
+#ifdef CONFIG_MCA_LEGACY
+       /* rEnE (rene@bss.lu): got this from 3c509 driver source , adapted for AT1720 */
+
+    /* Based on Erik Nygren's (nygren@mit.edu) 3c529 patch, heavily
+       modified by Chris Beauregard (cpbeaure@csclub.uwaterloo.ca)
+       to support standard MCA probing. */
+
+       /* redone for multi-card detection by ZP Gu (zpg@castle.net) */
+       /* now works as a module */
+
+       if (MCA_bus) {
+               int j;
+               int l_i;
+               u_char pos3, pos4;
+
+               for (j = 0; at1720_mca_adapters[j].name != NULL; j ++) {
+                       slot = 0;
+                       while (slot != MCA_NOTFOUND) {
+
+                               slot = mca_find_unused_adapter( at1720_mca_adapters[j].id, slot );
+                               if (slot == MCA_NOTFOUND) break;
+
+                               /* if we get this far, an adapter has been detected and is
+                               enabled */
+
+                               pos3 = mca_read_stored_pos( slot, 3 );
+                               pos4 = mca_read_stored_pos( slot, 4 );
+
+                               for (l_i = 0; l_i < 8; l_i++)
+                                       if (( pos3 & 0x07) == at1700_ioaddr_pattern[l_i])
+                                               break;
+                               ioaddr = at1700_mca_probe_list[l_i];
+
+                               for (irq = 0; irq < 0x10; irq++)
+                                       if (((((pos4>>4) & 0x0f) | (pos3 & 0xf0)) & 0xff) == at1700_irq_pattern[irq])
+                                               break;
+
+                                       /* probing for a card at a particular IO/IRQ */
+                               if ((dev->irq && dev->irq != irq) ||
+                                   (dev->base_addr && dev->base_addr != ioaddr)) {
+                                       slot++;         /* probing next slot */
+                                       continue;
+                               }
+
+                               dev->irq = irq;
+
+                               /* claim the slot */
+                               mca_set_adapter_name( slot, at1720_mca_adapters[j].name );
+                               mca_mark_as_used(slot);
+
+                               goto found;
+                       }
+               }
+               /* if we get here, we didn't find an MCA adapter - try ISA */
+       }
+#endif
+       slot = -1;
+       /* We must check for the EEPROM-config boards first, else accessing
+          IOCONFIG0 will move the board! */
+       if (at1700_probe_list[inb(ioaddr + IOCONFIG1) & 0x07] == ioaddr &&
+           read_eeprom(ioaddr, 4) == 0x0000 &&
+           (read_eeprom(ioaddr, 5) & 0xff00) == 0xF400)
+               is_at1700 = 1;
+       else if (inb(ioaddr + SAPROM    ) == 0x00 &&
+                inb(ioaddr + SAPROM + 1) == 0x00 &&
+                inb(ioaddr + SAPROM + 2) == 0x0e)
+               is_fmv18x = 1;
+       else {
+               goto err_out;
+       }
+
+#ifdef CONFIG_MCA_LEGACY
+found:
+#endif
+
+               /* Reset the internal state machines. */
+       outb(0, ioaddr + RESET);
+
+       if (is_at1700) {
+               irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04)
+                                                  | (read_eeprom(ioaddr, 0)>>14)];
+       } else {
+               /* Check PnP mode for FMV-183/184/183A/184A. */
+               /* This PnP routine is very poor. IO and IRQ should be known. */
+               if (inb(ioaddr + CARDSTATUS1) & 0x20) {
+                       irq = dev->irq;
+                       for (i = 0; i < 8; i++) {
+                               if (irq == fmv_irqmap_pnp[i])
+                                       break;
+                       }
+                       if (i == 8) {
+                               goto err_mca;
+                       }
+               } else {
+                       if (fmv18x_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr)
+                               goto err_mca;
+                       irq = fmv_irqmap[(inb(ioaddr + IOCONFIG)>>6) & 0x03];
+               }
+       }
+
+       printk("%s: %s found at %#3x, IRQ %d, address ", dev->name,
+                  is_at1700 ? "AT1700" : "FMV-18X", ioaddr, irq);
+
+       dev->base_addr = ioaddr;
+       dev->irq = irq;
+
+       if (is_at1700) {
+               for(i = 0; i < 3; i++) {
+                       unsigned short eeprom_val = read_eeprom(ioaddr, 4+i);
+                       ((unsigned short *)dev->dev_addr)[i] = ntohs(eeprom_val);
+               }
+       } else {
+               for(i = 0; i < 6; i++) {
+                       unsigned char val = inb(ioaddr + SAPROM + i);
+                       dev->dev_addr[i] = val;
+               }
+       }
+       printk("%pM", dev->dev_addr);
+
+       /* The EEPROM word 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
+          rather than 150 ohm shielded twisted pair compensation.
+          0x0000 == auto-sense the interface
+          0x0800 == use TP interface
+          0x1800 == use coax interface
+          */
+       {
+               const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2"};
+               if (is_at1700) {
+                       ushort setup_value = read_eeprom(ioaddr, 12);
+                       dev->if_port = setup_value >> 8;
+               } else {
+                       ushort setup_value = inb(ioaddr + CARDSTATUS);
+                       switch (setup_value & 0x07) {
+                       case 0x01: /* 10base5 */
+                       case 0x02: /* 10base2 */
+                               dev->if_port = 0x18; break;
+                       case 0x04: /* 10baseT */
+                               dev->if_port = 0x08; break;
+                       default:   /* auto-sense */
+                               dev->if_port = 0x00; break;
+                       }
+               }
+               printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);
+       }
+
+       /* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit
+          bus access, two 4K Tx queues, and disabled Tx and Rx. */
+       outb(0xda, ioaddr + CONFIG_0);
+
+       /* Set the station address in bank zero. */
+       outb(0x00, ioaddr + CONFIG_1);
+       for (i = 0; i < 6; i++)
+               outb(dev->dev_addr[i], ioaddr + PORT_OFFSET(8 + i));
+
+       /* Switch to bank 1 and set the multicast table to accept none. */
+       outb(0x04, ioaddr + CONFIG_1);
+       for (i = 0; i < 8; i++)
+               outb(0x00, ioaddr + PORT_OFFSET(8 + i));
+
+
+       /* Switch to bank 2 */
+       /* Lock our I/O address, and set manual processing mode for 16 collisions. */
+       outb(0x08, ioaddr + CONFIG_1);
+       outb(dev->if_port, ioaddr + MODE13);
+       outb(0x00, ioaddr + COL16CNTL);
+
+       if (net_debug)
+               printk(version);
+
+       dev->netdev_ops = &at1700_netdev_ops;
+       dev->watchdog_timeo = TX_TIMEOUT;
+
+       spin_lock_init(&lp->lock);
+
+       lp->jumpered = is_fmv18x;
+       lp->mca_slot = slot;
+       /* Snarf the interrupt vector now. */
+       ret = request_irq(irq, net_interrupt, 0, DRV_NAME, dev);
+       if (ret) {
+               printk(KERN_ERR "AT1700 at %#3x is unusable due to a "
+                      "conflict on IRQ %d.\n",
+                      ioaddr, irq);
+               goto err_mca;
+       }
+
+       return 0;
+
+err_mca:
+#ifdef CONFIG_MCA_LEGACY
+       if (slot >= 0)
+               mca_mark_as_unused(slot);
+#endif
+err_out:
+       release_region(ioaddr, AT1700_IO_EXTENT);
+       return ret;
+}
+
+
+/*  EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK   0x40    /* EEPROM shift clock, in reg. 16. */
+#define EE_CS                  0x20    /* EEPROM chip select, in reg. 16. */
+#define EE_DATA_WRITE  0x80    /* EEPROM chip data in, in reg. 17. */
+#define EE_DATA_READ   0x80    /* EEPROM chip data out, in reg. 17. */
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD   (5 << 6)
+#define EE_READ_CMD            (6 << 6)
+#define EE_ERASE_CMD   (7 << 6)
+
+static int __init read_eeprom(long ioaddr, int location)
+{
+       int i;
+       unsigned short retval = 0;
+       long ee_addr = ioaddr + EEPROM_Ctrl;
+       long ee_daddr = ioaddr + EEPROM_Data;
+       int read_cmd = location | EE_READ_CMD;
+
+       /* Shift the read command bits out. */
+       for (i = 9; i >= 0; i--) {
+               short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+               outb(EE_CS, ee_addr);
+               outb(dataval, ee_daddr);
+               outb(EE_CS | EE_SHIFT_CLK, ee_addr);    /* EEPROM clock tick. */
+       }
+       outb(EE_DATA_WRITE, ee_daddr);
+       for (i = 16; i > 0; i--) {
+               outb(EE_CS, ee_addr);
+               outb(EE_CS | EE_SHIFT_CLK, ee_addr);
+               retval = (retval << 1) | ((inb(ee_daddr) & EE_DATA_READ) ? 1 : 0);
+       }
+
+       /* Terminate the EEPROM access. */
+       outb(EE_CS, ee_addr);
+       outb(EE_SHIFT_CLK, ee_addr);
+       outb(0, ee_addr);
+       return retval;
+}
+
+
+
+static int net_open(struct net_device *dev)
+{
+       struct net_local *lp = netdev_priv(dev);
+       int ioaddr = dev->base_addr;
+
+       /* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit
+          bus access, and two 4K Tx queues. */
+       outb(0x5a, ioaddr + CONFIG_0);
+
+       /* Powerup, switch to register bank 2, and enable the Rx and Tx. */
+       outb(0xe8, ioaddr + CONFIG_1);
+
+       lp->tx_started = 0;
+       lp->tx_queue_ready = 1;
+       lp->rx_started = 0;
+       lp->tx_queue = 0;
+       lp->tx_queue_len = 0;
+
+       /* Turn on hardware Tx and Rx interrupts. */
+       outb(0x82, ioaddr + TX_INTR);
+       outb(0x81, ioaddr + RX_INTR);
+
+       /* Enable the IRQ on boards of fmv18x it is feasible. */
+       if (lp->jumpered) {
+               outb(0x80, ioaddr + IOCONFIG1);
+       }
+
+       netif_start_queue(dev);
+       return 0;
+}
+
+static void net_tx_timeout (struct net_device *dev)
+{
+       struct net_local *lp = netdev_priv(dev);
+       int ioaddr = dev->base_addr;
+
+       printk ("%s: transmit timed out with status %04x, %s?\n", dev->name,
+               inw (ioaddr + STATUS), inb (ioaddr + TX_STATUS) & 0x80
+               ? "IRQ conflict" : "network cable problem");
+       printk ("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
+        dev->name, inw(ioaddr + TX_STATUS), inw(ioaddr + TX_INTR), inw(ioaddr + TX_MODE),
+               inw(ioaddr + CONFIG_0), inw(ioaddr + DATAPORT), inw(ioaddr + TX_START),
+               inw(ioaddr + MODE13 - 1), inw(ioaddr + RX_CTRL));
+       dev->stats.tx_errors++;
+       /* ToDo: We should try to restart the adaptor... */
+       outw(0xffff, ioaddr + MODE24);
+       outw (0xffff, ioaddr + TX_STATUS);
+       outb (0x5a, ioaddr + CONFIG_0);
+       outb (0xe8, ioaddr + CONFIG_1);
+       outw (0x8182, ioaddr + TX_INTR);
+       outb (0x00, ioaddr + TX_START);
+       outb (0x03, ioaddr + COL16CNTL);
+
+       dev->trans_start = jiffies; /* prevent tx timeout */
+
+       lp->tx_started = 0;
+       lp->tx_queue_ready = 1;
+       lp->rx_started = 0;
+       lp->tx_queue = 0;
+       lp->tx_queue_len = 0;
+
+       netif_wake_queue(dev);
+}
+
+
+static netdev_tx_t net_send_packet (struct sk_buff *skb,
+                                   struct net_device *dev)
+{
+       struct net_local *lp = netdev_priv(dev);
+       int ioaddr = dev->base_addr;
+       short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+       short len = skb->len;
+       unsigned char *buf = skb->data;
+       static u8 pad[ETH_ZLEN];
+
+       netif_stop_queue (dev);
+
+       /* We may not start transmitting unless we finish transferring
+          a packet into the Tx queue. During executing the following
+          codes we possibly catch a Tx interrupt. Thus we flag off
+          tx_queue_ready, so that we prevent the interrupt routine
+          (net_interrupt) to start transmitting. */
+       lp->tx_queue_ready = 0;
+       {
+               outw (length, ioaddr + DATAPORT);
+               /* Packet data */
+               outsw (ioaddr + DATAPORT, buf, len >> 1);
+               /* Check for dribble byte */
+               if (len & 1) {
+                       outw(skb->data[skb->len-1], ioaddr + DATAPORT);
+                       len++;
+               }
+               /* Check for packet padding */
+               if (length != skb->len)
+                       outsw(ioaddr + DATAPORT, pad, (length - len + 1) >> 1);
+
+               lp->tx_queue++;
+               lp->tx_queue_len += length + 2;
+       }
+       lp->tx_queue_ready = 1;
+
+       if (lp->tx_started == 0) {
+               /* If the Tx is idle, always trigger a transmit. */
+               outb (0x80 | lp->tx_queue, ioaddr + TX_START);
+               lp->tx_queue = 0;
+               lp->tx_queue_len = 0;
+               lp->tx_started = 1;
+               netif_start_queue (dev);
+       } else if (lp->tx_queue_len < 4096 - 1502)
+               /* Yes, there is room for one more packet. */
+               netif_start_queue (dev);
+       dev_kfree_skb (skb);
+
+       return NETDEV_TX_OK;
+}
+
+/* The typical workload of the driver:
+   Handle the network interface interrupts. */
+static irqreturn_t net_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev = dev_id;
+       struct net_local *lp;
+       int ioaddr, status;
+       int handled = 0;
+
+       if (dev == NULL) {
+               printk ("at1700_interrupt(): irq %d for unknown device.\n", irq);
+               return IRQ_NONE;
+       }
+
+       ioaddr = dev->base_addr;
+       lp = netdev_priv(dev);
+
+       spin_lock (&lp->lock);
+
+       status = inw(ioaddr + TX_STATUS);
+       outw(status, ioaddr + TX_STATUS);
+
+       if (net_debug > 4)
+               printk("%s: Interrupt with status %04x.\n", dev->name, status);
+       if (lp->rx_started == 0 &&
+           (status & 0xff00 || (inb(ioaddr + RX_MODE) & 0x40) == 0)) {
+               /* Got a packet(s).
+                  We cannot execute net_rx more than once at the same time for
+                  the same device. During executing net_rx, we possibly catch a
+                  Tx interrupt. Thus we flag on rx_started, so that we prevent
+                  the interrupt routine (net_interrupt) to dive into net_rx
+                  again. */
+               handled = 1;
+               lp->rx_started = 1;
+               outb(0x00, ioaddr + RX_INTR);   /* Disable RX intr. */
+               net_rx(dev);
+               outb(0x81, ioaddr + RX_INTR);   /* Enable  RX intr. */
+               lp->rx_started = 0;
+       }
+       if (status & 0x00ff) {
+               handled = 1;
+               if (status & 0x02) {
+                       /* More than 16 collisions occurred */
+                       if (net_debug > 4)
+                               printk("%s: 16 Collision occur during Txing.\n", dev->name);
+                       /* Cancel sending a packet. */
+                       outb(0x03, ioaddr + COL16CNTL);
+                       dev->stats.collisions++;
+               }
+               if (status & 0x82) {
+                       dev->stats.tx_packets++;
+                       /* The Tx queue has any packets and is not being
+                          transferred a packet from the host, start
+                          transmitting. */
+                       if (lp->tx_queue && lp->tx_queue_ready) {
+                               outb(0x80 | lp->tx_queue, ioaddr + TX_START);
+                               lp->tx_queue = 0;
+                               lp->tx_queue_len = 0;
+                               dev->trans_start = jiffies;
+                               netif_wake_queue (dev);
+                       } else {
+                               lp->tx_started = 0;
+                               netif_wake_queue (dev);
+                       }
+               }
+       }
+
+       spin_unlock (&lp->lock);
+       return IRQ_RETVAL(handled);
+}
+
+/* We have a good packet(s), get it/them out of the buffers. */
+static void
+net_rx(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr;
+       int boguscount = 5;
+
+       while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {
+               ushort status = inw(ioaddr + DATAPORT);
+               ushort pkt_len = inw(ioaddr + DATAPORT);
+
+               if (net_debug > 4)
+                       printk("%s: Rxing packet mode %02x status %04x.\n",
+                                  dev->name, inb(ioaddr + RX_MODE), status);
+#ifndef final_version
+               if (status == 0) {
+                       outb(0x05, ioaddr + RX_CTRL);
+                       break;
+               }
+#endif
+
+               if ((status & 0xF0) != 0x20) {  /* There was an error. */
+                       dev->stats.rx_errors++;
+                       if (status & 0x08) dev->stats.rx_length_errors++;
+                       if (status & 0x04) dev->stats.rx_frame_errors++;
+                       if (status & 0x02) dev->stats.rx_crc_errors++;
+                       if (status & 0x01) dev->stats.rx_over_errors++;
+               } else {
+                       /* Malloc up new buffer. */
+                       struct sk_buff *skb;
+
+                       if (pkt_len > 1550) {
+                               printk("%s: The AT1700 claimed a very large packet, size %d.\n",
+                                          dev->name, pkt_len);
+                               /* Prime the FIFO and then flush the packet. */
+                               inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT);
+                               outb(0x05, ioaddr + RX_CTRL);
+                               dev->stats.rx_errors++;
+                               break;
+                       }
+                       skb = dev_alloc_skb(pkt_len+3);
+                       if (skb == NULL) {
+                               printk("%s: Memory squeeze, dropping packet (len %d).\n",
+                                          dev->name, pkt_len);
+                               /* Prime the FIFO and then flush the packet. */
+                               inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT);
+                               outb(0x05, ioaddr + RX_CTRL);
+                               dev->stats.rx_dropped++;
+                               break;
+                       }
+                       skb_reserve(skb,2);
+
+                       insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
+                       skb->protocol=eth_type_trans(skb, dev);
+                       netif_rx(skb);
+                       dev->stats.rx_packets++;
+                       dev->stats.rx_bytes += pkt_len;
+               }
+               if (--boguscount <= 0)
+                       break;
+       }
+
+       /* If any worth-while packets have been received, dev_rint()
+          has done a mark_bh(NET_BH) for us and will work on them
+          when we get to the bottom-half routine. */
+       {
+               int i;
+               for (i = 0; i < 20; i++) {
+                       if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
+                               break;
+                       inw(ioaddr + DATAPORT);                         /* dummy status read */
+                       outb(0x05, ioaddr + RX_CTRL);
+               }
+
+               if (net_debug > 5)
+                       printk("%s: Exint Rx packet with mode %02x after %d ticks.\n",
+                                  dev->name, inb(ioaddr + RX_MODE), i);
+       }
+}
+
+/* The inverse routine to net_open(). */
+static int net_close(struct net_device *dev)
+{
+       struct net_local *lp = netdev_priv(dev);
+       int ioaddr = dev->base_addr;
+
+       netif_stop_queue(dev);
+
+       /* Set configuration register 0 to disable Tx and Rx. */
+       outb(0xda, ioaddr + CONFIG_0);
+
+       /* No statistic counters on the chip to update. */
+
+       /* Disable the IRQ on boards of fmv18x where it is feasible. */
+       if (lp->jumpered)
+               outb(0x00, ioaddr + IOCONFIG1);
+
+       /* Power-down the chip.  Green, green, green! */
+       outb(0x00, ioaddr + CONFIG_1);
+       return 0;
+}
+
+/*
+  Set the multicast/promiscuous mode for this adaptor.
+*/
+
+static void
+set_rx_mode(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr;
+       struct net_local *lp = netdev_priv(dev);
+       unsigned char mc_filter[8];              /* Multicast hash filter */
+       unsigned long flags;
+
+       if (dev->flags & IFF_PROMISC) {
+               memset(mc_filter, 0xff, sizeof(mc_filter));
+               outb(3, ioaddr + RX_MODE);      /* Enable promiscuous mode */
+       } else if (netdev_mc_count(dev) > MC_FILTERBREAK ||
+                          (dev->flags & IFF_ALLMULTI)) {
+               /* Too many to filter perfectly -- accept all multicasts. */
+               memset(mc_filter, 0xff, sizeof(mc_filter));
+               outb(2, ioaddr + RX_MODE);      /* Use normal mode. */
+       } else if (netdev_mc_empty(dev)) {
+               memset(mc_filter, 0x00, sizeof(mc_filter));
+               outb(1, ioaddr + RX_MODE);      /* Ignore almost all multicasts. */
+       } else {
+               struct netdev_hw_addr *ha;
+
+               memset(mc_filter, 0, sizeof(mc_filter));
+               netdev_for_each_mc_addr(ha, dev) {
+                       unsigned int bit =
+                               ether_crc_le(ETH_ALEN, ha->addr) >> 26;
+                       mc_filter[bit >> 3] |= (1 << bit);
+               }
+               outb(0x02, ioaddr + RX_MODE);   /* Use normal mode. */
+       }
+
+       spin_lock_irqsave (&lp->lock, flags);
+       if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) {
+               int i;
+               int saved_bank = inw(ioaddr + CONFIG_0);
+               /* Switch to bank 1 and set the multicast table. */
+               outw((saved_bank & ~0x0C00) | 0x0480, ioaddr + CONFIG_0);
+               for (i = 0; i < 8; i++)
+                       outb(mc_filter[i], ioaddr + PORT_OFFSET(8 + i));
+               memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter));
+               outw(saved_bank, ioaddr + CONFIG_0);
+       }
+       spin_unlock_irqrestore (&lp->lock, flags);
+}
+
+#ifdef MODULE
+static struct net_device *dev_at1700;
+
+module_param(io, int, 0);
+module_param(irq, int, 0);
+module_param(net_debug, int, 0);
+MODULE_PARM_DESC(io, "AT1700/FMV18X I/O base address");
+MODULE_PARM_DESC(irq, "AT1700/FMV18X IRQ number");
+MODULE_PARM_DESC(net_debug, "AT1700/FMV18X debug level (0-6)");
+
+static int __init at1700_module_init(void)
+{
+       if (io == 0)
+               printk("at1700: You should not use auto-probing with insmod!\n");
+       dev_at1700 = at1700_probe(-1);
+       if (IS_ERR(dev_at1700))
+               return PTR_ERR(dev_at1700);
+       return 0;
+}
+
+static void __exit at1700_module_exit(void)
+{
+       unregister_netdev(dev_at1700);
+       cleanup_card(dev_at1700);
+       free_netdev(dev_at1700);
+}
+module_init(at1700_module_init);
+module_exit(at1700_module_exit);
+#endif /* MODULE */
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/fujitsu/eth16i.c b/drivers/net/ethernet/fujitsu/eth16i.c
new file mode 100644 (file)
index 0000000..12d28e9
--- /dev/null
@@ -0,0 +1,1484 @@
+/* eth16i.c An ICL EtherTeam 16i and 32 EISA ethernet driver for Linux
+
+   Written 1994-1999 by Mika Kuoppala
+
+   Copyright (C) 1994-1999 by Mika Kuoppala
+   Based on skeleton.c and heavily on at1700.c by Donald Becker
+
+   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 miku@iki.fi
+
+   This driver supports following cards :
+       - ICL EtherTeam 16i
+       - ICL EtherTeam 32 EISA
+         (Uses true 32 bit transfers rather than 16i compatibility mode)
+
+   Example Module usage:
+        insmod eth16i.o io=0x2a0 mediatype=bnc
+
+       mediatype can be one of the following: bnc,tp,dix,auto,eprom
+
+       'auto' will try to autoprobe mediatype.
+       'eprom' will use whatever type defined in eprom.
+
+   I have benchmarked driver with PII/300Mhz as a ftp client
+   and 486/33Mhz as a ftp server. Top speed was 1128.37 kilobytes/sec.
+
+   Sources:
+     - skeleton.c  a sample network driver core for linux,
+       written by Donald Becker <becker@scyld.com>
+     - at1700.c a driver for Allied Telesis AT1700, written
+       by Donald Becker.
+     - e16iSRV.asm a Netware 3.X Server Driver for ICL EtherTeam16i
+       written by Markku Viima
+     - The Fujitsu MB86965 databook.
+
+   Author thanks following persons due to their valueble assistance:
+        Markku Viima (ICL)
+       Ari Valve (ICL)
+       Donald Becker
+       Kurt Huwig <kurt@huwig.de>
+
+   Revision history:
+
+   Version     Date            Description
+
+   0.01         15.12-94        Initial version (card detection)
+   0.02         23.01-95        Interrupt is now hooked correctly
+   0.03         01.02-95        Rewrote initialization part
+   0.04         07.02-95        Base skeleton done...
+                                Made a few changes to signature checking
+                                to make it a bit reliable.
+                                - fixed bug in tx_buf mapping
+                                - fixed bug in initialization (DLC_EN
+                                  wasn't enabled when initialization
+                                  was done.)
+   0.05         08.02-95        If there were more than one packet to send,
+                                transmit was jammed due to invalid
+                                register write...now fixed
+   0.06         19.02-95        Rewrote interrupt handling
+   0.07         13.04-95        Wrote EEPROM read routines
+                                Card configuration now set according to
+                                data read from EEPROM
+   0.08         23.06-95        Wrote part that tries to probe used interface
+                                port if AUTO is selected
+
+   0.09         01.09-95        Added module support
+
+   0.10         04.09-95        Fixed receive packet allocation to work
+                                with kernels > 1.3.x
+
+   0.20                20.09-95        Added support for EtherTeam32 EISA
+
+   0.21         17.10-95        Removed the unnecessary extern
+                               init_etherdev() declaration. Some
+                               other cleanups.
+
+   0.22                22.02-96        Receive buffer was not flushed
+                               correctly when faulty packet was
+                               received. Now fixed.
+
+   0.23                26.02-96        Made resetting the adapter
+                               more reliable.
+
+   0.24                27.02-96        Rewrote faulty packet handling in eth16i_rx
+
+   0.25                22.05-96        kfree() was missing from cleanup_module.
+
+   0.26                11.06-96        Sometimes card was not found by
+                               check_signature(). Now made more reliable.
+
+   0.27                23.06-96        Oops. 16 consecutive collisions halted
+                               adapter. Now will try to retransmit
+                               MAX_COL_16 times before finally giving up.
+
+   0.28                28.10-97        Added dev_id parameter (NULL) for free_irq
+
+   0.29         29.10-97        Multiple card support for module users
+
+   0.30         30.10-97        Fixed irq allocation bug.
+                                (request_irq moved from probe to open)
+
+   0.30a        21.08-98        Card detection made more relaxed. Driver
+                                had problems with some TCP/IP-PROM boots
+                               to find the card. Suggested by
+                               Kurt Huwig <kurt@huwig.de>
+
+   0.31         28.08-98        Media interface port can now be selected
+                                with module parameters or kernel
+                               boot parameters.
+
+   0.32         31.08-98        IRQ was never freed if open/close
+                                pair wasn't called. Now fixed.
+
+   0.33         10.09-98        When eth16i_open() was called after
+                                eth16i_close() chip never recovered.
+                               Now more shallow reset is made on
+                               close.
+
+   0.34         29.06-99       Fixed one bad #ifdef.
+                               Changed ioaddr -> io for consistency
+
+   0.35         01.07-99        transmit,-receive bytes were never
+                                updated in stats.
+
+   Bugs:
+       In some cases the media interface autoprobing code doesn't find
+       the correct interface type. In this case you can
+       manually choose the interface type in DOS with E16IC.EXE which is
+       configuration software for EtherTeam16i and EtherTeam32 cards.
+       This is also true for IRQ setting. You cannot use module
+       parameter to configure IRQ of the card (yet).
+
+   To do:
+       - Real multicast support
+       - Rewrite the media interface autoprobing code. Its _horrible_ !
+       - Possibly merge all the MB86965 specific code to external
+         module for use by eth16.c and Donald's at1700.c
+       - IRQ configuration with module parameter. I will do
+         this when i will get enough info about setting
+         irq without configuration utility.
+*/
+
+static char *version =
+    "eth16i.c: v0.35 01-Jul-1999 Mika Kuoppala (miku@iki.fi)\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/spinlock.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/bitops.h>
+#include <linux/jiffies.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/dma.h>
+
+
+
+/* Few macros */
+#define BITSET(ioaddr, bnum)   ((outb(((inb(ioaddr)) | (bnum)), ioaddr)))
+#define BITCLR(ioaddr, bnum)   ((outb(((inb(ioaddr)) & (~(bnum))), ioaddr)))
+
+/* This is the I/O address space for Etherteam 16i adapter. */
+#define ETH16I_IO_EXTENT       32
+
+/* Ticks before deciding that transmit has timed out */
+#define TX_TIMEOUT             (400*HZ/1000)
+
+/* Maximum loop count when receiving packets */
+#define MAX_RX_LOOP            20
+
+/* Some interrupt masks */
+#define ETH16I_INTR_ON        0xef8a       /* Higher is receive mask */
+#define ETH16I_INTR_OFF               0x0000
+
+/* Buffers header status byte meanings */
+#define PKT_GOOD               BIT(5)
+#define PKT_GOOD_RMT           BIT(4)
+#define PKT_SHORT              BIT(3)
+#define PKT_ALIGN_ERR          BIT(2)
+#define PKT_CRC_ERR            BIT(1)
+#define PKT_RX_BUF_OVERFLOW    BIT(0)
+
+/* Transmit status register (DLCR0) */
+#define TX_STATUS_REG          0
+#define TX_DONE                BIT(7)
+#define NET_BUSY               BIT(6)
+#define TX_PKT_RCD             BIT(5)
+#define CR_LOST                BIT(4)
+#define TX_JABBER_ERR         BIT(3)
+#define COLLISION              BIT(2)
+#define COLLISIONS_16          BIT(1)
+
+/* Receive status register (DLCR1) */
+#define RX_STATUS_REG          1
+#define RX_PKT                 BIT(7)  /* Packet received */
+#define BUS_RD_ERR             BIT(6)
+#define SHORT_PKT_ERR          BIT(3)
+#define ALIGN_ERR              BIT(2)
+#define CRC_ERR                BIT(1)
+#define RX_BUF_OVERFLOW        BIT(0)
+
+/* Transmit Interrupt Enable Register (DLCR2) */
+#define TX_INTR_REG            2
+#define TX_INTR_DONE           BIT(7)
+#define TX_INTR_COL            BIT(2)
+#define TX_INTR_16_COL         BIT(1)
+
+/* Receive Interrupt Enable Register (DLCR3) */
+#define RX_INTR_REG            3
+#define RX_INTR_RECEIVE        BIT(7)
+#define RX_INTR_SHORT_PKT      BIT(3)
+#define RX_INTR_CRC_ERR        BIT(1)
+#define RX_INTR_BUF_OVERFLOW   BIT(0)
+
+/* Transmit Mode Register (DLCR4) */
+#define TRANSMIT_MODE_REG      4
+#define LOOPBACK_CONTROL       BIT(1)
+#define CONTROL_OUTPUT         BIT(2)
+
+/* Receive Mode Register (DLCR5) */
+#define RECEIVE_MODE_REG       5
+#define RX_BUFFER_EMPTY        BIT(6)
+#define ACCEPT_BAD_PACKETS     BIT(5)
+#define RECEIVE_SHORT_ADDR     BIT(4)
+#define ACCEPT_SHORT_PACKETS   BIT(3)
+#define REMOTE_RESET           BIT(2)
+
+#define ADDRESS_FILTER_MODE    BIT(1) | BIT(0)
+#define REJECT_ALL             0
+#define ACCEPT_ALL             3
+#define MODE_1                 1            /* NODE ID, BC, MC, 2-24th bit */
+#define MODE_2                 2            /* NODE ID, BC, MC, Hash Table */
+
+/* Configuration Register 0 (DLCR6) */
+#define CONFIG_REG_0           6
+#define DLC_EN                 BIT(7)
+#define SRAM_CYCLE_TIME_100NS  BIT(6)
+#define SYSTEM_BUS_WIDTH_8     BIT(5)       /* 1 = 8bit, 0 = 16bit */
+#define BUFFER_WIDTH_8         BIT(4)       /* 1 = 8bit, 0 = 16bit */
+#define TBS1                   BIT(3)
+#define TBS0                   BIT(2)
+#define SRAM_BS1               BIT(1)       /* 00=8kb,  01=16kb  */
+#define SRAM_BS0               BIT(0)       /* 10=32kb, 11=64kb  */
+
+#ifndef ETH16I_TX_BUF_SIZE                   /* 0 = 2kb, 1 = 4kb  */
+#define ETH16I_TX_BUF_SIZE     3             /* 2 = 8kb, 3 = 16kb */
+#endif
+#define TX_BUF_1x2048          0
+#define TX_BUF_2x2048          1
+#define TX_BUF_2x4098          2
+#define TX_BUF_2x8192          3
+
+/* Configuration Register 1 (DLCR7) */
+#define CONFIG_REG_1           7
+#define POWERUP                BIT(5)
+
+/* Transmit start register */
+#define TRANSMIT_START_REG     10
+#define TRANSMIT_START_RB      2
+#define TX_START               BIT(7)       /* Rest of register bit indicate*/
+                                            /* number of packets in tx buffer*/
+/* Node ID registers (DLCR8-13) */
+#define NODE_ID_0              8
+#define NODE_ID_RB             0
+
+/* Hash Table registers (HT8-15) */
+#define HASH_TABLE_0           8
+#define HASH_TABLE_RB          1
+
+/* Buffer memory ports */
+#define BUFFER_MEM_PORT_LB     8
+#define DATAPORT               BUFFER_MEM_PORT_LB
+#define BUFFER_MEM_PORT_HB     9
+
+/* 16 Collision control register (BMPR11) */
+#define COL_16_REG             11
+#define HALT_ON_16             0x00
+#define RETRANS_AND_HALT_ON_16 0x02
+
+/* Maximum number of attempts to send after 16 concecutive collisions */
+#define MAX_COL_16            10
+
+/* DMA Burst and Transceiver Mode Register (BMPR13) */
+#define TRANSCEIVER_MODE_REG   13
+#define TRANSCEIVER_MODE_RB    2
+#define IO_BASE_UNLOCK        BIT(7)
+#define LOWER_SQUELCH_TRESH    BIT(6)
+#define LINK_TEST_DISABLE      BIT(5)
+#define AUI_SELECT             BIT(4)
+#define DIS_AUTO_PORT_SEL      BIT(3)
+
+/* Filter Self Receive Register (BMPR14)  */
+#define FILTER_SELF_RX_REG     14
+#define SKIP_RX_PACKET         BIT(2)
+#define FILTER_SELF_RECEIVE    BIT(0)
+
+/* EEPROM Control Register (BMPR 16) */
+#define EEPROM_CTRL_REG        16
+
+/* EEPROM Data Register (BMPR 17) */
+#define EEPROM_DATA_REG        17
+
+/* NMC93CSx6 EEPROM Control Bits */
+#define CS_0                   0x00
+#define CS_1                   0x20
+#define SK_0                   0x00
+#define SK_1                   0x40
+#define DI_0                   0x00
+#define DI_1                   0x80
+
+/* NMC93CSx6 EEPROM Instructions */
+#define EEPROM_READ            0x80
+
+/* NMC93CSx6 EEPROM Addresses */
+#define E_NODEID_0             0x02
+#define E_NODEID_1             0x03
+#define E_NODEID_2             0x04
+#define E_PORT_SELECT          0x14
+  #define E_PORT_BNC           0x00
+  #define E_PORT_DIX           0x01
+  #define E_PORT_TP            0x02
+  #define E_PORT_AUTO          0x03
+  #define E_PORT_FROM_EPROM    0x04
+#define E_PRODUCT_CFG          0x30
+
+
+/* Macro to slow down io between EEPROM clock transitions */
+#define eeprom_slow_io() do { int _i = 40; while(--_i > 0) { inb(0x80); }}while(0)
+
+/* Jumperless Configuration Register (BMPR19) */
+#define JUMPERLESS_CONFIG      19
+
+/* ID ROM registers, writing to them also resets some parts of chip */
+#define ID_ROM_0               24
+#define ID_ROM_7               31
+#define RESET                  ID_ROM_0
+
+/* This is the I/O address list to be probed when seeking the card */
+static unsigned int eth16i_portlist[] __initdata = {
+       0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0
+};
+
+static unsigned int eth32i_portlist[] __initdata = {
+       0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000,
+       0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0
+};
+
+/* This is the Interrupt lookup table for Eth16i card */
+static unsigned int eth16i_irqmap[] __initdata = { 9, 10, 5, 15, 0 };
+#define NUM_OF_ISA_IRQS    4
+
+/* This is the Interrupt lookup table for Eth32i card */
+static unsigned int eth32i_irqmap[] __initdata = { 3, 5, 7, 9, 10, 11, 12, 15, 0 };
+#define EISA_IRQ_REG   0xc89
+#define NUM_OF_EISA_IRQS   8
+
+static unsigned int eth16i_tx_buf_map[] = { 2048, 2048, 4096, 8192 };
+
+/* Use 0 for production, 1 for verification, >2 for debug */
+#ifndef ETH16I_DEBUG
+#define ETH16I_DEBUG 0
+#endif
+static unsigned int eth16i_debug = ETH16I_DEBUG;
+
+/* Information for each board */
+
+struct eth16i_local {
+       unsigned char     tx_started;
+       unsigned char     tx_buf_busy;
+       unsigned short    tx_queue;  /* Number of packets in transmit buffer */
+       unsigned short    tx_queue_len;
+       unsigned int      tx_buf_size;
+       unsigned long     open_time;
+       unsigned long     tx_buffered_packets;
+       unsigned long     tx_buffered_bytes;
+       unsigned long     col_16;
+       spinlock_t        lock;
+};
+
+/* Function prototypes */
+
+static int     eth16i_probe1(struct net_device *dev, int ioaddr);
+static int     eth16i_check_signature(int ioaddr);
+static int     eth16i_probe_port(int ioaddr);
+static void    eth16i_set_port(int ioaddr, int porttype);
+static int     eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l);
+static int     eth16i_receive_probe_packet(int ioaddr);
+static int     eth16i_get_irq(int ioaddr);
+static int     eth16i_read_eeprom(int ioaddr, int offset);
+static int     eth16i_read_eeprom_word(int ioaddr);
+static void    eth16i_eeprom_cmd(int ioaddr, unsigned char command);
+static int     eth16i_open(struct net_device *dev);
+static int     eth16i_close(struct net_device *dev);
+static netdev_tx_t eth16i_tx(struct sk_buff *skb, struct net_device *dev);
+static void    eth16i_rx(struct net_device *dev);
+static void    eth16i_timeout(struct net_device *dev);
+static irqreturn_t eth16i_interrupt(int irq, void *dev_id);
+static void    eth16i_reset(struct net_device *dev);
+static void    eth16i_timeout(struct net_device *dev);
+static void    eth16i_skip_packet(struct net_device *dev);
+static void    eth16i_multicast(struct net_device *dev);
+static void    eth16i_select_regbank(unsigned char regbank, int ioaddr);
+static void    eth16i_initialize(struct net_device *dev, int boot);
+
+#if 0
+static int     eth16i_set_irq(struct net_device *dev);
+#endif
+
+#ifdef MODULE
+static ushort  eth16i_parse_mediatype(const char* s);
+#endif
+
+static char cardname[] __initdata = "ICL EtherTeam 16i/32";
+
+static int __init do_eth16i_probe(struct net_device *dev)
+{
+       int i;
+       int ioaddr;
+       int base_addr = dev->base_addr;
+
+       if(eth16i_debug > 4)
+               printk(KERN_DEBUG "Probing started for %s\n", cardname);
+
+       if(base_addr > 0x1ff)           /* Check only single location */
+               return eth16i_probe1(dev, base_addr);
+       else if(base_addr != 0)         /* Don't probe at all */
+               return -ENXIO;
+
+       /* Seek card from the ISA io address space */
+       for(i = 0; (ioaddr = eth16i_portlist[i]) ; i++)
+               if(eth16i_probe1(dev, ioaddr) == 0)
+                       return 0;
+
+       /* Seek card from the EISA io address space */
+       for(i = 0; (ioaddr = eth32i_portlist[i]) ; i++)
+               if(eth16i_probe1(dev, ioaddr) == 0)
+                       return 0;
+
+       return -ENODEV;
+}
+
+#ifndef MODULE
+struct net_device * __init eth16i_probe(int unit)
+{
+       struct net_device *dev = alloc_etherdev(sizeof(struct eth16i_local));
+       int err;
+
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       sprintf(dev->name, "eth%d", unit);
+       netdev_boot_setup_check(dev);
+
+       err = do_eth16i_probe(dev);
+       if (err)
+               goto out;
+       return dev;
+out:
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+#endif
+
+static const struct net_device_ops eth16i_netdev_ops = {
+       .ndo_open               = eth16i_open,
+       .ndo_stop               = eth16i_close,
+       .ndo_start_xmit         = eth16i_tx,
+       .ndo_set_multicast_list = eth16i_multicast,
+       .ndo_tx_timeout         = eth16i_timeout,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
+static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
+{
+       struct eth16i_local *lp = netdev_priv(dev);
+       static unsigned version_printed;
+       int retval;
+
+       /* Let's grab the region */
+       if (!request_region(ioaddr, ETH16I_IO_EXTENT, cardname))
+               return -EBUSY;
+
+       /*
+         The MB86985 chip has on register which holds information in which
+         io address the chip lies. First read this register and compare
+         it to our current io address and if match then this could
+         be our chip.
+         */
+
+       if(ioaddr < 0x1000) {
+               if(eth16i_portlist[(inb(ioaddr + JUMPERLESS_CONFIG) & 0x07)]
+                  != ioaddr) {
+                       retval = -ENODEV;
+                       goto out;
+               }
+       }
+
+       /* Now we will go a bit deeper and try to find the chip's signature */
+
+       if(eth16i_check_signature(ioaddr) != 0) {
+               retval = -ENODEV;
+               goto out;
+       }
+
+       /*
+          Now it seems that we have found a ethernet chip in this particular
+          ioaddr. The MB86985 chip has this feature, that when you read a
+          certain register it will increase it's io base address to next
+          configurable slot. Now when we have found the chip, first thing is
+          to make sure that the chip's ioaddr will hold still here.
+          */
+
+       eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
+       outb(0x00, ioaddr + TRANSCEIVER_MODE_REG);
+
+       outb(0x00, ioaddr + RESET);             /* Reset some parts of chip */
+       BITSET(ioaddr + CONFIG_REG_0, BIT(7));  /* Disable the data link */
+
+       if( (eth16i_debug & version_printed++) == 0)
+               printk(KERN_INFO "%s", version);
+
+       dev->base_addr = ioaddr;
+       dev->irq = eth16i_get_irq(ioaddr);
+
+       /* Try to obtain interrupt vector */
+
+       if ((retval = request_irq(dev->irq, (void *)&eth16i_interrupt, 0, cardname, dev))) {
+               printk(KERN_WARNING "%s at %#3x, but is unusable due to conflicting IRQ %d.\n",
+                      cardname, ioaddr, dev->irq);
+               goto out;
+       }
+
+       printk(KERN_INFO "%s: %s at %#3x, IRQ %d, ",
+              dev->name, cardname, ioaddr, dev->irq);
+
+
+       /* Now we will have to lock the chip's io address */
+       eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
+       outb(0x38, ioaddr + TRANSCEIVER_MODE_REG);
+
+       eth16i_initialize(dev, 1); /* Initialize rest of the chip's registers */
+
+       /* Now let's same some energy by shutting down the chip ;) */
+       BITCLR(ioaddr + CONFIG_REG_1, POWERUP);
+
+       /* Initialize the device structure */
+       dev->netdev_ops         = &eth16i_netdev_ops;
+       dev->watchdog_timeo     = TX_TIMEOUT;
+       spin_lock_init(&lp->lock);
+
+       retval = register_netdev(dev);
+       if (retval)
+               goto out1;
+       return 0;
+out1:
+       free_irq(dev->irq, dev);
+out:
+       release_region(ioaddr, ETH16I_IO_EXTENT);
+       return retval;
+}
+
+
+static void eth16i_initialize(struct net_device *dev, int boot)
+{
+       int ioaddr = dev->base_addr;
+       int i, node_w = 0;
+       unsigned char node_byte = 0;
+
+       /* Setup station address */
+       eth16i_select_regbank(NODE_ID_RB, ioaddr);
+       for(i = 0 ; i < 3 ; i++) {
+               unsigned short node_val = eth16i_read_eeprom(ioaddr, E_NODEID_0 + i);
+               ((unsigned short *)dev->dev_addr)[i] = ntohs(node_val);
+       }
+
+       for(i = 0; i < 6; i++) {
+               outb( ((unsigned char *)dev->dev_addr)[i], ioaddr + NODE_ID_0 + i);
+               if(boot) {
+                       printk("%02x", inb(ioaddr + NODE_ID_0 + i));
+                       if(i != 5)
+                               printk(":");
+               }
+       }
+
+       /* Now we will set multicast addresses to accept none */
+       eth16i_select_regbank(HASH_TABLE_RB, ioaddr);
+       for(i = 0; i < 8; i++)
+               outb(0x00, ioaddr + HASH_TABLE_0 + i);
+
+       /*
+         Now let's disable the transmitter and receiver, set the buffer ram
+         cycle time, bus width and buffer data path width. Also we shall
+         set transmit buffer size and total buffer size.
+         */
+
+       eth16i_select_regbank(2, ioaddr);
+
+       node_byte = 0;
+       node_w = eth16i_read_eeprom(ioaddr, E_PRODUCT_CFG);
+
+       if( (node_w & 0xFF00) == 0x0800)
+               node_byte |= BUFFER_WIDTH_8;
+
+       node_byte |= SRAM_BS1;
+
+       if( (node_w & 0x00FF) == 64)
+               node_byte |= SRAM_BS0;
+
+       node_byte |= DLC_EN | SRAM_CYCLE_TIME_100NS | (ETH16I_TX_BUF_SIZE << 2);
+
+       outb(node_byte, ioaddr + CONFIG_REG_0);
+
+       /* We shall halt the transmitting, if 16 collisions are detected */
+       outb(HALT_ON_16, ioaddr + COL_16_REG);
+
+#ifdef MODULE
+       /* if_port already set by init_module() */
+#else
+       dev->if_port = (dev->mem_start < E_PORT_FROM_EPROM) ?
+               dev->mem_start : E_PORT_FROM_EPROM;
+#endif
+
+       /* Set interface port type */
+       if(boot) {
+               static const char * const porttype[] = {
+                       "BNC", "DIX", "TP", "AUTO", "FROM_EPROM"
+               };
+
+               switch(dev->if_port)
+               {
+
+               case E_PORT_FROM_EPROM:
+                       dev->if_port = eth16i_read_eeprom(ioaddr, E_PORT_SELECT);
+                       break;
+
+               case E_PORT_AUTO:
+                       dev->if_port = eth16i_probe_port(ioaddr);
+                       break;
+
+               case E_PORT_BNC:
+               case E_PORT_TP:
+               case E_PORT_DIX:
+                       break;
+               }
+
+               printk(" %s interface.\n", porttype[dev->if_port]);
+
+               eth16i_set_port(ioaddr, dev->if_port);
+       }
+
+       /* Set Receive Mode to normal operation */
+       outb(MODE_2, ioaddr + RECEIVE_MODE_REG);
+}
+
+static int eth16i_probe_port(int ioaddr)
+{
+       int i;
+       int retcode;
+       unsigned char dummy_packet[64];
+
+       /* Powerup the chip */
+       outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
+
+       BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+
+       eth16i_select_regbank(NODE_ID_RB, ioaddr);
+
+       for(i = 0; i < 6; i++) {
+               dummy_packet[i] = inb(ioaddr + NODE_ID_0 + i);
+               dummy_packet[i+6] = inb(ioaddr + NODE_ID_0 + i);
+       }
+
+       dummy_packet[12] = 0x00;
+       dummy_packet[13] = 0x04;
+       memset(dummy_packet + 14, 0, sizeof(dummy_packet) - 14);
+
+       eth16i_select_regbank(2, ioaddr);
+
+       for(i = 0; i < 3; i++) {
+               BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+               BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
+               eth16i_set_port(ioaddr, i);
+
+               if(eth16i_debug > 1)
+                       printk(KERN_DEBUG "Set port number %d\n", i);
+
+               retcode = eth16i_send_probe_packet(ioaddr, dummy_packet, 64);
+               if(retcode == 0) {
+                       retcode = eth16i_receive_probe_packet(ioaddr);
+                       if(retcode != -1) {
+                               if(eth16i_debug > 1)
+                                       printk(KERN_DEBUG "Eth16i interface port found at %d\n", i);
+                               return i;
+                       }
+               }
+               else {
+                       if(eth16i_debug > 1)
+                               printk(KERN_DEBUG "TRANSMIT_DONE timeout when probing interface port\n");
+               }
+       }
+
+       if( eth16i_debug > 1)
+               printk(KERN_DEBUG "Using default port\n");
+
+       return E_PORT_BNC;
+}
+
+static void eth16i_set_port(int ioaddr, int porttype)
+{
+       unsigned short temp = 0;
+
+       eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr);
+       outb(LOOPBACK_CONTROL, ioaddr + TRANSMIT_MODE_REG);
+
+       temp |= DIS_AUTO_PORT_SEL;
+
+       switch(porttype) {
+
+       case E_PORT_BNC :
+               temp |= AUI_SELECT;
+               break;
+
+       case E_PORT_TP :
+               break;
+
+       case E_PORT_DIX :
+               temp |= AUI_SELECT;
+               BITSET(ioaddr + TRANSMIT_MODE_REG, CONTROL_OUTPUT);
+               break;
+       }
+
+       outb(temp, ioaddr + TRANSCEIVER_MODE_REG);
+
+       if(eth16i_debug > 1) {
+               printk(KERN_DEBUG "TRANSMIT_MODE_REG = %x\n", inb(ioaddr + TRANSMIT_MODE_REG));
+               printk(KERN_DEBUG "TRANSCEIVER_MODE_REG = %x\n",
+                      inb(ioaddr+TRANSCEIVER_MODE_REG));
+       }
+}
+
+static int eth16i_send_probe_packet(int ioaddr, unsigned char *b, int l)
+{
+       unsigned long starttime;
+
+       outb(0xff, ioaddr + TX_STATUS_REG);
+
+       outw(l, ioaddr + DATAPORT);
+       outsw(ioaddr + DATAPORT, (unsigned short *)b, (l + 1) >> 1);
+
+       starttime = jiffies;
+       outb(TX_START | 1, ioaddr + TRANSMIT_START_REG);
+
+       while( (inb(ioaddr + TX_STATUS_REG) & 0x80) == 0) {
+               if( time_after(jiffies, starttime + TX_TIMEOUT)) {
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+static int eth16i_receive_probe_packet(int ioaddr)
+{
+       unsigned long starttime;
+
+       starttime = jiffies;
+
+       while((inb(ioaddr + TX_STATUS_REG) & 0x20) == 0) {
+               if( time_after(jiffies, starttime + TX_TIMEOUT)) {
+
+                       if(eth16i_debug > 1)
+                               printk(KERN_DEBUG "Timeout occurred waiting transmit packet received\n");
+                       starttime = jiffies;
+                       while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) {
+                               if( time_after(jiffies, starttime + TX_TIMEOUT)) {
+                                       if(eth16i_debug > 1)
+                                               printk(KERN_DEBUG "Timeout occurred waiting receive packet\n");
+                                       return -1;
+                               }
+                       }
+
+                       if(eth16i_debug > 1)
+                               printk(KERN_DEBUG "RECEIVE_PACKET\n");
+                       return 0; /* Found receive packet */
+               }
+       }
+
+       if(eth16i_debug > 1) {
+               printk(KERN_DEBUG "TRANSMIT_PACKET_RECEIVED %x\n", inb(ioaddr + TX_STATUS_REG));
+               printk(KERN_DEBUG "RX_STATUS_REG = %x\n", inb(ioaddr + RX_STATUS_REG));
+       }
+
+       return 0; /* Return success */
+}
+
+#if 0
+static int eth16i_set_irq(struct net_device* dev)
+{
+       const int ioaddr = dev->base_addr;
+       const int irq = dev->irq;
+       int i = 0;
+
+       if(ioaddr < 0x1000) {
+               while(eth16i_irqmap[i] && eth16i_irqmap[i] != irq)
+                       i++;
+
+               if(i < NUM_OF_ISA_IRQS) {
+                       u8 cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
+                       cbyte = (cbyte & 0x3F) | (i << 6);
+                       outb(cbyte, ioaddr + JUMPERLESS_CONFIG);
+                       return 0;
+               }
+       }
+       else {
+               printk(KERN_NOTICE "%s: EISA Interrupt cannot be set. Use EISA Configuration utility.\n", dev->name);
+       }
+
+       return -1;
+
+}
+#endif
+
+static int __init eth16i_get_irq(int ioaddr)
+{
+       unsigned char cbyte;
+
+       if( ioaddr < 0x1000) {
+               cbyte = inb(ioaddr + JUMPERLESS_CONFIG);
+               return eth16i_irqmap[((cbyte & 0xC0) >> 6)];
+       } else {  /* Oh..the card is EISA so method getting IRQ different */
+               unsigned short index = 0;
+               cbyte = inb(ioaddr + EISA_IRQ_REG);
+               while( (cbyte & 0x01) == 0) {
+                       cbyte = cbyte >> 1;
+                       index++;
+               }
+               return eth32i_irqmap[index];
+       }
+}
+
+static int __init eth16i_check_signature(int ioaddr)
+{
+       int i;
+       unsigned char creg[4] = { 0 };
+
+       for(i = 0; i < 4 ; i++) {
+
+               creg[i] = inb(ioaddr + TRANSMIT_MODE_REG + i);
+
+               if(eth16i_debug > 1)
+                       printk("eth16i: read signature byte %x at %x\n",
+                              creg[i],
+                              ioaddr + TRANSMIT_MODE_REG + i);
+       }
+
+       creg[0] &= 0x0F;      /* Mask collision cnr */
+       creg[2] &= 0x7F;      /* Mask DCLEN bit */
+
+#if 0
+       /*
+          This was removed because the card was sometimes left to state
+          from which it couldn't be find anymore. If there is need
+          to more strict check still this have to be fixed.
+          */
+       if( ! ((creg[0] == 0x06) && (creg[1] == 0x41)) ) {
+               if(creg[1] != 0x42)
+                       return -1;
+       }
+#endif
+
+       if( !((creg[2] == 0x36) && (creg[3] == 0xE0)) ) {
+               creg[2] &= 0x40;
+               creg[3] &= 0x03;
+
+               if( !((creg[2] == 0x40) && (creg[3] == 0x00)) )
+                       return -1;
+       }
+
+       if(eth16i_read_eeprom(ioaddr, E_NODEID_0) != 0)
+               return -1;
+
+       if((eth16i_read_eeprom(ioaddr, E_NODEID_1) & 0xFF00) != 0x4B00)
+               return -1;
+
+       return 0;
+}
+
+static int eth16i_read_eeprom(int ioaddr, int offset)
+{
+       int data = 0;
+
+       eth16i_eeprom_cmd(ioaddr, EEPROM_READ | offset);
+       outb(CS_1, ioaddr + EEPROM_CTRL_REG);
+       data = eth16i_read_eeprom_word(ioaddr);
+       outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
+
+       return data;
+}
+
+static int eth16i_read_eeprom_word(int ioaddr)
+{
+       int i;
+       int data = 0;
+
+       for(i = 16; i > 0; i--) {
+               outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
+               eeprom_slow_io();
+               outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
+               eeprom_slow_io();
+               data = (data << 1) |
+                       ((inb(ioaddr + EEPROM_DATA_REG) & DI_1) ? 1 : 0);
+
+               eeprom_slow_io();
+       }
+
+       return data;
+}
+
+static void eth16i_eeprom_cmd(int ioaddr, unsigned char command)
+{
+       int i;
+
+       outb(CS_0 | SK_0, ioaddr + EEPROM_CTRL_REG);
+       outb(DI_0, ioaddr + EEPROM_DATA_REG);
+       outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
+       outb(DI_1, ioaddr + EEPROM_DATA_REG);
+       outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
+
+       for(i = 7; i >= 0; i--) {
+               short cmd = ( (command & (1 << i)) ? DI_1 : DI_0 );
+               outb(cmd, ioaddr + EEPROM_DATA_REG);
+               outb(CS_1 | SK_0, ioaddr + EEPROM_CTRL_REG);
+               eeprom_slow_io();
+               outb(CS_1 | SK_1, ioaddr + EEPROM_CTRL_REG);
+               eeprom_slow_io();
+       }
+}
+
+static int eth16i_open(struct net_device *dev)
+{
+       struct eth16i_local *lp = netdev_priv(dev);
+       int ioaddr = dev->base_addr;
+
+       /* Powerup the chip */
+       outb(0xc0 | POWERUP, ioaddr + CONFIG_REG_1);
+
+       /* Initialize the chip */
+       eth16i_initialize(dev, 0);
+
+       /* Set the transmit buffer size */
+       lp->tx_buf_size = eth16i_tx_buf_map[ETH16I_TX_BUF_SIZE & 0x03];
+
+       if(eth16i_debug > 0)
+               printk(KERN_DEBUG "%s: transmit buffer size %d\n",
+                      dev->name, lp->tx_buf_size);
+
+       /* Now enable Transmitter and Receiver sections */
+       BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
+
+       /* Now switch to register bank 2, for run time operation */
+       eth16i_select_regbank(2, ioaddr);
+
+       lp->open_time = jiffies;
+       lp->tx_started = 0;
+       lp->tx_queue = 0;
+       lp->tx_queue_len = 0;
+
+       /* Turn on interrupts*/
+       outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+
+       netif_start_queue(dev);
+       return 0;
+}
+
+static int eth16i_close(struct net_device *dev)
+{
+       struct eth16i_local *lp = netdev_priv(dev);
+       int ioaddr = dev->base_addr;
+
+       eth16i_reset(dev);
+
+       /* Turn off interrupts*/
+       outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
+
+       netif_stop_queue(dev);
+
+       lp->open_time = 0;
+
+       /* Disable transmit and receive */
+       BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+
+       /* Reset the chip */
+       /* outb(0xff, ioaddr + RESET); */
+       /* outw(0xffff, ioaddr + TX_STATUS_REG);    */
+
+       outb(0x00, ioaddr + CONFIG_REG_1);
+
+       return 0;
+}
+
+static void eth16i_timeout(struct net_device *dev)
+{
+       struct eth16i_local *lp = netdev_priv(dev);
+       int ioaddr = dev->base_addr;
+       /*
+          If we get here, some higher level has decided that
+          we are broken. There should really be a "kick me"
+          function call instead.
+          */
+
+       outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
+       printk(KERN_WARNING "%s: transmit timed out with status %04x, %s ?\n",
+              dev->name,
+       inw(ioaddr + TX_STATUS_REG),  (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ?
+                      "IRQ conflict" : "network cable problem");
+
+       dev->trans_start = jiffies; /* prevent tx timeout */
+
+       /* Let's dump all registers */
+       if(eth16i_debug > 0) {
+               printk(KERN_DEBUG "%s: timeout: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
+                      dev->name, inb(ioaddr + 0),
+                      inb(ioaddr + 1), inb(ioaddr + 2),
+                      inb(ioaddr + 3), inb(ioaddr + 4),
+                      inb(ioaddr + 5),
+                      inb(ioaddr + 6), inb(ioaddr + 7));
+
+               printk(KERN_DEBUG "%s: transmit start reg: %02x. collision reg %02x\n",
+                      dev->name, inb(ioaddr + TRANSMIT_START_REG),
+                      inb(ioaddr + COL_16_REG));
+                       printk(KERN_DEBUG "lp->tx_queue = %d\n", lp->tx_queue);
+               printk(KERN_DEBUG "lp->tx_queue_len = %d\n", lp->tx_queue_len);
+               printk(KERN_DEBUG "lp->tx_started = %d\n", lp->tx_started);
+       }
+       dev->stats.tx_errors++;
+       eth16i_reset(dev);
+       dev->trans_start = jiffies; /* prevent tx timeout */
+       outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+       netif_wake_queue(dev);
+}
+
+static netdev_tx_t eth16i_tx(struct sk_buff *skb, struct net_device *dev)
+{
+       struct eth16i_local *lp = netdev_priv(dev);
+       int ioaddr = dev->base_addr;
+       int status = 0;
+       ushort length = skb->len;
+       unsigned char *buf;
+       unsigned long flags;
+
+       if (length < ETH_ZLEN) {
+               if (skb_padto(skb, ETH_ZLEN))
+                       return NETDEV_TX_OK;
+               length = ETH_ZLEN;
+       }
+       buf = skb->data;
+
+       netif_stop_queue(dev);
+
+       /* Turn off TX interrupts */
+       outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
+
+       /* We would be better doing the disable_irq tricks the 3c509 does,
+          that would make this suck a lot less */
+
+       spin_lock_irqsave(&lp->lock, flags);
+
+       if( (length + 2) > (lp->tx_buf_size - lp->tx_queue_len)) {
+               if(eth16i_debug > 0)
+                       printk(KERN_WARNING "%s: Transmit buffer full.\n", dev->name);
+       }
+       else {
+               outw(length, ioaddr + DATAPORT);
+
+               if( ioaddr < 0x1000 )
+                       outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+               else {
+                       unsigned char frag = length % 4;
+                       outsl(ioaddr + DATAPORT, buf, length >> 2);
+                       if( frag != 0 ) {
+                               outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
+                               if( frag == 3 )
+                                       outsw(ioaddr + DATAPORT,
+                                             (buf + (length & 0xFFFC) + 2), 1);
+                       }
+               }
+               lp->tx_buffered_packets++;
+               lp->tx_buffered_bytes = length;
+               lp->tx_queue++;
+               lp->tx_queue_len += length + 2;
+       }
+       lp->tx_buf_busy = 0;
+
+       if(lp->tx_started == 0) {
+               /* If the transmitter is idle..always trigger a transmit */
+               outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
+               lp->tx_queue = 0;
+               lp->tx_queue_len = 0;
+               lp->tx_started = 1;
+               netif_wake_queue(dev);
+       }
+       else if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
+               /* There is still more room for one more packet in tx buffer */
+               netif_wake_queue(dev);
+       }
+
+       spin_unlock_irqrestore(&lp->lock, flags);
+
+       outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+       /* Turn TX interrupts back on */
+       /* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */
+       status = 0;
+       dev_kfree_skb(skb);
+       return NETDEV_TX_OK;
+}
+
+static void eth16i_rx(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr;
+       int boguscount = MAX_RX_LOOP;
+
+       /* Loop until all packets have been read */
+       while( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) {
+
+               /* Read status byte from receive buffer */
+               ushort status = inw(ioaddr + DATAPORT);
+
+               /* Get the size of the packet from receive buffer */
+               ushort pkt_len = inw(ioaddr + DATAPORT);
+
+               if(eth16i_debug > 4)
+                       printk(KERN_DEBUG "%s: Receiving packet mode %02x status %04x.\n",
+                              dev->name,
+                              inb(ioaddr + RECEIVE_MODE_REG), status);
+
+               if( !(status & PKT_GOOD) ) {
+                       dev->stats.rx_errors++;
+
+                       if( (pkt_len < ETH_ZLEN) || (pkt_len > ETH_FRAME_LEN) ) {
+                               dev->stats.rx_length_errors++;
+                               eth16i_reset(dev);
+                               return;
+                       }
+                       else {
+                               eth16i_skip_packet(dev);
+                               dev->stats.rx_dropped++;
+                       }
+               }
+               else {   /* Ok so now we should have a good packet */
+                       struct sk_buff *skb;
+
+                       skb = dev_alloc_skb(pkt_len + 3);
+                       if( skb == NULL ) {
+                               printk(KERN_WARNING "%s: Could'n allocate memory for packet (len %d)\n",
+                                      dev->name, pkt_len);
+                               eth16i_skip_packet(dev);
+                               dev->stats.rx_dropped++;
+                               break;
+                       }
+
+                       skb_reserve(skb,2);
+
+                       /*
+                          Now let's get the packet out of buffer.
+                          size is (pkt_len + 1) >> 1, cause we are now reading words
+                          and it have to be even aligned.
+                          */
+
+                       if(ioaddr < 0x1000)
+                               insw(ioaddr + DATAPORT, skb_put(skb, pkt_len),
+                                    (pkt_len + 1) >> 1);
+                       else {
+                               unsigned char *buf = skb_put(skb, pkt_len);
+                               unsigned char frag = pkt_len % 4;
+
+                               insl(ioaddr + DATAPORT, buf, pkt_len >> 2);
+
+                               if(frag != 0) {
+                                       unsigned short rest[2];
+                                       rest[0] = inw( ioaddr + DATAPORT );
+                                       if(frag == 3)
+                                               rest[1] = inw( ioaddr + DATAPORT );
+
+                                       memcpy(buf + (pkt_len & 0xfffc), (char *)rest, frag);
+                               }
+                       }
+
+                       skb->protocol=eth_type_trans(skb, dev);
+
+                       if( eth16i_debug > 5 ) {
+                               int i;
+                               printk(KERN_DEBUG "%s: Received packet of length %d.\n",
+                                      dev->name, pkt_len);
+                               for(i = 0; i < 14; i++)
+                                       printk(KERN_DEBUG " %02x", skb->data[i]);
+                               printk(KERN_DEBUG ".\n");
+                       }
+                       netif_rx(skb);
+                       dev->stats.rx_packets++;
+                       dev->stats.rx_bytes += pkt_len;
+
+               } /* else */
+
+               if(--boguscount <= 0)
+                       break;
+
+       } /* while */
+}
+
+static irqreturn_t eth16i_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev = dev_id;
+       struct eth16i_local *lp;
+       int ioaddr = 0, status;
+       int handled = 0;
+
+       ioaddr = dev->base_addr;
+       lp = netdev_priv(dev);
+
+       /* Turn off all interrupts from adapter */
+       outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
+
+       /* eth16i_tx won't be called */
+       spin_lock(&lp->lock);
+
+       status = inw(ioaddr + TX_STATUS_REG);      /* Get the status */
+       outw(status, ioaddr + TX_STATUS_REG);      /* Clear status bits */
+
+       if (status)
+               handled = 1;
+
+       if(eth16i_debug > 3)
+               printk(KERN_DEBUG "%s: Interrupt with status %04x.\n", dev->name, status);
+
+       if( status & 0x7f00 ) {
+
+               dev->stats.rx_errors++;
+
+               if(status & (BUS_RD_ERR << 8) )
+                       printk(KERN_WARNING "%s: Bus read error.\n",dev->name);
+               if(status & (SHORT_PKT_ERR << 8) )   dev->stats.rx_length_errors++;
+               if(status & (ALIGN_ERR << 8) )       dev->stats.rx_frame_errors++;
+               if(status & (CRC_ERR << 8) )        dev->stats.rx_crc_errors++;
+               if(status & (RX_BUF_OVERFLOW << 8) ) dev->stats.rx_over_errors++;
+       }
+       if( status & 0x001a) {
+
+               dev->stats.tx_errors++;
+
+               if(status & CR_LOST) dev->stats.tx_carrier_errors++;
+               if(status & TX_JABBER_ERR) dev->stats.tx_window_errors++;
+
+#if 0
+               if(status & COLLISION) {
+                       dev->stats.collisions +=
+                               ((inb(ioaddr+TRANSMIT_MODE_REG) & 0xF0) >> 4);
+               }
+#endif
+               if(status & COLLISIONS_16) {
+                       if(lp->col_16 < MAX_COL_16) {
+                               lp->col_16++;
+                               dev->stats.collisions++;
+                               /* Resume transmitting, skip failed packet */
+                               outb(0x02, ioaddr + COL_16_REG);
+                       }
+                       else {
+                               printk(KERN_WARNING "%s: bailing out due to many consecutive 16-in-a-row collisions. Network cable problem?\n", dev->name);
+                       }
+               }
+       }
+
+       if( status & 0x00ff ) {          /* Let's check the transmit status reg */
+
+               if(status & TX_DONE) {         /* The transmit has been done */
+                       dev->stats.tx_packets = lp->tx_buffered_packets;
+                       dev->stats.tx_bytes += lp->tx_buffered_bytes;
+                       lp->col_16 = 0;
+
+                       if(lp->tx_queue) {           /* Is there still packets ? */
+                               /* There was packet(s) so start transmitting and write also
+                                  how many packets there is to be sended */
+                               outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
+                               lp->tx_queue = 0;
+                               lp->tx_queue_len = 0;
+                               lp->tx_started = 1;
+                       }
+                       else {
+                               lp->tx_started = 0;
+                       }
+                       netif_wake_queue(dev);
+               }
+       }
+
+       if( ( status & 0x8000 ) ||
+           ( (inb(ioaddr + RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 0) ) {
+               eth16i_rx(dev);  /* We have packet in receive buffer */
+       }
+
+       /* Turn interrupts back on */
+       outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+
+       if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
+               /* There is still more room for one more packet in tx buffer */
+               netif_wake_queue(dev);
+       }
+
+       spin_unlock(&lp->lock);
+
+       return IRQ_RETVAL(handled);
+}
+
+static void eth16i_skip_packet(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr;
+
+       inw(ioaddr + DATAPORT);
+       inw(ioaddr + DATAPORT);
+       inw(ioaddr + DATAPORT);
+
+       outb(SKIP_RX_PACKET, ioaddr + FILTER_SELF_RX_REG);
+       while( inb( ioaddr + FILTER_SELF_RX_REG ) != 0);
+}
+
+static void eth16i_reset(struct net_device *dev)
+{
+       struct eth16i_local *lp = netdev_priv(dev);
+       int ioaddr = dev->base_addr;
+
+       if(eth16i_debug > 1)
+               printk(KERN_DEBUG "%s: Resetting device.\n", dev->name);
+
+       BITSET(ioaddr + CONFIG_REG_0, DLC_EN);
+       outw(0xffff, ioaddr + TX_STATUS_REG);
+       eth16i_select_regbank(2, ioaddr);
+
+       lp->tx_started = 0;
+       lp->tx_buf_busy = 0;
+       lp->tx_queue = 0;
+       lp->tx_queue_len = 0;
+       BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
+}
+
+static void eth16i_multicast(struct net_device *dev)
+{
+       int ioaddr = dev->base_addr;
+
+       if (!netdev_mc_empty(dev) || dev->flags&(IFF_ALLMULTI|IFF_PROMISC))
+       {
+               outb(3, ioaddr + RECEIVE_MODE_REG);
+       } else {
+               outb(2, ioaddr + RECEIVE_MODE_REG);
+       }
+}
+
+static void eth16i_select_regbank(unsigned char banknbr, int ioaddr)
+{
+       unsigned char data;
+
+       data = inb(ioaddr + CONFIG_REG_1);
+       outb( ((data & 0xF3) | ( (banknbr & 0x03) << 2)), ioaddr + CONFIG_REG_1);
+}
+
+#ifdef MODULE
+
+static ushort eth16i_parse_mediatype(const char* s)
+{
+       if(!s)
+               return E_PORT_FROM_EPROM;
+
+        if (!strncmp(s, "bnc", 3))
+               return E_PORT_BNC;
+        else if (!strncmp(s, "tp", 2))
+                return E_PORT_TP;
+        else if (!strncmp(s, "dix", 3))
+                return E_PORT_DIX;
+        else if (!strncmp(s, "auto", 4))
+               return E_PORT_AUTO;
+       else
+               return E_PORT_FROM_EPROM;
+}
+
+#define MAX_ETH16I_CARDS 4  /* Max number of Eth16i cards per module */
+
+static struct net_device *dev_eth16i[MAX_ETH16I_CARDS];
+static int io[MAX_ETH16I_CARDS];
+#if 0
+static int irq[MAX_ETH16I_CARDS];
+#endif
+static char* mediatype[MAX_ETH16I_CARDS];
+static int debug = -1;
+
+MODULE_AUTHOR("Mika Kuoppala <miku@iki.fi>");
+MODULE_DESCRIPTION("ICL EtherTeam 16i/32 driver");
+MODULE_LICENSE("GPL");
+
+
+module_param_array(io, int, NULL, 0);
+MODULE_PARM_DESC(io, "eth16i I/O base address(es)");
+
+#if 0
+module_param_array(irq, int, NULL, 0);
+MODULE_PARM_DESC(irq, "eth16i interrupt request number");
+#endif
+
+module_param_array(mediatype, charp, NULL, 0);
+MODULE_PARM_DESC(mediatype, "eth16i media type of interface(s) (bnc,tp,dix,auto,eprom)");
+
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "eth16i debug level (0-6)");
+
+int __init init_module(void)
+{
+       int this_dev, found = 0;
+       struct net_device *dev;
+
+       for (this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++) {
+               dev = alloc_etherdev(sizeof(struct eth16i_local));
+               if (!dev)
+                       break;
+
+               dev->base_addr = io[this_dev];
+
+               if(debug != -1)
+                       eth16i_debug = debug;
+
+               if(eth16i_debug > 1)
+                       printk(KERN_NOTICE "eth16i(%d): interface type %s\n", this_dev, mediatype[this_dev] ? mediatype[this_dev] : "none" );
+
+               dev->if_port = eth16i_parse_mediatype(mediatype[this_dev]);
+
+               if(io[this_dev] == 0) {
+                       if (this_dev != 0) { /* Only autoprobe 1st one */
+                               free_netdev(dev);
+                               break;
+                       }
+
+                       printk(KERN_NOTICE "eth16i.c: Presently autoprobing (not recommended) for a single card.\n");
+               }
+
+               if (do_eth16i_probe(dev) == 0) {
+                       dev_eth16i[found++] = dev;
+                       continue;
+               }
+               printk(KERN_WARNING "eth16i.c No Eth16i card found (i/o = 0x%x).\n",
+                      io[this_dev]);
+               free_netdev(dev);
+               break;
+       }
+       if (found)
+               return 0;
+       return -ENXIO;
+}
+
+void __exit cleanup_module(void)
+{
+       int this_dev;
+
+       for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++) {
+               struct net_device *dev = dev_eth16i[this_dev];
+
+               if (netdev_priv(dev)) {
+                       unregister_netdev(dev);
+                       free_irq(dev->irq, dev);
+                       release_region(dev->base_addr, ETH16I_IO_EXTENT);
+                       free_netdev(dev);
+               }
+       }
+}
+#endif /* MODULE */
diff --git a/drivers/net/ethernet/fujitsu/fmvj18x_cs.c b/drivers/net/ethernet/fujitsu/fmvj18x_cs.c
new file mode 100644 (file)
index 0000000..723815e
--- /dev/null
@@ -0,0 +1,1187 @@
+/*======================================================================
+    fmvj18x_cs.c 2.8 2002/03/23
+
+    A fmvj18x (and its compatibles) PCMCIA client driver
+
+    Contributed by Shingo Fujimoto, shingo@flab.fujitsu.co.jp
+
+    TDK LAK-CD021 and CONTEC C-NET(PC)C support added by 
+    Nobuhiro Katayama, kata-n@po.iijnet.or.jp
+
+    The PCMCIA client code is based on code written by David Hinds.
+    Network code is based on the "FMV-18x driver" by Yutaka TAMIYA
+    but is actually largely Donald Becker's AT1700 driver, which
+    carries the following attribution:
+
+    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
+   
+======================================================================*/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#define DRV_NAME       "fmvj18x_cs"
+#define DRV_VERSION    "2.9"
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <linux/ethtool.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/ioport.h>
+#include <linux/crc32.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ciscode.h>
+#include <pcmcia/ds.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+/*====================================================================*/
+
+/* Module parameters */
+
+MODULE_DESCRIPTION("fmvj18x and compatible PCMCIA ethernet driver");
+MODULE_LICENSE("GPL");
+
+#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
+
+/* SRAM configuration */
+/* 0:4KB*2 TX buffer   else:8KB*2 TX buffer */
+INT_MODULE_PARM(sram_config, 0);
+
+
+/*====================================================================*/
+/*
+    PCMCIA event handlers
+ */
+static int fmvj18x_config(struct pcmcia_device *link);
+static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id);
+static int fmvj18x_setup_mfc(struct pcmcia_device *link);
+static void fmvj18x_release(struct pcmcia_device *link);
+static void fmvj18x_detach(struct pcmcia_device *p_dev);
+
+/*
+    LAN controller(MBH86960A) specific routines
+ */
+static int fjn_config(struct net_device *dev, struct ifmap *map);
+static int fjn_open(struct net_device *dev);
+static int fjn_close(struct net_device *dev);
+static netdev_tx_t fjn_start_xmit(struct sk_buff *skb,
+                                       struct net_device *dev);
+static irqreturn_t fjn_interrupt(int irq, void *dev_id);
+static void fjn_rx(struct net_device *dev);
+static void fjn_reset(struct net_device *dev);
+static void set_rx_mode(struct net_device *dev);
+static void fjn_tx_timeout(struct net_device *dev);
+static const struct ethtool_ops netdev_ethtool_ops;
+
+/*
+    card type
+ */
+typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN, 
+              XXX10304, NEC, KME
+} cardtype_t;
+
+/*
+    driver specific data structure
+*/
+typedef struct local_info_t {
+       struct pcmcia_device    *p_dev;
+    long open_time;
+    uint tx_started:1;
+    uint tx_queue;
+    u_short tx_queue_len;
+    cardtype_t cardtype;
+    u_short sent;
+    u_char __iomem *base;
+} local_info_t;
+
+#define MC_FILTERBREAK 64
+
+/*====================================================================*/
+/* 
+    ioport offset from the base address 
+ */
+#define TX_STATUS               0 /* transmit status register */
+#define RX_STATUS               1 /* receive status register */
+#define TX_INTR                 2 /* transmit interrupt mask register */
+#define RX_INTR                 3 /* receive interrupt mask register */
+#define TX_MODE                 4 /* transmit mode register */
+#define RX_MODE                 5 /* receive mode register */
+#define CONFIG_0                6 /* configuration register 0 */
+#define CONFIG_1                7 /* configuration register 1 */
+
+#define NODE_ID                 8 /* node ID register            (bank 0) */
+#define MAR_ADR                 8 /* multicast address registers (bank 1) */
+
+#define DATAPORT                8 /* buffer mem port registers   (bank 2) */
+#define TX_START               10 /* transmit start register */
+#define COL_CTRL               11 /* 16 collision control register */
+#define BMPR12                 12 /* reserved */
+#define BMPR13                 13 /* reserved */
+#define RX_SKIP                14 /* skip received packet register */
+
+#define LAN_CTRL               16 /* LAN card control register */
+
+#define MAC_ID               0x1a /* hardware address */
+#define UNGERMANN_MAC_ID     0x18 /* UNGERMANN-BASS hardware address */
+
+/* 
+    control bits 
+ */
+#define ENA_TMT_OK           0x80
+#define ENA_TMT_REC          0x20
+#define ENA_COL              0x04
+#define ENA_16_COL           0x02
+#define ENA_TBUS_ERR         0x01
+
+#define ENA_PKT_RDY          0x80
+#define ENA_BUS_ERR          0x40
+#define ENA_LEN_ERR          0x08
+#define ENA_ALG_ERR          0x04
+#define ENA_CRC_ERR          0x02
+#define ENA_OVR_FLO          0x01
+
+/* flags */
+#define F_TMT_RDY            0x80 /* can accept new packet */
+#define F_NET_BSY            0x40 /* carrier is detected */
+#define F_TMT_OK             0x20 /* send packet successfully */
+#define F_SRT_PKT            0x10 /* short packet error */
+#define F_COL_ERR            0x04 /* collision error */
+#define F_16_COL             0x02 /* 16 collision error */
+#define F_TBUS_ERR           0x01 /* bus read error */
+
+#define F_PKT_RDY            0x80 /* packet(s) in buffer */
+#define F_BUS_ERR            0x40 /* bus read error */
+#define F_LEN_ERR            0x08 /* short packet */
+#define F_ALG_ERR            0x04 /* frame error */
+#define F_CRC_ERR            0x02 /* CRC error */
+#define F_OVR_FLO            0x01 /* overflow error */
+
+#define F_BUF_EMP            0x40 /* receive buffer is empty */
+
+#define F_SKP_PKT            0x05 /* drop packet in buffer */
+
+/* default bitmaps */
+#define D_TX_INTR  ( ENA_TMT_OK )
+#define D_RX_INTR  ( ENA_PKT_RDY | ENA_LEN_ERR \
+                  | ENA_ALG_ERR | ENA_CRC_ERR | ENA_OVR_FLO )
+#define TX_STAT_M  ( F_TMT_RDY )
+#define RX_STAT_M  ( F_PKT_RDY | F_LEN_ERR \
+                   | F_ALG_ERR | F_CRC_ERR | F_OVR_FLO )
+
+/* commands */
+#define D_TX_MODE            0x06 /* no tests, detect carrier */
+#define ID_MATCHED           0x02 /* (RX_MODE) */
+#define RECV_ALL             0x03 /* (RX_MODE) */
+#define CONFIG0_DFL          0x5a /* 16bit bus, 4K x 2 Tx queues */
+#define CONFIG0_DFL_1        0x5e /* 16bit bus, 8K x 2 Tx queues */
+#define CONFIG0_RST          0xda /* Data Link Controller off (CONFIG_0) */
+#define CONFIG0_RST_1        0xde /* Data Link Controller off (CONFIG_0) */
+#define BANK_0               0xa0 /* bank 0 (CONFIG_1) */
+#define BANK_1               0xa4 /* bank 1 (CONFIG_1) */
+#define BANK_2               0xa8 /* bank 2 (CONFIG_1) */
+#define CHIP_OFF             0x80 /* contrl chip power off (CONFIG_1) */
+#define DO_TX                0x80 /* do transmit packet */
+#define SEND_PKT             0x81 /* send a packet */
+#define AUTO_MODE            0x07 /* Auto skip packet on 16 col detected */
+#define MANU_MODE            0x03 /* Stop and skip packet on 16 col */
+#define TDK_AUTO_MODE        0x47 /* Auto skip packet on 16 col detected */
+#define TDK_MANU_MODE        0x43 /* Stop and skip packet on 16 col */
+#define INTR_OFF             0x0d /* LAN controller ignores interrupts */
+#define INTR_ON              0x1d /* LAN controller will catch interrupts */
+
+#define TX_TIMEOUT             ((400*HZ)/1000)
+
+#define BANK_0U              0x20 /* bank 0 (CONFIG_1) */
+#define BANK_1U              0x24 /* bank 1 (CONFIG_1) */
+#define BANK_2U              0x28 /* bank 2 (CONFIG_1) */
+
+static const struct net_device_ops fjn_netdev_ops = {
+       .ndo_open               = fjn_open,
+       .ndo_stop               = fjn_close,
+       .ndo_start_xmit         = fjn_start_xmit,
+       .ndo_tx_timeout         = fjn_tx_timeout,
+       .ndo_set_config         = fjn_config,
+       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
+static int fmvj18x_probe(struct pcmcia_device *link)
+{
+    local_info_t *lp;
+    struct net_device *dev;
+
+    dev_dbg(&link->dev, "fmvj18x_attach()\n");
+
+    /* Make up a FMVJ18x specific data structure */
+    dev = alloc_etherdev(sizeof(local_info_t));
+    if (!dev)
+       return -ENOMEM;
+    lp = netdev_priv(dev);
+    link->priv = dev;
+    lp->p_dev = link;
+    lp->base = NULL;
+
+    /* The io structure describes IO port mapping */
+    link->resource[0]->end = 32;
+    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+
+    /* General socket configuration */
+    link->config_flags |= CONF_ENABLE_IRQ;
+
+    dev->netdev_ops = &fjn_netdev_ops;
+    dev->watchdog_timeo = TX_TIMEOUT;
+
+    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
+
+    return fmvj18x_config(link);
+} /* fmvj18x_attach */
+
+/*====================================================================*/
+
+static void fmvj18x_detach(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+
+    dev_dbg(&link->dev, "fmvj18x_detach\n");
+
+    unregister_netdev(dev);
+
+    fmvj18x_release(link);
+
+    free_netdev(dev);
+} /* fmvj18x_detach */
+
+/*====================================================================*/
+
+static int mfc_try_io_port(struct pcmcia_device *link)
+{
+    int i, ret;
+    static const unsigned int serial_base[5] =
+       { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+
+    for (i = 0; i < 5; i++) {
+       link->resource[1]->start = serial_base[i];
+       link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
+       if (link->resource[1]->start == 0) {
+           link->resource[1]->end = 0;
+           pr_notice("out of resource for serial\n");
+       }
+       ret = pcmcia_request_io(link);
+       if (ret == 0)
+               return ret;
+    }
+    return ret;
+}
+
+static int ungermann_try_io_port(struct pcmcia_device *link)
+{
+    int ret;
+    unsigned int ioaddr;
+    /*
+       Ungermann-Bass Access/CARD accepts 0x300,0x320,0x340,0x360
+       0x380,0x3c0 only for ioport.
+    */
+    for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) {
+       link->resource[0]->start = ioaddr;
+       ret = pcmcia_request_io(link);
+       if (ret == 0) {
+           /* calculate ConfigIndex value */
+           link->config_index =
+               ((link->resource[0]->start & 0x0f0) >> 3) | 0x22;
+           return ret;
+       }
+    }
+    return ret;        /* RequestIO failed */
+}
+
+static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
+{
+       return 0; /* strange, but that's what the code did already before... */
+}
+
+static int fmvj18x_config(struct pcmcia_device *link)
+{
+    struct net_device *dev = link->priv;
+    local_info_t *lp = netdev_priv(dev);
+    int i, ret;
+    unsigned int ioaddr;
+    cardtype_t cardtype;
+    char *card_name = "unknown";
+    u8 *buf;
+    size_t len;
+    u_char buggybuf[32];
+
+    dev_dbg(&link->dev, "fmvj18x_config\n");
+
+    link->io_lines = 5;
+
+    len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf);
+    kfree(buf);
+
+    if (len) {
+       /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */
+       ret = pcmcia_loop_config(link, fmvj18x_ioprobe, NULL);
+       if (ret != 0)
+               goto failed;
+
+       switch (link->manf_id) {
+       case MANFID_TDK:
+           cardtype = TDK;
+           if (link->card_id == PRODID_TDK_GN3410 ||
+               link->card_id == PRODID_TDK_NP9610 ||
+               link->card_id == PRODID_TDK_MN3200) {
+               /* MultiFunction Card */
+               link->config_base = 0x800;
+               link->config_index = 0x47;
+               link->resource[1]->end = 8;
+           }
+           break;
+       case MANFID_NEC:
+           cardtype = NEC; /* MultiFunction Card */
+           link->config_base = 0x800;
+           link->config_index = 0x47;
+           link->resource[1]->end = 8;
+           break;
+       case MANFID_KME:
+           cardtype = KME; /* MultiFunction Card */
+           link->config_base = 0x800;
+           link->config_index = 0x47;
+           link->resource[1]->end = 8;
+           break;
+       case MANFID_CONTEC:
+           cardtype = CONTEC;
+           break;
+       case MANFID_FUJITSU:
+           if (link->config_base == 0x0fe0)
+               cardtype = MBH10302;
+           else if (link->card_id == PRODID_FUJITSU_MBH10302) 
+                /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302),
+                   but these are MBH10304 based card. */ 
+               cardtype = MBH10304;
+           else if (link->card_id == PRODID_FUJITSU_MBH10304)
+               cardtype = MBH10304;
+           else
+               cardtype = LA501;
+           break;
+       default:
+           cardtype = MBH10304;
+       }
+    } else {
+       /* old type card */
+       switch (link->manf_id) {
+       case MANFID_FUJITSU:
+           if (link->card_id == PRODID_FUJITSU_MBH10304) {
+               cardtype = XXX10304;    /* MBH10304 with buggy CIS */
+               link->config_index = 0x20;
+           } else {
+               cardtype = MBH10302;    /* NextCom NC5310, etc. */
+               link->config_index = 1;
+           }
+           break;
+       case MANFID_UNGERMANN:
+           cardtype = UNGERMANN;
+           break;
+       default:
+           cardtype = MBH10302;
+           link->config_index = 1;
+       }
+    }
+
+    if (link->resource[1]->end != 0) {
+       ret = mfc_try_io_port(link);
+       if (ret != 0) goto failed;
+    } else if (cardtype == UNGERMANN) {
+       ret = ungermann_try_io_port(link);
+       if (ret != 0) goto failed;
+    } else { 
+           ret = pcmcia_request_io(link);
+           if (ret)
+                   goto failed;
+    }
+    ret = pcmcia_request_irq(link, fjn_interrupt);
+    if (ret)
+           goto failed;
+    ret = pcmcia_enable_device(link);
+    if (ret)
+           goto failed;
+
+    dev->irq = link->irq;
+    dev->base_addr = link->resource[0]->start;
+
+    if (resource_size(link->resource[1]) != 0) {
+       ret = fmvj18x_setup_mfc(link);
+       if (ret != 0) goto failed;
+    }
+
+    ioaddr = dev->base_addr;
+
+    /* Reset controller */
+    if (sram_config == 0) 
+       outb(CONFIG0_RST, ioaddr + CONFIG_0);
+    else
+       outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
+
+    /* Power On chip and select bank 0 */
+    if (cardtype == MBH10302)
+       outb(BANK_0, ioaddr + CONFIG_1);
+    else
+       outb(BANK_0U, ioaddr + CONFIG_1);
+    
+    /* Set hardware address */
+    switch (cardtype) {
+    case MBH10304:
+    case TDK:
+    case LA501:
+    case CONTEC:
+    case NEC:
+    case KME:
+       if (cardtype == MBH10304) {
+           card_name = "FMV-J182";
+
+           len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf);
+           if (len < 11) {
+                   kfree(buf);
+                   goto failed;
+           }
+           /* Read MACID from CIS */
+           for (i = 5; i < 11; i++)
+                   dev->dev_addr[i] = buf[i];
+           kfree(buf);
+       } else {
+           if (pcmcia_get_mac_from_cis(link, dev))
+               goto failed;
+           if( cardtype == TDK ) {
+               card_name = "TDK LAK-CD021";
+           } else if( cardtype == LA501 ) {
+               card_name = "LA501";
+           } else if( cardtype == NEC ) {
+               card_name = "PK-UG-J001";
+           } else if( cardtype == KME ) {
+               card_name = "Panasonic";
+           } else {
+               card_name = "C-NET(PC)C";
+           }
+       }
+       break;
+    case UNGERMANN:
+       /* Read MACID from register */
+       for (i = 0; i < 6; i++) 
+           dev->dev_addr[i] = inb(ioaddr + UNGERMANN_MAC_ID + i);
+       card_name = "Access/CARD";
+       break;
+    case XXX10304:
+       /* Read MACID from Buggy CIS */
+       if (fmvj18x_get_hwinfo(link, buggybuf) == -1) {
+           pr_notice("unable to read hardware net address\n");
+           goto failed;
+       }
+       for (i = 0 ; i < 6; i++) {
+           dev->dev_addr[i] = buggybuf[i];
+       }
+       card_name = "FMV-J182";
+       break;
+    case MBH10302:
+    default:
+       /* Read MACID from register */
+       for (i = 0; i < 6; i++) 
+           dev->dev_addr[i] = inb(ioaddr + MAC_ID + i);
+       card_name = "FMV-J181";
+       break;
+    }
+
+    lp->cardtype = cardtype;
+    SET_NETDEV_DEV(dev, &link->dev);
+
+    if (register_netdev(dev) != 0) {
+       pr_notice("register_netdev() failed\n");
+       goto failed;
+    }
+
+    /* print current configuration */
+    netdev_info(dev, "%s, sram %s, port %#3lx, irq %d, hw_addr %pM\n",
+               card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2",
+               dev->base_addr, dev->irq, dev->dev_addr);
+
+    return 0;
+    
+failed:
+    fmvj18x_release(link);
+    return -ENODEV;
+} /* fmvj18x_config */
+/*====================================================================*/
+
+static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
+{
+    u_char __iomem *base;
+    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 -1;
+
+    base = ioremap(link->resource[2]->start, resource_size(link->resource[2]));
+    pcmcia_map_mem_page(link, link->resource[2], 0);
+
+    /*
+     *  MBH10304 CISTPL_FUNCE_LAN_NODE_ID format
+     *  22 0d xx xx xx 04 06 yy yy yy yy yy yy ff
+     *  'xx' is garbage.
+     *  'yy' is MAC address.
+    */ 
+    for (i = 0; i < 0x200; i++) {
+       if (readb(base+i*2) == 0x22) {  
+               if (readb(base+(i-1)*2) == 0xff &&
+                   readb(base+(i+5)*2) == 0x04 &&
+                   readb(base+(i+6)*2) == 0x06 &&
+                   readb(base+(i+13)*2) == 0xff)
+                       break;
+       }
+    }
+
+    if (i != 0x200) {
+       for (j = 0 ; j < 6; j++,i++) {
+           node_id[j] = readb(base+(i+7)*2);
+       }
+    }
+
+    iounmap(base);
+    j = pcmcia_release_window(link, link->resource[2]);
+    return (i != 0x200) ? 0 : -1;
+
+} /* fmvj18x_get_hwinfo */
+/*====================================================================*/
+
+static int fmvj18x_setup_mfc(struct pcmcia_device *link)
+{
+    int i;
+    struct net_device *dev = link->priv;
+    unsigned int ioaddr;
+    local_info_t *lp = netdev_priv(dev);
+
+    /* Allocate a small memory window */
+    link->resource[3]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+    link->resource[3]->start = link->resource[3]->end = 0;
+    i = pcmcia_request_window(link, link->resource[3], 0);
+    if (i != 0)
+       return -1;
+
+    lp->base = ioremap(link->resource[3]->start,
+                      resource_size(link->resource[3]));
+    if (lp->base == NULL) {
+       netdev_notice(dev, "ioremap failed\n");
+       return -1;
+    }
+
+    i = pcmcia_map_mem_page(link, link->resource[3], 0);
+    if (i != 0) {
+       iounmap(lp->base);
+       lp->base = NULL;
+       return -1;
+    }
+    
+    ioaddr = dev->base_addr;
+    writeb(0x47, lp->base+0x800);      /* Config Option Register of LAN */
+    writeb(0x0,  lp->base+0x802);      /* Config and Status Register */
+
+    writeb(ioaddr & 0xff, lp->base+0x80a);       /* I/O Base(Low) of LAN */
+    writeb((ioaddr >> 8) & 0xff, lp->base+0x80c); /* I/O Base(High) of LAN */
+   
+    writeb(0x45, lp->base+0x820);      /* Config Option Register of Modem */
+    writeb(0x8,  lp->base+0x822);      /* Config and Status Register */
+
+    return 0;
+
+}
+/*====================================================================*/
+
+static void fmvj18x_release(struct pcmcia_device *link)
+{
+
+    struct net_device *dev = link->priv;
+    local_info_t *lp = netdev_priv(dev);
+    u_char __iomem *tmp;
+
+    dev_dbg(&link->dev, "fmvj18x_release\n");
+
+    if (lp->base != NULL) {
+       tmp = lp->base;
+       lp->base = NULL;    /* set NULL before iounmap */
+       iounmap(tmp);
+    }
+
+    pcmcia_disable_device(link);
+
+}
+
+static int fmvj18x_suspend(struct pcmcia_device *link)
+{
+       struct net_device *dev = link->priv;
+
+       if (link->open)
+               netif_device_detach(dev);
+
+       return 0;
+}
+
+static int fmvj18x_resume(struct pcmcia_device *link)
+{
+       struct net_device *dev = link->priv;
+
+       if (link->open) {
+               fjn_reset(dev);
+               netif_device_attach(dev);
+       }
+
+       return 0;
+}
+
+/*====================================================================*/
+
+static const struct pcmcia_device_id fmvj18x_ids[] = {
+       PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004),
+       PCMCIA_DEVICE_PROD_ID12("EAGLE Technology", "NE200 ETHERNET LAN MBH10302 04", 0x528c88c4, 0x74f91e59),
+       PCMCIA_DEVICE_PROD_ID12("Eiger Labs,Inc", "EPX-10BT PC Card Ethernet 10BT", 0x53af556e, 0x877f9922),
+       PCMCIA_DEVICE_PROD_ID12("Eiger labs,Inc.", "EPX-10BT PC Card Ethernet 10BT", 0xf47e6c66, 0x877f9922),
+       PCMCIA_DEVICE_PROD_ID12("FUJITSU", "LAN Card(FMV-J182)", 0x6ee5a3d8, 0x5baf31db),
+       PCMCIA_DEVICE_PROD_ID12("FUJITSU", "MBH10308", 0x6ee5a3d8, 0x3f04875e),
+       PCMCIA_DEVICE_PROD_ID12("FUJITSU TOWA", "LA501", 0xb8451188, 0x12939ba2),
+       PCMCIA_DEVICE_PROD_ID12("HITACHI", "HT-4840-11", 0xf4f43949, 0x773910f4),
+       PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310B Ver1.0       ", 0x8cef4d3a, 0x075fc7b6),
+       PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310 Ver1.0        ", 0x8cef4d3a, 0xbccf43e6),
+       PCMCIA_DEVICE_PROD_ID12("RATOC System Inc.", "10BASE_T CARD R280", 0x85c10e17, 0xd9413666),
+       PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CD02x", 0x1eae9475, 0x8fa0ee70),
+       PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CF010", 0x1eae9475, 0x7683bc9a),
+       PCMCIA_DEVICE_PROD_ID1("CONTEC Co.,Ltd.", 0x58d8fee2),
+       PCMCIA_DEVICE_PROD_ID1("PCMCIA LAN MBH10304  ES", 0x2599f454),
+       PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da),
+       PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080),
+       PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
+       PCMCIA_PFC_DEVICE_PROD_ID12(0, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
+       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a),
+       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a),
+       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0e01),
+       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05),
+       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0b05),
+       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101),
+       PCMCIA_DEVICE_NULL,
+};
+MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids);
+
+static struct pcmcia_driver fmvj18x_cs_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "fmvj18x_cs",
+       .probe          = fmvj18x_probe,
+       .remove         = fmvj18x_detach,
+       .id_table       = fmvj18x_ids,
+       .suspend        = fmvj18x_suspend,
+       .resume         = fmvj18x_resume,
+};
+
+static int __init init_fmvj18x_cs(void)
+{
+       return pcmcia_register_driver(&fmvj18x_cs_driver);
+}
+
+static void __exit exit_fmvj18x_cs(void)
+{
+       pcmcia_unregister_driver(&fmvj18x_cs_driver);
+}
+
+module_init(init_fmvj18x_cs);
+module_exit(exit_fmvj18x_cs);
+
+/*====================================================================*/
+
+static irqreturn_t fjn_interrupt(int dummy, void *dev_id)
+{
+    struct net_device *dev = dev_id;
+    local_info_t *lp = netdev_priv(dev);
+    unsigned int ioaddr;
+    unsigned short tx_stat, rx_stat;
+
+    ioaddr = dev->base_addr;
+
+    /* avoid multiple interrupts */
+    outw(0x0000, ioaddr + TX_INTR);
+
+    /* wait for a while */
+    udelay(1);
+
+    /* get status */
+    tx_stat = inb(ioaddr + TX_STATUS);
+    rx_stat = inb(ioaddr + RX_STATUS);
+
+    /* clear status */
+    outb(tx_stat, ioaddr + TX_STATUS);
+    outb(rx_stat, ioaddr + RX_STATUS);
+    
+    pr_debug("%s: interrupt, rx_status %02x.\n", dev->name, rx_stat);
+    pr_debug("               tx_status %02x.\n", tx_stat);
+    
+    if (rx_stat || (inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
+       /* there is packet(s) in rx buffer */
+       fjn_rx(dev);
+    }
+    if (tx_stat & F_TMT_RDY) {
+       dev->stats.tx_packets += lp->sent ;
+        lp->sent = 0 ;
+       if (lp->tx_queue) {
+           outb(DO_TX | lp->tx_queue, ioaddr + TX_START);
+           lp->sent = lp->tx_queue ;
+           lp->tx_queue = 0;
+           lp->tx_queue_len = 0;
+           dev->trans_start = jiffies;
+       } else {
+           lp->tx_started = 0;
+       }
+       netif_wake_queue(dev);
+    }
+    pr_debug("%s: exiting interrupt,\n", dev->name);
+    pr_debug("    tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat);
+
+    outb(D_TX_INTR, ioaddr + TX_INTR);
+    outb(D_RX_INTR, ioaddr + RX_INTR);
+
+    if (lp->base != NULL) {
+       /* Ack interrupt for multifunction card */
+       writeb(0x01, lp->base+0x802);
+       writeb(0x09, lp->base+0x822);
+    }
+
+    return IRQ_HANDLED;
+
+} /* fjn_interrupt */
+
+/*====================================================================*/
+
+static void fjn_tx_timeout(struct net_device *dev)
+{
+    struct local_info_t *lp = netdev_priv(dev);
+    unsigned int ioaddr = dev->base_addr;
+
+    netdev_notice(dev, "transmit timed out with status %04x, %s?\n",
+                 htons(inw(ioaddr + TX_STATUS)),
+                 inb(ioaddr + TX_STATUS) & F_TMT_RDY
+                 ? "IRQ conflict" : "network cable problem");
+    netdev_notice(dev, "timeout registers: %04x %04x %04x "
+                 "%04x %04x %04x %04x %04x.\n",
+                 htons(inw(ioaddr + 0)), htons(inw(ioaddr + 2)),
+                 htons(inw(ioaddr + 4)), htons(inw(ioaddr + 6)),
+                 htons(inw(ioaddr + 8)), htons(inw(ioaddr + 10)),
+                 htons(inw(ioaddr + 12)), htons(inw(ioaddr + 14)));
+    dev->stats.tx_errors++;
+    /* ToDo: We should try to restart the adaptor... */
+    local_irq_disable();
+    fjn_reset(dev);
+
+    lp->tx_started = 0;
+    lp->tx_queue = 0;
+    lp->tx_queue_len = 0;
+    lp->sent = 0;
+    lp->open_time = jiffies;
+    local_irq_enable();
+    netif_wake_queue(dev);
+}
+
+static netdev_tx_t fjn_start_xmit(struct sk_buff *skb,
+                                       struct net_device *dev)
+{
+    struct local_info_t *lp = netdev_priv(dev);
+    unsigned int ioaddr = dev->base_addr;
+    short length = skb->len;
+    
+    if (length < ETH_ZLEN)
+    {
+       if (skb_padto(skb, ETH_ZLEN))
+               return NETDEV_TX_OK;
+       length = ETH_ZLEN;
+    }
+
+    netif_stop_queue(dev);
+
+    {
+       unsigned char *buf = skb->data;
+
+       if (length > ETH_FRAME_LEN) {
+           netdev_notice(dev, "Attempting to send a large packet (%d bytes)\n",
+                         length);
+           return NETDEV_TX_BUSY;
+       }
+
+       netdev_dbg(dev, "Transmitting a packet of length %lu\n",
+                  (unsigned long)skb->len);
+       dev->stats.tx_bytes += skb->len;
+
+       /* Disable both interrupts. */
+       outw(0x0000, ioaddr + TX_INTR);
+
+       /* wait for a while */
+       udelay(1);
+
+       outw(length, ioaddr + DATAPORT);
+       outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+
+       lp->tx_queue++;
+       lp->tx_queue_len += ((length+3) & ~1);
+
+       if (lp->tx_started == 0) {
+           /* If the Tx is idle, always trigger a transmit. */
+           outb(DO_TX | lp->tx_queue, ioaddr + TX_START);
+           lp->sent = lp->tx_queue ;
+           lp->tx_queue = 0;
+           lp->tx_queue_len = 0;
+           lp->tx_started = 1;
+           netif_start_queue(dev);
+       } else {
+           if( sram_config == 0 ) {
+               if (lp->tx_queue_len < (4096 - (ETH_FRAME_LEN +2)) )
+                   /* Yes, there is room for one more packet. */
+                   netif_start_queue(dev);
+           } else {
+               if (lp->tx_queue_len < (8192 - (ETH_FRAME_LEN +2)) && 
+                                               lp->tx_queue < 127 )
+                   /* Yes, there is room for one more packet. */
+                   netif_start_queue(dev);
+           }
+       }
+
+       /* Re-enable interrupts */
+       outb(D_TX_INTR, ioaddr + TX_INTR);
+       outb(D_RX_INTR, ioaddr + RX_INTR);
+    }
+    dev_kfree_skb (skb);
+
+    return NETDEV_TX_OK;
+} /* fjn_start_xmit */
+
+/*====================================================================*/
+
+static void fjn_reset(struct net_device *dev)
+{
+    struct local_info_t *lp = netdev_priv(dev);
+    unsigned int ioaddr = dev->base_addr;
+    int i;
+
+    netdev_dbg(dev, "fjn_reset() called\n");
+
+    /* Reset controller */
+    if( sram_config == 0 ) 
+       outb(CONFIG0_RST, ioaddr + CONFIG_0);
+    else
+       outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
+
+    /* Power On chip and select bank 0 */
+    if (lp->cardtype == MBH10302)
+       outb(BANK_0, ioaddr + CONFIG_1);
+    else
+       outb(BANK_0U, ioaddr + CONFIG_1);
+
+    /* Set Tx modes */
+    outb(D_TX_MODE, ioaddr + TX_MODE);
+    /* set Rx modes */
+    outb(ID_MATCHED, ioaddr + RX_MODE);
+
+    /* Set hardware address */
+    for (i = 0; i < 6; i++) 
+        outb(dev->dev_addr[i], ioaddr + NODE_ID + i);
+
+    /* (re)initialize the multicast table */
+    set_rx_mode(dev);
+
+    /* Switch to bank 2 (runtime mode) */
+    if (lp->cardtype == MBH10302)
+       outb(BANK_2, ioaddr + CONFIG_1);
+    else
+       outb(BANK_2U, ioaddr + CONFIG_1);
+
+    /* set 16col ctrl bits */
+    if( lp->cardtype == TDK || lp->cardtype == CONTEC) 
+        outb(TDK_AUTO_MODE, ioaddr + COL_CTRL);
+    else
+        outb(AUTO_MODE, ioaddr + COL_CTRL);
+
+    /* clear Reserved Regs */
+    outb(0x00, ioaddr + BMPR12);
+    outb(0x00, ioaddr + BMPR13);
+
+    /* reset Skip packet reg. */
+    outb(0x01, ioaddr + RX_SKIP);
+
+    /* Enable Tx and Rx */
+    if( sram_config == 0 )
+       outb(CONFIG0_DFL, ioaddr + CONFIG_0);
+    else
+       outb(CONFIG0_DFL_1, ioaddr + CONFIG_0);
+
+    /* Init receive pointer ? */
+    inw(ioaddr + DATAPORT);
+    inw(ioaddr + DATAPORT);
+
+    /* Clear all status */
+    outb(0xff, ioaddr + TX_STATUS);
+    outb(0xff, ioaddr + RX_STATUS);
+
+    if (lp->cardtype == MBH10302)
+       outb(INTR_OFF, ioaddr + LAN_CTRL);
+
+    /* Turn on Rx interrupts */
+    outb(D_TX_INTR, ioaddr + TX_INTR);
+    outb(D_RX_INTR, ioaddr + RX_INTR);
+
+    /* Turn on interrupts from LAN card controller */
+    if (lp->cardtype == MBH10302)
+       outb(INTR_ON, ioaddr + LAN_CTRL);
+} /* fjn_reset */
+
+/*====================================================================*/
+
+static void fjn_rx(struct net_device *dev)
+{
+    unsigned int ioaddr = dev->base_addr;
+    int boguscount = 10;       /* 5 -> 10: by agy 19940922 */
+
+    pr_debug("%s: in rx_packet(), rx_status %02x.\n",
+         dev->name, inb(ioaddr + RX_STATUS));
+
+    while ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
+       u_short status = inw(ioaddr + DATAPORT);
+
+       netdev_dbg(dev, "Rxing packet mode %02x status %04x.\n",
+                  inb(ioaddr + RX_MODE), status);
+#ifndef final_version
+       if (status == 0) {
+           outb(F_SKP_PKT, ioaddr + RX_SKIP);
+           break;
+       }
+#endif
+       if ((status & 0xF0) != 0x20) {  /* There was an error. */
+           dev->stats.rx_errors++;
+           if (status & F_LEN_ERR) dev->stats.rx_length_errors++;
+           if (status & F_ALG_ERR) dev->stats.rx_frame_errors++;
+           if (status & F_CRC_ERR) dev->stats.rx_crc_errors++;
+           if (status & F_OVR_FLO) dev->stats.rx_over_errors++;
+       } else {
+           u_short pkt_len = inw(ioaddr + DATAPORT);
+           /* Malloc up new buffer. */
+           struct sk_buff *skb;
+
+           if (pkt_len > 1550) {
+               netdev_notice(dev, "The FMV-18x claimed a very large packet, size %d\n",
+                             pkt_len);
+               outb(F_SKP_PKT, ioaddr + RX_SKIP);
+               dev->stats.rx_errors++;
+               break;
+           }
+           skb = dev_alloc_skb(pkt_len+2);
+           if (skb == NULL) {
+               netdev_notice(dev, "Memory squeeze, dropping packet (len %d)\n",
+                             pkt_len);
+               outb(F_SKP_PKT, ioaddr + RX_SKIP);
+               dev->stats.rx_dropped++;
+               break;
+           }
+
+           skb_reserve(skb, 2);
+           insw(ioaddr + DATAPORT, skb_put(skb, pkt_len),
+                (pkt_len + 1) >> 1);
+           skb->protocol = eth_type_trans(skb, dev);
+
+           {
+               int i;
+               pr_debug("%s: Rxed packet of length %d: ",
+                       dev->name, pkt_len);
+               for (i = 0; i < 14; i++)
+                       pr_debug(" %02x", skb->data[i]);
+               pr_debug(".\n");
+           }
+
+           netif_rx(skb);
+           dev->stats.rx_packets++;
+           dev->stats.rx_bytes += pkt_len;
+       }
+       if (--boguscount <= 0)
+           break;
+    }
+
+    /* If any worth-while packets have been received, dev_rint()
+          has done a netif_wake_queue() for us and will work on them
+          when we get to the bottom-half routine. */
+/*
+    if (lp->cardtype != TDK) {
+       int i;
+       for (i = 0; i < 20; i++) {
+           if ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == F_BUF_EMP)
+               break;
+           (void)inw(ioaddr + DATAPORT);  /+ dummy status read +/
+           outb(F_SKP_PKT, ioaddr + RX_SKIP);
+       }
+
+       if (i > 0)
+           pr_debug("%s: Exint Rx packet with mode %02x after "
+                 "%d ticks.\n", dev->name, inb(ioaddr + RX_MODE), i);
+    }
+*/
+} /* fjn_rx */
+
+/*====================================================================*/
+
+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, "PCMCIA 0x%lx", dev->base_addr);
+}
+
+static const struct ethtool_ops netdev_ethtool_ops = {
+       .get_drvinfo            = netdev_get_drvinfo,
+};
+
+static int fjn_config(struct net_device *dev, struct ifmap *map){
+    return 0;
+}
+
+static int fjn_open(struct net_device *dev)
+{
+    struct local_info_t *lp = netdev_priv(dev);
+    struct pcmcia_device *link = lp->p_dev;
+
+    pr_debug("fjn_open('%s').\n", dev->name);
+
+    if (!pcmcia_dev_present(link))
+       return -ENODEV;
+    
+    link->open++;
+    
+    fjn_reset(dev);
+    
+    lp->tx_started = 0;
+    lp->tx_queue = 0;
+    lp->tx_queue_len = 0;
+    lp->open_time = jiffies;
+    netif_start_queue(dev);
+    
+    return 0;
+} /* fjn_open */
+
+/*====================================================================*/
+
+static int fjn_close(struct net_device *dev)
+{
+    struct local_info_t *lp = netdev_priv(dev);
+    struct pcmcia_device *link = lp->p_dev;
+    unsigned int ioaddr = dev->base_addr;
+
+    pr_debug("fjn_close('%s').\n", dev->name);
+
+    lp->open_time = 0;
+    netif_stop_queue(dev);
+
+    /* Set configuration register 0 to disable Tx and Rx. */
+    if( sram_config == 0 ) 
+       outb(CONFIG0_RST ,ioaddr + CONFIG_0);
+    else
+       outb(CONFIG0_RST_1 ,ioaddr + CONFIG_0);
+
+    /* Update the statistics -- ToDo. */
+
+    /* Power-down the chip.  Green, green, green! */
+    outb(CHIP_OFF ,ioaddr + CONFIG_1);
+
+    /* Set the ethernet adaptor disable IRQ */
+    if (lp->cardtype == MBH10302)
+       outb(INTR_OFF, ioaddr + LAN_CTRL);
+
+    link->open--;
+
+    return 0;
+} /* fjn_close */
+
+/*====================================================================*/
+
+/*
+  Set the multicast/promiscuous mode for this adaptor.
+*/
+
+static void set_rx_mode(struct net_device *dev)
+{
+    unsigned int ioaddr = dev->base_addr;
+    u_char mc_filter[8];                /* Multicast hash filter */
+    u_long flags;
+    int i;
+    
+    int saved_bank;
+    int saved_config_0 = inb(ioaddr + CONFIG_0);
+     
+    local_irq_save(flags); 
+
+    /* Disable Tx and Rx */
+    if (sram_config == 0) 
+       outb(CONFIG0_RST, ioaddr + CONFIG_0);
+    else
+       outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
+
+    if (dev->flags & IFF_PROMISC) {
+       memset(mc_filter, 0xff, sizeof(mc_filter));
+       outb(3, ioaddr + RX_MODE);      /* Enable promiscuous mode */
+    } else if (netdev_mc_count(dev) > MC_FILTERBREAK ||
+              (dev->flags & IFF_ALLMULTI)) {
+       /* Too many to filter perfectly -- accept all multicasts. */
+       memset(mc_filter, 0xff, sizeof(mc_filter));
+       outb(2, ioaddr + RX_MODE);      /* Use normal mode. */
+    } else if (netdev_mc_empty(dev)) {
+       memset(mc_filter, 0x00, sizeof(mc_filter));
+       outb(1, ioaddr + RX_MODE);      /* Ignore almost all multicasts. */
+    } else {
+       struct netdev_hw_addr *ha;
+
+       memset(mc_filter, 0, sizeof(mc_filter));
+       netdev_for_each_mc_addr(ha, dev) {
+           unsigned int bit = ether_crc_le(ETH_ALEN, ha->addr) >> 26;
+           mc_filter[bit >> 3] |= (1 << (bit & 7));
+       }
+       outb(2, ioaddr + RX_MODE);      /* Use normal mode. */
+    }
+
+    /* Switch to bank 1 and set the multicast table. */
+    saved_bank = inb(ioaddr + CONFIG_1);
+    outb(0xe4, ioaddr + CONFIG_1);
+
+    for (i = 0; i < 8; i++)
+       outb(mc_filter[i], ioaddr + MAR_ADR + i);
+    outb(saved_bank, ioaddr + CONFIG_1);
+
+    outb(saved_config_0, ioaddr + CONFIG_0);
+
+    local_irq_restore(flags);
+}
index f5a738ff59f57b22ab821e1dfa274d3e0685f7ff..80d291ea672f16af9b31208447e6bfd4c856d7f1 100644 (file)
@@ -21,16 +21,6 @@ menuconfig NET_PCMCIA
 
 if NET_PCMCIA && PCMCIA
 
-config PCMCIA_FMVJ18X
-       tristate "Fujitsu FMV-J18x PCMCIA support"
-       select CRC32
-       help
-         Say Y here if you intend to attach a Fujitsu FMV-J18x or compatible
-         PCMCIA (PC-card) Ethernet card to your computer.
-
-         To compile this driver as a module, choose M here: the module will be
-         called fmvj18x_cs.  If unsure, say N.
-
 config PCMCIA_XIRC2PS
        tristate "Xircom 16-bit PCMCIA support"
        help
index f9c98836d75b5c734999f84ee9377b8eedfa8209..ccf5535e9d3f076397d35996971aa29ab8a8d719 100644 (file)
@@ -3,7 +3,6 @@
 #
 
 # 16-bit client drivers
-obj-$(CONFIG_PCMCIA_FMVJ18X)   += fmvj18x_cs.o
 obj-$(CONFIG_PCMCIA_XIRC2PS)   += xirc2ps_cs.o
 obj-$(CONFIG_ARCNET_COM20020_CS)+= com20020_cs.o
 
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
deleted file mode 100644 (file)
index 723815e..0000000
+++ /dev/null
@@ -1,1187 +0,0 @@
-/*======================================================================
-    fmvj18x_cs.c 2.8 2002/03/23
-
-    A fmvj18x (and its compatibles) PCMCIA client driver
-
-    Contributed by Shingo Fujimoto, shingo@flab.fujitsu.co.jp
-
-    TDK LAK-CD021 and CONTEC C-NET(PC)C support added by 
-    Nobuhiro Katayama, kata-n@po.iijnet.or.jp
-
-    The PCMCIA client code is based on code written by David Hinds.
-    Network code is based on the "FMV-18x driver" by Yutaka TAMIYA
-    but is actually largely Donald Becker's AT1700 driver, which
-    carries the following attribution:
-
-    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
-   
-======================================================================*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#define DRV_NAME       "fmvj18x_cs"
-#define DRV_VERSION    "2.9"
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/in.h>
-#include <linux/delay.h>
-#include <linux/ethtool.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/if_arp.h>
-#include <linux/ioport.h>
-#include <linux/crc32.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ciscode.h>
-#include <pcmcia/ds.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-/*====================================================================*/
-
-/* Module parameters */
-
-MODULE_DESCRIPTION("fmvj18x and compatible PCMCIA ethernet driver");
-MODULE_LICENSE("GPL");
-
-#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
-
-/* SRAM configuration */
-/* 0:4KB*2 TX buffer   else:8KB*2 TX buffer */
-INT_MODULE_PARM(sram_config, 0);
-
-
-/*====================================================================*/
-/*
-    PCMCIA event handlers
- */
-static int fmvj18x_config(struct pcmcia_device *link);
-static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id);
-static int fmvj18x_setup_mfc(struct pcmcia_device *link);
-static void fmvj18x_release(struct pcmcia_device *link);
-static void fmvj18x_detach(struct pcmcia_device *p_dev);
-
-/*
-    LAN controller(MBH86960A) specific routines
- */
-static int fjn_config(struct net_device *dev, struct ifmap *map);
-static int fjn_open(struct net_device *dev);
-static int fjn_close(struct net_device *dev);
-static netdev_tx_t fjn_start_xmit(struct sk_buff *skb,
-                                       struct net_device *dev);
-static irqreturn_t fjn_interrupt(int irq, void *dev_id);
-static void fjn_rx(struct net_device *dev);
-static void fjn_reset(struct net_device *dev);
-static void set_rx_mode(struct net_device *dev);
-static void fjn_tx_timeout(struct net_device *dev);
-static const struct ethtool_ops netdev_ethtool_ops;
-
-/*
-    card type
- */
-typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN, 
-              XXX10304, NEC, KME
-} cardtype_t;
-
-/*
-    driver specific data structure
-*/
-typedef struct local_info_t {
-       struct pcmcia_device    *p_dev;
-    long open_time;
-    uint tx_started:1;
-    uint tx_queue;
-    u_short tx_queue_len;
-    cardtype_t cardtype;
-    u_short sent;
-    u_char __iomem *base;
-} local_info_t;
-
-#define MC_FILTERBREAK 64
-
-/*====================================================================*/
-/* 
-    ioport offset from the base address 
- */
-#define TX_STATUS               0 /* transmit status register */
-#define RX_STATUS               1 /* receive status register */
-#define TX_INTR                 2 /* transmit interrupt mask register */
-#define RX_INTR                 3 /* receive interrupt mask register */
-#define TX_MODE                 4 /* transmit mode register */
-#define RX_MODE                 5 /* receive mode register */
-#define CONFIG_0                6 /* configuration register 0 */
-#define CONFIG_1                7 /* configuration register 1 */
-
-#define NODE_ID                 8 /* node ID register            (bank 0) */
-#define MAR_ADR                 8 /* multicast address registers (bank 1) */
-
-#define DATAPORT                8 /* buffer mem port registers   (bank 2) */
-#define TX_START               10 /* transmit start register */
-#define COL_CTRL               11 /* 16 collision control register */
-#define BMPR12                 12 /* reserved */
-#define BMPR13                 13 /* reserved */
-#define RX_SKIP                14 /* skip received packet register */
-
-#define LAN_CTRL               16 /* LAN card control register */
-
-#define MAC_ID               0x1a /* hardware address */
-#define UNGERMANN_MAC_ID     0x18 /* UNGERMANN-BASS hardware address */
-
-/* 
-    control bits 
- */
-#define ENA_TMT_OK           0x80
-#define ENA_TMT_REC          0x20
-#define ENA_COL              0x04
-#define ENA_16_COL           0x02
-#define ENA_TBUS_ERR         0x01
-
-#define ENA_PKT_RDY          0x80
-#define ENA_BUS_ERR          0x40
-#define ENA_LEN_ERR          0x08
-#define ENA_ALG_ERR          0x04
-#define ENA_CRC_ERR          0x02
-#define ENA_OVR_FLO          0x01
-
-/* flags */
-#define F_TMT_RDY            0x80 /* can accept new packet */
-#define F_NET_BSY            0x40 /* carrier is detected */
-#define F_TMT_OK             0x20 /* send packet successfully */
-#define F_SRT_PKT            0x10 /* short packet error */
-#define F_COL_ERR            0x04 /* collision error */
-#define F_16_COL             0x02 /* 16 collision error */
-#define F_TBUS_ERR           0x01 /* bus read error */
-
-#define F_PKT_RDY            0x80 /* packet(s) in buffer */
-#define F_BUS_ERR            0x40 /* bus read error */
-#define F_LEN_ERR            0x08 /* short packet */
-#define F_ALG_ERR            0x04 /* frame error */
-#define F_CRC_ERR            0x02 /* CRC error */
-#define F_OVR_FLO            0x01 /* overflow error */
-
-#define F_BUF_EMP            0x40 /* receive buffer is empty */
-
-#define F_SKP_PKT            0x05 /* drop packet in buffer */
-
-/* default bitmaps */
-#define D_TX_INTR  ( ENA_TMT_OK )
-#define D_RX_INTR  ( ENA_PKT_RDY | ENA_LEN_ERR \
-                  | ENA_ALG_ERR | ENA_CRC_ERR | ENA_OVR_FLO )
-#define TX_STAT_M  ( F_TMT_RDY )
-#define RX_STAT_M  ( F_PKT_RDY | F_LEN_ERR \
-                   | F_ALG_ERR | F_CRC_ERR | F_OVR_FLO )
-
-/* commands */
-#define D_TX_MODE            0x06 /* no tests, detect carrier */
-#define ID_MATCHED           0x02 /* (RX_MODE) */
-#define RECV_ALL             0x03 /* (RX_MODE) */
-#define CONFIG0_DFL          0x5a /* 16bit bus, 4K x 2 Tx queues */
-#define CONFIG0_DFL_1        0x5e /* 16bit bus, 8K x 2 Tx queues */
-#define CONFIG0_RST          0xda /* Data Link Controller off (CONFIG_0) */
-#define CONFIG0_RST_1        0xde /* Data Link Controller off (CONFIG_0) */
-#define BANK_0               0xa0 /* bank 0 (CONFIG_1) */
-#define BANK_1               0xa4 /* bank 1 (CONFIG_1) */
-#define BANK_2               0xa8 /* bank 2 (CONFIG_1) */
-#define CHIP_OFF             0x80 /* contrl chip power off (CONFIG_1) */
-#define DO_TX                0x80 /* do transmit packet */
-#define SEND_PKT             0x81 /* send a packet */
-#define AUTO_MODE            0x07 /* Auto skip packet on 16 col detected */
-#define MANU_MODE            0x03 /* Stop and skip packet on 16 col */
-#define TDK_AUTO_MODE        0x47 /* Auto skip packet on 16 col detected */
-#define TDK_MANU_MODE        0x43 /* Stop and skip packet on 16 col */
-#define INTR_OFF             0x0d /* LAN controller ignores interrupts */
-#define INTR_ON              0x1d /* LAN controller will catch interrupts */
-
-#define TX_TIMEOUT             ((400*HZ)/1000)
-
-#define BANK_0U              0x20 /* bank 0 (CONFIG_1) */
-#define BANK_1U              0x24 /* bank 1 (CONFIG_1) */
-#define BANK_2U              0x28 /* bank 2 (CONFIG_1) */
-
-static const struct net_device_ops fjn_netdev_ops = {
-       .ndo_open               = fjn_open,
-       .ndo_stop               = fjn_close,
-       .ndo_start_xmit         = fjn_start_xmit,
-       .ndo_tx_timeout         = fjn_tx_timeout,
-       .ndo_set_config         = fjn_config,
-       .ndo_set_multicast_list = set_rx_mode,
-       .ndo_change_mtu         = eth_change_mtu,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_validate_addr      = eth_validate_addr,
-};
-
-static int fmvj18x_probe(struct pcmcia_device *link)
-{
-    local_info_t *lp;
-    struct net_device *dev;
-
-    dev_dbg(&link->dev, "fmvj18x_attach()\n");
-
-    /* Make up a FMVJ18x specific data structure */
-    dev = alloc_etherdev(sizeof(local_info_t));
-    if (!dev)
-       return -ENOMEM;
-    lp = netdev_priv(dev);
-    link->priv = dev;
-    lp->p_dev = link;
-    lp->base = NULL;
-
-    /* The io structure describes IO port mapping */
-    link->resource[0]->end = 32;
-    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-
-    /* General socket configuration */
-    link->config_flags |= CONF_ENABLE_IRQ;
-
-    dev->netdev_ops = &fjn_netdev_ops;
-    dev->watchdog_timeo = TX_TIMEOUT;
-
-    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
-
-    return fmvj18x_config(link);
-} /* fmvj18x_attach */
-
-/*====================================================================*/
-
-static void fmvj18x_detach(struct pcmcia_device *link)
-{
-    struct net_device *dev = link->priv;
-
-    dev_dbg(&link->dev, "fmvj18x_detach\n");
-
-    unregister_netdev(dev);
-
-    fmvj18x_release(link);
-
-    free_netdev(dev);
-} /* fmvj18x_detach */
-
-/*====================================================================*/
-
-static int mfc_try_io_port(struct pcmcia_device *link)
-{
-    int i, ret;
-    static const unsigned int serial_base[5] =
-       { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
-
-    for (i = 0; i < 5; i++) {
-       link->resource[1]->start = serial_base[i];
-       link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
-       if (link->resource[1]->start == 0) {
-           link->resource[1]->end = 0;
-           pr_notice("out of resource for serial\n");
-       }
-       ret = pcmcia_request_io(link);
-       if (ret == 0)
-               return ret;
-    }
-    return ret;
-}
-
-static int ungermann_try_io_port(struct pcmcia_device *link)
-{
-    int ret;
-    unsigned int ioaddr;
-    /*
-       Ungermann-Bass Access/CARD accepts 0x300,0x320,0x340,0x360
-       0x380,0x3c0 only for ioport.
-    */
-    for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) {
-       link->resource[0]->start = ioaddr;
-       ret = pcmcia_request_io(link);
-       if (ret == 0) {
-           /* calculate ConfigIndex value */
-           link->config_index =
-               ((link->resource[0]->start & 0x0f0) >> 3) | 0x22;
-           return ret;
-       }
-    }
-    return ret;        /* RequestIO failed */
-}
-
-static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
-{
-       return 0; /* strange, but that's what the code did already before... */
-}
-
-static int fmvj18x_config(struct pcmcia_device *link)
-{
-    struct net_device *dev = link->priv;
-    local_info_t *lp = netdev_priv(dev);
-    int i, ret;
-    unsigned int ioaddr;
-    cardtype_t cardtype;
-    char *card_name = "unknown";
-    u8 *buf;
-    size_t len;
-    u_char buggybuf[32];
-
-    dev_dbg(&link->dev, "fmvj18x_config\n");
-
-    link->io_lines = 5;
-
-    len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf);
-    kfree(buf);
-
-    if (len) {
-       /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */
-       ret = pcmcia_loop_config(link, fmvj18x_ioprobe, NULL);
-       if (ret != 0)
-               goto failed;
-
-       switch (link->manf_id) {
-       case MANFID_TDK:
-           cardtype = TDK;
-           if (link->card_id == PRODID_TDK_GN3410 ||
-               link->card_id == PRODID_TDK_NP9610 ||
-               link->card_id == PRODID_TDK_MN3200) {
-               /* MultiFunction Card */
-               link->config_base = 0x800;
-               link->config_index = 0x47;
-               link->resource[1]->end = 8;
-           }
-           break;
-       case MANFID_NEC:
-           cardtype = NEC; /* MultiFunction Card */
-           link->config_base = 0x800;
-           link->config_index = 0x47;
-           link->resource[1]->end = 8;
-           break;
-       case MANFID_KME:
-           cardtype = KME; /* MultiFunction Card */
-           link->config_base = 0x800;
-           link->config_index = 0x47;
-           link->resource[1]->end = 8;
-           break;
-       case MANFID_CONTEC:
-           cardtype = CONTEC;
-           break;
-       case MANFID_FUJITSU:
-           if (link->config_base == 0x0fe0)
-               cardtype = MBH10302;
-           else if (link->card_id == PRODID_FUJITSU_MBH10302) 
-                /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302),
-                   but these are MBH10304 based card. */ 
-               cardtype = MBH10304;
-           else if (link->card_id == PRODID_FUJITSU_MBH10304)
-               cardtype = MBH10304;
-           else
-               cardtype = LA501;
-           break;
-       default:
-           cardtype = MBH10304;
-       }
-    } else {
-       /* old type card */
-       switch (link->manf_id) {
-       case MANFID_FUJITSU:
-           if (link->card_id == PRODID_FUJITSU_MBH10304) {
-               cardtype = XXX10304;    /* MBH10304 with buggy CIS */
-               link->config_index = 0x20;
-           } else {
-               cardtype = MBH10302;    /* NextCom NC5310, etc. */
-               link->config_index = 1;
-           }
-           break;
-       case MANFID_UNGERMANN:
-           cardtype = UNGERMANN;
-           break;
-       default:
-           cardtype = MBH10302;
-           link->config_index = 1;
-       }
-    }
-
-    if (link->resource[1]->end != 0) {
-       ret = mfc_try_io_port(link);
-       if (ret != 0) goto failed;
-    } else if (cardtype == UNGERMANN) {
-       ret = ungermann_try_io_port(link);
-       if (ret != 0) goto failed;
-    } else { 
-           ret = pcmcia_request_io(link);
-           if (ret)
-                   goto failed;
-    }
-    ret = pcmcia_request_irq(link, fjn_interrupt);
-    if (ret)
-           goto failed;
-    ret = pcmcia_enable_device(link);
-    if (ret)
-           goto failed;
-
-    dev->irq = link->irq;
-    dev->base_addr = link->resource[0]->start;
-
-    if (resource_size(link->resource[1]) != 0) {
-       ret = fmvj18x_setup_mfc(link);
-       if (ret != 0) goto failed;
-    }
-
-    ioaddr = dev->base_addr;
-
-    /* Reset controller */
-    if (sram_config == 0) 
-       outb(CONFIG0_RST, ioaddr + CONFIG_0);
-    else
-       outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
-
-    /* Power On chip and select bank 0 */
-    if (cardtype == MBH10302)
-       outb(BANK_0, ioaddr + CONFIG_1);
-    else
-       outb(BANK_0U, ioaddr + CONFIG_1);
-    
-    /* Set hardware address */
-    switch (cardtype) {
-    case MBH10304:
-    case TDK:
-    case LA501:
-    case CONTEC:
-    case NEC:
-    case KME:
-       if (cardtype == MBH10304) {
-           card_name = "FMV-J182";
-
-           len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf);
-           if (len < 11) {
-                   kfree(buf);
-                   goto failed;
-           }
-           /* Read MACID from CIS */
-           for (i = 5; i < 11; i++)
-                   dev->dev_addr[i] = buf[i];
-           kfree(buf);
-       } else {
-           if (pcmcia_get_mac_from_cis(link, dev))
-               goto failed;
-           if( cardtype == TDK ) {
-               card_name = "TDK LAK-CD021";
-           } else if( cardtype == LA501 ) {
-               card_name = "LA501";
-           } else if( cardtype == NEC ) {
-               card_name = "PK-UG-J001";
-           } else if( cardtype == KME ) {
-               card_name = "Panasonic";
-           } else {
-               card_name = "C-NET(PC)C";
-           }
-       }
-       break;
-    case UNGERMANN:
-       /* Read MACID from register */
-       for (i = 0; i < 6; i++) 
-           dev->dev_addr[i] = inb(ioaddr + UNGERMANN_MAC_ID + i);
-       card_name = "Access/CARD";
-       break;
-    case XXX10304:
-       /* Read MACID from Buggy CIS */
-       if (fmvj18x_get_hwinfo(link, buggybuf) == -1) {
-           pr_notice("unable to read hardware net address\n");
-           goto failed;
-       }
-       for (i = 0 ; i < 6; i++) {
-           dev->dev_addr[i] = buggybuf[i];
-       }
-       card_name = "FMV-J182";
-       break;
-    case MBH10302:
-    default:
-       /* Read MACID from register */
-       for (i = 0; i < 6; i++) 
-           dev->dev_addr[i] = inb(ioaddr + MAC_ID + i);
-       card_name = "FMV-J181";
-       break;
-    }
-
-    lp->cardtype = cardtype;
-    SET_NETDEV_DEV(dev, &link->dev);
-
-    if (register_netdev(dev) != 0) {
-       pr_notice("register_netdev() failed\n");
-       goto failed;
-    }
-
-    /* print current configuration */
-    netdev_info(dev, "%s, sram %s, port %#3lx, irq %d, hw_addr %pM\n",
-               card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2",
-               dev->base_addr, dev->irq, dev->dev_addr);
-
-    return 0;
-    
-failed:
-    fmvj18x_release(link);
-    return -ENODEV;
-} /* fmvj18x_config */
-/*====================================================================*/
-
-static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
-{
-    u_char __iomem *base;
-    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 -1;
-
-    base = ioremap(link->resource[2]->start, resource_size(link->resource[2]));
-    pcmcia_map_mem_page(link, link->resource[2], 0);
-
-    /*
-     *  MBH10304 CISTPL_FUNCE_LAN_NODE_ID format
-     *  22 0d xx xx xx 04 06 yy yy yy yy yy yy ff
-     *  'xx' is garbage.
-     *  'yy' is MAC address.
-    */ 
-    for (i = 0; i < 0x200; i++) {
-       if (readb(base+i*2) == 0x22) {  
-               if (readb(base+(i-1)*2) == 0xff &&
-                   readb(base+(i+5)*2) == 0x04 &&
-                   readb(base+(i+6)*2) == 0x06 &&
-                   readb(base+(i+13)*2) == 0xff)
-                       break;
-       }
-    }
-
-    if (i != 0x200) {
-       for (j = 0 ; j < 6; j++,i++) {
-           node_id[j] = readb(base+(i+7)*2);
-       }
-    }
-
-    iounmap(base);
-    j = pcmcia_release_window(link, link->resource[2]);
-    return (i != 0x200) ? 0 : -1;
-
-} /* fmvj18x_get_hwinfo */
-/*====================================================================*/
-
-static int fmvj18x_setup_mfc(struct pcmcia_device *link)
-{
-    int i;
-    struct net_device *dev = link->priv;
-    unsigned int ioaddr;
-    local_info_t *lp = netdev_priv(dev);
-
-    /* Allocate a small memory window */
-    link->resource[3]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
-    link->resource[3]->start = link->resource[3]->end = 0;
-    i = pcmcia_request_window(link, link->resource[3], 0);
-    if (i != 0)
-       return -1;
-
-    lp->base = ioremap(link->resource[3]->start,
-                      resource_size(link->resource[3]));
-    if (lp->base == NULL) {
-       netdev_notice(dev, "ioremap failed\n");
-       return -1;
-    }
-
-    i = pcmcia_map_mem_page(link, link->resource[3], 0);
-    if (i != 0) {
-       iounmap(lp->base);
-       lp->base = NULL;
-       return -1;
-    }
-    
-    ioaddr = dev->base_addr;
-    writeb(0x47, lp->base+0x800);      /* Config Option Register of LAN */
-    writeb(0x0,  lp->base+0x802);      /* Config and Status Register */
-
-    writeb(ioaddr & 0xff, lp->base+0x80a);       /* I/O Base(Low) of LAN */
-    writeb((ioaddr >> 8) & 0xff, lp->base+0x80c); /* I/O Base(High) of LAN */
-   
-    writeb(0x45, lp->base+0x820);      /* Config Option Register of Modem */
-    writeb(0x8,  lp->base+0x822);      /* Config and Status Register */
-
-    return 0;
-
-}
-/*====================================================================*/
-
-static void fmvj18x_release(struct pcmcia_device *link)
-{
-
-    struct net_device *dev = link->priv;
-    local_info_t *lp = netdev_priv(dev);
-    u_char __iomem *tmp;
-
-    dev_dbg(&link->dev, "fmvj18x_release\n");
-
-    if (lp->base != NULL) {
-       tmp = lp->base;
-       lp->base = NULL;    /* set NULL before iounmap */
-       iounmap(tmp);
-    }
-
-    pcmcia_disable_device(link);
-
-}
-
-static int fmvj18x_suspend(struct pcmcia_device *link)
-{
-       struct net_device *dev = link->priv;
-
-       if (link->open)
-               netif_device_detach(dev);
-
-       return 0;
-}
-
-static int fmvj18x_resume(struct pcmcia_device *link)
-{
-       struct net_device *dev = link->priv;
-
-       if (link->open) {
-               fjn_reset(dev);
-               netif_device_attach(dev);
-       }
-
-       return 0;
-}
-
-/*====================================================================*/
-
-static const struct pcmcia_device_id fmvj18x_ids[] = {
-       PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004),
-       PCMCIA_DEVICE_PROD_ID12("EAGLE Technology", "NE200 ETHERNET LAN MBH10302 04", 0x528c88c4, 0x74f91e59),
-       PCMCIA_DEVICE_PROD_ID12("Eiger Labs,Inc", "EPX-10BT PC Card Ethernet 10BT", 0x53af556e, 0x877f9922),
-       PCMCIA_DEVICE_PROD_ID12("Eiger labs,Inc.", "EPX-10BT PC Card Ethernet 10BT", 0xf47e6c66, 0x877f9922),
-       PCMCIA_DEVICE_PROD_ID12("FUJITSU", "LAN Card(FMV-J182)", 0x6ee5a3d8, 0x5baf31db),
-       PCMCIA_DEVICE_PROD_ID12("FUJITSU", "MBH10308", 0x6ee5a3d8, 0x3f04875e),
-       PCMCIA_DEVICE_PROD_ID12("FUJITSU TOWA", "LA501", 0xb8451188, 0x12939ba2),
-       PCMCIA_DEVICE_PROD_ID12("HITACHI", "HT-4840-11", 0xf4f43949, 0x773910f4),
-       PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310B Ver1.0       ", 0x8cef4d3a, 0x075fc7b6),
-       PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310 Ver1.0        ", 0x8cef4d3a, 0xbccf43e6),
-       PCMCIA_DEVICE_PROD_ID12("RATOC System Inc.", "10BASE_T CARD R280", 0x85c10e17, 0xd9413666),
-       PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CD02x", 0x1eae9475, 0x8fa0ee70),
-       PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CF010", 0x1eae9475, 0x7683bc9a),
-       PCMCIA_DEVICE_PROD_ID1("CONTEC Co.,Ltd.", 0x58d8fee2),
-       PCMCIA_DEVICE_PROD_ID1("PCMCIA LAN MBH10304  ES", 0x2599f454),
-       PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da),
-       PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080),
-       PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
-       PCMCIA_PFC_DEVICE_PROD_ID12(0, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
-       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a),
-       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a),
-       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0e01),
-       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05),
-       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0b05),
-       PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101),
-       PCMCIA_DEVICE_NULL,
-};
-MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids);
-
-static struct pcmcia_driver fmvj18x_cs_driver = {
-       .owner          = THIS_MODULE,
-       .name           = "fmvj18x_cs",
-       .probe          = fmvj18x_probe,
-       .remove         = fmvj18x_detach,
-       .id_table       = fmvj18x_ids,
-       .suspend        = fmvj18x_suspend,
-       .resume         = fmvj18x_resume,
-};
-
-static int __init init_fmvj18x_cs(void)
-{
-       return pcmcia_register_driver(&fmvj18x_cs_driver);
-}
-
-static void __exit exit_fmvj18x_cs(void)
-{
-       pcmcia_unregister_driver(&fmvj18x_cs_driver);
-}
-
-module_init(init_fmvj18x_cs);
-module_exit(exit_fmvj18x_cs);
-
-/*====================================================================*/
-
-static irqreturn_t fjn_interrupt(int dummy, void *dev_id)
-{
-    struct net_device *dev = dev_id;
-    local_info_t *lp = netdev_priv(dev);
-    unsigned int ioaddr;
-    unsigned short tx_stat, rx_stat;
-
-    ioaddr = dev->base_addr;
-
-    /* avoid multiple interrupts */
-    outw(0x0000, ioaddr + TX_INTR);
-
-    /* wait for a while */
-    udelay(1);
-
-    /* get status */
-    tx_stat = inb(ioaddr + TX_STATUS);
-    rx_stat = inb(ioaddr + RX_STATUS);
-
-    /* clear status */
-    outb(tx_stat, ioaddr + TX_STATUS);
-    outb(rx_stat, ioaddr + RX_STATUS);
-    
-    pr_debug("%s: interrupt, rx_status %02x.\n", dev->name, rx_stat);
-    pr_debug("               tx_status %02x.\n", tx_stat);
-    
-    if (rx_stat || (inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
-       /* there is packet(s) in rx buffer */
-       fjn_rx(dev);
-    }
-    if (tx_stat & F_TMT_RDY) {
-       dev->stats.tx_packets += lp->sent ;
-        lp->sent = 0 ;
-       if (lp->tx_queue) {
-           outb(DO_TX | lp->tx_queue, ioaddr + TX_START);
-           lp->sent = lp->tx_queue ;
-           lp->tx_queue = 0;
-           lp->tx_queue_len = 0;
-           dev->trans_start = jiffies;
-       } else {
-           lp->tx_started = 0;
-       }
-       netif_wake_queue(dev);
-    }
-    pr_debug("%s: exiting interrupt,\n", dev->name);
-    pr_debug("    tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat);
-
-    outb(D_TX_INTR, ioaddr + TX_INTR);
-    outb(D_RX_INTR, ioaddr + RX_INTR);
-
-    if (lp->base != NULL) {
-       /* Ack interrupt for multifunction card */
-       writeb(0x01, lp->base+0x802);
-       writeb(0x09, lp->base+0x822);
-    }
-
-    return IRQ_HANDLED;
-
-} /* fjn_interrupt */
-
-/*====================================================================*/
-
-static void fjn_tx_timeout(struct net_device *dev)
-{
-    struct local_info_t *lp = netdev_priv(dev);
-    unsigned int ioaddr = dev->base_addr;
-
-    netdev_notice(dev, "transmit timed out with status %04x, %s?\n",
-                 htons(inw(ioaddr + TX_STATUS)),
-                 inb(ioaddr + TX_STATUS) & F_TMT_RDY
-                 ? "IRQ conflict" : "network cable problem");
-    netdev_notice(dev, "timeout registers: %04x %04x %04x "
-                 "%04x %04x %04x %04x %04x.\n",
-                 htons(inw(ioaddr + 0)), htons(inw(ioaddr + 2)),
-                 htons(inw(ioaddr + 4)), htons(inw(ioaddr + 6)),
-                 htons(inw(ioaddr + 8)), htons(inw(ioaddr + 10)),
-                 htons(inw(ioaddr + 12)), htons(inw(ioaddr + 14)));
-    dev->stats.tx_errors++;
-    /* ToDo: We should try to restart the adaptor... */
-    local_irq_disable();
-    fjn_reset(dev);
-
-    lp->tx_started = 0;
-    lp->tx_queue = 0;
-    lp->tx_queue_len = 0;
-    lp->sent = 0;
-    lp->open_time = jiffies;
-    local_irq_enable();
-    netif_wake_queue(dev);
-}
-
-static netdev_tx_t fjn_start_xmit(struct sk_buff *skb,
-                                       struct net_device *dev)
-{
-    struct local_info_t *lp = netdev_priv(dev);
-    unsigned int ioaddr = dev->base_addr;
-    short length = skb->len;
-    
-    if (length < ETH_ZLEN)
-    {
-       if (skb_padto(skb, ETH_ZLEN))
-               return NETDEV_TX_OK;
-       length = ETH_ZLEN;
-    }
-
-    netif_stop_queue(dev);
-
-    {
-       unsigned char *buf = skb->data;
-
-       if (length > ETH_FRAME_LEN) {
-           netdev_notice(dev, "Attempting to send a large packet (%d bytes)\n",
-                         length);
-           return NETDEV_TX_BUSY;
-       }
-
-       netdev_dbg(dev, "Transmitting a packet of length %lu\n",
-                  (unsigned long)skb->len);
-       dev->stats.tx_bytes += skb->len;
-
-       /* Disable both interrupts. */
-       outw(0x0000, ioaddr + TX_INTR);
-
-       /* wait for a while */
-       udelay(1);
-
-       outw(length, ioaddr + DATAPORT);
-       outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
-
-       lp->tx_queue++;
-       lp->tx_queue_len += ((length+3) & ~1);
-
-       if (lp->tx_started == 0) {
-           /* If the Tx is idle, always trigger a transmit. */
-           outb(DO_TX | lp->tx_queue, ioaddr + TX_START);
-           lp->sent = lp->tx_queue ;
-           lp->tx_queue = 0;
-           lp->tx_queue_len = 0;
-           lp->tx_started = 1;
-           netif_start_queue(dev);
-       } else {
-           if( sram_config == 0 ) {
-               if (lp->tx_queue_len < (4096 - (ETH_FRAME_LEN +2)) )
-                   /* Yes, there is room for one more packet. */
-                   netif_start_queue(dev);
-           } else {
-               if (lp->tx_queue_len < (8192 - (ETH_FRAME_LEN +2)) && 
-                                               lp->tx_queue < 127 )
-                   /* Yes, there is room for one more packet. */
-                   netif_start_queue(dev);
-           }
-       }
-
-       /* Re-enable interrupts */
-       outb(D_TX_INTR, ioaddr + TX_INTR);
-       outb(D_RX_INTR, ioaddr + RX_INTR);
-    }
-    dev_kfree_skb (skb);
-
-    return NETDEV_TX_OK;
-} /* fjn_start_xmit */
-
-/*====================================================================*/
-
-static void fjn_reset(struct net_device *dev)
-{
-    struct local_info_t *lp = netdev_priv(dev);
-    unsigned int ioaddr = dev->base_addr;
-    int i;
-
-    netdev_dbg(dev, "fjn_reset() called\n");
-
-    /* Reset controller */
-    if( sram_config == 0 ) 
-       outb(CONFIG0_RST, ioaddr + CONFIG_0);
-    else
-       outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
-
-    /* Power On chip and select bank 0 */
-    if (lp->cardtype == MBH10302)
-       outb(BANK_0, ioaddr + CONFIG_1);
-    else
-       outb(BANK_0U, ioaddr + CONFIG_1);
-
-    /* Set Tx modes */
-    outb(D_TX_MODE, ioaddr + TX_MODE);
-    /* set Rx modes */
-    outb(ID_MATCHED, ioaddr + RX_MODE);
-
-    /* Set hardware address */
-    for (i = 0; i < 6; i++) 
-        outb(dev->dev_addr[i], ioaddr + NODE_ID + i);
-
-    /* (re)initialize the multicast table */
-    set_rx_mode(dev);
-
-    /* Switch to bank 2 (runtime mode) */
-    if (lp->cardtype == MBH10302)
-       outb(BANK_2, ioaddr + CONFIG_1);
-    else
-       outb(BANK_2U, ioaddr + CONFIG_1);
-
-    /* set 16col ctrl bits */
-    if( lp->cardtype == TDK || lp->cardtype == CONTEC) 
-        outb(TDK_AUTO_MODE, ioaddr + COL_CTRL);
-    else
-        outb(AUTO_MODE, ioaddr + COL_CTRL);
-
-    /* clear Reserved Regs */
-    outb(0x00, ioaddr + BMPR12);
-    outb(0x00, ioaddr + BMPR13);
-
-    /* reset Skip packet reg. */
-    outb(0x01, ioaddr + RX_SKIP);
-
-    /* Enable Tx and Rx */
-    if( sram_config == 0 )
-       outb(CONFIG0_DFL, ioaddr + CONFIG_0);
-    else
-       outb(CONFIG0_DFL_1, ioaddr + CONFIG_0);
-
-    /* Init receive pointer ? */
-    inw(ioaddr + DATAPORT);
-    inw(ioaddr + DATAPORT);
-
-    /* Clear all status */
-    outb(0xff, ioaddr + TX_STATUS);
-    outb(0xff, ioaddr + RX_STATUS);
-
-    if (lp->cardtype == MBH10302)
-       outb(INTR_OFF, ioaddr + LAN_CTRL);
-
-    /* Turn on Rx interrupts */
-    outb(D_TX_INTR, ioaddr + TX_INTR);
-    outb(D_RX_INTR, ioaddr + RX_INTR);
-
-    /* Turn on interrupts from LAN card controller */
-    if (lp->cardtype == MBH10302)
-       outb(INTR_ON, ioaddr + LAN_CTRL);
-} /* fjn_reset */
-
-/*====================================================================*/
-
-static void fjn_rx(struct net_device *dev)
-{
-    unsigned int ioaddr = dev->base_addr;
-    int boguscount = 10;       /* 5 -> 10: by agy 19940922 */
-
-    pr_debug("%s: in rx_packet(), rx_status %02x.\n",
-         dev->name, inb(ioaddr + RX_STATUS));
-
-    while ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
-       u_short status = inw(ioaddr + DATAPORT);
-
-       netdev_dbg(dev, "Rxing packet mode %02x status %04x.\n",
-                  inb(ioaddr + RX_MODE), status);
-#ifndef final_version
-       if (status == 0) {
-           outb(F_SKP_PKT, ioaddr + RX_SKIP);
-           break;
-       }
-#endif
-       if ((status & 0xF0) != 0x20) {  /* There was an error. */
-           dev->stats.rx_errors++;
-           if (status & F_LEN_ERR) dev->stats.rx_length_errors++;
-           if (status & F_ALG_ERR) dev->stats.rx_frame_errors++;
-           if (status & F_CRC_ERR) dev->stats.rx_crc_errors++;
-           if (status & F_OVR_FLO) dev->stats.rx_over_errors++;
-       } else {
-           u_short pkt_len = inw(ioaddr + DATAPORT);
-           /* Malloc up new buffer. */
-           struct sk_buff *skb;
-
-           if (pkt_len > 1550) {
-               netdev_notice(dev, "The FMV-18x claimed a very large packet, size %d\n",
-                             pkt_len);
-               outb(F_SKP_PKT, ioaddr + RX_SKIP);
-               dev->stats.rx_errors++;
-               break;
-           }
-           skb = dev_alloc_skb(pkt_len+2);
-           if (skb == NULL) {
-               netdev_notice(dev, "Memory squeeze, dropping packet (len %d)\n",
-                             pkt_len);
-               outb(F_SKP_PKT, ioaddr + RX_SKIP);
-               dev->stats.rx_dropped++;
-               break;
-           }
-
-           skb_reserve(skb, 2);
-           insw(ioaddr + DATAPORT, skb_put(skb, pkt_len),
-                (pkt_len + 1) >> 1);
-           skb->protocol = eth_type_trans(skb, dev);
-
-           {
-               int i;
-               pr_debug("%s: Rxed packet of length %d: ",
-                       dev->name, pkt_len);
-               for (i = 0; i < 14; i++)
-                       pr_debug(" %02x", skb->data[i]);
-               pr_debug(".\n");
-           }
-
-           netif_rx(skb);
-           dev->stats.rx_packets++;
-           dev->stats.rx_bytes += pkt_len;
-       }
-       if (--boguscount <= 0)
-           break;
-    }
-
-    /* If any worth-while packets have been received, dev_rint()
-          has done a netif_wake_queue() for us and will work on them
-          when we get to the bottom-half routine. */
-/*
-    if (lp->cardtype != TDK) {
-       int i;
-       for (i = 0; i < 20; i++) {
-           if ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == F_BUF_EMP)
-               break;
-           (void)inw(ioaddr + DATAPORT);  /+ dummy status read +/
-           outb(F_SKP_PKT, ioaddr + RX_SKIP);
-       }
-
-       if (i > 0)
-           pr_debug("%s: Exint Rx packet with mode %02x after "
-                 "%d ticks.\n", dev->name, inb(ioaddr + RX_MODE), i);
-    }
-*/
-} /* fjn_rx */
-
-/*====================================================================*/
-
-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, "PCMCIA 0x%lx", dev->base_addr);
-}
-
-static const struct ethtool_ops netdev_ethtool_ops = {
-       .get_drvinfo            = netdev_get_drvinfo,
-};
-
-static int fjn_config(struct net_device *dev, struct ifmap *map){
-    return 0;
-}
-
-static int fjn_open(struct net_device *dev)
-{
-    struct local_info_t *lp = netdev_priv(dev);
-    struct pcmcia_device *link = lp->p_dev;
-
-    pr_debug("fjn_open('%s').\n", dev->name);
-
-    if (!pcmcia_dev_present(link))
-       return -ENODEV;
-    
-    link->open++;
-    
-    fjn_reset(dev);
-    
-    lp->tx_started = 0;
-    lp->tx_queue = 0;
-    lp->tx_queue_len = 0;
-    lp->open_time = jiffies;
-    netif_start_queue(dev);
-    
-    return 0;
-} /* fjn_open */
-
-/*====================================================================*/
-
-static int fjn_close(struct net_device *dev)
-{
-    struct local_info_t *lp = netdev_priv(dev);
-    struct pcmcia_device *link = lp->p_dev;
-    unsigned int ioaddr = dev->base_addr;
-
-    pr_debug("fjn_close('%s').\n", dev->name);
-
-    lp->open_time = 0;
-    netif_stop_queue(dev);
-
-    /* Set configuration register 0 to disable Tx and Rx. */
-    if( sram_config == 0 ) 
-       outb(CONFIG0_RST ,ioaddr + CONFIG_0);
-    else
-       outb(CONFIG0_RST_1 ,ioaddr + CONFIG_0);
-
-    /* Update the statistics -- ToDo. */
-
-    /* Power-down the chip.  Green, green, green! */
-    outb(CHIP_OFF ,ioaddr + CONFIG_1);
-
-    /* Set the ethernet adaptor disable IRQ */
-    if (lp->cardtype == MBH10302)
-       outb(INTR_OFF, ioaddr + LAN_CTRL);
-
-    link->open--;
-
-    return 0;
-} /* fjn_close */
-
-/*====================================================================*/
-
-/*
-  Set the multicast/promiscuous mode for this adaptor.
-*/
-
-static void set_rx_mode(struct net_device *dev)
-{
-    unsigned int ioaddr = dev->base_addr;
-    u_char mc_filter[8];                /* Multicast hash filter */
-    u_long flags;
-    int i;
-    
-    int saved_bank;
-    int saved_config_0 = inb(ioaddr + CONFIG_0);
-     
-    local_irq_save(flags); 
-
-    /* Disable Tx and Rx */
-    if (sram_config == 0) 
-       outb(CONFIG0_RST, ioaddr + CONFIG_0);
-    else
-       outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
-
-    if (dev->flags & IFF_PROMISC) {
-       memset(mc_filter, 0xff, sizeof(mc_filter));
-       outb(3, ioaddr + RX_MODE);      /* Enable promiscuous mode */
-    } else if (netdev_mc_count(dev) > MC_FILTERBREAK ||
-              (dev->flags & IFF_ALLMULTI)) {
-       /* Too many to filter perfectly -- accept all multicasts. */
-       memset(mc_filter, 0xff, sizeof(mc_filter));
-       outb(2, ioaddr + RX_MODE);      /* Use normal mode. */
-    } else if (netdev_mc_empty(dev)) {
-       memset(mc_filter, 0x00, sizeof(mc_filter));
-       outb(1, ioaddr + RX_MODE);      /* Ignore almost all multicasts. */
-    } else {
-       struct netdev_hw_addr *ha;
-
-       memset(mc_filter, 0, sizeof(mc_filter));
-       netdev_for_each_mc_addr(ha, dev) {
-           unsigned int bit = ether_crc_le(ETH_ALEN, ha->addr) >> 26;
-           mc_filter[bit >> 3] |= (1 << (bit & 7));
-       }
-       outb(2, ioaddr + RX_MODE);      /* Use normal mode. */
-    }
-
-    /* Switch to bank 1 and set the multicast table. */
-    saved_bank = inb(ioaddr + CONFIG_1);
-    outb(0xe4, ioaddr + CONFIG_1);
-
-    for (i = 0; i < 8; i++)
-       outb(mc_filter[i], ioaddr + MAR_ADR + i);
-    outb(saved_bank, ioaddr + CONFIG_1);
-
-    outb(saved_config_0, ioaddr + CONFIG_0);
-
-    local_irq_restore(flags);
-}