fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / net / ewrk3.c
index d896baa..c8c41f0 100644 (file)
 #include <linux/types.h>
 #include <linux/unistd.h>
 #include <linux/ctype.h>
+#include <linux/bitops.h>
 
-#include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/uaccess.h>
@@ -202,7 +202,6 @@ static int ewrk3_debug = 1;
 #define EWRK3_IOP_INC 0x20     /* I/O address increment */
 #define EWRK3_TOTAL_SIZE 0x20  /* required I/O address length */
 
-/* If you change this, remember to also change MODULE_PARM array limits */
 #ifndef MAX_NUM_EWRK3S
 #define MAX_NUM_EWRK3S 21
 #endif
@@ -274,6 +273,7 @@ struct ewrk3_stats {
 struct ewrk3_private {
        char adapter_name[80];  /* Name exported to /proc/ioports */
        u_long shmem_base;      /* Shared memory start address */
+       void __iomem *shmem;
        u_long shmem_length;    /* Shared memory window length */
        struct net_device_stats stats;  /* Public stats */
        struct ewrk3_stats pktStats; /* Private stats counters */
@@ -282,7 +282,7 @@ struct ewrk3_private {
        u_char lemac;           /* Chip rev. level */
        u_char hard_strapped;   /* Don't allow a full open */
        u_char txc;             /* Transmit cut through */
-       u_char *mctbl;          /* Pointer to the multicast table */
+       void __iomem *mctbl;    /* Pointer to the multicast table */
        u_char led_mask;        /* Used to reserve LED access for ethtool */
        spinlock_t hw_lock;
 };
@@ -300,11 +300,13 @@ struct ewrk3_private {
  */
 static int ewrk3_open(struct net_device *dev);
 static int ewrk3_queue_pkt(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t ewrk3_interrupt(int irq, void *dev_id);
 static int ewrk3_close(struct net_device *dev);
 static struct net_device_stats *ewrk3_get_stats(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static const struct ethtool_ops ethtool_ops_203;
+static const struct ethtool_ops ethtool_ops;
 
 /*
    ** Private functions
@@ -357,13 +359,13 @@ struct net_device * __init ewrk3_probe(int unit)
        SET_MODULE_OWNER(dev);
 
        err = ewrk3_probe1(dev, dev->base_addr, dev->irq);
-       if (err) 
+       if (err)
                goto out;
        return dev;
 out:
        free_netdev(dev);
        return ERR_PTR(err);
-       
+
 }
 #endif
 
@@ -376,7 +378,7 @@ static int __init ewrk3_probe1(struct net_device *dev, u_long iobase, int irq)
 
        /* Address PROM pattern */
        err = isa_probe(dev, iobase);
-       if (err != 0) 
+       if (err != 0)
                err = eisa_probe(dev, iobase);
 
        if (err)
@@ -389,7 +391,7 @@ static int __init ewrk3_probe1(struct net_device *dev, u_long iobase, int irq)
        return err;
 }
 
-static int __init 
+static int __init
 ewrk3_hw_init(struct net_device *dev, u_long iobase)
 {
        struct ewrk3_private *lp;
@@ -433,19 +435,19 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
                printk("%s: Device has a bad on-board EEPROM.\n", dev->name);
                return -ENXIO;
        }
-       
+
        EthwrkSignature(name, eeprom_image);
-       if (*name == '\0') 
+       if (*name == '\0')
                return -ENXIO;
 
        dev->base_addr = iobase;
-                               
+
        if (iobase > 0x400) {
                outb(eisa_cr, EISA_CR);         /* Rewrite the EISA CR */
        }
        lemac = eeprom_image[EEPROM_CHIPVER];
        cmr = inb(EWRK3_CMR);
-       
+
        if (((lemac == LeMAC) && ((cmr & CMR_NO_EEPROM) != CMR_NO_EEPROM)) ||
            ((lemac == LeMAC2) && !(cmr & CMR_HS))) {
                printk("%s: %s at %#4lx", dev->name, name, iobase);
@@ -466,7 +468,7 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
                printk("%2.2x:", dev->dev_addr[i]);
        }
        printk("%2.2x,\n", dev->dev_addr[i]);
-       
+
        if (status) {
                printk("      which has an EEPROM CRC error.\n");
                return -ENXIO;
@@ -488,7 +490,7 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
        if (eeprom_image[EEPROM_SETUP] & SETUP_DRAM)
                cmr |= CMR_DRAM;
        outb(cmr, EWRK3_CMR);
-       
+
        cr = inb(EWRK3_CR);     /* Set up the Control Register */
        cr |= eeprom_image[EEPROM_SETUP] & SETUP_APD;
        if (cr & SETUP_APD)
@@ -522,7 +524,7 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
        ** uncommenting this line.
        */
 /*          FORCE_2K_MODE; */
-       
+
        if (hard_strapped) {
                printk("      is hard strapped.\n");
        } else if (mem_start) {
@@ -532,51 +534,54 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
                printk("      is in I/O only mode");
        }
 
-       lp = (struct ewrk3_private *) dev->priv;
+       lp = netdev_priv(dev);
        lp->shmem_base = mem_start;
+       lp->shmem = ioremap(mem_start, shmem_length);
+       if (!lp->shmem)
+               return -ENOMEM;
        lp->shmem_length = shmem_length;
        lp->lemac = lemac;
        lp->hard_strapped = hard_strapped;
        lp->led_mask = CR_LED;
        spin_lock_init(&lp->hw_lock);
-       
+
        lp->mPage = 64;
        if (cmr & CMR_DRAM)
                lp->mPage <<= 1;        /* 2 DRAMS on module */
-       
+
        sprintf(lp->adapter_name, "%s (%s)", name, dev->name);
-       
+
        lp->irq_mask = ICR_TNEM | ICR_TXDM | ICR_RNEM | ICR_RXDM;
-       
+
        if (!hard_strapped) {
                /*
                ** Enable EWRK3 board interrupts for autoprobing
                */
                icr |= ICR_IE;  /* Enable interrupts */
                outb(icr, EWRK3_ICR);
-               
+
                /* The DMA channel may be passed in on this parameter. */
                dev->dma = 0;
-               
+
                /* To auto-IRQ we enable the initialization-done and DMA err,
                   interrupts. For now we will always get a DMA error. */
                if (dev->irq < 2) {
 #ifndef MODULE
                        u_char irqnum;
                        unsigned long irq_mask;
-                       
+
 
                        irq_mask = probe_irq_on();
-                       
+
                        /*
                        ** Trigger a TNE interrupt.
                        */
                        icr |= ICR_TNEM;
                        outb(1, EWRK3_TDQ);     /* Write to the TX done queue */
                        outb(icr, EWRK3_ICR);   /* Unmask the TXD interrupt */
-                       
+
                        irqnum = irq[((icr & IRQ_SEL) >> 4)];
-                       
+
                        mdelay(20);
                        dev->irq = probe_irq_off(irq_mask);
                        if ((dev->irq) && (irqnum == dev->irq)) {
@@ -589,6 +594,7 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
                                } else {
                                        printk(", but incorrect IRQ line detected.\n");
                                }
+                               iounmap(lp->shmem);
                                return -ENXIO;
                        }
 
@@ -610,18 +616,22 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
        dev->get_stats = ewrk3_get_stats;
        dev->set_multicast_list = set_multicast_list;
        dev->do_ioctl = ewrk3_ioctl;
+       if (lp->adapter_name[4] == '3')
+               SET_ETHTOOL_OPS(dev, &ethtool_ops_203);
+       else
+               SET_ETHTOOL_OPS(dev, &ethtool_ops);
        dev->tx_timeout = ewrk3_timeout;
        dev->watchdog_timeo = QUEUE_PKT_TIMEOUT;
-       
+
        dev->mem_start = 0;
 
        return 0;
 }
-\f
+
 
 static int ewrk3_open(struct net_device *dev)
 {
-       struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+       struct ewrk3_private *lp = netdev_priv(dev);
        u_long iobase = dev->base_addr;
        int i, status = 0;
        u_char icr, csr;
@@ -684,7 +694,7 @@ static int ewrk3_open(struct net_device *dev)
  */
 static void ewrk3_init(struct net_device *dev)
 {
-       struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+       struct ewrk3_private *lp = netdev_priv(dev);
        u_char csr, page;
        u_long iobase = dev->base_addr;
        int i;
@@ -722,14 +732,14 @@ static void ewrk3_init(struct net_device *dev)
 /*
  *  Transmit timeout
  */
+
 static void ewrk3_timeout(struct net_device *dev)
 {
-       struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+       struct ewrk3_private *lp = netdev_priv(dev);
        u_char icr, csr;
        u_long iobase = dev->base_addr;
-       
-       if (!lp->hard_strapped) 
+
+       if (!lp->hard_strapped)
        {
                printk(KERN_WARNING"%s: transmit timed/locked out, status %04x, resetting.\n",
                       dev->name, inb(EWRK3_CSR));
@@ -761,9 +771,9 @@ static void ewrk3_timeout(struct net_device *dev)
  */
 static int ewrk3_queue_pkt (struct sk_buff *skb, struct net_device *dev)
 {
-       struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+       struct ewrk3_private *lp = netdev_priv(dev);
        u_long iobase = dev->base_addr;
-       u_long buf = 0;
+       void __iomem *buf = NULL;
        u_char icr;
        u_char page;
 
@@ -796,13 +806,13 @@ static int ewrk3_queue_pkt (struct sk_buff *skb, struct net_device *dev)
        if (lp->shmem_length == IO_ONLY) {
                outb (page, EWRK3_IOPR);
        } else if (lp->shmem_length == SHMEM_2K) {
-               buf = lp->shmem_base;
+               buf = lp->shmem;
                outb (page, EWRK3_MPR);
        } else if (lp->shmem_length == SHMEM_32K) {
-               buf = ((((short) page << 11) & 0x7800) + lp->shmem_base);
+               buf = (((short) page << 11) & 0x7800) + lp->shmem;
                outb ((page >> 4), EWRK3_MPR);
        } else if (lp->shmem_length == SHMEM_64K) {
-               buf = ((((short) page << 11) & 0xf800) + lp->shmem_base);
+               buf = (((short) page << 11) & 0xf800) + lp->shmem;
                outb ((page >> 5), EWRK3_MPR);
        } else {
                printk (KERN_ERR "%s: Oops - your private data area is hosed!\n",
@@ -826,30 +836,28 @@ static int ewrk3_queue_pkt (struct sk_buff *skb, struct net_device *dev)
                }
                outb (page, EWRK3_TQ);  /* Start sending pkt */
        } else {
-               isa_writeb ((char) (TCR_QMODE | TCR_PAD | TCR_IFC), buf);       /* ctrl byte */
+               writeb ((char) (TCR_QMODE | TCR_PAD | TCR_IFC), buf);   /* ctrl byte */
                buf += 1;
-               isa_writeb ((char) (skb->len & 0xff), buf);     /* length (16 bit xfer) */
+               writeb ((char) (skb->len & 0xff), buf); /* length (16 bit xfer) */
                buf += 1;
                if (lp->txc) {
-                       isa_writeb ((char)
-                                   (((skb->len >> 8) & 0xff) | XCT), buf);
+                       writeb(((skb->len >> 8) & 0xff) | XCT, buf);
                        buf += 1;
-                       isa_writeb (0x04, buf); /* index byte */
+                       writeb (0x04, buf);     /* index byte */
                        buf += 1;
-                       isa_writeb (0x00, (buf + skb->len));    /* Write the XCT flag */
-                       isa_memcpy_toio (buf, skb->data, PRELOAD);      /* Write PRELOAD bytes */
+                       writeb (0x00, (buf + skb->len));        /* Write the XCT flag */
+                       memcpy_toio (buf, skb->data, PRELOAD);  /* Write PRELOAD bytes */
                        outb (page, EWRK3_TQ);  /* Start sending pkt */
-                       isa_memcpy_toio (buf + PRELOAD,
+                       memcpy_toio (buf + PRELOAD,
                                         skb->data + PRELOAD,
                                         skb->len - PRELOAD);
-                       isa_writeb (0xff, (buf + skb->len));    /* Write the XCT flag */
+                       writeb (0xff, (buf + skb->len));        /* Write the XCT flag */
                } else {
-                       isa_writeb ((char)
-                                   ((skb->len >> 8) & 0xff), buf);
+                       writeb ((skb->len >> 8) & 0xff, buf);
                        buf += 1;
-                       isa_writeb (0x04, buf); /* index byte */
+                       writeb (0x04, buf);     /* index byte */
                        buf += 1;
-                       isa_memcpy_toio (buf, skb->data, skb->len);     /* Write data bytes */
+                       memcpy_toio (buf, skb->data, skb->len); /* Write data bytes */
                        outb (page, EWRK3_TQ);  /* Start sending pkt */
                }
        }
@@ -876,14 +884,14 @@ err_out:
 /*
    ** The EWRK3 interrupt handler.
  */
-static irqreturn_t ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ewrk3_interrupt(int irq, void *dev_id)
 {
        struct net_device *dev = dev_id;
        struct ewrk3_private *lp;
        u_long iobase;
        u_char icr, cr, csr;
 
-       lp = (struct ewrk3_private *) dev->priv;
+       lp = netdev_priv(dev);
        iobase = dev->base_addr;
 
        /* get the interrupt information */
@@ -931,11 +939,11 @@ static irqreturn_t ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 /* Called with lp->hw_lock held */
 static int ewrk3_rx(struct net_device *dev)
 {
-       struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+       struct ewrk3_private *lp = netdev_priv(dev);
        u_long iobase = dev->base_addr;
        int i, status = 0;
        u_char page;
-       u_long buf = 0;
+       void __iomem *buf = NULL;
 
        while (inb(EWRK3_RQC) && !status) {     /* Whilst there's incoming data */
                if ((page = inb(EWRK3_RQ)) < lp->mPage) {       /* Get next entry's buffer page */
@@ -945,13 +953,13 @@ static int ewrk3_rx(struct net_device *dev)
                        if (lp->shmem_length == IO_ONLY) {
                                outb(page, EWRK3_IOPR);
                        } else if (lp->shmem_length == SHMEM_2K) {
-                               buf = lp->shmem_base;
+                               buf = lp->shmem;
                                outb(page, EWRK3_MPR);
                        } else if (lp->shmem_length == SHMEM_32K) {
-                               buf = ((((short) page << 11) & 0x7800) + lp->shmem_base);
+                               buf = (((short) page << 11) & 0x7800) + lp->shmem;
                                outb((page >> 4), EWRK3_MPR);
                        } else if (lp->shmem_length == SHMEM_64K) {
-                               buf = ((((short) page << 11) & 0xf800) + lp->shmem_base);
+                               buf = (((short) page << 11) & 0xf800) + lp->shmem;
                                outb((page >> 5), EWRK3_MPR);
                        } else {
                                status = -1;
@@ -967,9 +975,9 @@ static int ewrk3_rx(struct net_device *dev)
                                        pkt_len = inb(EWRK3_DATA);
                                        pkt_len |= ((u_short) inb(EWRK3_DATA) << 8);
                                } else {
-                                       rx_status = isa_readb(buf);
+                                       rx_status = readb(buf);
                                        buf += 1;
-                                       pkt_len = isa_readw(buf);
+                                       pkt_len = readw(buf);
                                        buf += 3;
                                }
 
@@ -996,7 +1004,7 @@ static int ewrk3_rx(struct net_device *dev)
                                                                *p++ = inb(EWRK3_DATA);
                                                        }
                                                } else {
-                                                       isa_memcpy_fromio(p, buf, pkt_len);
+                                                       memcpy_fromio(p, buf, pkt_len);
                                                }
 
                                                for (i = 1; i < EWRK3_PKT_STAT_SZ - 1; i++) {
@@ -1059,7 +1067,7 @@ static int ewrk3_rx(struct net_device *dev)
 */
 static int ewrk3_tx(struct net_device *dev)
 {
-       struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+       struct ewrk3_private *lp = netdev_priv(dev);
        u_long iobase = dev->base_addr;
        u_char tx_status;
 
@@ -1095,12 +1103,12 @@ static int ewrk3_tx(struct net_device *dev)
 
 static int ewrk3_close(struct net_device *dev)
 {
-       struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+       struct ewrk3_private *lp = netdev_priv(dev);
        u_long iobase = dev->base_addr;
        u_char icr, csr;
 
        netif_stop_queue(dev);
-       
+
        if (ewrk3_debug > 1) {
                printk("%s: Shutting down ethercard, status was %2.2x.\n",
                       dev->name, inb(EWRK3_CSR));
@@ -1130,7 +1138,7 @@ static int ewrk3_close(struct net_device *dev)
 
 static struct net_device_stats *ewrk3_get_stats(struct net_device *dev)
 {
-       struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+       struct ewrk3_private *lp = netdev_priv(dev);
 
        /* Null body since there is no framing error counter */
        return &lp->stats;
@@ -1141,16 +1149,16 @@ static struct net_device_stats *ewrk3_get_stats(struct net_device *dev)
  */
 static void set_multicast_list(struct net_device *dev)
 {
-       struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+       struct ewrk3_private *lp = netdev_priv(dev);
        u_long iobase = dev->base_addr;
        u_char csr;
 
        csr = inb(EWRK3_CSR);
 
        if (lp->shmem_length == IO_ONLY) {
-               lp->mctbl = (char *) PAGE0_HTE;
+               lp->mctbl = NULL;
        } else {
-               lp->mctbl = (char *) (lp->shmem_base + PAGE0_HTE);
+               lp->mctbl = lp->shmem + PAGE0_HTE;
        }
 
        csr &= ~(CSR_PME | CSR_MCE);
@@ -1174,12 +1182,12 @@ static void set_multicast_list(struct net_device *dev)
  */
 static void SetMulticastFilter(struct net_device *dev)
 {
-       struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+       struct ewrk3_private *lp = netdev_priv(dev);
        struct dev_mc_list *dmi = dev->mc_list;
        u_long iobase = dev->base_addr;
        int i;
        char *addrs, bit, byte;
-       short *p = (short *) lp->mctbl;
+       short __iomem *p = lp->mctbl;
        u16 hashcode;
        u32 crc;
 
@@ -1187,7 +1195,7 @@ static void SetMulticastFilter(struct net_device *dev)
 
        if (lp->shmem_length == IO_ONLY) {
                outb(0, EWRK3_IOPR);
-               outw(EEPROM_OFFSET(lp->mctbl), EWRK3_PIR1);
+               outw(PAGE0_HTE, EWRK3_PIR1);
        } else {
                outb(0, EWRK3_MPR);
        }
@@ -1197,7 +1205,7 @@ static void SetMulticastFilter(struct net_device *dev)
                        if (lp->shmem_length == IO_ONLY) {
                                outb(0xff, EWRK3_DATA);
                        } else {        /* memset didn't work here */
-                               isa_writew(0xffff, (int) p);
+                               writew(0xffff, p);
                                p++;
                                i++;
                        }
@@ -1214,8 +1222,8 @@ static void SetMulticastFilter(struct net_device *dev)
                                outb(0x00, EWRK3_DATA);
                        }
                } else {
-                       isa_memset_io((int) lp->mctbl, 0, (HASH_TABLE_LEN >> 3));
-                       isa_writeb(0x80, (int) (lp->mctbl + (HASH_TABLE_LEN >> 4) - 1));
+                       memset_io(lp->mctbl, 0, HASH_TABLE_LEN >> 3);
+                       writeb(0x80, lp->mctbl + (HASH_TABLE_LEN >> 4) - 1);
                }
 
                /* Update table */
@@ -1232,13 +1240,13 @@ static void SetMulticastFilter(struct net_device *dev)
                                if (lp->shmem_length == IO_ONLY) {
                                        u_char tmp;
 
-                                       outw((short) ((long) lp->mctbl) + byte, EWRK3_PIR1);
+                                       outw(PAGE0_HTE + byte, EWRK3_PIR1);
                                        tmp = inb(EWRK3_DATA);
                                        tmp |= bit;
-                                       outw((short) ((long) lp->mctbl) + byte, EWRK3_PIR1);
+                                       outw(PAGE0_HTE + byte, EWRK3_PIR1);
                                        outb(tmp, EWRK3_DATA);
                                } else {
-                                       isa_writeb(isa_readb((int)(lp->mctbl + byte)) | bit, (int)(lp->mctbl + byte));
+                                       writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte);
                                }
                        }
                }
@@ -1300,15 +1308,9 @@ static int __init eisa_probe(struct net_device *dev, u_long ioaddr)
        if (ioaddr < 0x1000)
                goto out;
 
-       if (ioaddr == 0) {      /* Autoprobing */
-               iobase = EISA_SLOT_INC;         /* Get the first slot address */
-               i = 1;
-               maxSlots = MAX_EISA_SLOTS;
-       } else {                /* Probe a specific location */
-               iobase = ioaddr;
-               i = (ioaddr >> 12);
-               maxSlots = i + 1;
-       }
+       iobase = ioaddr;
+       i = (ioaddr >> 12);
+       maxSlots = i + 1;
 
        for (i = 1; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) {
                if (EISA_signature(name, EISA_ID) == 0) {
@@ -1520,195 +1522,172 @@ static int __init EISA_signature(char *name, s32 eisa_id)
        return status;          /* return the device name string */
 }
 
-static int ewrk3_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static void ewrk3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-       struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
-       u_long iobase = dev->base_addr;
-       u32 ethcmd;
-
-       if (get_user(ethcmd, (u32 __user *)useraddr))
-               return -EFAULT;
-
-       switch (ethcmd) {
-
-       /* Get driver info */
-       case ETHTOOL_GDRVINFO: {
-               struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-               int fwrev = Read_EEPROM(dev->base_addr, EEPROM_REVLVL);
-
-               strcpy(info.driver, DRV_NAME);
-               strcpy(info.version, DRV_VERSION);
-               sprintf(info.fw_version, "%d", fwrev);
-               strcpy(info.bus_info, "N/A");
-               info.eedump_len = EEPROM_MAX;
-               if (copy_to_user(useraddr, &info, sizeof(info)))
-                       return -EFAULT;
-               return 0;
-       }
-
-       /* Get settings */
-       case ETHTOOL_GSET: {
-               struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-               u_char cr = inb(EWRK3_CR);
+       int fwrev = Read_EEPROM(dev->base_addr, EEPROM_REVLVL);
 
-               switch (lp->adapter_name[4]) {
-               case '3': /* DE203 */
-                       ecmd.supported = SUPPORTED_BNC;
-                       ecmd.port = PORT_BNC;
-                       break;
-
-               case '4': /* DE204 */
-                       ecmd.supported = SUPPORTED_TP;
-                       ecmd.port = PORT_TP;
-                       break;
+       strcpy(info->driver, DRV_NAME);
+       strcpy(info->version, DRV_VERSION);
+       sprintf(info->fw_version, "%d", fwrev);
+       strcpy(info->bus_info, "N/A");
+       info->eedump_len = EEPROM_MAX;
+}
 
-               case '5': /* DE205 */
-                       ecmd.supported = SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_AUI;
-                       ecmd.autoneg = !(cr & CR_APD);
-                       /*
-                       ** Port is only valid if autoneg is disabled
-                       ** and even then we don't know if AUI is jumpered.
-                       */
-                       if (!ecmd.autoneg)
-                               ecmd.port = (cr & CR_PSEL) ? PORT_BNC : PORT_TP;
-                       break;
-               }
+static int ewrk3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+       struct ewrk3_private *lp = netdev_priv(dev);
+       unsigned long iobase = dev->base_addr;
+       u8 cr = inb(EWRK3_CR);
+
+       switch (lp->adapter_name[4]) {
+       case '3': /* DE203 */
+               ecmd->supported = SUPPORTED_BNC;
+               ecmd->port = PORT_BNC;
+               break;
 
-               ecmd.supported |= SUPPORTED_10baseT_Half;
-               ecmd.speed = SPEED_10;
-               ecmd.duplex = DUPLEX_HALF;
+       case '4': /* DE204 */
+               ecmd->supported = SUPPORTED_TP;
+               ecmd->port = PORT_TP;
+               break;
 
-               if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-                       return -EFAULT;
-               return 0;
+       case '5': /* DE205 */
+               ecmd->supported = SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_AUI;
+               ecmd->autoneg = !(cr & CR_APD);
+               /*
+               ** Port is only valid if autoneg is disabled
+               ** and even then we don't know if AUI is jumpered.
+               */
+               if (!ecmd->autoneg)
+                       ecmd->port = (cr & CR_PSEL) ? PORT_BNC : PORT_TP;
+               break;
        }
 
-       /* Set settings */
-       case ETHTOOL_SSET: {
-               struct ethtool_cmd ecmd;
-               u_char cr;
-               u_long flags;
-
-               /* DE205 is the only card with anything to set */
-               if (lp->adapter_name[4] != '5')
-                       return -EOPNOTSUPP;
-
-               if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-                       return -EFAULT;
-
-               /* Sanity-check parameters */
-               if (ecmd.speed != SPEED_10)
-                       return -EINVAL;
-               if (ecmd.port != PORT_TP && ecmd.port != PORT_BNC)
-                       return -EINVAL; /* AUI is not software-selectable */
-               if (ecmd.transceiver != XCVR_INTERNAL)
-                       return -EINVAL;
-               if (ecmd.duplex != DUPLEX_HALF)
-                       return -EINVAL;
-               if (ecmd.phy_address != 0)
-                       return -EINVAL;
-
-               spin_lock_irqsave(&lp->hw_lock, flags);
-               cr = inb(EWRK3_CR);
-
-               /* If Autoneg is set, change to Auto Port mode */
-               /* Otherwise, disable Auto Port and set port explicitly */
-               if (ecmd.autoneg) {
-                       cr &= ~CR_APD;
-               } else {
-                       cr |= CR_APD;
-                       if (ecmd.port == PORT_TP)
-                               cr &= ~CR_PSEL;         /* Force TP */
-                       else
-                               cr |= CR_PSEL;          /* Force BNC */
-               }
-
-               /* Commit the changes */
-               outb(cr, EWRK3_CR);
+       ecmd->supported |= SUPPORTED_10baseT_Half;
+       ecmd->speed = SPEED_10;
+       ecmd->duplex = DUPLEX_HALF;
+       return 0;
+}
 
-               spin_unlock_irqrestore(&lp->hw_lock, flags);
-               if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-                       return -EFAULT;
-               return 0;
-       }
+static int ewrk3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+       struct ewrk3_private *lp = netdev_priv(dev);
+       unsigned long iobase = dev->base_addr;
+       unsigned long flags;
+       u8 cr;
 
-       /* Get link status */
-       case ETHTOOL_GLINK: {
-               struct ethtool_value edata = { ETHTOOL_GLINK };
-               u_char cmr = inb(EWRK3_CMR);
+       /* DE205 is the only card with anything to set */
+       if (lp->adapter_name[4] != '5')
+               return -EOPNOTSUPP;
 
-               /* DE203 has BNC only and link status does not apply */
-               if (lp->adapter_name[4] == '3')
-                       return -EOPNOTSUPP;
+       /* Sanity-check parameters */
+       if (ecmd->speed != SPEED_10)
+               return -EINVAL;
+       if (ecmd->port != PORT_TP && ecmd->port != PORT_BNC)
+               return -EINVAL; /* AUI is not software-selectable */
+       if (ecmd->transceiver != XCVR_INTERNAL)
+               return -EINVAL;
+       if (ecmd->duplex != DUPLEX_HALF)
+               return -EINVAL;
+       if (ecmd->phy_address != 0)
+               return -EINVAL;
 
-               /* On DE204 this is always valid since TP is the only port. */
-               /* On DE205 this reflects TP status even if BNC or AUI is selected. */
-               edata.data = !(cmr & CMR_LINK);
+       spin_lock_irqsave(&lp->hw_lock, flags);
+       cr = inb(EWRK3_CR);
 
-               if (copy_to_user(useraddr, &edata, sizeof(edata)))
-                       return -EFAULT;
-               return 0;
+       /* If Autoneg is set, change to Auto Port mode */
+       /* Otherwise, disable Auto Port and set port explicitly */
+       if (ecmd->autoneg) {
+               cr &= ~CR_APD;
+       } else {
+               cr |= CR_APD;
+               if (ecmd->port == PORT_TP)
+                       cr &= ~CR_PSEL;         /* Force TP */
+               else
+                       cr |= CR_PSEL;          /* Force BNC */
        }
 
-       /* Blink LED for identification */
-       case ETHTOOL_PHYS_ID: {
-               struct ethtool_value edata;
-               u_long flags;
-               u_char cr;
-               int count;
-
-               if (copy_from_user(&edata, useraddr, sizeof(edata)))
-                       return -EFAULT;
-
-               /* Toggle LED 4x per second */
-               count = edata.data << 2;
+       /* Commit the changes */
+       outb(cr, EWRK3_CR);
+       spin_unlock_irqrestore(&lp->hw_lock, flags);
+       return 0;
+}
 
-               spin_lock_irqsave(&lp->hw_lock, flags);
+static u32 ewrk3_get_link(struct net_device *dev)
+{
+       unsigned long iobase = dev->base_addr;
+       u8 cmr = inb(EWRK3_CMR);
+       /* DE203 has BNC only and link status does not apply */
+       /* On DE204 this is always valid since TP is the only port. */
+       /* On DE205 this reflects TP status even if BNC or AUI is selected. */
+       return !(cmr & CMR_LINK);
+}
 
-               /* Bail if a PHYS_ID is already in progress */
-               if (lp->led_mask == 0) {
-                       spin_unlock_irqrestore(&lp->hw_lock, flags);
-                       return -EBUSY;
-               }
+static int ewrk3_phys_id(struct net_device *dev, u32 data)
+{
+       struct ewrk3_private *lp = netdev_priv(dev);
+       unsigned long iobase = dev->base_addr;
+       unsigned long flags;
+       u8 cr;
+       int count;
 
-               /* Prevent ISR from twiddling the LED */
-               lp->led_mask = 0;
+       /* Toggle LED 4x per second */
+       count = data << 2;
 
-               while (count--) {
-                       /* Toggle the LED */
-                       cr = inb(EWRK3_CR);
-                       outb(cr ^ CR_LED, EWRK3_CR);
+       spin_lock_irqsave(&lp->hw_lock, flags);
 
-                       /* Wait a little while */
-                       spin_unlock_irqrestore(&lp->hw_lock, flags);
-                       set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule_timeout(HZ>>2);
-                       spin_lock_irqsave(&lp->hw_lock, flags);
+       /* Bail if a PHYS_ID is already in progress */
+       if (lp->led_mask == 0) {
+               spin_unlock_irqrestore(&lp->hw_lock, flags);
+               return -EBUSY;
+       }
 
-                       /* Exit if we got a signal */
-                       if (signal_pending(current))
-                               break;
-               }
+       /* Prevent ISR from twiddling the LED */
+       lp->led_mask = 0;
 
-               lp->led_mask = CR_LED;
+       while (count--) {
+               /* Toggle the LED */
                cr = inb(EWRK3_CR);
-               outb(cr & ~CR_LED, EWRK3_CR);
+               outb(cr ^ CR_LED, EWRK3_CR);
+
+               /* Wait a little while */
                spin_unlock_irqrestore(&lp->hw_lock, flags);
-               return signal_pending(current) ? -ERESTARTSYS : 0;
-       }
+               msleep(250);
+               spin_lock_irqsave(&lp->hw_lock, flags);
 
+               /* Exit if we got a signal */
+               if (signal_pending(current))
+                       break;
        }
 
-       return -EOPNOTSUPP;
+       lp->led_mask = CR_LED;
+       cr = inb(EWRK3_CR);
+       outb(cr & ~CR_LED, EWRK3_CR);
+       spin_unlock_irqrestore(&lp->hw_lock, flags);
+       return signal_pending(current) ? -ERESTARTSYS : 0;
 }
 
+static const struct ethtool_ops ethtool_ops_203 = {
+       .get_drvinfo = ewrk3_get_drvinfo,
+       .get_settings = ewrk3_get_settings,
+       .set_settings = ewrk3_set_settings,
+       .phys_id = ewrk3_phys_id,
+};
+
+static const struct ethtool_ops ethtool_ops = {
+       .get_drvinfo = ewrk3_get_drvinfo,
+       .get_settings = ewrk3_get_settings,
+       .set_settings = ewrk3_set_settings,
+       .get_link = ewrk3_get_link,
+       .phys_id = ewrk3_phys_id,
+};
+
 /*
    ** Perform IOCTL call functions here. Some are privileged operations and the
    ** effective uid is checked in those cases.
  */
 static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-       struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+       struct ewrk3_private *lp = netdev_priv(dev);
        struct ewrk3_ioctl *ioc = (struct ewrk3_ioctl *) &rq->ifr_ifru;
        u_long iobase = dev->base_addr;
        int i, j, status = 0;
@@ -1718,14 +1697,10 @@ static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                u_char addr[HASH_TABLE_LEN * ETH_ALEN];
                u_short val[(HASH_TABLE_LEN * ETH_ALEN) >> 1];
        };
-       
-       union ewrk3_addr *tmp;
 
-       /* ethtool IOCTLs are handled elsewhere */
-       if (cmd == SIOCETHTOOL)
-               return ewrk3_ethtool_ioctl(dev, rq->ifr_data);
+       union ewrk3_addr *tmp;
 
-       /* Other than ethtool, all we handle are private IOCTLs */
+       /* All we handle are private IOCTLs */
        if (cmd != EWRK3IOCTL)
                return -EOPNOTSUPP;
 
@@ -1742,7 +1717,7 @@ static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                if (copy_to_user(ioc->data, tmp->addr, ioc->len))
                        status = -EFAULT;
                break;
-               
+
        case EWRK3_SET_HWADDR:  /* Set the hardware address */
                if (capable(CAP_NET_ADMIN)) {
                        spin_lock_irqsave(&lp->hw_lock, flags);
@@ -1805,7 +1780,7 @@ static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                        }
                } else {
                        outb(0, EWRK3_MPR);
-                       isa_memcpy_fromio(tmp->addr, lp->shmem_base + PAGE0_HTE, (HASH_TABLE_LEN >> 3));
+                       memcpy_fromio(tmp->addr, lp->shmem + PAGE0_HTE, (HASH_TABLE_LEN >> 3));
                }
                spin_unlock_irqrestore(&lp->hw_lock, flags);
 
@@ -1965,8 +1940,8 @@ static int ndevs;
 static int io[MAX_NUM_EWRK3S+1] = { 0x300, 0, };
 
 /* '21' below should really be 'MAX_NUM_EWRK3S' */
-MODULE_PARM(io, "0-21i");
-MODULE_PARM(irq, "0-21i");
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
 MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address(es)");
 MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number(s)");
 
@@ -1975,10 +1950,13 @@ static __exit void ewrk3_exit_module(void)
        int i;
 
        for( i=0; i<ndevs; i++ ) {
-               unregister_netdev(ewrk3_devs[i]);
-               release_region(ewrk3_devs[i]->base_addr, EWRK3_TOTAL_SIZE);
-               free_netdev(ewrk3_devs[i]);
+               struct net_device *dev = ewrk3_devs[i];
+               struct ewrk3_private *lp = netdev_priv(dev);
                ewrk3_devs[i] = NULL;
+               unregister_netdev(dev);
+               release_region(dev->base_addr, EWRK3_TOTAL_SIZE);
+               iounmap(lp->shmem);
+               free_netdev(dev);
        }
 }
 
@@ -2012,7 +1990,7 @@ module_init(ewrk3_init_module);
 #endif                         /* MODULE */
 MODULE_LICENSE("GPL");
 
-\f
+
 
 /*
  * Local variables: