drivers/net: delete intel 486 panther onboard ethernet support
authorPaul Gortmaker <paul.gortmaker@windriver.com>
Wed, 9 Jan 2013 03:11:54 +0000 (22:11 -0500)
committerPaul Gortmaker <paul.gortmaker@windriver.com>
Tue, 22 Jan 2013 15:39:48 +0000 (10:39 -0500)
This driver was specific to a "professional workstation" line
of products from around 1993 that used the i82596 ethernet chip
as an on-board ethernet solution.

With a 486 processor, and the premium top of the line model maxing
out at a clock speed of 50MHz, we can safely retire this support.

Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
drivers/net/ethernet/i825xx/Kconfig
drivers/net/ethernet/i825xx/Makefile
drivers/net/ethernet/i825xx/lp486e.c [deleted file]

index c39698a..46edb81 100644 (file)
@@ -93,14 +93,6 @@ config LASI_82596
          Say Y here to support the builtin Intel 82596 ethernet controller
          found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet.
 
-config LP486E
-       tristate "LP486E on board Ethernet"
-       depends on ISA
-       ---help---
-         Say Y here to support the 82596-based on-board Ethernet controller
-         for the Panther motherboard, which is one of the two shipped in the
-         Intel Professional Workstation.
-
 config MVME16x_NET
        tristate "MVME16x Ethernet support"
        depends on MVME16x
index e5ab9d0..4f01584 100644 (file)
@@ -7,7 +7,6 @@ obj-$(CONFIG_EEXPRESS) += eexpress.o
 obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
 obj-$(CONFIG_ELPLUS) += 3c505.o
 obj-$(CONFIG_EL16) += 3c507.o
-obj-$(CONFIG_LP486E) += lp486e.o
 obj-$(CONFIG_NI52) += ni52.o
 obj-$(CONFIG_SUN3_82586) += sun3_82586.o
 obj-$(CONFIG_ZNET) += znet.o
diff --git a/drivers/net/ethernet/i825xx/lp486e.c b/drivers/net/ethernet/i825xx/lp486e.c
deleted file mode 100644 (file)
index 3735bfa..0000000
+++ /dev/null
@@ -1,1337 +0,0 @@
-/* Intel Professional Workstation/panther ethernet driver */
-/* lp486e.c: A panther 82596 ethernet driver for linux. */
-/*
-    History and copyrights:
-
-    Driver skeleton
-        Written 1993 by Donald Becker.
-        Copyright 1993 United States Government as represented by the Director,
-        National Security Agency.  This software may only be used and
-       distributed according to the terms of the GNU General Public License
-       as modified by SRC, incorporated herein by reference.
-
-        The author may be reached as becker@scyld.com, or C/O
-       Scyld Computing Corporation
-       410 Severn Ave., Suite 210
-       Annapolis MD 21403
-
-    Apricot
-        Written 1994 by Mark Evans.
-        This driver is for the Apricot 82596 bus-master interface
-
-        Modularised 12/94 Mark Evans
-
-    Professional Workstation
-       Derived from apricot.c by Ard van Breemen
-       <ard@murphy.nl>|<ard@cstmel.hobby.nl>|<ard@cstmel.nl.eu.org>
-
-       Credits:
-       Thanks to Murphy Software BV for letting me write this in their time.
-       Well, actually, I get paid doing this...
-       (Also: see http://www.murphy.nl for murphy, and my homepage ~ard for
-       more information on the Professional Workstation)
-
-    Present version
-       aeb@cwi.nl
-*/
-/*
-    There are currently two motherboards that I know of in the
-    professional workstation. The only one that I know is the
-    intel panther motherboard. -- ard
-*/
-/*
-The pws is equipped with an intel 82596. This is a very intelligent controller
-which runs its own micro-code. Communication with the hostprocessor is done
-through linked lists of commands and buffers in the hostprocessors memory.
-A complete description of the 82596 is available from intel. Search for
-a file called "29021806.pdf". It is a complete description of the chip itself.
-To use it for the pws some additions are needed regarding generation of
-the PORT and CA signal, and the interrupt glue needed for a pc.
-I/O map:
-PORT  SIZE ACTION MEANING
-0xCB0    2 WRITE  Lower 16 bits for PORT command
-0xCB2    2 WRITE  Upper 16 bits for PORT command, and issue of PORT command
-0xCB4    1 WRITE  Generation of CA signal
-0xCB8    1 WRITE  Clear interrupt glue
-All other communication is through memory!
-*/
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#define DRV_NAME "lp486e"
-
-/* debug print flags */
-#define LOG_SRCDST    0x80000000
-#define LOG_STATINT   0x40000000
-#define LOG_STARTINT  0x20000000
-
-#define i596_debug debug
-
-static int i596_debug = 0;
-
-static const char * const medianame[] = {
-       "10baseT", "AUI",
-       "10baseT-FD", "AUI-FD",
-};
-
-#define LP486E_TOTAL_SIZE 16
-
-#define I596_NULL (0xffffffff)
-
-#define CMD_EOL                0x8000  /* The last command of the list, stop. */
-#define CMD_SUSP       0x4000  /* Suspend after doing cmd. */
-#define CMD_INTR       0x2000  /* Interrupt after doing cmd. */
-
-#define CMD_FLEX       0x0008  /* Enable flexible memory model */
-
-enum commands {
-       CmdNOP = 0,
-       CmdIASetup = 1,
-       CmdConfigure = 2,
-       CmdMulticastList = 3,
-       CmdTx = 4,
-       CmdTDR = 5,
-       CmdDump = 6,
-       CmdDiagnose = 7
-};
-
-#if 0
-static const char *CUcmdnames[8] = { "NOP", "IASetup", "Configure", "MulticastList",
-                                    "Tx", "TDR", "Dump", "Diagnose" };
-#endif
-
-/* Status word bits */
-#define        STAT_CX         0x8000  /* The CU finished executing a command
-                                  with the Interrupt bit set */
-#define        STAT_FR         0x4000  /* The RU finished receiving a frame */
-#define        STAT_CNA        0x2000  /* The CU left the active state */
-#define        STAT_RNR        0x1000  /* The RU left the active state */
-#define STAT_ACK       (STAT_CX | STAT_FR | STAT_CNA | STAT_RNR)
-#define        STAT_CUS        0x0700  /* Status of CU: 0: idle, 1: suspended,
-                                  2: active, 3-7: unused */
-#define STAT_RUS       0x00f0  /* Status of RU: 0: idle, 1: suspended,
-                                  2: no resources, 4: ready,
-                                  10: no resources due to no more RBDs,
-                                  12: no more RBDs, other: unused */
-#define        STAT_T          0x0008  /* Bus throttle timers loaded */
-#define        STAT_ZERO       0x0807  /* Always zero */
-
-#if 0
-static char *CUstates[8] = {
-       "idle", "suspended", "active", 0, 0, 0, 0, 0
-};
-static char *RUstates[16] = {
-       "idle", "suspended", "no resources", 0, "ready", 0, 0, 0,
-       0, 0, "no RBDs", 0, "out of RBDs", 0, 0, 0
-};
-
-static void
-i596_out_status(int status) {
-       int bad = 0;
-       char *s;
-
-       printk("status %4.4x:", status);
-       if (status == 0xffff)
-               printk(" strange..\n");
-       else {
-               if (status & STAT_CX)
-                       printk("  CU done");
-               if (status & STAT_CNA)
-                       printk("  CU stopped");
-               if (status & STAT_FR)
-                       printk("  got a frame");
-               if (status & STAT_RNR)
-                       printk("  RU stopped");
-               if (status & STAT_T)
-                       printk("  throttled");
-               if (status & STAT_ZERO)
-                       bad = 1;
-               s = CUstates[(status & STAT_CUS) >> 8];
-               if (!s)
-                       bad = 1;
-               else
-                       printk("  CU(%s)", s);
-               s = RUstates[(status & STAT_RUS) >> 4];
-               if (!s)
-                       bad = 1;
-               else
-                       printk("  RU(%s)", s);
-               if (bad)
-                       printk("  bad status");
-               printk("\n");
-       }
-}
-#endif
-
-/* Command word bits */
-#define ACK_CX         0x8000
-#define ACK_FR         0x4000
-#define ACK_CNA                0x2000
-#define ACK_RNR                0x1000
-
-#define CUC_START      0x0100
-#define CUC_RESUME     0x0200
-#define CUC_SUSPEND    0x0300
-#define CUC_ABORT      0x0400
-
-#define RX_START       0x0010
-#define RX_RESUME      0x0020
-#define RX_SUSPEND     0x0030
-#define RX_ABORT       0x0040
-
-typedef u32 phys_addr;
-
-static inline phys_addr
-va_to_pa(void *x) {
-       return x ? virt_to_bus(x) : I596_NULL;
-}
-
-static inline void *
-pa_to_va(phys_addr x) {
-       return (x == I596_NULL) ? NULL : bus_to_virt(x);
-}
-
-/* status bits for cmd */
-#define CMD_STAT_C     0x8000  /* CU command complete */
-#define CMD_STAT_B     0x4000  /* CU command in progress */
-#define CMD_STAT_OK    0x2000  /* CU command completed without errors */
-#define CMD_STAT_A     0x1000  /* CU command abnormally terminated */
-
-struct i596_cmd {              /* 8 bytes */
-       unsigned short status;
-       unsigned short command;
-       phys_addr pa_next;      /* va_to_pa(struct i596_cmd *next) */
-};
-
-#define EOF            0x8000
-#define SIZE_MASK      0x3fff
-
-struct i596_tbd {
-       unsigned short size;
-       unsigned short pad;
-       phys_addr pa_next;      /* va_to_pa(struct i596_tbd *next) */
-       phys_addr pa_data;      /* va_to_pa(char *data) */
-       struct sk_buff *skb;
-};
-
-struct tx_cmd {
-       struct i596_cmd cmd;
-       phys_addr pa_tbd;       /* va_to_pa(struct i596_tbd *tbd) */
-       unsigned short size;
-       unsigned short pad;
-};
-
-/* status bits for rfd */
-#define RFD_STAT_C     0x8000  /* Frame reception complete */
-#define RFD_STAT_B     0x4000  /* Frame reception in progress */
-#define RFD_STAT_OK    0x2000  /* Frame received without errors */
-#define RFD_STATUS     0x1fff
-#define RFD_LENGTH_ERR 0x1000
-#define RFD_CRC_ERR    0x0800
-#define RFD_ALIGN_ERR  0x0400
-#define RFD_NOBUFS_ERR 0x0200
-#define RFD_DMA_ERR    0x0100  /* DMA overrun failure to acquire system bus */
-#define RFD_SHORT_FRAME_ERR    0x0080
-#define RFD_NOEOP_ERR  0x0040
-#define RFD_TRUNC_ERR  0x0020
-#define RFD_MULTICAST  0x0002  /* 0: destination had our address
-                                  1: destination was broadcast/multicast */
-#define RFD_COLLISION  0x0001
-
-/* receive frame descriptor */
-struct i596_rfd {
-       unsigned short stat;
-       unsigned short cmd;
-       phys_addr pa_next;      /* va_to_pa(struct i596_rfd *next) */
-       phys_addr pa_rbd;       /* va_to_pa(struct i596_rbd *rbd) */
-       unsigned short count;
-       unsigned short size;
-       char data[1532];
-};
-
-#define RBD_EL         0x8000
-#define RBD_P          0x4000
-#define RBD_SIZEMASK   0x3fff
-#define RBD_EOF                0x8000
-#define RBD_F          0x4000
-
-/* receive buffer descriptor */
-struct i596_rbd {
-       unsigned short size;
-       unsigned short pad;
-       phys_addr pa_next;      /* va_to_pa(struct i596_tbd *next) */
-       phys_addr pa_data;      /* va_to_pa(char *data) */
-       phys_addr pa_prev;      /* va_to_pa(struct i596_tbd *prev) */
-
-       /* Driver private part */
-       struct sk_buff *skb;
-};
-
-#define RX_RING_SIZE 64
-#define RX_SKBSIZE (ETH_FRAME_LEN+10)
-#define RX_RBD_SIZE 32
-
-/* System Control Block - 40 bytes */
-struct i596_scb {
-       u16 status;             /* 0 */
-       u16 command;            /* 2 */
-       phys_addr pa_cmd;       /* 4 - va_to_pa(struct i596_cmd *cmd) */
-       phys_addr pa_rfd;       /* 8 - va_to_pa(struct i596_rfd *rfd) */
-       u32 crc_err;            /* 12 */
-       u32 align_err;          /* 16 */
-       u32 resource_err;       /* 20 */
-       u32 over_err;           /* 24 */
-       u32 rcvdt_err;          /* 28 */
-       u32 short_err;          /* 32 */
-       u16 t_on;               /* 36 */
-       u16 t_off;              /* 38 */
-};
-
-/* Intermediate System Configuration Pointer - 8 bytes */
-struct i596_iscp {
-       u32 busy;               /* 0 */
-       phys_addr pa_scb;       /* 4 - va_to_pa(struct i596_scb *scb) */
-};
-
-/* System Configuration Pointer - 12 bytes */
-struct i596_scp {
-       u32 sysbus;             /* 0 */
-       u32 pad;                /* 4 */
-       phys_addr pa_iscp;      /* 8 - va_to_pa(struct i596_iscp *iscp) */
-};
-
-/* Selftest and dump results - needs 16-byte alignment */
-/*
- * The size of the dump area is 304 bytes. When the dump is executed
- * by the Port command an extra word will be appended to the dump area.
- * The extra word is a copy of the Dump status word (containing the
- * C, B, OK bits). [I find 0xa006, with a0 for C+OK and 6 for dump]
- */
-struct i596_dump {
-       u16 dump[153];          /* (304 = 130h) + 2 bytes */
-};
-
-struct i596_private {          /* aligned to a 16-byte boundary */
-       struct i596_scp scp;    /* 0 - needs 16-byte alignment */
-       struct i596_iscp iscp;  /* 12 */
-       struct i596_scb scb;    /* 20 */
-       u32 dummy;              /* 60 */
-       struct i596_dump dump;  /* 64 - needs 16-byte alignment */
-
-       struct i596_cmd set_add;
-       char eth_addr[8];       /* directly follows set_add */
-
-       struct i596_cmd set_conf;
-       char i596_config[16];   /* directly follows set_conf */
-
-       struct i596_cmd tdr;
-       unsigned long tdr_stat; /* directly follows tdr */
-
-       int last_restart;
-       struct i596_rbd *rbd_list;
-       struct i596_rbd *rbd_tail;
-       struct i596_rfd *rx_tail;
-       struct i596_cmd *cmd_tail;
-       struct i596_cmd *cmd_head;
-       int cmd_backlog;
-       unsigned long last_cmd;
-       spinlock_t cmd_lock;
-};
-
-static char init_setup[14] = {
-       0x8E,   /* length 14 bytes, prefetch on */
-       0xC8,   /* default: fifo to 8, monitor off */
-       0x40,   /* default: don't save bad frames (apricot.c had 0x80) */
-       0x2E,   /* (default is 0x26)
-                  No source address insertion, 8 byte preamble */
-       0x00,   /* default priority and backoff */
-       0x60,   /* default interframe spacing */
-       0x00,   /* default slot time LSB */
-       0xf2,   /* default slot time and nr of retries */
-       0x00,   /* default various bits
-                  (0: promiscuous mode, 1: broadcast disable,
-                   2: encoding mode, 3: transmit on no CRS,
-                   4: no CRC insertion, 5: CRC type,
-                   6: bit stuffing, 7: padding) */
-       0x00,   /* default carrier sense and collision detect */
-       0x40,   /* default minimum frame length */
-       0xff,   /* (default is 0xff, and that is what apricot.c has;
-                  elp486.c has 0xfb: Enable crc append in memory.) */
-       0x00,   /* default: not full duplex */
-       0x7f    /* (default is 0x3f) multi IA */
-};
-
-static int i596_open(struct net_device *dev);
-static netdev_tx_t i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t i596_interrupt(int irq, void *dev_id);
-static int i596_close(struct net_device *dev);
-static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
-static void print_eth(char *);
-static void set_multicast_list(struct net_device *dev);
-static void i596_tx_timeout(struct net_device *dev);
-
-static int
-i596_timeout(struct net_device *dev, char *msg, int ct) {
-       struct i596_private *lp;
-       int boguscnt = ct;
-
-       lp = netdev_priv(dev);
-       while (lp->scb.command) {
-               if (--boguscnt == 0) {
-                       printk("%s: %s timed out - stat %4.4x, cmd %4.4x\n",
-                              dev->name, msg,
-                              lp->scb.status, lp->scb.command);
-                       return 1;
-               }
-               udelay(5);
-               barrier();
-       }
-       return 0;
-}
-
-static inline int
-init_rx_bufs(struct net_device *dev, int num) {
-       struct i596_private *lp;
-       struct i596_rfd *rfd;
-       int i;
-       // struct i596_rbd *rbd;
-
-       lp = netdev_priv(dev);
-       lp->scb.pa_rfd = I596_NULL;
-
-       for (i = 0; i < num; i++) {
-               rfd = kmalloc(sizeof(struct i596_rfd), GFP_KERNEL);
-               if (rfd == NULL)
-                       break;
-
-               rfd->stat = 0;
-               rfd->pa_rbd = I596_NULL;
-               rfd->count = 0;
-               rfd->size = 1532;
-               if (i == 0) {
-                       rfd->cmd = CMD_EOL;
-                       lp->rx_tail = rfd;
-               } else {
-                       rfd->cmd = 0;
-               }
-               rfd->pa_next = lp->scb.pa_rfd;
-               lp->scb.pa_rfd = va_to_pa(rfd);
-               lp->rx_tail->pa_next = lp->scb.pa_rfd;
-       }
-
-#if 0
-       for (i = 0; i<RX_RBD_SIZE; i++) {
-               rbd = kmalloc(sizeof(struct i596_rbd), GFP_KERNEL);
-               if (rbd) {
-                       rbd->pad = 0;
-                       rbd->count = 0;
-                       rbd->skb = dev_alloc_skb(RX_SKBSIZE);
-                       if (!rbd->skb) {
-                               printk("dev_alloc_skb failed");
-                       }
-                       rbd->next = rfd->rbd;
-                       if (i) {
-                               rfd->rbd->prev = rbd;
-                               rbd->size = RX_SKBSIZE;
-                       } else {
-                               rbd->size = (RX_SKBSIZE | RBD_EL);
-                               lp->rbd_tail = rbd;
-                       }
-
-                       rfd->rbd = rbd;
-               }
-       }
-       lp->rbd_tail->next = rfd->rbd;
-#endif
-       return i;
-}
-
-static inline void
-remove_rx_bufs(struct net_device *dev) {
-       struct i596_private *lp;
-       struct i596_rfd *rfd;
-
-       lp = netdev_priv(dev);
-       lp->rx_tail->pa_next = I596_NULL;
-
-       do {
-               rfd = pa_to_va(lp->scb.pa_rfd);
-               lp->scb.pa_rfd = rfd->pa_next;
-               kfree(rfd);
-       } while (rfd != lp->rx_tail);
-
-       lp->rx_tail = NULL;
-
-#if 0
-       for (lp->rbd_list) {
-       }
-#endif
-}
-
-#define PORT_RESET              0x00    /* reset 82596 */
-#define PORT_SELFTEST           0x01    /* selftest */
-#define PORT_ALTSCP             0x02    /* alternate SCB address */
-#define PORT_DUMP               0x03    /* dump */
-
-#define IOADDR 0xcb0           /* real constant */
-#define IRQ    10              /* default IRQ - can be changed by ECU */
-
-/* The 82596 requires two 16-bit write cycles for a port command */
-static inline void
-PORT(phys_addr a, unsigned int cmd) {
-       if (a & 0xf)
-               printk("lp486e.c: PORT: address not aligned\n");
-       outw(((a & 0xffff) | cmd), IOADDR);
-       outw(((a>>16) & 0xffff), IOADDR+2);
-}
-
-static inline void
-CA(void) {
-       outb(0, IOADDR+4);
-       udelay(8);
-}
-
-static inline void
-CLEAR_INT(void) {
-       outb(0, IOADDR+8);
-}
-
-#if 0
-/* selftest or dump */
-static void
-i596_port_do(struct net_device *dev, int portcmd, char *cmdname) {
-       struct i596_private *lp = netdev_priv(dev);
-       u16 *outp;
-       int i, m;
-
-       memset((void *)&(lp->dump), 0, sizeof(struct i596_dump));
-       outp = &(lp->dump.dump[0]);
-
-       PORT(va_to_pa(outp), portcmd);
-       mdelay(30);             /* random, unmotivated */
-
-       printk("lp486e i82596 %s result:\n", cmdname);
-       for (m = ARRAY_SIZE(lp->dump.dump); m && lp->dump.dump[m-1] == 0; m--)
-               ;
-       for (i = 0; i < m; i++) {
-               printk(" %04x", lp->dump.dump[i]);
-               if (i%8 == 7)
-                       printk("\n");
-       }
-       printk("\n");
-}
-#endif
-
-static int
-i596_scp_setup(struct net_device *dev) {
-       struct i596_private *lp = netdev_priv(dev);
-       int boguscnt;
-
-       /* Setup SCP, ISCP, SCB */
-       /*
-        * sysbus bits:
-        *  only a single byte is significant - here 0x44
-        *  0x80: big endian mode (details depend on stepping)
-        *  0x40: 1
-        *  0x20: interrupt pin is active low
-        *  0x10: lock function disabled
-        *  0x08: external triggering of bus throttle timers
-        *  0x06: 00: 82586 compat mode, 01: segmented mode, 10: linear mode
-        *  0x01: unused
-        */
-       lp->scp.sysbus = 0x00440000;            /* linear mode */
-       lp->scp.pad = 0;                        /* must be zero */
-       lp->scp.pa_iscp = va_to_pa(&(lp->iscp));
-
-       /*
-        * The CPU sets the ISCP to 1 before it gives the first CA()
-        */
-       lp->iscp.busy = 0x0001;
-       lp->iscp.pa_scb = va_to_pa(&(lp->scb));
-
-       lp->scb.command = 0;
-       lp->scb.status = 0;
-       lp->scb.pa_cmd = I596_NULL;
-       /* lp->scb.pa_rfd has been initialised already */
-
-       lp->last_cmd = jiffies;
-       lp->cmd_backlog = 0;
-       lp->cmd_head = NULL;
-
-       /*
-        * Reset the 82596.
-        * We need to wait 10 systemclock cycles, and
-        * 5 serial clock cycles.
-        */
-       PORT(0, PORT_RESET);    /* address part ignored */
-       udelay(100);
-
-       /*
-        * Before the CA signal is asserted, the default SCP address
-        * (0x00fffff4) can be changed to a 16-byte aligned value
-        */
-       PORT(va_to_pa(&lp->scp), PORT_ALTSCP);  /* change the scp address */
-
-       /*
-        * The initialization procedure begins when a
-        * Channel Attention signal is asserted after a reset.
-        */
-
-       CA();
-
-       /*
-        * The ISCP busy is cleared by the 82596 after the SCB address is read.
-        */
-       boguscnt = 100;
-       while (lp->iscp.busy) {
-               if (--boguscnt == 0) {
-                       /* No i82596 present? */
-                       printk("%s: i82596 initialization timed out\n",
-                              dev->name);
-                       return 1;
-               }
-               udelay(5);
-               barrier();
-       }
-       /* I find here boguscnt==100, so no delay was required. */
-
-       return 0;
-}
-
-static int
-init_i596(struct net_device *dev) {
-       struct i596_private *lp;
-
-       if (i596_scp_setup(dev))
-               return 1;
-
-       lp = netdev_priv(dev);
-       lp->scb.command = 0;
-
-       memcpy ((void *)lp->i596_config, init_setup, 14);
-       lp->set_conf.command = CmdConfigure;
-       i596_add_cmd(dev, (void *)&lp->set_conf);
-
-       memcpy ((void *)lp->eth_addr, dev->dev_addr, 6);
-       lp->set_add.command = CmdIASetup;
-       i596_add_cmd(dev, &lp->set_add);
-
-       lp->tdr.command = CmdTDR;
-       i596_add_cmd(dev, &lp->tdr);
-
-       if (lp->scb.command && i596_timeout(dev, "i82596 init", 200))
-               return 1;
-
-       lp->scb.command = RX_START;
-       CA();
-
-       barrier();
-
-       if (lp->scb.command && i596_timeout(dev, "Receive Unit start", 100))
-               return 1;
-
-       return 0;
-}
-
-/* Receive a single frame */
-static inline int
-i596_rx_one(struct net_device *dev, struct i596_private *lp,
-           struct i596_rfd *rfd, int *frames) {
-
-       if (rfd->stat & RFD_STAT_OK) {
-               /* a good frame */
-               int pkt_len = (rfd->count & 0x3fff);
-               struct sk_buff *skb = netdev_alloc_skb(dev, pkt_len);
-
-               (*frames)++;
-
-               if (rfd->cmd & CMD_EOL)
-                       printk("Received on EOL\n");
-
-               if (skb == NULL) {
-                       printk ("%s: i596_rx Memory squeeze, "
-                               "dropping packet.\n", dev->name);
-                       dev->stats.rx_dropped++;
-                       return 1;
-               }
-
-               memcpy(skb_put(skb,pkt_len), rfd->data, pkt_len);
-
-               skb->protocol = eth_type_trans(skb,dev);
-               netif_rx(skb);
-               dev->stats.rx_packets++;
-       } else {
-#if 0
-               printk("Frame reception error status %04x\n",
-                      rfd->stat);
-#endif
-               dev->stats.rx_errors++;
-               if (rfd->stat & RFD_COLLISION)
-                       dev->stats.collisions++;
-               if (rfd->stat & RFD_SHORT_FRAME_ERR)
-                       dev->stats.rx_length_errors++;
-               if (rfd->stat & RFD_DMA_ERR)
-                       dev->stats.rx_over_errors++;
-               if (rfd->stat & RFD_NOBUFS_ERR)
-                       dev->stats.rx_fifo_errors++;
-               if (rfd->stat & RFD_ALIGN_ERR)
-                       dev->stats.rx_frame_errors++;
-               if (rfd->stat & RFD_CRC_ERR)
-                       dev->stats.rx_crc_errors++;
-               if (rfd->stat & RFD_LENGTH_ERR)
-                       dev->stats.rx_length_errors++;
-       }
-       rfd->stat = rfd->count = 0;
-       return 0;
-}
-
-static int
-i596_rx(struct net_device *dev) {
-       struct i596_private *lp = netdev_priv(dev);
-       struct i596_rfd *rfd;
-       int frames = 0;
-
-       while (1) {
-               rfd = pa_to_va(lp->scb.pa_rfd);
-               if (!rfd) {
-                       printk(KERN_ERR "i596_rx: NULL rfd?\n");
-                       return 0;
-               }
-#if 1
-               if (rfd->stat && !(rfd->stat & (RFD_STAT_C | RFD_STAT_B)))
-                       printk("SF:%p-%04x\n", rfd, rfd->stat);
-#endif
-               if (!(rfd->stat & RFD_STAT_C))
-                       break;          /* next one not ready */
-               if (i596_rx_one(dev, lp, rfd, &frames))
-                       break;          /* out of memory */
-               rfd->cmd = CMD_EOL;
-               lp->rx_tail->cmd = 0;
-               lp->rx_tail = rfd;
-               lp->scb.pa_rfd = rfd->pa_next;
-               barrier();
-       }
-
-       return frames;
-}
-
-static void
-i596_cleanup_cmd(struct net_device *dev) {
-       struct i596_private *lp;
-       struct i596_cmd *cmd;
-
-       lp = netdev_priv(dev);
-       while (lp->cmd_head) {
-               cmd = lp->cmd_head;
-
-               lp->cmd_head = pa_to_va(lp->cmd_head->pa_next);
-               lp->cmd_backlog--;
-
-               switch ((cmd->command) & 0x7) {
-                       case CmdTx: {
-                               struct tx_cmd *tx_cmd = (struct tx_cmd *) cmd;
-                               struct i596_tbd * tx_cmd_tbd;
-                               tx_cmd_tbd = pa_to_va(tx_cmd->pa_tbd);
-
-                               dev_kfree_skb_any(tx_cmd_tbd->skb);
-
-                               dev->stats.tx_errors++;
-                               dev->stats.tx_aborted_errors++;
-
-                               cmd->pa_next = I596_NULL;
-                               kfree((unsigned char *)tx_cmd);
-                               netif_wake_queue(dev);
-                               break;
-                       }
-                       case CmdMulticastList: {
-                               // unsigned short count = *((unsigned short *) (ptr + 1));
-
-                               cmd->pa_next = I596_NULL;
-                               kfree((unsigned char *)cmd);
-                               break;
-                       }
-                       default: {
-                               cmd->pa_next = I596_NULL;
-                               break;
-                       }
-               }
-               barrier();
-       }
-
-       if (lp->scb.command && i596_timeout(dev, "i596_cleanup_cmd", 100))
-               ;
-
-       lp->scb.pa_cmd = va_to_pa(lp->cmd_head);
-}
-
-static void i596_reset(struct net_device *dev, struct i596_private *lp, int ioaddr) {
-
-       if (lp->scb.command && i596_timeout(dev, "i596_reset", 100))
-               ;
-
-       netif_stop_queue(dev);
-
-       lp->scb.command = CUC_ABORT | RX_ABORT;
-       CA();
-       barrier();
-
-       /* wait for shutdown */
-       if (lp->scb.command && i596_timeout(dev, "i596_reset(2)", 400))
-               ;
-
-       i596_cleanup_cmd(dev);
-       i596_rx(dev);
-
-       netif_start_queue(dev);
-       /*dev_kfree_skb(skb, FREE_WRITE);*/
-       init_i596(dev);
-}
-
-static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) {
-       struct i596_private *lp = netdev_priv(dev);
-       int ioaddr = dev->base_addr;
-       unsigned long flags;
-
-       cmd->status = 0;
-       cmd->command |= (CMD_EOL | CMD_INTR);
-       cmd->pa_next = I596_NULL;
-
-       spin_lock_irqsave(&lp->cmd_lock, flags);
-
-       if (lp->cmd_head) {
-               lp->cmd_tail->pa_next = va_to_pa(cmd);
-       } else {
-               lp->cmd_head = cmd;
-               if (lp->scb.command && i596_timeout(dev, "i596_add_cmd", 100))
-                       ;
-               lp->scb.pa_cmd = va_to_pa(cmd);
-               lp->scb.command = CUC_START;
-               CA();
-       }
-       lp->cmd_tail = cmd;
-       lp->cmd_backlog++;
-
-       lp->cmd_head = pa_to_va(lp->scb.pa_cmd);
-       spin_unlock_irqrestore(&lp->cmd_lock, flags);
-
-       if (lp->cmd_backlog > 16) {
-               int tickssofar = jiffies - lp->last_cmd;
-               if (tickssofar < HZ/4)
-                       return;
-
-               printk(KERN_WARNING "%s: command unit timed out, status resetting.\n", dev->name);
-               i596_reset(dev, lp, ioaddr);
-       }
-}
-
-static int i596_open(struct net_device *dev)
-{
-       int i;
-
-       i = request_irq(dev->irq, i596_interrupt, IRQF_SHARED, dev->name, dev);
-       if (i) {
-               printk(KERN_ERR "%s: IRQ %d not free\n", dev->name, dev->irq);
-               return i;
-       }
-
-       if ((i = init_rx_bufs(dev, RX_RING_SIZE)) < RX_RING_SIZE)
-               printk(KERN_ERR "%s: only able to allocate %d receive buffers\n", dev->name, i);
-
-       if (i < 4) {
-               free_irq(dev->irq, dev);
-               return -EAGAIN;
-       }
-       netif_start_queue(dev);
-       init_i596(dev);
-       return 0;                       /* Always succeed */
-}
-
-static netdev_tx_t i596_start_xmit (struct sk_buff *skb, struct net_device *dev) {
-       struct tx_cmd *tx_cmd;
-       short length;
-
-       length = skb->len;
-
-       if (length < ETH_ZLEN) {
-               if (skb_padto(skb, ETH_ZLEN))
-                       return NETDEV_TX_OK;
-               length = ETH_ZLEN;
-       }
-
-       tx_cmd = kmalloc((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC);
-       if (tx_cmd == NULL) {
-               printk(KERN_WARNING "%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name);
-               dev->stats.tx_dropped++;
-               dev_kfree_skb (skb);
-       } else {
-               struct i596_tbd *tx_cmd_tbd;
-               tx_cmd_tbd = (struct i596_tbd *) (tx_cmd + 1);
-               tx_cmd->pa_tbd = va_to_pa (tx_cmd_tbd);
-               tx_cmd_tbd->pa_next = I596_NULL;
-
-               tx_cmd->cmd.command = (CMD_FLEX | CmdTx);
-
-               tx_cmd->pad = 0;
-               tx_cmd->size = 0;
-               tx_cmd_tbd->pad = 0;
-               tx_cmd_tbd->size = (EOF | length);
-
-               tx_cmd_tbd->pa_data = va_to_pa (skb->data);
-               tx_cmd_tbd->skb = skb;
-
-               if (i596_debug & LOG_SRCDST)
-                       print_eth (skb->data);
-
-               i596_add_cmd (dev, (struct i596_cmd *) tx_cmd);
-
-               dev->stats.tx_packets++;
-       }
-
-       return NETDEV_TX_OK;
-}
-
-static void
-i596_tx_timeout (struct net_device *dev) {
-       struct i596_private *lp = netdev_priv(dev);
-       int ioaddr = dev->base_addr;
-
-       /* Transmitter timeout, serious problems. */
-       printk(KERN_WARNING "%s: transmit timed out, status resetting.\n", dev->name);
-       dev->stats.tx_errors++;
-
-       /* Try to restart the adaptor */
-       if (lp->last_restart == dev->stats.tx_packets) {
-               printk ("Resetting board.\n");
-
-               /* Shutdown and restart */
-               i596_reset (dev, lp, ioaddr);
-       } else {
-               /* Issue a channel attention signal */
-               printk ("Kicking board.\n");
-               lp->scb.command = (CUC_START | RX_START);
-               CA();
-               lp->last_restart = dev->stats.tx_packets;
-       }
-       netif_wake_queue(dev);
-}
-
-static void print_eth(char *add)
-{
-       int i;
-
-       printk ("Dest  ");
-       for (i = 0; i < 6; i++)
-               printk(" %2.2X", (unsigned char) add[i]);
-       printk ("\n");
-
-       printk ("Source");
-       for (i = 0; i < 6; i++)
-               printk(" %2.2X", (unsigned char) add[i+6]);
-       printk ("\n");
-
-       printk ("type %2.2X%2.2X\n",
-               (unsigned char) add[12], (unsigned char) add[13]);
-}
-
-static const struct net_device_ops i596_netdev_ops = {
-       .ndo_open               = i596_open,
-       .ndo_stop               = i596_close,
-       .ndo_start_xmit         = i596_start_xmit,
-       .ndo_set_rx_mode        = set_multicast_list,
-       .ndo_tx_timeout         = i596_tx_timeout,
-       .ndo_change_mtu         = eth_change_mtu,
-       .ndo_set_mac_address    = eth_mac_addr,
-       .ndo_validate_addr      = eth_validate_addr,
-};
-
-static int __init lp486e_probe(struct net_device *dev) {
-       struct i596_private *lp;
-       unsigned char eth_addr[6] = { 0, 0xaa, 0, 0, 0, 0 };
-       unsigned char *bios;
-       int i, j;
-       int ret = -ENOMEM;
-       static int probed;
-
-       if (probed)
-               return -ENODEV;
-       probed++;
-
-       if (!request_region(IOADDR, LP486E_TOTAL_SIZE, DRV_NAME)) {
-               printk(KERN_ERR "lp486e: IO address 0x%x in use\n", IOADDR);
-               return -EBUSY;
-       }
-
-       lp = netdev_priv(dev);
-       spin_lock_init(&lp->cmd_lock);
-
-       /*
-        * Do we really have this thing?
-        */
-       if (i596_scp_setup(dev)) {
-               ret = -ENODEV;
-               goto err_out_kfree;
-       }
-
-       dev->base_addr = IOADDR;
-       dev->irq = IRQ;
-
-
-       /*
-        * How do we find the ethernet address? I don't know.
-        * One possibility is to look at the EISA configuration area
-        * [0xe8000-0xe9fff]. This contains the ethernet address
-        * but not at a fixed address - things depend on setup options.
-        *
-        * If we find no address, or the wrong address, use
-        *   ifconfig eth0 hw ether a1:a2:a3:a4:a5:a6
-        * with the value found in the BIOS setup.
-        */
-       bios = bus_to_virt(0xe8000);
-       for (j = 0; j < 0x2000; j++) {
-               if (bios[j] == 0 && bios[j+1] == 0xaa && bios[j+2] == 0) {
-                       printk("%s: maybe address at BIOS 0x%x:",
-                              dev->name, 0xe8000+j);
-                       for (i = 0; i < 6; i++) {
-                               eth_addr[i] = bios[i+j];
-                               printk(" %2.2X", eth_addr[i]);
-                       }
-                       printk("\n");
-               }
-       }
-
-       printk("%s: lp486e 82596 at %#3lx, IRQ %d,",
-              dev->name, dev->base_addr, dev->irq);
-       for (i = 0; i < 6; i++)
-               printk(" %2.2X", dev->dev_addr[i] = eth_addr[i]);
-       printk("\n");
-
-       /* The LP486E-specific entries in the device structure. */
-       dev->netdev_ops = &i596_netdev_ops;
-       dev->watchdog_timeo = 5*HZ;
-
-#if 0
-       /* selftest reports 0x320925ae - don't know what that means */
-       i596_port_do(dev, PORT_SELFTEST, "selftest");
-       i596_port_do(dev, PORT_DUMP, "dump");
-#endif
-       return 0;
-
-err_out_kfree:
-       release_region(IOADDR, LP486E_TOTAL_SIZE);
-       return ret;
-}
-
-static inline void
-i596_handle_CU_completion(struct net_device *dev,
-                         struct i596_private *lp,
-                         unsigned short status,
-                         unsigned short *ack_cmdp) {
-       struct i596_cmd *cmd;
-       int frames_out = 0;
-       int commands_done = 0;
-       int cmd_val;
-       unsigned long flags;
-
-       spin_lock_irqsave(&lp->cmd_lock, flags);
-       cmd = lp->cmd_head;
-
-       while (lp->cmd_head && (lp->cmd_head->status & CMD_STAT_C)) {
-               cmd = lp->cmd_head;
-
-               lp->cmd_head = pa_to_va(lp->cmd_head->pa_next);
-               lp->cmd_backlog--;
-
-               commands_done++;
-               cmd_val = cmd->command & 0x7;
-#if 0
-               printk("finished CU %s command (%d)\n",
-                      CUcmdnames[cmd_val], cmd_val);
-#endif
-               switch (cmd_val) {
-               case CmdTx:
-               {
-                       struct tx_cmd *tx_cmd;
-                       struct i596_tbd *tx_cmd_tbd;
-
-                       tx_cmd = (struct tx_cmd *) cmd;
-                       tx_cmd_tbd = pa_to_va(tx_cmd->pa_tbd);
-
-                       frames_out++;
-                       if (cmd->status & CMD_STAT_OK) {
-                               if (i596_debug)
-                                       print_eth(pa_to_va(tx_cmd_tbd->pa_data));
-                       } else {
-                               dev->stats.tx_errors++;
-                               if (i596_debug)
-                                       printk("transmission failure:%04x\n",
-                                              cmd->status);
-                               if (cmd->status & 0x0020)
-                                       dev->stats.collisions++;
-                               if (!(cmd->status & 0x0040))
-                                       dev->stats.tx_heartbeat_errors++;
-                               if (cmd->status & 0x0400)
-                                       dev->stats.tx_carrier_errors++;
-                               if (cmd->status & 0x0800)
-                                       dev->stats.collisions++;
-                               if (cmd->status & 0x1000)
-                                       dev->stats.tx_aborted_errors++;
-                       }
-                       dev_kfree_skb_irq(tx_cmd_tbd->skb);
-
-                       cmd->pa_next = I596_NULL;
-                       kfree((unsigned char *)tx_cmd);
-                       netif_wake_queue(dev);
-                       break;
-               }
-
-               case CmdMulticastList:
-                       cmd->pa_next = I596_NULL;
-                       kfree((unsigned char *)cmd);
-                       break;
-
-               case CmdTDR:
-               {
-                       unsigned long status = *((unsigned long *) (cmd + 1));
-                       if (status & 0x8000) {
-                               if (i596_debug)
-                                       printk("%s: link ok.\n", dev->name);
-                       } else {
-                               if (status & 0x4000)
-                                       printk("%s: Transceiver problem.\n",
-                                              dev->name);
-                               if (status & 0x2000)
-                                       printk("%s: Termination problem.\n",
-                                              dev->name);
-                               if (status & 0x1000)
-                                       printk("%s: Short circuit.\n",
-                                              dev->name);
-                               printk("%s: Time %ld.\n",
-                                      dev->name, status & 0x07ff);
-                       }
-               }
-               default:
-                       cmd->pa_next = I596_NULL;
-                       lp->last_cmd = jiffies;
-
-               }
-               barrier();
-       }
-
-       cmd = lp->cmd_head;
-       while (cmd && (cmd != lp->cmd_tail)) {
-               cmd->command &= 0x1fff;
-               cmd = pa_to_va(cmd->pa_next);
-               barrier();
-       }
-
-       if (lp->cmd_head)
-               *ack_cmdp |= CUC_START;
-       lp->scb.pa_cmd = va_to_pa(lp->cmd_head);
-       spin_unlock_irqrestore(&lp->cmd_lock, flags);
-}
-
-static irqreturn_t
-i596_interrupt(int irq, void *dev_instance)
-{
-       struct net_device *dev = dev_instance;
-       struct i596_private *lp = netdev_priv(dev);
-       unsigned short status, ack_cmd = 0;
-       int frames_in = 0;
-
-       /*
-        * The 82596 examines the command, performs the required action,
-        * and then clears the SCB command word.
-        */
-       if (lp->scb.command && i596_timeout(dev, "interrupt", 40))
-               ;
-
-       /*
-        * The status word indicates the status of the 82596.
-        * It is modified only by the 82596.
-        *
-        * [So, we must not clear it. I find often status 0xffff,
-        *  which is not one of the values allowed by the docs.]
-        */
-       status = lp->scb.status;
-#if 0
-       if (i596_debug) {
-               printk("%s: i596 interrupt, ", dev->name);
-               i596_out_status(status);
-       }
-#endif
-       /* Impossible, but it happens - perhaps when we get
-          a receive interrupt but scb.pa_rfd is I596_NULL. */
-       if (status == 0xffff) {
-               printk("%s: i596_interrupt: got status 0xffff\n", dev->name);
-               goto out;
-       }
-
-       ack_cmd = (status & STAT_ACK);
-
-       if (status & (STAT_CX | STAT_CNA))
-               i596_handle_CU_completion(dev, lp, status, &ack_cmd);
-
-       if (status & (STAT_FR | STAT_RNR)) {
-               /* Restart the receive unit when it got inactive somehow */
-               if ((status & STAT_RNR) && netif_running(dev))
-                       ack_cmd |= RX_START;
-
-               if (status & STAT_FR) {
-                       frames_in = i596_rx(dev);
-                       if (!frames_in)
-                               printk("receive frame reported, but no frames\n");
-               }
-       }
-
-       /* acknowledge the interrupt */
-       /*
-       if ((lp->scb.pa_cmd != I596_NULL) && netif_running(dev))
-               ack_cmd |= CUC_START;
-       */
-
-       if (lp->scb.command && i596_timeout(dev, "i596 interrupt", 100))
-               ;
-
-       lp->scb.command = ack_cmd;
-
-       CLEAR_INT();
-       CA();
-
- out:
-       return IRQ_HANDLED;
-}
-
-static int i596_close(struct net_device *dev) {
-       struct i596_private *lp = netdev_priv(dev);
-
-       netif_stop_queue(dev);
-
-       if (i596_debug)
-               printk("%s: Shutting down ethercard, status was %4.4x.\n",
-                      dev->name, lp->scb.status);
-
-       lp->scb.command = (CUC_ABORT | RX_ABORT);
-       CA();
-
-       i596_cleanup_cmd(dev);
-
-       if (lp->scb.command && i596_timeout(dev, "i596_close", 200))
-               ;
-
-       free_irq(dev->irq, dev);
-       remove_rx_bufs(dev);
-
-       return 0;
-}
-
-/*
-*      Set or clear the multicast filter for this adaptor.
-*/
-
-static void set_multicast_list(struct net_device *dev) {
-       struct i596_private *lp = netdev_priv(dev);
-       struct i596_cmd *cmd;
-
-       if (i596_debug > 1)
-               printk ("%s: set multicast list %d\n",
-                       dev->name, netdev_mc_count(dev));
-
-       if (!netdev_mc_empty(dev)) {
-               struct netdev_hw_addr *ha;
-               char *cp;
-               cmd = kmalloc(sizeof(struct i596_cmd) + 2 +
-                             netdev_mc_count(dev) * 6, GFP_ATOMIC);
-               if (cmd == NULL) {
-                       printk (KERN_ERR "%s: set_multicast Memory squeeze.\n", dev->name);
-                       return;
-               }
-               cmd->command = CmdMulticastList;
-               *((unsigned short *) (cmd + 1)) = netdev_mc_count(dev) * 6;
-               cp = ((char *)(cmd + 1))+2;
-               netdev_for_each_mc_addr(ha, dev) {
-                       memcpy(cp, ha->addr, 6);
-                       cp += 6;
-               }
-               if (i596_debug & LOG_SRCDST)
-                       print_eth (((char *)(cmd + 1)) + 2);
-               i596_add_cmd(dev, cmd);
-       } else {
-               if (lp->set_conf.pa_next != I596_NULL) {
-                       return;
-               }
-               if (netdev_mc_empty(dev) &&
-                   !(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) {
-                       lp->i596_config[8] &= ~0x01;
-               } else {
-                       lp->i596_config[8] |= 0x01;
-               }
-
-               i596_add_cmd(dev, &lp->set_conf);
-       }
-}
-
-MODULE_AUTHOR("Ard van Breemen <ard@cstmel.nl.eu.org>");
-MODULE_DESCRIPTION("Intel Panther onboard i82596 driver");
-MODULE_LICENSE("GPL");
-
-static struct net_device *dev_lp486e;
-static int full_duplex;
-static int options;
-static int io = IOADDR;
-static int irq = IRQ;
-
-module_param(debug, int, 0);
-//module_param(max_interrupt_work, int, 0);
-//module_param(reverse_probe, int, 0);
-//module_param(rx_copybreak, int, 0);
-module_param(options, int, 0);
-module_param(full_duplex, int, 0);
-
-static int __init lp486e_init_module(void) {
-       int err;
-       struct net_device *dev = alloc_etherdev(sizeof(struct i596_private));
-       if (!dev)
-               return -ENOMEM;
-
-       dev->irq = irq;
-       dev->base_addr = io;
-       err = lp486e_probe(dev);
-       if (err) {
-               free_netdev(dev);
-               return err;
-       }
-       err = register_netdev(dev);
-       if (err) {
-               release_region(dev->base_addr, LP486E_TOTAL_SIZE);
-               free_netdev(dev);
-               return err;
-       }
-       dev_lp486e = dev;
-       full_duplex = 0;
-       options = 0;
-       return 0;
-}
-
-static void __exit lp486e_cleanup_module(void) {
-       unregister_netdev(dev_lp486e);
-       release_region(dev_lp486e->base_addr, LP486E_TOTAL_SIZE);
-       free_netdev(dev_lp486e);
-}
-
-module_init(lp486e_init_module);
-module_exit(lp486e_cleanup_module);