Merge branch 'linus' into cont_syslog
[safe/jmp/linux-2.6] / drivers / net / ne.c
index 0de8fdd..b8e2923 100644 (file)
@@ -50,14 +50,12 @@ static const char version2[] =
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
 
-#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
-#include <asm/tx4938/rbtx4938.h>
-#endif
-
 #include "8390.h"
 
 #define DRV_NAME "ne"
@@ -66,6 +64,25 @@ static const char version2[] =
 
 /* Do we support clones that don't adhere to 14,15 of the SAprom ? */
 #define SUPPORT_NE_BAD_CLONES
+/* 0xbad = bad sig or no reset ack */
+#define BAD 0xbad
+
+#define MAX_NE_CARDS   4       /* Max number of NE cards per module */
+static struct platform_device *pdev_ne[MAX_NE_CARDS];
+static int io[MAX_NE_CARDS];
+static int irq[MAX_NE_CARDS];
+static int bad[MAX_NE_CARDS];
+
+#ifdef MODULE
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(bad, int, NULL, 0);
+MODULE_PARM_DESC(io, "I/O base address(es),required");
+MODULE_PARM_DESC(irq, "IRQ number(s)");
+MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
+MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver");
+MODULE_LICENSE("GPL");
+#endif /* MODULE */
 
 /* Do we perform extra sanity checks on stuff ? */
 /* #define NE_SANITY_CHECK */
@@ -76,8 +93,17 @@ static const char version2[] =
 /* Do we have a non std. amount of memory? (in units of 256 byte pages) */
 /* #define PACKETBUF_MEMSIZE   0x40 */
 
+/* This is set up so that no ISA autoprobe takes place. We can't guarantee
+that the ne2k probe is the last 8390 based probe to take place (as it
+is at boot) and so the probe will get confused by any other 8390 cards.
+ISA device autoprobes on a running machine are not recommended anyway. */
+#if !defined(MODULE) && (defined(CONFIG_ISA) || defined(CONFIG_M32R))
+/* Do we need a portlist for the ISA auto-probe ? */
+#define NEEDS_PORTLIST
+#endif
+
 /* A zero-terminated list of I/O addresses to be probed at boot. */
-#ifndef MODULE
+#ifdef NEEDS_PORTLIST
 static unsigned int netcard_portlist[] __initdata = {
        0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0
 };
@@ -115,8 +141,8 @@ bad_clone_list[] __initdata = {
     {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
     {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
     {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
-#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
-    {"RBHMA4X00-RTL8019", "RBHMA4X00/RTL8019", {0x00, 0x60, 0x0a}},  /* Toshiba built-in */
+#ifdef CONFIG_MACH_TX49XX
+    {"RBHMA4X00-RTL8019", "RBHMA4X00-RTL8019", {0x00, 0x60, 0x0a}},  /* Toshiba built-in */
 #endif
     {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
     {NULL,}
@@ -138,18 +164,16 @@ bad_clone_list[] __initdata = {
 
 #if defined(CONFIG_PLAT_MAPPI)
 #  define DCR_VAL 0x4b
-#elif defined(CONFIG_PLAT_OAKS32R)
-#  define DCR_VAL 0x48
+#elif defined(CONFIG_PLAT_OAKS32R)  || \
+   defined(CONFIG_MACH_TX49XX)
+#  define DCR_VAL 0x48         /* 8-bit mode */
 #else
 #  define DCR_VAL 0x49
 #endif
 
-static int ne_probe1(struct net_device *dev, int ioaddr);
+static int ne_probe1(struct net_device *dev, unsigned long ioaddr);
 static int ne_probe_isapnp(struct net_device *dev);
 
-static int ne_open(struct net_device *dev);
-static int ne_close(struct net_device *dev);
-
 static void ne_reset_8390(struct net_device *dev);
 static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
                          int ring_page);
@@ -158,7 +182,7 @@ static void ne_block_input(struct net_device *dev, int count,
 static void ne_block_output(struct net_device *dev, const int count,
                const unsigned char *buf, const int start_page);
 
-\f
+
 /*  Probe for various non-shared-memory ethercards.
 
    NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
@@ -182,16 +206,19 @@ static void ne_block_output(struct net_device *dev, const int count,
 
 static int __init do_ne_probe(struct net_device *dev)
 {
-       unsigned int base_addr = dev->base_addr;
-#ifndef MODULE
+       unsigned long base_addr = dev->base_addr;
+#ifdef NEEDS_PORTLIST
        int orig_irq = dev->irq;
 #endif
 
-       SET_MODULE_OWNER(dev);
-
        /* First check any supplied i/o locations. User knows best. <cough> */
-       if (base_addr > 0x1ff)  /* Check a single specified location. */
-               return ne_probe1(dev, base_addr);
+       if (base_addr > 0x1ff) {        /* Check a single specified location. */
+               int ret = ne_probe1(dev, base_addr);
+               if (ret)
+                       printk(KERN_WARNING "ne.c: No NE*000 card found at "
+                               "i/o = %#lx\n", base_addr);
+               return ret;
+       }
        else if (base_addr != 0)        /* Don't probe at all. */
                return -ENXIO;
 
@@ -199,7 +226,7 @@ static int __init do_ne_probe(struct net_device *dev)
        if (isapnp_present() && (ne_probe_isapnp(dev) == 0))
                return 0;
 
-#ifndef MODULE
+#ifdef NEEDS_PORTLIST
        /* Last resort. The semi-risky ISA auto-probe. */
        for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
                int ioaddr = netcard_portlist[base_addr];
@@ -212,41 +239,6 @@ static int __init do_ne_probe(struct net_device *dev)
        return -ENODEV;
 }
 
-static void cleanup_card(struct net_device *dev)
-{
-       struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
-       if (idev)
-               pnp_device_detach(idev);
-       free_irq(dev->irq, dev);
-       release_region(dev->base_addr, NE_IO_EXTENT);
-}
-
-#ifndef MODULE
-struct net_device * __init ne_probe(int unit)
-{
-       struct net_device *dev = alloc_ei_netdev();
-       int err;
-
-       if (!dev)
-               return ERR_PTR(-ENOMEM);
-
-       sprintf(dev->name, "eth%d", unit);
-       netdev_boot_setup_check(dev);
-
-#ifdef CONFIG_TOSHIBA_RBTX4938
-       dev->base_addr = 0x07f20280;
-       dev->irq = RBTX4938_RTL_8019_IRQ;
-#endif
-       err = do_ne_probe(dev);
-       if (err)
-               goto out;
-       return dev;
-out:
-       free_netdev(dev);
-       return ERR_PTR(err);
-}
-#endif
-
 static int __init ne_probe_isapnp(struct net_device *dev)
 {
        int i;
@@ -292,7 +284,7 @@ static int __init ne_probe_isapnp(struct net_device *dev)
        return -ENODEV;
 }
 
-static int __init ne_probe1(struct net_device *dev, int ioaddr)
+static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
 {
        int i;
        unsigned char SA_prom[32];
@@ -329,9 +321,9 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
        }
 
        if (ei_debug  &&  version_printed++ == 0)
-               printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
+               printk(KERN_INFO "%s%s", version1, version2);
 
-       printk(KERN_INFO "NE*000 ethercard probe at %#3x:", ioaddr);
+       printk(KERN_INFO "NE*000 ethercard probe at %#3lx:", ioaddr);
 
        /* A user with a poor card that fails to ack the reset, or that
           does not have a valid 0x57,0x57 signature can still use this
@@ -339,7 +331,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
           with an otherwise unused dev->mem_end value of "0xBAD" will
           cause the driver to skip these parts of the probe. */
 
-       bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
+       bad_card = ((dev->base_addr != 0) && (dev->mem_end == BAD));
 
        /* Reset card. Who knows what dain-bramaged state it was left in. */
 
@@ -350,7 +342,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
                outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
 
                while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
-               if (jiffies - reset_start_time > 2*HZ/100) {
+               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
                        if (bad_card) {
                                printk(" (warning: no reset ack)");
                                break;
@@ -365,7 +357,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
        }
 
        /* Read the 16 bytes of station address PROM.
-          We must first initialize registers, similar to NS8390_init(eifdev, 0).
+          We must first initialize registers, similar to NS8390p_init(eifdev, 0).
           We can't reliably read the SAPROM address without this.
           (I learned the hard way!). */
        {
@@ -386,7 +378,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
                        {E8390_RREAD+E8390_START, E8390_CMD},
                };
 
-               for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
+               for (i = 0; i < ARRAY_SIZE(program_seq); i++)
                        outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
 
        }
@@ -404,10 +396,22 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
                /* We must set the 8390 for word mode. */
                outb_p(DCR_VAL, ioaddr + EN0_DCFG);
                start_page = NESM_START_PG;
-               stop_page = NESM_STOP_PG;
+
+               /*
+                * Realtek RTL8019AS datasheet says that the PSTOP register
+                * shouldn't exceed 0x60 in 8-bit mode.
+                * This chip can be identified by reading the signature from
+                * the  remote byte count registers (otherwise write-only)...
+                */
+               if ((DCR_VAL & 0x01) == 0 &&            /* 8-bit mode */
+                   inb(ioaddr + EN0_RCNTLO) == 0x50 &&
+                   inb(ioaddr + EN0_RCNTHI) == 0x70)
+                       stop_page = 0x60;
+               else
+                       stop_page = NESM_STOP_PG;
        } else {
                start_page = NE1SM_START_PG;
-               stop_page = NE1SM_STOP_PG;
+               stop_page  = NE1SM_STOP_PG;
        }
 
 #if  defined(CONFIG_PLAT_MAPPI) || defined(CONFIG_PLAT_OAKS32R)
@@ -488,7 +492,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
 
        /* Snarf the interrupt now.  There's no point in waiting since we cannot
           share and the board will usually be enabled. */
-       ret = request_irq(dev->irq, ei_interrupt, 0, name, dev);
+       ret = request_irq(dev->irq, eip_interrupt, 0, name, dev);
        if (ret) {
                printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
                goto err_out;
@@ -502,30 +506,21 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
        for (i = 0 ; i < ETHER_ADDR_LEN ; i++) {
                dev->dev_addr[i] = SA_prom[i]
                        = inb_p(ioaddr + EN1_PHYS_SHIFT(i));
-               printk(" %2.2x", SA_prom[i]);
        }
 #else
        for(i = 0; i < ETHER_ADDR_LEN; i++) {
-               printk(" %2.2x", SA_prom[i]);
                dev->dev_addr[i] = SA_prom[i];
        }
 #endif
 
-       printk("\n%s: %s found at %#x, using IRQ %d.\n",
-               dev->name, name, ioaddr, dev->irq);
+       printk("%pM\n", dev->dev_addr);
 
        ei_status.name = name;
        ei_status.tx_start_page = start_page;
        ei_status.stop_page = stop_page;
-#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938)
-       wordlength = 1;
-#endif
 
-#ifdef CONFIG_PLAT_OAKS32R
-       ei_status.word16 = 0;
-#else
-       ei_status.word16 = (wordlength == 2);
-#endif
+       /* Use 16-bit mode only if this wasn't overridden by DCR_VAL */
+       ei_status.word16 = (wordlength == 2 && (DCR_VAL & 0x01));
 
        ei_status.rx_start_page = start_page + TX_PAGES;
 #ifdef PACKETBUF_MEMSIZE
@@ -538,16 +533,15 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
        ei_status.block_output = &ne_block_output;
        ei_status.get_8390_hdr = &ne_get_8390_hdr;
        ei_status.priv = 0;
-       dev->open = &ne_open;
-       dev->stop = &ne_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-       dev->poll_controller = ei_poll;
-#endif
-       NS8390_init(dev, 0);
+
+       dev->netdev_ops = &eip_netdev_ops;
+       NS8390p_init(dev, 0);
 
        ret = register_netdev(dev);
        if (ret)
                goto out_irq;
+       printk(KERN_INFO "%s: %s found at %#lx, using IRQ %d.\n",
+              dev->name, name, ioaddr, dev->irq);
        return 0;
 
 out_irq:
@@ -557,20 +551,6 @@ err_out:
        return ret;
 }
 
-static int ne_open(struct net_device *dev)
-{
-       ei_open(dev);
-       return 0;
-}
-
-static int ne_close(struct net_device *dev)
-{
-       if (ei_debug > 1)
-               printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
-       ei_close(dev);
-       return 0;
-}
-
 /* Hard reset the card.  This used to pause for the same period that a
    8390 reset command required, but that shouldn't be necessary. */
 
@@ -589,7 +569,7 @@ static void ne_reset_8390(struct net_device *dev)
 
        /* This check _should_not_ be necessary, omit eventually. */
        while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
-               if (jiffies - reset_start_time > 2*HZ/100) {
+               if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
                        printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
                        break;
                }
@@ -796,80 +776,231 @@ retry:
 #endif
 
        while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
-               if (jiffies - dma_start > 2*HZ/100) {           /* 20ms */
+               if (time_after(jiffies, dma_start + 2*HZ/100)) {                /* 20ms */
                        printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
                        ne_reset_8390(dev);
-                       NS8390_init(dev,1);
+                       NS8390p_init(dev, 1);
                        break;
                }
 
        outb_p(ENISR_RDC, nic_base + EN0_ISR);  /* Ack intr. */
        ei_status.dmaing &= ~0x01;
-       return;
 }
 
-\f
-#ifdef MODULE
-#define MAX_NE_CARDS   4       /* Max number of NE cards per module */
-static struct net_device *dev_ne[MAX_NE_CARDS];
-static int io[MAX_NE_CARDS];
-static int irq[MAX_NE_CARDS];
-static int bad[MAX_NE_CARDS];  /* 0xbad = bad sig or no reset ack */
+static int __init ne_drv_probe(struct platform_device *pdev)
+{
+       struct net_device *dev;
+       int err, this_dev = pdev->id;
+       struct resource *res;
 
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(bad, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O base address(es),required");
-MODULE_PARM_DESC(irq, "IRQ number(s)");
-MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
-MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver");
-MODULE_LICENSE("GPL");
+       dev = alloc_eip_netdev();
+       if (!dev)
+               return -ENOMEM;
+
+       /* ne.c doesn't populate resources in platform_device, but
+        * rbtx4927_ne_init and rbtx4938_ne_init do register devices
+        * with resources.
+        */
+       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (res) {
+               dev->base_addr = res->start;
+               dev->irq = platform_get_irq(pdev, 0);
+       } else {
+               if (this_dev < 0 || this_dev >= MAX_NE_CARDS)
+                       return -EINVAL;
+               dev->base_addr = io[this_dev];
+               dev->irq = irq[this_dev];
+               dev->mem_end = bad[this_dev];
+       }
+       err = do_ne_probe(dev);
+       if (err) {
+               free_netdev(dev);
+               return err;
+       }
+       platform_set_drvdata(pdev, dev);
+
+       /* Update with any values found by probing, don't update if
+        * resources were specified.
+        */
+       if (!res) {
+               io[this_dev] = dev->base_addr;
+               irq[this_dev] = dev->irq;
+       }
+       return 0;
+}
 
-/* This is set up so that no ISA autoprobe takes place. We can't guarantee
-that the ne2k probe is the last 8390 based probe to take place (as it
-is at boot) and so the probe will get confused by any other 8390 cards.
-ISA device autoprobes on a running machine are not recommended anyway. */
+static int ne_drv_remove(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+
+       if (dev) {
+               struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+               netif_device_detach(dev);
+               unregister_netdev(dev);
+               if (idev)
+                       pnp_device_detach(idev);
+               /* Careful ne_drv_remove can be called twice, once from
+                * the platform_driver.remove and again when the
+                * platform_device is being removed.
+                */
+               ei_status.priv = 0;
+               free_irq(dev->irq, dev);
+               release_region(dev->base_addr, NE_IO_EXTENT);
+               free_netdev(dev);
+               platform_set_drvdata(pdev, NULL);
+       }
+       return 0;
+}
+
+/* Remove unused devices or all if true. */
+static void ne_loop_rm_unreg(int all)
+{
+       int this_dev;
+       struct platform_device *pdev;
+       for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
+               pdev = pdev_ne[this_dev];
+               /* No network device == unused */
+               if (pdev && (!platform_get_drvdata(pdev) || all)) {
+                       ne_drv_remove(pdev);
+                       platform_device_unregister(pdev);
+                       pdev_ne[this_dev] = NULL;
+               }
+       }
+}
+
+#ifdef CONFIG_PM
+static int ne_drv_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+
+       if (netif_running(dev)) {
+               struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+               netif_device_detach(dev);
+               if (idev)
+                       pnp_stop_dev(idev);
+       }
+       return 0;
+}
+
+static int ne_drv_resume(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+
+       if (netif_running(dev)) {
+               struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
+               if (idev)
+                       pnp_start_dev(idev);
+               ne_reset_8390(dev);
+               NS8390p_init(dev, 1);
+               netif_device_attach(dev);
+       }
+       return 0;
+}
+#else
+#define ne_drv_suspend NULL
+#define ne_drv_resume NULL
+#endif
+
+static struct platform_driver ne_driver = {
+       .remove         = ne_drv_remove,
+       .suspend        = ne_drv_suspend,
+       .resume         = ne_drv_resume,
+       .driver         = {
+               .name   = DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
 
-int init_module(void)
+static void __init ne_add_devices(void)
 {
-       int this_dev, found = 0;
+       int this_dev;
+       struct platform_device *pdev;
 
        for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-               struct net_device *dev = alloc_ei_netdev();
-               if (!dev)
-                       break;
-               dev->irq = irq[this_dev];
-               dev->mem_end = bad[this_dev];
-               dev->base_addr = io[this_dev];
-               if (do_ne_probe(dev) == 0) {
-                       dev_ne[found++] = dev;
+               if (pdev_ne[this_dev])
                        continue;
-               }
-               free_netdev(dev);
-               if (found)
-                       break;
-               if (io[this_dev] != 0)
-                       printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]);
-               else
-                       printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n");
-               return -ENXIO;
+               pdev = platform_device_register_simple(
+                       DRV_NAME, this_dev, NULL, 0);
+               if (IS_ERR(pdev))
+                       continue;
+               pdev_ne[this_dev] = pdev;
        }
-       if (found)
-               return 0;
-       return -ENODEV;
 }
 
-void cleanup_module(void)
+#ifdef MODULE
+int __init init_module(void)
+{
+       int retval;
+       ne_add_devices();
+       retval = platform_driver_probe(&ne_driver, ne_drv_probe);
+       if (retval) {
+               if (io[0] == 0)
+                       printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\""
+                               " value(s) for ISA cards.\n");
+               ne_loop_rm_unreg(1);
+               return retval;
+       }
+
+       /* Unregister unused platform_devices. */
+       ne_loop_rm_unreg(0);
+       return retval;
+}
+#else /* MODULE */
+static int __init ne_init(void)
+{
+       int retval = platform_driver_probe(&ne_driver, ne_drv_probe);
+
+       /* Unregister unused platform_devices. */
+       ne_loop_rm_unreg(0);
+       return retval;
+}
+module_init(ne_init);
+
+struct net_device * __init ne_probe(int unit)
 {
        int this_dev;
+       struct net_device *dev;
+
+       /* Find an empty slot, that is no net_device and zero io port. */
+       this_dev = 0;
+       while ((pdev_ne[this_dev] && platform_get_drvdata(pdev_ne[this_dev])) ||
+               io[this_dev]) {
+               if (++this_dev == MAX_NE_CARDS)
+                       return ERR_PTR(-ENOMEM);
+       }
 
+       /* Get irq, io from kernel command line */
+       dev = alloc_eip_netdev();
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
+
+       sprintf(dev->name, "eth%d", unit);
+       netdev_boot_setup_check(dev);
+
+       io[this_dev] = dev->base_addr;
+       irq[this_dev] = dev->irq;
+       bad[this_dev] = dev->mem_end;
+
+       free_netdev(dev);
+
+       ne_add_devices();
+
+       /* return the first device found */
        for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-               struct net_device *dev = dev_ne[this_dev];
-               if (dev) {
-                       unregister_netdev(dev);
-                       cleanup_card(dev);
-                       free_netdev(dev);
+               if (pdev_ne[this_dev]) {
+                       dev = platform_get_drvdata(pdev_ne[this_dev]);
+                       if (dev)
+                               return dev;
                }
        }
+
+       return ERR_PTR(-ENODEV);
 }
 #endif /* MODULE */
+
+static void __exit ne_exit(void)
+{
+       platform_driver_unregister(&ne_driver);
+       ne_loop_rm_unreg(1);
+}
+module_exit(ne_exit);