fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / net / 3c509.c
index 707da81..f791bf0 100644 (file)
@@ -28,7 +28,7 @@
        FIXES:
                Alan Cox:       Removed the 'Unexpected interrupt' bug.
                Michael Meskes: Upgraded to Donald Becker's version 1.07.
        FIXES:
                Alan Cox:       Removed the 'Unexpected interrupt' bug.
                Michael Meskes: Upgraded to Donald Becker's version 1.07.
-               Alan Cox:       Increased the eeprom delay. Regardless of 
+               Alan Cox:       Increased the eeprom delay. Regardless of
                                what the docs say some people definitely
                                get problems with lower (but in card spec)
                                delays
                                what the docs say some people definitely
                                get problems with lower (but in card spec)
                                delays
                v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
                    - Introduce driver model for EISA cards.
 */
                v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
                    - Introduce driver model for EISA cards.
 */
-/*
-  FIXES for PC-9800:
-  Shu Iwanaga: 3c569B(PC-9801 C-bus) support
-*/
 
 #define DRV_NAME       "3c509"
 #define DRV_VERSION    "1.19b"
 
 #define DRV_NAME       "3c509"
 #define DRV_VERSION    "1.19b"
@@ -72,7 +68,6 @@
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
 static int max_interrupt_work = 10;
 
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
 static int max_interrupt_work = 10;
 
-#include <linux/config.h>
 #include <linux/module.h>
 #ifdef CONFIG_MCA
 #include <linux/mca.h>
 #include <linux/module.h>
 #ifdef CONFIG_MCA
 #include <linux/mca.h>
@@ -88,21 +83,26 @@ static int max_interrupt_work = 10;
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/pm.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/pm.h>
+#include <linux/pm_legacy.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>       /* for udelay() */
 #include <linux/spinlock.h>
 #include <linux/ethtool.h>
 #include <linux/device.h>
 #include <linux/eisa.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>       /* for udelay() */
 #include <linux/spinlock.h>
 #include <linux/ethtool.h>
 #include <linux/device.h>
 #include <linux/eisa.h>
+#include <linux/bitops.h>
 
 #include <asm/uaccess.h>
 
 #include <asm/uaccess.h>
-#include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
 static char versionA[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
 static char versionB[] __initdata = "http://www.scyld.com/network/3c509.html\n";
 
 #include <asm/io.h>
 #include <asm/irq.h>
 
 static char versionA[] __initdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
 static char versionB[] __initdata = "http://www.scyld.com/network/3c509.html\n";
 
+#if defined(CONFIG_PM) && (defined(CONFIG_MCA) || defined(CONFIG_EISA))
+#define EL3_SUSPEND
+#endif
+
 #ifdef EL3_DEBUG
 static int el3_debug = EL3_DEBUG;
 #else
 #ifdef EL3_DEBUG
 static int el3_debug = EL3_DEBUG;
 #else
@@ -162,7 +162,7 @@ enum RxFilter {
 #define WN4_MEDIA      0x0A            /* Window 4: Various transcvr/media bits. */
 #define        MEDIA_TP        0x00C0          /* Enable link beat and jabber for 10baseT. */
 #define WN4_NETDIAG    0x06            /* Window 4: Net diagnostic */
 #define WN4_MEDIA      0x0A            /* Window 4: Various transcvr/media bits. */
 #define        MEDIA_TP        0x00C0          /* Enable link beat and jabber for 10baseT. */
 #define WN4_NETDIAG    0x06            /* Window 4: Net diagnostic */
-#define FD_ENABLE      0x8000          /* Enable full-duplex ("external loopback") */  
+#define FD_ENABLE      0x8000          /* Enable full-duplex ("external loopback") */
 
 /*
  * Must be a power of two (we use a binary and in the
 
 /*
  * Must be a power of two (we use a binary and in the
@@ -177,9 +177,6 @@ struct el3_private {
        /* skb send-queue */
        int head, size;
        struct sk_buff *queue[SKB_QUEUE_SIZE];
        /* skb send-queue */
        int head, size;
        struct sk_buff *queue[SKB_QUEUE_SIZE];
-#ifdef CONFIG_PM
-       struct pm_dev *pmdev;
-#endif
        enum {
                EL3_MCA,
                EL3_PNP,
        enum {
                EL3_MCA,
                EL3_PNP,
@@ -194,41 +191,52 @@ static ushort id_read_eeprom(int index);
 static ushort read_eeprom(int ioaddr, int index);
 static int el3_open(struct net_device *dev);
 static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static ushort read_eeprom(int ioaddr, int index);
 static int el3_open(struct net_device *dev);
 static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t el3_interrupt(int irq, void *dev_id);
 static void update_stats(struct net_device *dev);
 static struct net_device_stats *el3_get_stats(struct net_device *dev);
 static int el3_rx(struct net_device *dev);
 static int el3_close(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static void el3_tx_timeout (struct net_device *dev);
 static void update_stats(struct net_device *dev);
 static struct net_device_stats *el3_get_stats(struct net_device *dev);
 static int el3_rx(struct net_device *dev);
 static int el3_close(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
 static void el3_tx_timeout (struct net_device *dev);
-static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
 static void el3_down(struct net_device *dev);
 static void el3_up(struct net_device *dev);
 static void el3_down(struct net_device *dev);
 static void el3_up(struct net_device *dev);
-#ifdef CONFIG_PM
-static int el3_suspend(struct pm_dev *pdev);
-static int el3_resume(struct pm_dev *pdev);
-static int el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data);
+static const struct ethtool_ops ethtool_ops;
+#ifdef EL3_SUSPEND
+static int el3_suspend(struct device *, pm_message_t);
+static int el3_resume(struct device *);
+#else
+#define el3_suspend NULL
+#define el3_resume NULL
 #endif
 #endif
+
+
 /* generic device remove for all device types */
 #if defined(CONFIG_EISA) || defined(CONFIG_MCA)
 static int el3_device_remove (struct device *device);
 #endif
 /* generic device remove for all device types */
 #if defined(CONFIG_EISA) || defined(CONFIG_MCA)
 static int el3_device_remove (struct device *device);
 #endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void el3_poll_controller(struct net_device *dev);
+#endif
 
 #ifdef CONFIG_EISA
 
 #ifdef CONFIG_EISA
-struct eisa_device_id el3_eisa_ids[] = {
+static struct eisa_device_id el3_eisa_ids[] = {
                { "TCM5092" },
                { "TCM5093" },
                { "TCM5092" },
                { "TCM5093" },
+               { "TCM5095" },
                { "" }
 };
                { "" }
 };
+MODULE_DEVICE_TABLE(eisa, el3_eisa_ids);
 
 static int el3_eisa_probe (struct device *device);
 
 
 static int el3_eisa_probe (struct device *device);
 
-struct eisa_driver el3_eisa_driver = {
+static struct eisa_driver el3_eisa_driver = {
                .id_table = el3_eisa_ids,
                .driver   = {
                                .name    = "3c509",
                                .probe   = el3_eisa_probe,
                .id_table = el3_eisa_ids,
                .driver   = {
                                .name    = "3c509",
                                .probe   = el3_eisa_probe,
-                               .remove  = __devexit_p (el3_device_remove)
+                               .remove  = __devexit_p (el3_device_remove),
+                               .suspend = el3_suspend,
+                               .resume  = el3_resume,
                }
 };
 #endif
                }
 };
 #endif
@@ -261,11 +269,13 @@ static struct mca_driver el3_mca_driver = {
                                .bus = &mca_bus_type,
                                .probe = el3_mca_probe,
                                .remove = __devexit_p(el3_device_remove),
                                .bus = &mca_bus_type,
                                .probe = el3_mca_probe,
                                .remove = __devexit_p(el3_device_remove),
+                               .suspend = el3_suspend,
+                               .resume  = el3_resume,
                },
 };
 #endif /* CONFIG_MCA */
 
                },
 };
 #endif /* CONFIG_MCA */
 
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
+#if defined(__ISAPNP__)
 static struct isapnp_device_id el3_isapnp_adapters[] __initdata = {
        {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
                ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090),
 static struct isapnp_device_id el3_isapnp_adapters[] __initdata = {
        {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
                ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090),
@@ -325,7 +335,10 @@ static int __init el3_common_init(struct net_device *dev)
        dev->set_multicast_list = &set_multicast_list;
        dev->tx_timeout = el3_tx_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
        dev->set_multicast_list = &set_multicast_list;
        dev->tx_timeout = el3_tx_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
-       dev->do_ioctl = netdev_ioctl;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       dev->poll_controller = el3_poll_controller;
+#endif
+       SET_ETHTOOL_OPS(dev, &ethtool_ops);
 
        err = register_netdev(dev);
        if (err) {
 
        err = register_netdev(dev);
        if (err) {
@@ -338,7 +351,7 @@ static int __init el3_common_init(struct net_device *dev)
        {
                const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
                printk("%s: 3c5x9 found at %#3.3lx, %s port, address ",
        {
                const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
                printk("%s: 3c5x9 found at %#3.3lx, %s port, address ",
-                       dev->name, dev->base_addr, 
+                       dev->name, dev->base_addr,
                        if_names[(dev->if_port & 0x03)]);
        }
 
                        if_names[(dev->if_port & 0x03)]);
        }
 
@@ -358,11 +371,7 @@ static void el3_common_remove (struct net_device *dev)
        struct el3_private *lp = netdev_priv(dev);
 
        (void) lp;                              /* Keep gcc quiet... */
        struct el3_private *lp = netdev_priv(dev);
 
        (void) lp;                              /* Keep gcc quiet... */
-#ifdef CONFIG_PM
-       if (lp->pmdev)
-               pm_unregister(lp->pmdev);
-#endif
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
+#if defined(__ISAPNP__)
        if (lp->type == EL3_PNP)
                pnp_device_detach(to_pnp_dev(lp->dev));
 #endif
        if (lp->type == EL3_PNP)
                pnp_device_detach(to_pnp_dev(lp->dev));
 #endif
@@ -381,7 +390,7 @@ static int __init el3_probe(int card_idx)
        u16 phys_addr[3];
        static int current_tag;
        int err = -ENODEV;
        u16 phys_addr[3];
        static int current_tag;
        int err = -ENODEV;
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
+#if defined(__ISAPNP__)
        static int pnp_cards;
        struct pnp_dev *idev = NULL;
 
        static int pnp_cards;
        struct pnp_dev *idev = NULL;
 
@@ -436,9 +445,6 @@ __again:
 no_pnp:
 #endif /* __ISAPNP__ */
 
 no_pnp:
 #endif /* __ISAPNP__ */
 
-#ifdef CONFIG_X86_PC9800
-       id_port = 0x71d0;
-#else
        /* Select an open I/O location at 0x1*0 to do contention select. */
        for ( ; id_port < 0x200; id_port += 0x10) {
                if (!request_region(id_port, 1, "3c509"))
        /* Select an open I/O location at 0x1*0 to do contention select. */
        for ( ; id_port < 0x200; id_port += 0x10) {
                if (!request_region(id_port, 1, "3c509"))
@@ -456,7 +462,7 @@ no_pnp:
                printk(" WARNING: No I/O port available for 3c509 activation.\n");
                return -ENODEV;
        }
                printk(" WARNING: No I/O port available for 3c509 activation.\n");
                return -ENODEV;
        }
-#endif /* CONFIG_X86_PC9800 */
+
        /* Next check for all ISA bus boards by sending the ID sequence to the
           ID_PORT.  We find cards past the first by setting the 'current_tag'
           on cards as they are found.  Cards with their tag set will not
        /* Next check for all ISA bus boards by sending the ID sequence to the
           ID_PORT.  We find cards past the first by setting the 'current_tag'
           on cards as they are found.  Cards with their tag set will not
@@ -487,7 +493,7 @@ no_pnp:
                phys_addr[i] = htons(id_read_eeprom(i));
        }
 
                phys_addr[i] = htons(id_read_eeprom(i));
        }
 
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
+#if defined(__ISAPNP__)
        if (nopnp == 0) {
                /* The ISA PnP 3c509 cards respond to the ID sequence.
                   This check is needed in order not to register them twice. */
        if (nopnp == 0) {
                /* The ISA PnP 3c509 cards respond to the ID sequence.
                   This check is needed in order not to register them twice. */
@@ -512,19 +518,9 @@ no_pnp:
        {
                unsigned int iobase = id_read_eeprom(8);
                if_port = iobase >> 14;
        {
                unsigned int iobase = id_read_eeprom(8);
                if_port = iobase >> 14;
-#ifdef CONFIG_X86_PC9800
-               ioaddr = 0x40d0 + ((iobase & 0x1f) << 8);
-#else
                ioaddr = 0x200 + ((iobase & 0x1f) << 4);
                ioaddr = 0x200 + ((iobase & 0x1f) << 4);
-#endif
        }
        irq = id_read_eeprom(9) >> 12;
        }
        irq = id_read_eeprom(9) >> 12;
-#ifdef CONFIG_X86_PC9800
-       if (irq == 7)
-               irq = 6;
-       else if (irq == 15)
-               irq = 13;
-#endif
 
        dev = alloc_etherdev(sizeof (struct el3_private));
        if (!dev)
 
        dev = alloc_etherdev(sizeof (struct el3_private));
        if (!dev)
@@ -533,7 +529,7 @@ no_pnp:
        SET_MODULE_OWNER(dev);
 
        netdev_boot_setup_check(dev);
        SET_MODULE_OWNER(dev);
 
        netdev_boot_setup_check(dev);
-       
+
        /* Set passed-in IRQ or I/O Addr. */
        if (dev->irq > 1  &&  dev->irq < 16)
                        irq = dev->irq;
        /* Set passed-in IRQ or I/O Addr. */
        if (dev->irq > 1  &&  dev->irq < 16)
                        irq = dev->irq;
@@ -555,11 +551,7 @@ no_pnp:
        outb(0xd0 + ++current_tag, id_port);
 
        /* Activate the adaptor at the EEPROM location. */
        outb(0xd0 + ++current_tag, id_port);
 
        /* Activate the adaptor at the EEPROM location. */
-#ifdef CONFIG_X86_PC9800
-       outb((ioaddr >> 8) | 0xe0, id_port);
-#else
        outb((ioaddr >> 4) | 0xe0, id_port);
        outb((ioaddr >> 4) | 0xe0, id_port);
-#endif
 
        EL3WINDOW(0);
        if (inw(ioaddr) != 0x6d50)
 
        EL3WINDOW(0);
        if (inw(ioaddr) != 0x6d50)
@@ -568,7 +560,7 @@ no_pnp:
        /* Free the interrupt so that some other card can use it. */
        outw(0x0f00, ioaddr + WN0_IRQ);
 
        /* Free the interrupt so that some other card can use it. */
        outw(0x0f00, ioaddr + WN0_IRQ);
 
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
+#if defined(__ISAPNP__)
  found:                                                        /* PNP jumps here... */
 #endif /* __ISAPNP__ */
 
  found:                                                        /* PNP jumps here... */
 #endif /* __ISAPNP__ */
 
@@ -577,7 +569,7 @@ no_pnp:
        dev->irq = irq;
        dev->if_port = if_port;
        lp = netdev_priv(dev);
        dev->irq = irq;
        dev->if_port = if_port;
        lp = netdev_priv(dev);
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
+#if defined(__ISAPNP__)
        lp->dev = &idev->dev;
 #endif
        err = el3_common_init(dev);
        lp->dev = &idev->dev;
 #endif
        err = el3_common_init(dev);
@@ -585,23 +577,13 @@ no_pnp:
        if (err)
                goto out1;
 
        if (err)
                goto out1;
 
-#ifdef CONFIG_PM
-       /* register power management */
-       lp->pmdev = pm_register(PM_ISA_DEV, card_idx, el3_pm_callback);
-       if (lp->pmdev) {
-               struct pm_dev *p;
-               p = lp->pmdev;
-               p->data = (struct net_device *)dev;
-       }
-#endif
-
        el3_cards++;
        lp->next_dev = el3_root_dev;
        el3_root_dev = dev;
        return 0;
 
 out1:
        el3_cards++;
        lp->next_dev = el3_root_dev;
        el3_root_dev = dev;
        return 0;
 
 out1:
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
+#if defined(__ISAPNP__)
        if (idev)
                pnp_device_detach(idev);
 #endif
        if (idev)
                pnp_device_detach(idev);
 #endif
@@ -649,7 +631,7 @@ static int __init el3_mca_probe(struct device *device)
        if_port = pos4 & 0x03;
 
        irq = mca_device_transform_irq(mdev, irq);
        if_port = pos4 & 0x03;
 
        irq = mca_device_transform_irq(mdev, irq);
-       ioaddr = mca_device_transform_ioport(mdev, ioaddr); 
+       ioaddr = mca_device_transform_ioport(mdev, ioaddr);
        if (el3_debug > 2) {
                        printk("3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
        }
        if (el3_debug > 2) {
                        printk("3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
        }
@@ -686,7 +668,7 @@ static int __init el3_mca_probe(struct device *device)
        el3_cards++;
        return 0;
 }
        el3_cards++;
        return 0;
 }
-               
+
 #endif /* CONFIG_MCA */
 
 #ifdef CONFIG_EISA
 #endif /* CONFIG_MCA */
 
 #ifdef CONFIG_EISA
@@ -703,7 +685,7 @@ static int __init el3_eisa_probe (struct device *device)
        /* Yeepee, The driver framework is calling us ! */
        edev = to_eisa_device (device);
        ioaddr = edev->base_addr;
        /* Yeepee, The driver framework is calling us ! */
        edev = to_eisa_device (device);
        ioaddr = edev->base_addr;
-       
+
        if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509"))
                return -EBUSY;
 
        if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509"))
                return -EBUSY;
 
@@ -770,7 +752,7 @@ static int __devexit el3_device_remove (struct device *device)
 static ushort read_eeprom(int ioaddr, int index)
 {
        outw(EEPROM_READ + index, ioaddr + 10);
 static ushort read_eeprom(int ioaddr, int index)
 {
        outw(EEPROM_READ + index, ioaddr + 10);
-       /* Pause for at least 162 us. for the read to take place. 
+       /* Pause for at least 162 us. for the read to take place.
           Some chips seem to require much longer */
        mdelay(2);
        return inw(ioaddr + 12);
           Some chips seem to require much longer */
        mdelay(2);
        return inw(ioaddr + 12);
@@ -788,7 +770,7 @@ static ushort __init id_read_eeprom(int index)
        /* Pause for at least 162 us. for the read to take place. */
        /* Some chips seem to require much longer */
        mdelay(4);
        /* Pause for at least 162 us. for the read to take place. */
        /* Some chips seem to require much longer */
        mdelay(4);
-       
+
        for (bit = 15; bit >= 0; bit--)
                word = (word << 1) + (inb(id_port) & 0x01);
 
        for (bit = 15; bit >= 0; bit--)
                word = (word << 1) + (inb(id_port) & 0x01);
 
@@ -857,7 +839,7 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        netif_stop_queue (dev);
 
        lp->stats.tx_bytes += skb->len;
        netif_stop_queue (dev);
 
        lp->stats.tx_bytes += skb->len;
-       
+
        if (el3_debug > 4) {
                printk("%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
                           dev->name, skb->len, inw(ioaddr + EL3_STATUS));
        if (el3_debug > 4) {
                printk("%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
                           dev->name, skb->len, inw(ioaddr + EL3_STATUS));
@@ -898,11 +880,7 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        outw(skb->len, ioaddr + TX_FIFO);
        outw(0x00, ioaddr + TX_FIFO);
        /* ... and the packet rounded to a doubleword. */
        outw(skb->len, ioaddr + TX_FIFO);
        outw(0x00, ioaddr + TX_FIFO);
        /* ... and the packet rounded to a doubleword. */
-#ifdef  __powerpc__
-       outsl_ns(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
-#else
        outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
        outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
-#endif
 
        dev->trans_start = jiffies;
        if (inw(ioaddr + TX_FREE) > 1536)
 
        dev->trans_start = jiffies;
        if (inw(ioaddr + TX_FREE) > 1536)
@@ -932,18 +910,13 @@ el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 /* The EL3 interrupt handler. */
 static irqreturn_t
 
 /* The EL3 interrupt handler. */
 static irqreturn_t
-el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+el3_interrupt(int irq, void *dev_id)
 {
 {
-       struct net_device *dev = (struct net_device *)dev_id;
+       struct net_device *dev = dev_id;
        struct el3_private *lp;
        int ioaddr, status;
        int i = max_interrupt_work;
 
        struct el3_private *lp;
        int ioaddr, status;
        int i = max_interrupt_work;
 
-       if (dev == NULL) {
-               printk ("el3_interrupt(): irq %d for unknown device.\n", irq);
-               return IRQ_NONE;
-       }
-
        lp = netdev_priv(dev);
        spin_lock(&lp->lock);
 
        lp = netdev_priv(dev);
        spin_lock(&lp->lock);
 
@@ -1020,6 +993,19 @@ el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 }
 
 
 }
 
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void el3_poll_controller(struct net_device *dev)
+{
+       disable_irq(dev->irq);
+       el3_interrupt(dev->irq, dev);
+       enable_irq(dev->irq);
+}
+#endif
+
 static struct net_device_stats *
 el3_get_stats(struct net_device *dev)
 {
 static struct net_device_stats *
 el3_get_stats(struct net_device *dev)
 {
@@ -1030,7 +1016,7 @@ el3_get_stats(struct net_device *dev)
         *      This is fast enough not to bother with disable IRQ
         *      stuff.
         */
         *      This is fast enough not to bother with disable IRQ
         *      stuff.
         */
-        
+
        spin_lock_irqsave(&lp->lock, flags);
        update_stats(dev);
        spin_unlock_irqrestore(&lp->lock, flags);
        spin_lock_irqsave(&lp->lock, flags);
        update_stats(dev);
        spin_unlock_irqrestore(&lp->lock, flags);
@@ -1109,13 +1095,8 @@ el3_rx(struct net_device *dev)
                                skb_reserve(skb, 2);     /* Align IP on 16 byte */
 
                                /* 'skb->data' points to the start of sk_buff data area. */
                                skb_reserve(skb, 2);     /* Align IP on 16 byte */
 
                                /* 'skb->data' points to the start of sk_buff data area. */
-#ifdef  __powerpc__
-                               insl_ns(ioaddr+RX_FIFO, skb_put(skb,pkt_len),
-                                                          (pkt_len + 3) >> 2);
-#else
                                insl(ioaddr + RX_FIFO, skb_put(skb,pkt_len),
                                         (pkt_len + 3) >> 2);
                                insl(ioaddr + RX_FIFO, skb_put(skb,pkt_len),
                                         (pkt_len + 3) >> 2);
-#endif
 
                                outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
                                skb->protocol = eth_type_trans(skb,dev);
 
                                outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
                                skb->protocol = eth_type_trans(skb,dev);
@@ -1174,7 +1155,7 @@ el3_close(struct net_device *dev)
 {
        int ioaddr = dev->base_addr;
        struct el3_private *lp = netdev_priv(dev);
 {
        int ioaddr = dev->base_addr;
        struct el3_private *lp = netdev_priv(dev);
-       
+
        if (el3_debug > 2)
                printk("%s: Shutting down ethercard.\n", dev->name);
 
        if (el3_debug > 2)
                printk("%s: Shutting down ethercard.\n", dev->name);
 
@@ -1193,7 +1174,7 @@ el3_close(struct net_device *dev)
        return 0;
 }
 
        return 0;
 }
 
-static int 
+static int
 el3_link_ok(struct net_device *dev)
 {
        int ioaddr = dev->base_addr;
 el3_link_ok(struct net_device *dev)
 {
        int ioaddr = dev->base_addr;
@@ -1210,9 +1191,9 @@ el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
        u16 tmp;
        int ioaddr = dev->base_addr;
 {
        u16 tmp;
        int ioaddr = dev->base_addr;
-       
+
        EL3WINDOW(0);
        EL3WINDOW(0);
-       /* obtain current transceiver via WN4_MEDIA? */ 
+       /* obtain current transceiver via WN4_MEDIA? */
        tmp = inw(ioaddr + WN0_ADDR_CONF);
        ecmd->transceiver = XCVR_INTERNAL;
        switch (tmp >> 14) {
        tmp = inw(ioaddr + WN0_ADDR_CONF);
        ecmd->transceiver = XCVR_INTERNAL;
        switch (tmp >> 14) {
@@ -1306,123 +1287,64 @@ el3_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
        return 0;
 }
 
        return 0;
 }
 
-/**
- * netdev_ethtool_ioctl: Handle network interface SIOCETHTOOL ioctls
- * @dev: network interface on which out-of-band action is to be performed
- * @useraddr: userspace address to which data is to be read and returned
- *
- * Process the various commands of the SIOCETHTOOL interface.
- */
+static void el3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+       strcpy(info->driver, DRV_NAME);
+       strcpy(info->version, DRV_VERSION);
+}
 
 
-static int
-netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+static int el3_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
 {
-       u32 ethcmd;
        struct el3_private *lp = netdev_priv(dev);
        struct el3_private *lp = netdev_priv(dev);
+       int ret;
 
 
-       /* dev_ioctl() in ../../net/core/dev.c has already checked
-          capable(CAP_NET_ADMIN), so don't bother with that here.  */
-
-       if (get_user(ethcmd, (u32 *)useraddr))
-               return -EFAULT;
-
-       switch (ethcmd) {
-
-       case ETHTOOL_GDRVINFO: {
-               struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-               strcpy (info.driver, DRV_NAME);
-               strcpy (info.version, DRV_VERSION);
-               if (copy_to_user (useraddr, &info, sizeof (info)))
-                       return -EFAULT;
-               return 0;
-       }
-
-       /* get settings */
-       case ETHTOOL_GSET: {
-               int ret;
-               struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-               spin_lock_irq(&lp->lock);
-               ret = el3_netdev_get_ecmd(dev, &ecmd);
-               spin_unlock_irq(&lp->lock);
-               if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-                       return -EFAULT;
-               return ret;
-       }
-
-       /* set settings */
-       case ETHTOOL_SSET: {
-               int ret;
-               struct ethtool_cmd ecmd;
-               if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-                       return -EFAULT;
-               spin_lock_irq(&lp->lock);
-               ret = el3_netdev_set_ecmd(dev, &ecmd);
-               spin_unlock_irq(&lp->lock);
-               return ret;
-       }
-
-       /* get link status */
-       case ETHTOOL_GLINK: {
-               struct ethtool_value edata = { ETHTOOL_GLINK };
-               spin_lock_irq(&lp->lock);
-               edata.data = el3_link_ok(dev);
-               spin_unlock_irq(&lp->lock);
-               if (copy_to_user(useraddr, &edata, sizeof(edata)))
-                       return -EFAULT;
-               return 0;
-       }
-
-       /* get message-level */
-       case ETHTOOL_GMSGLVL: {
-               struct ethtool_value edata = {ETHTOOL_GMSGLVL};
-               edata.data = el3_debug;
-               if (copy_to_user(useraddr, &edata, sizeof(edata)))
-                       return -EFAULT;
-               return 0;
-       }
-       /* set message-level */
-       case ETHTOOL_SMSGLVL: {
-               struct ethtool_value edata;
-               if (copy_from_user(&edata, useraddr, sizeof(edata)))
-                       return -EFAULT;
-               el3_debug = edata.data;
-               return 0;
-       }
+       spin_lock_irq(&lp->lock);
+       ret = el3_netdev_get_ecmd(dev, ecmd);
+       spin_unlock_irq(&lp->lock);
+       return ret;
+}
 
 
-       default:
-               break;
-       }
+static int el3_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+       struct el3_private *lp = netdev_priv(dev);
+       int ret;
 
 
-       return -EOPNOTSUPP;
+       spin_lock_irq(&lp->lock);
+       ret = el3_netdev_set_ecmd(dev, ecmd);
+       spin_unlock_irq(&lp->lock);
+       return ret;
 }
 
 }
 
-/**
- * netdev_ioctl: Handle network interface ioctls
- * @dev: network interface on which out-of-band action is to be performed
- * @rq: user request data
- * @cmd: command issued by user
- *
- * Process the various out-of-band ioctls passed to this driver.
- */
-
-static int
-netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+static u32 el3_get_link(struct net_device *dev)
 {
 {
-       int rc = 0;
+       struct el3_private *lp = netdev_priv(dev);
+       u32 ret;
 
 
-       switch (cmd) {
-       case SIOCETHTOOL:
-               rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
-               break;
+       spin_lock_irq(&lp->lock);
+       ret = el3_link_ok(dev);
+       spin_unlock_irq(&lp->lock);
+       return ret;
+}
 
 
-       default:
-               rc = -EOPNOTSUPP;
-               break;
-       }
+static u32 el3_get_msglevel(struct net_device *dev)
+{
+       return el3_debug;
+}
 
 
-       return rc;
+static void el3_set_msglevel(struct net_device *dev, u32 v)
+{
+       el3_debug = v;
 }
 
 }
 
+static const struct ethtool_ops ethtool_ops = {
+       .get_drvinfo = el3_get_drvinfo,
+       .get_settings = el3_get_settings,
+       .set_settings = el3_set_settings,
+       .get_link = el3_get_link,
+       .get_msglevel = el3_get_msglevel,
+       .set_msglevel = el3_set_msglevel,
+};
+
 static void
 el3_down(struct net_device *dev)
 {
 static void
 el3_down(struct net_device *dev)
 {
@@ -1456,17 +1378,11 @@ el3_up(struct net_device *dev)
 {
        int i, sw_info, net_diag;
        int ioaddr = dev->base_addr;
 {
        int i, sw_info, net_diag;
        int ioaddr = dev->base_addr;
-       
+
        /* Activating the board required and does no harm otherwise */
        outw(0x0001, ioaddr + 4);
 
        /* Set the IRQ line. */
        /* Activating the board required and does no harm otherwise */
        outw(0x0001, ioaddr + 4);
 
        /* Set the IRQ line. */
-#ifdef CONFIG_X86_PC9800
-       if (dev->irq == 6)
-               dev->irq = 7;
-       else if (dev->irq == 13)
-               dev->irq = 15;
-#endif
        outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
 
        /* Set the station address in window 2 each time opened. */
        outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
 
        /* Set the station address in window 2 each time opened. */
@@ -1482,7 +1398,7 @@ el3_up(struct net_device *dev)
                /* Combine secondary sw_info word (the adapter level) and primary
                        sw_info word (duplex setting plus other useless bits) */
                EL3WINDOW(0);
                /* Combine secondary sw_info word (the adapter level) and primary
                        sw_info word (duplex setting plus other useless bits) */
                EL3WINDOW(0);
-               sw_info = (read_eeprom(ioaddr, 0x14) & 0x400f) | 
+               sw_info = (read_eeprom(ioaddr, 0x14) & 0x400f) |
                        (read_eeprom(ioaddr, 0x0d) & 0xBff0);
 
                EL3WINDOW(4);
                        (read_eeprom(ioaddr, 0x0d) & 0xBff0);
 
                EL3WINDOW(4);
@@ -1545,20 +1461,17 @@ el3_up(struct net_device *dev)
 }
 
 /* Power Management support functions */
 }
 
 /* Power Management support functions */
-#ifdef CONFIG_PM
+#ifdef EL3_SUSPEND
 
 static int
 
 static int
-el3_suspend(struct pm_dev *pdev)
+el3_suspend(struct device *pdev, pm_message_t state)
 {
        unsigned long flags;
        struct net_device *dev;
        struct el3_private *lp;
        int ioaddr;
 {
        unsigned long flags;
        struct net_device *dev;
        struct el3_private *lp;
        int ioaddr;
-       
-       if (!pdev && !pdev->data)
-               return -EINVAL;
 
 
-       dev = (struct net_device *)pdev->data;
+       dev = pdev->driver_data;
        lp = netdev_priv(dev);
        ioaddr = dev->base_addr;
 
        lp = netdev_priv(dev);
        ioaddr = dev->base_addr;
 
@@ -1575,17 +1488,14 @@ el3_suspend(struct pm_dev *pdev)
 }
 
 static int
 }
 
 static int
-el3_resume(struct pm_dev *pdev)
+el3_resume(struct device *pdev)
 {
        unsigned long flags;
        struct net_device *dev;
        struct el3_private *lp;
        int ioaddr;
 {
        unsigned long flags;
        struct net_device *dev;
        struct el3_private *lp;
        int ioaddr;
-       
-       if (!pdev && !pdev->data)
-               return -EINVAL;
 
 
-       dev = (struct net_device *)pdev->data;
+       dev = pdev->driver_data;
        lp = netdev_priv(dev);
        ioaddr = dev->base_addr;
 
        lp = netdev_priv(dev);
        ioaddr = dev->base_addr;
 
@@ -1596,41 +1506,28 @@ el3_resume(struct pm_dev *pdev)
 
        if (netif_running(dev))
                netif_device_attach(dev);
 
        if (netif_running(dev))
                netif_device_attach(dev);
-               
-       spin_unlock_irqrestore(&lp->lock, flags);
-       return 0;
-}
-
-static int
-el3_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data)
-{
-       switch (rqst) {
-               case PM_SUSPEND:
-                       return el3_suspend(pdev);
 
 
-               case PM_RESUME:
-                       return el3_resume(pdev);
-       }
+       spin_unlock_irqrestore(&lp->lock, flags);
        return 0;
 }
 
        return 0;
 }
 
-#endif /* CONFIG_PM */
+#endif /* EL3_SUSPEND */
 
 /* Parameters that may be passed into the module. */
 static int debug = -1;
 static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static int xcvr[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
 
 
 /* Parameters that may be passed into the module. */
 static int debug = -1;
 static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
 static int xcvr[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
 
-MODULE_PARM(debug,"i");
-MODULE_PARM(irq,"1-8i");
-MODULE_PARM(xcvr,"1-12i");
-MODULE_PARM(max_interrupt_work, "i");
+module_param(debug,int, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(xcvr, int, NULL, 0);
+module_param(max_interrupt_work, int, 0);
 MODULE_PARM_DESC(debug, "debug level (0-6)");
 MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
 MODULE_PARM_DESC(xcvr,"transceiver(s) (0=internal, 1=external)");
 MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
 MODULE_PARM_DESC(debug, "debug level (0-6)");
 MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
 MODULE_PARM_DESC(xcvr,"transceiver(s) (0=internal, 1=external)");
 MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
-#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800)
-MODULE_PARM(nopnp, "i");
+#if defined(__ISAPNP__)
+module_param(nopnp, int, 0);
 MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
 MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters);
 #endif /* __ISAPNP__ */
 MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
 MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters);
 #endif /* __ISAPNP__ */
@@ -1639,6 +1536,7 @@ MODULE_LICENSE("GPL");
 
 static int __init el3_init_module(void)
 {
 
 static int __init el3_init_module(void)
 {
+       int ret = 0;
        el3_cards = 0;
 
        if (debug >= 0)
        el3_cards = 0;
 
        if (debug >= 0)
@@ -1654,14 +1552,16 @@ static int __init el3_init_module(void)
        }
 
 #ifdef CONFIG_EISA
        }
 
 #ifdef CONFIG_EISA
-       if (eisa_driver_register (&el3_eisa_driver) < 0) {
-               eisa_driver_unregister (&el3_eisa_driver);
-       }
+       ret = eisa_driver_register(&el3_eisa_driver);
 #endif
 #ifdef CONFIG_MCA
 #endif
 #ifdef CONFIG_MCA
-       mca_register_driver(&el3_mca_driver);
+       {
+               int err = mca_register_driver(&el3_mca_driver);
+               if (ret == 0)
+                       ret = err;
+       }
 #endif
 #endif
-       return 0;
+       return ret;
 }
 
 static void __exit el3_cleanup_module(void)
 }
 
 static void __exit el3_cleanup_module(void)