]> git.hungrycats.org Git - linux/commitdiff
[PATCH] depca update
authorMarc Zyngier <mzyngier@freesurf.fr>
Sat, 20 Sep 2003 09:55:06 +0000 (05:55 -0400)
committerStephen Hemminger <shemminger@osdl.org>
Sat, 20 Sep 2003 09:55:06 +0000 (05:55 -0400)
I finally found some time to hack the depca driver, in basically the
same way I did with the de4x5 driver. The patch is quite big (shuffles
a lot of code around, removes lots of global variables), mainly in
order to use the driver model on every bus supported by this driver.

I also removed the probing from Space.c, so the usual warning about
device renumbering applies.

Tested on alpha (DE422, EISA) and i386 (two DE201, ISA), built-in and
modular. The MCA part is completly untested, since I lack the hardware
(no, I do not own every single piece of junk hardware out
there... ;-).

drivers/net/Space.c
drivers/net/depca.c

index 673ebcced9809b82297071b5c0ae95d21159b4eb..651ffca8a9be86cfe3a927b7ddbbf0ce33e229bb 100644 (file)
@@ -58,7 +58,6 @@ extern int at1500_probe(struct net_device *);
 extern int at1700_probe(struct net_device *);
 extern int fmv18x_probe(struct net_device *);
 extern int eth16i_probe(struct net_device *);
-extern int depca_probe(struct net_device *);
 extern int i82596_probe(struct net_device *);
 extern int ewrk3_probe(struct net_device *);
 extern int el1_probe(struct net_device *);
@@ -252,9 +251,6 @@ static struct devprobe isa_probes[] __initdata = {
 #ifdef CONFIG_EEXPRESS_PRO     /* Intel EtherExpress Pro/10 */
        {eepro_probe, 0},
 #endif
-#ifdef CONFIG_DEPCA            /* DEC DEPCA */
-       {depca_probe, 0},
-#endif
 #ifdef CONFIG_EWRK3             /* DEC EtherWORKS 3 */
        {ewrk3_probe, 0},
 #endif
index 623b9b54d79673c321f68ff17574a4e32a524d1f..e9700be215699fa84fc4a954e01d51bff76ef1a3 100644 (file)
@@ -1,4 +1,4 @@
-/*  depca.c: A DIGITAL DEPCA  & EtherWORKS ethernet driver for linux.
+/*  depca.c: A DIGITAL DEPCA & EtherWORKS ethernet driver for linux.
 
     Written 1994, 1995 by David C. Davies.
 
 #include <linux/types.h>
 #include <linux/unistd.h>
 #include <linux/ctype.h>
-#include <linux/mca-legacy.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
 #endif
 
 #ifdef CONFIG_EISA
-#include <linux/device.h>
 #include <linux/eisa.h>
 #endif
 
@@ -305,21 +305,21 @@ static int depca_debug = 1;
 ** EISA bus defines
 */
 #define DEPCA_EISA_IO_PORTS 0x0c00     /* I/O port base address, slot 0 */
-#define MAX_EISA_SLOTS 16
-#define EISA_SLOT_INC 0x1000
 
 /*
 ** ISA Bus defines
 */
 #define DEPCA_RAM_BASE_ADDRESSES {0xc0000,0xd0000,0xe0000,0x00000}
-#define DEPCA_IO_PORTS {0x300, 0x200, 0}
 #define DEPCA_TOTAL_SIZE 0x10
-static short mem_chkd;
 
-/*
-** Adapter ID for the MCA EtherWORKS DE210/212 adapter
-*/
-#define DE212_ID 0x6def
+static struct {
+       u_long iobase;
+       struct platform_device *device;
+} depca_io_ports[] = {
+       { 0x300, NULL },
+       { 0x200, NULL },
+       { 0    , NULL },
+};
 
 /*
 ** Name <-> Adapter mapping
@@ -330,34 +330,86 @@ static short mem_chkd;
                         "DE210","DE212",\
                          "DE422",\
                          ""}
-static enum {
+
+static char* __initdata depca_signature[] = DEPCA_SIGNATURE;
+
+enum depca_type {
        DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown
-} adapter;
+};
+
+static char depca_string[] = "depca";
+
+static int depca_device_remove (struct device *device);
 
 #ifdef CONFIG_EISA
 struct eisa_device_id depca_eisa_ids[] = {
-       { "DEC4220" },
+       { "DEC4220", de422 },
        { "" }
 };
 
 static int depca_eisa_probe  (struct device *device);
-static int depca_eisa_remove (struct device *device);
 
 struct eisa_driver depca_eisa_driver = {
        .id_table = depca_eisa_ids,
        .driver   = {
-               .name    = "depca",
+               .name    = depca_string,
                .probe   = depca_eisa_probe,
-               .remove  = __devexit_p (depca_eisa_remove)
+               .remove  = __devexit_p (depca_device_remove)
        }
 };
 #endif
 
+#ifdef CONFIG_MCA
+/*
+** Adapter ID for the MCA EtherWORKS DE210/212 adapter
+*/
+#define DE210_ID 0x628d
+#define DE212_ID 0x6def
+
+static short depca_mca_adapter_ids[] = {
+       DE210_ID,
+       DE212_ID,
+       0x0000
+};
+
+static char *depca_mca_adapter_name[] = {
+       "DEC EtherWORKS MC Adapter (DE210)",
+       "DEC EtherWORKS MC Adapter (DE212)",
+       NULL
+};
+
+static enum depca_type depca_mca_adapter_type[] = {
+       de210,
+       de212,
+       0
+};
+
+static int depca_mca_probe (struct device *);
+
+static struct mca_driver depca_mca_driver = {
+       .id_table = depca_mca_adapter_ids,
+       .driver   = {
+               .name   = depca_string,
+               .bus    = &mca_bus_type,
+               .probe  = depca_mca_probe,
+               .remove = __devexit_p(depca_device_remove),
+       },
+};
+#endif
+
+static int depca_isa_probe (struct device *);
+
+static struct device_driver depca_isa_driver = {
+       .name   = depca_string,
+       .bus    = &platform_bus_type,
+       .probe  = depca_isa_probe,
+       .remove = __devexit_p(depca_device_remove),
+};
+       
 /*
 ** Miscellaneous info...
 */
 #define DEPCA_STRLEN 16
-#define MAX_NUM_DEPCAS 2
 
 /*
 ** Memory Alignment. Each descriptor is 4 longwords long. To force a
@@ -402,10 +454,13 @@ struct depca_init {
 #define DEPCA_PKT_BIN_SZ  128  /* Should be >=100 unless you
                                   increase DEPCA_PKT_STAT_SZ */
 struct depca_private {
-       char devname[DEPCA_STRLEN];     /* Device Product String                  */
        char adapter_name[DEPCA_STRLEN];        /* /proc/ioports string                  */
-       char adapter;           /* Adapter type                           */
-       char mca_slot;          /* MCA slot, if MCA else -1               */
+       enum depca_type adapter;                /* Adapter type */
+       enum {
+                DEPCA_BUS_MCA = 1,
+                DEPCA_BUS_ISA,
+                DEPCA_BUS_EISA,
+        } depca_bus;           /* type of bus */
        struct depca_init init_block;   /* Shadow Initialization block            */
 /* CPU address space fields */
        struct depca_rx_desc *rx_ring;  /* Pointer to start of RX descriptor ring */
@@ -467,45 +522,39 @@ static void set_multicast_list(struct net_device *dev);
 /*
 ** Private functions
 */
-static int depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot);
 static void depca_init_ring(struct net_device *dev);
 static int depca_rx(struct net_device *dev);
 static int depca_tx(struct net_device *dev);
 
 static void LoadCSRs(struct net_device *dev);
 static int InitRestartDepca(struct net_device *dev);
-static void DepcaSignature(char *name, u_long paddr);
+static int DepcaSignature(char *name, u_long paddr);
 static int DevicePresent(u_long ioaddr);
 static int get_hw_addr(struct net_device *dev);
 static void SetMulticastFilter(struct net_device *dev);
-static void isa_probe(struct net_device *dev, u_long iobase);
-#ifdef CONFIG_MCA
-static void mca_probe(struct net_device *dev, u_long iobase);
-#endif
-static struct net_device *alloc_device(struct net_device *dev, u_long iobase);
-static int depca_dev_index(char *s);
-static struct net_device *insert_device(struct net_device *dev, u_long iobase, int (*init) (struct net_device *));
 static int load_packet(struct net_device *dev, struct sk_buff *skb);
 static void depca_dbg_open(struct net_device *dev);
 
-#ifdef MODULE
-static int autoprobed = 1, loading_module = 1;
-# else
 static u_char de1xx_irq[] __initdata = { 2, 3, 4, 5, 7, 9, 0 };
 static u_char de2xx_irq[] __initdata = { 5, 9, 10, 11, 15, 0 };
 static u_char de422_irq[] __initdata = { 5, 9, 10, 11, 0 };
 static u_char *depca_irq;
-static int autoprobed, loading_module;
-#endif                         /* MODULE */
 
-static char name[DEPCA_STRLEN];
-static int num_depcas, num_eth;
+static int irq;
+static int io;
+static char *adapter_name;
 static int mem;                        /* For loadable module assignment
                                   use insmod mem=0x????? .... */
-static char *adapter_name;     /* = '\0';     If no PROM when loadable module
-                                  use insmod adapter_name=DE??? ...
-                                  bss initializes this to zero
-                                */
+module_param (irq, int, 0);
+module_param (io, int, 0);
+module_param (adapter_name, charp, 0);
+module_param (mem, int, 0);
+MODULE_PARM_DESC(irq, "DEPCA IRQ number");
+MODULE_PARM_DESC(io, "DEPCA I/O base address");
+MODULE_PARM_DESC(adapter_name, "DEPCA adapter name");
+MODULE_PARM_DESC(mem, "DEPCA shared memory address");
+MODULE_LICENSE("GPL");
+
 /*
 ** Miscellaneous defines...
 */
@@ -513,52 +562,30 @@ static char *adapter_name;        /* = '\0';     If no PROM when loadable module
     outw(CSR0, DEPCA_ADDR);\
     outw(STOP, DEPCA_DATA)
 
-int __init depca_probe(struct net_device *dev)
-{
-       int tmp = num_depcas, status = -ENODEV;
-       u_long iobase = dev->base_addr;
-
-       SET_MODULE_OWNER(dev);
-
-       if ((iobase == 0) && loading_module) {
-               printk("Autoprobing is not supported when loading a module based driver.\n");
-               status = -EIO;
-       } else {
-#ifdef CONFIG_MCA
-               mca_probe(dev, iobase);
-#endif
-               isa_probe(dev, iobase);
-#ifdef CONFIG_EISA
-               eisa_driver_register (&depca_eisa_driver);
-#endif
-
-               if ((tmp == num_depcas) && (iobase != 0) && loading_module) {
-                       printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, iobase);
-               }
-
-               /*
-                  ** Walk the device list to check that at least one device
-                  ** initialised OK
-                */
-               for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next);
-
-               if (dev->priv)
-                       status = 0;
-               if (iobase == 0)
-                       autoprobed = 1;
-       }
-
-       return status;
-}
-
-static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_slot)
+static int __init depca_hw_init (struct net_device *dev, struct device *device)
 {
        struct depca_private *lp;
        int i, j, offset, netRAM, mem_len, status = 0;
        s16 nicsr;
-       u_long mem_start = 0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES;
-       int is_eisa = ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS);
+       u_long ioaddr;
+       u_long mem_start;
 
+       /*
+        * We are now supposed to enter this function with the
+        * following fields filled with proper values :
+        *
+        * dev->base_addr
+        * lp->mem_start
+        * lp->depca_bus
+        * lp->adapter
+        *
+        * dev->irq can be set if known from device configuration (on
+        * MCA or EISA) or module option. Otherwise, it will be auto
+        * detected.
+        */
+
+       ioaddr = dev->base_addr;
+       
        STOP_DEPCA;
 
        nicsr = inb(DEPCA_NICSR);
@@ -569,24 +596,34 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
                return -ENXIO;
        }
 
-       do {
-               strcpy(name, (adapter_name ? adapter_name : ""));
-               mem_start = (mem ? mem & 0xf0000 : mem_base[mem_chkd++]);
-               DepcaSignature(name, mem_start);
-       } while (!mem && mem_base[mem_chkd] && (adapter == unknown));
+       lp = (struct depca_private *) dev->priv;
+       mem_start = lp->mem_start;
 
-       if ((adapter == unknown) || !mem_start) {       /* DEPCA device not found */
+       if (!mem_start || lp->adapter < DEPCA || lp->adapter >=unknown)
                return -ENXIO;
-       }
 
-       dev->base_addr = ioaddr;
+       printk ("%s: %s at 0x%04lx",
+               device->bus_id, depca_signature[lp->adapter], ioaddr);
+       
+       switch (lp->depca_bus) {
+#ifdef CONFIG_MCA
+       case DEPCA_BUS_MCA:
+               printk(" (MCA slot %d)", to_mca_device(device)->slot + 1);
+               break;
+#endif
 
-       if (mca_slot != -1) {
-               printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, ioaddr, mca_slot);
-       } else if (is_eisa) {   /* EISA slot address */
-               printk("%s: %s at 0x%04lx (EISA slot %d)", dev->name, name, ioaddr, (int) ((ioaddr >> 12) & 0x0f));
-       } else {                /* ISA port address */
-               printk("%s: %s at 0x%04lx", dev->name, name, ioaddr);
+#ifdef CONFIG_EISA
+       case DEPCA_BUS_EISA:
+               printk(" (EISA slot %d)", to_eisa_device(device)->slot);
+               break;
+#endif
+
+       case DEPCA_BUS_ISA:
+               break;
+
+       default:
+               printk("Unknown DEPCA bus %d\n", lp->depca_bus);
+               return -ENXIO;
        }
 
        printk(", h/w address ");
@@ -601,18 +638,20 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
        printk("%2.2x", dev->dev_addr[i]);
 
        /* Set up the maximum amount of network RAM(kB) */
-       netRAM = ((adapter != DEPCA) ? 64 : 48);
-       if ((nicsr & _128KB) && (adapter == de422))
+       netRAM = ((lp->adapter != DEPCA) ? 64 : 48);
+       if ((nicsr & _128KB) && (lp->adapter == de422))
                netRAM = 128;
-       offset = 0x0000;
 
        /* Shared Memory Base Address */
        if (nicsr & BUF) {
-               offset = 0x8000;        /* 32kbyte RAM offset */
                nicsr &= ~BS;   /* DEPCA RAM in top 32k */
                netRAM -= 32;
+
+               /* Only EISA/ISA needs start address to be re-computed */
+               if (lp->depca_bus != DEPCA_BUS_MCA)
+                       mem_start += 0x8000;
        }
-       mem_start += offset;    /* (E)ISA start address */
+       
        if ((mem_len = (NUM_RX_DESC * (sizeof(struct depca_rx_desc) + RX_BUFF_SZ) + NUM_TX_DESC * (sizeof(struct depca_tx_desc) + TX_BUFF_SZ) + sizeof(struct depca_init)))
            > (netRAM << 10)) {
                printk(",\n       requests %dkB RAM: only %dkB is available!\n", (mem_len >> 10), netRAM);
@@ -622,23 +661,14 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
        printk(",\n      has %dkB RAM at 0x%.5lx", netRAM, mem_start);
 
        /* Enable the shadow RAM. */
-       if (adapter != DEPCA) {
+       if (lp->adapter != DEPCA) {
                nicsr |= SHE;
                outb(nicsr, DEPCA_NICSR);
        }
 
-       /* Define the device private memory */
-       if (!is_eisa) {
-               dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL);
-               if (dev->priv == NULL)
-                       return -ENOMEM;
-       }
-       lp = (struct depca_private *) dev->priv;
-       memset((char *) dev->priv, 0, sizeof(struct depca_private));
-       lp->adapter = adapter;
-       lp->mca_slot = mca_slot;
        lp->lock = SPIN_LOCK_UNLOCKED;
-       sprintf(lp->adapter_name, "%s (%s)", name, dev->name);
+       sprintf(lp->adapter_name, "%s (%s)",
+               depca_signature[lp->adapter], device->bus_id);
        status = -EBUSY;
 
        /* Initialisation Block */
@@ -702,7 +732,6 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
        /* 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
                unsigned char irqnum;
                unsigned long irq_mask, delay;
 
@@ -725,6 +754,9 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
                case de422:
                        depca_irq = de422_irq;
                        break;
+
+               default:
+                       break;  /* Not reached */
                }
 
                /* Trigger an initialization just for the interrupt. */
@@ -733,6 +765,7 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
                delay = jiffies + HZ/50;
                while (time_before(jiffies, delay))
                        yield();
+
                irqnum = probe_irq_off(irq_mask);
 
                status = -ENXIO;
@@ -746,13 +779,11 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
                                        printk(" and uses IRQ%d.\n", dev->irq);
                                }
 
-                       status = -ENXIO;
                        if (!dev->irq) {
                                printk(" but incorrect IRQ line detected.\n");
-                               goto out_priv;
+                               return -ENXIO;
                        }
                }
-#endif                         /* MODULE */
        } else {
                printk(" and assigned IRQ%d.\n", dev->irq);
        }
@@ -773,17 +804,14 @@ static int __init depca_hw_init(struct net_device *dev, u_long ioaddr, int mca_s
 
        dev->mem_start = 0;
 
-       /* Fill in the generic field of the device structure. */
-       if (!is_eisa)
-               ether_setup(dev);
+       device->driver_data = dev;
+       SET_NETDEV_DEV (dev, device);
+       
+       register_netdev (dev);
        return 0;
-      out_priv:
-       if (!is_eisa) {
-               kfree(dev->priv);
-               dev->priv = NULL;
-       } else {
-               unregister_netdev (dev);
-       }
+
+ out_priv:
+       
        return status;
 }
 \f
@@ -1284,215 +1312,265 @@ static void SetMulticastFilter(struct net_device *dev)
        return;
 }
 
+static int __init depca_common_init (u_long ioaddr, struct net_device **devp)
+{
+       int status = 0;
+       
+       if (!request_region (ioaddr, DEPCA_TOTAL_SIZE, depca_string)) {
+               status = -EBUSY;
+               goto out;
+       }
+       
+       if (DevicePresent(ioaddr)) {
+               status = -ENODEV;
+               goto out_release;
+       }
+
+       if (!(*devp = alloc_etherdev (sizeof (struct depca_private)))) {
+               status = -ENOMEM;
+               goto out_release;
+       }
+
+       return 0;
+       
+ out_release:
+       release_region (ioaddr, DEPCA_TOTAL_SIZE);
+ out:
+       return status;
+}
+
 #ifdef CONFIG_MCA
 /*
 ** Microchannel bus I/O device probe
 */
-static void __init mca_probe(struct net_device *dev, u_long ioaddr)
+static int __init depca_mca_probe(struct device *device)
 {
        unsigned char pos[2];
        unsigned char where;
-       unsigned long iobase;
-       int irq;
-       int slot = 0;
+       unsigned long iobase, mem_start;
+       int irq, err;
+       struct mca_device *mdev = to_mca_device (device);
+       struct net_device *dev;
+       struct depca_private *lp;
 
        /*
-          ** See if we've been here before.
-        */
-       if ((!ioaddr && autoprobed) || (ioaddr && !loading_module))
-               return;
-
-       if (MCA_bus) {
-               /*
-                  ** Search for the adapter.  If an address has been given, search 
-                  ** specifically for the card at that address.  Otherwise find the
-                  ** first card in the system.
-                */
-               while ((dev != NULL) && ((slot = mca_find_adapter(DE212_ID, slot)) != MCA_NOTFOUND)) {
-                       pos[0] = mca_read_stored_pos(slot, 2);
-                       pos[1] = mca_read_stored_pos(slot, 3);
-
-                       /*
-                          ** IO of card is handled by bits 1 and 2 of pos0.    
-                          **
-                          **    bit2 bit1    IO
-                          **       0    0    0x2c00
-                          **       0    1    0x2c10
-                          **       1    0    0x2c20
-                          **       1    1    0x2c30
-                        */
-                       where = (pos[0] & 6) >> 1;
-                       iobase = 0x2c00 + (0x10 * where);
-
-                       if ((ioaddr) && (ioaddr != iobase)) {
-                               /*
-                                  ** Card was found, but not at the right IO location. Continue 
-                                  ** scanning from the next MCA slot up for another card.
-                                */
-                               slot++;
-                               continue;
-                       }
-
-                       /*
-                          ** Found the adapter we were looking for. Now start setting it up.
-                          ** 
-                          ** First work on decoding the IRQ.  It's stored in the lower 4 bits
-                          ** of pos1.  Bits are as follows (from the ADF file):
-                          **
-                          **      Bits           
-                          **   3   2   1   0    IRQ 
-                          **   --------------------
-                          **   0   0   1   0     5
-                          **   0   0   0   1     9
-                          **   0   1   0   0    10
-                          **   1   0   0   0    11
-                          * */
-                       where = pos[1] & 0x0f;
-                       switch (where) {
-                       case 1:
-                               irq = 9;
-                               break;
-                       case 2:
-                               irq = 5;
-                               break;
-                       case 4:
-                               irq = 10;
-                               break;
-                       case 8:
-                               irq = 11;
-                               break;
-                       default:
-                               printk("%s: mca_probe IRQ error.  You should never get here (%d).\n", dev->name, where);
-                               return;
-                       }
+       ** Search for the adapter.  If an address has been given, search 
+       ** specifically for the card at that address.  Otherwise find the
+       ** first card in the system.
+       */
+       
+       pos[0] = mca_device_read_stored_pos(mdev, 2);
+       pos[1] = mca_device_read_stored_pos(mdev, 3);
 
-                       /*
-                          ** Shared memory address of adapter is stored in bits 3-5 of pos0.
-                          ** They are mapped as follows:
-                          **
-                          **    Bit
-                          **   5  4  3       Memory Addresses
-                          **   0  0  0       C0000-CFFFF (64K)
-                          **   1  0  0       C8000-CFFFF (32K)
-                          **   0  0  1       D0000-DFFFF (64K)
-                          **   1  0  1       D8000-DFFFF (32K)
-                          **   0  1  0       E0000-EFFFF (64K)
-                          **   1  1  0       E8000-EFFFF (32K)
-                        */
-                       where = (pos[0] & 0x18) >> 3;
-                       mem = 0xc0000 + (where * 0x10000);
-                       if (pos[0] & 0x20) {
-                               mem += 0x8000;
-                       }
+       /*
+       ** IO of card is handled by bits 1 and 2 of pos0.    
+       **
+       **    bit2 bit1    IO
+       **       0    0    0x2c00
+       **       0    1    0x2c10
+       **       1    0    0x2c20
+       **       1    1    0x2c30
+       */
+       where = (pos[0] & 6) >> 1;
+       iobase = 0x2c00 + (0x10 * where);
 
-                       /*
-                          ** Get everything allocated and initialized...  (almost just
-                          ** like the ISA and EISA probes)
-                        */
-                       if (!request_region (iobase, DEPCA_TOTAL_SIZE, "depca")) {
-                               if (autoprobed)
-                                       printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
-                               goto next;
-                       }
-                       if (DevicePresent(iobase) != 0) {
-                               /*
-                                  ** If the MCA configuration says the card should be here,
-                                  ** it really should be here.
-                                */
-                               printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not responding.\n", dev->name, iobase);
-                               goto release_next;
-                       }
+       /*
+       ** Found the adapter we were looking for. Now start setting it up.
+       ** 
+       ** First work on decoding the IRQ.  It's stored in the lower 4 bits
+       ** of pos1.  Bits are as follows (from the ADF file):
+       **
+       **      Bits           
+       **   3   2   1   0    IRQ 
+       **   --------------------
+       **   0   0   1   0     5
+       **   0   0   0   1     9
+       **   0   1   0   0    10
+       **   1   0   0   0    11
+       */
+       where = pos[1] & 0x0f;
+       switch (where) {
+       case 1:
+               irq = 9;
+               break;
+       case 2:
+               irq = 5;
+               break;
+       case 4:
+               irq = 10;
+               break;
+       case 8:
+               irq = 11;
+               break;
+       default:
+               printk("%s: mca_probe IRQ error.  You should never get here (%d).\n", dev->name, where);
+               return -EINVAL;
+       }
 
-                       if (!(dev = alloc_device(dev, iobase)))
-                               goto release_next;
+       /*
+       ** Shared memory address of adapter is stored in bits 3-5 of pos0.
+       ** They are mapped as follows:
+       **
+       **    Bit
+       **   5  4  3       Memory Addresses
+       **   0  0  0       C0000-CFFFF (64K)
+       **   1  0  0       C8000-CFFFF (32K)
+       **   0  0  1       D0000-DFFFF (64K)
+       **   1  0  1       D8000-DFFFF (32K)
+       **   0  1  0       E0000-EFFFF (64K)
+       **   1  1  0       E8000-EFFFF (32K)
+       */
+       where = (pos[0] & 0x18) >> 3;
+       mem_start = 0xc0000 + (where * 0x10000);
+       if (pos[0] & 0x20) {
+               mem_start += 0x8000;
+       }
 
-                       num_eth++;
-                       dev->irq = irq;
-                       if (depca_hw_init(dev, iobase, slot))
-                               goto release_next;
+       /* claim the slot */
+       strncpy(mdev->name, depca_mca_adapter_name[mdev->index],
+               sizeof(mdev->name));
+       mca_device_set_claim(mdev, 1);
+       
+        /*
+       ** Get everything allocated and initialized...  (almost just
+       ** like the ISA and EISA probes)
+       */
+       irq = mca_device_transform_irq(mdev, irq);
+       iobase = mca_device_transform_ioport(mdev, iobase);
+
+       if ((err = depca_common_init (iobase, &dev)))
+               goto out_unclaim;
+
+       dev->irq = irq;
+       dev->base_addr = iobase;
+       lp = dev->priv;
+       lp->depca_bus = DEPCA_BUS_MCA;
+       lp->adapter = depca_mca_adapter_type[mdev->index];
+       lp->mem_start = mem_start;
+       
+       if ((err = depca_hw_init(dev, device)))
+               goto out_free;
                        
-                       /*
-                       ** Adapter initialized correctly:  Name it in
-                       ** /proc/mca.
-                       */
-                       mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter");
-                       mca_mark_as_used(slot);
-                       num_depcas++;
-
-                       /*
-                          ** If this is a probe by a module, return after setting up the
-                          ** given card.
-                        */
-                       if (ioaddr)
-                               return;
-
-                       /*
-                       ** Set up to check the next slot and loop.
-                        */
-                       slot++;
-                       continue;
+       return 0;
 
-       release_next:
-                       release_region (iobase, DEPCA_TOTAL_SIZE);
-       next:
-                       slot++;
-               }
-       }
+ out_free:
+       free_netdev (dev);
+       release_region (iobase, DEPCA_TOTAL_SIZE);
+ out_unclaim:
+       mca_device_set_claim(mdev, 0);
 
-       return;
+       return err;;
 }
 #endif
 
 /*
 ** ISA bus I/O device probe
 */
-static void __init isa_probe(struct net_device *dev, u_long ioaddr)
+
+static void depca_platform_release (struct device *device)
 {
-       int i = num_depcas, maxSlots;
-       s32 ports[] = DEPCA_IO_PORTS;
-
-       if (!ioaddr && autoprobed)
-               return;         /* Been here before ! */
-       if (ioaddr > 0x400)
-               return;         /* EISA Address */
-       if (i >= MAX_NUM_DEPCAS)
-               return;         /* Too many ISA adapters */
-
-       if (ioaddr == 0) {      /* Autoprobing */
-               maxSlots = MAX_NUM_DEPCAS;
-       } else {                /* Probe a specific location */
-               ports[i] = ioaddr;
-               maxSlots = i + 1;
-       }
+       struct platform_device *pldev;
+
+       /* free device */
+       pldev = to_platform_device (device);
+       kfree (pldev);
+}
+
+static void __init depca_platform_probe (void)
+{
+       int i;
+       struct platform_device *pldev;
 
-       for (; (i < maxSlots) && (dev != NULL) && ports[i]; i++) {
-               if (!request_region (ports[i], DEPCA_TOTAL_SIZE, "depca")) {
-                       if (autoprobed)
-                               printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]);
+       for (i = 0; depca_io_ports[i].iobase; i++) {
+               depca_io_ports[i].device = NULL;
+               
+               /* if an address has been specified on the command
+                * line, use it (if valid) */
+               if (io && io != depca_io_ports[i].iobase)
                        continue;
-               }
+               
+               if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL)))
+                       continue;
+
+               memset (pldev, 0, sizeof (*pldev));
+               pldev->name = depca_string;
+               pldev->id   = i;
+               pldev->dev.platform_data = (void *) depca_io_ports[i].iobase;
+               pldev->dev.release       = depca_platform_release;
+               depca_io_ports[i].device = pldev;
 
-               if (DevicePresent(ports[i])) {
-                       release_region (ports[i], DEPCA_TOTAL_SIZE);
+               if (platform_device_register (pldev)) {
+                       kfree (pldev);
+                       depca_io_ports[i].device = NULL;
                        continue;
                }
 
-               if (!(dev = alloc_device(dev, ports[i]))) {
-                       release_region (ports[i], DEPCA_TOTAL_SIZE);
-                       continue;
+               if (!pldev->dev.driver) {
+               /* The driver was not bound to this device, there was
+                * no hardware at this address. Unregister it, as the
+                * release fuction will take care of freeing the
+                * allocated structure */
+                       
+                       depca_io_ports[i].device = NULL;
+                       platform_device_unregister (pldev);
                }
+       }
+}
 
-               num_eth++;
+static enum depca_type __init depca_shmem_probe (ulong *mem_start)
+{
+       u_long mem_base[] = DEPCA_RAM_BASE_ADDRESSES;
+       enum depca_type adapter = unknown;
+       int i;
 
-               if (depca_hw_init(dev, ports[i], -1)) {
-                       release_region (ports[i], DEPCA_TOTAL_SIZE);
-                       continue;
-               }
+       for (i = 0; mem_base[i]; i++) {
+               *mem_start = mem ? mem : mem_base[i];
+               adapter = DepcaSignature (adapter_name, *mem_start);
+               if (adapter != unknown)
+                       break;
+       }
+
+       return adapter;
+}
 
-               num_depcas++;
+static int __init depca_isa_probe (struct device *device)
+{
+       struct net_device *dev;
+       struct depca_private *lp;
+       u_long ioaddr, mem_start = 0;
+       enum depca_type adapter = unknown;
+       int status = 0;
+
+       ioaddr = (u_long) device->platform_data;
+
+       if ((status = depca_common_init (ioaddr, &dev)))
+               goto out;
+
+       adapter = depca_shmem_probe (&mem_start);
+       
+       if (adapter == unknown) {
+               status = -ENODEV;
+               goto out_free;
        }
 
-       return;
+       dev->base_addr = ioaddr;
+       dev->irq = irq;         /* Use whatever value the user gave
+                                * us, and 0 if he didn't. */
+       lp = dev->priv;
+       lp->depca_bus = DEPCA_BUS_ISA;
+       lp->adapter = adapter;
+       lp->mem_start = mem_start;
+       
+       if ((status = depca_hw_init(dev, device)))
+               goto out_free;
+       
+       return 0;
+
+ out_free:
+       free_netdev (dev);
+       release_region (ioaddr, DEPCA_TOTAL_SIZE);
+ out:
+       return status;
 }
 
 /*
@@ -1504,202 +1582,120 @@ static int __init depca_eisa_probe (struct device *device)
 {
        struct eisa_device *edev;
        struct net_device *dev;
-       u_long iobase;
+       struct depca_private *lp;
+       u_long ioaddr, mem_start;
        int status = 0;
 
        edev = to_eisa_device (device);
-       iobase = edev->base_addr + DEPCA_EISA_IO_PORTS;
+       ioaddr = edev->base_addr + DEPCA_EISA_IO_PORTS;
 
-       if (!request_region (iobase, DEPCA_TOTAL_SIZE, "depca")) {
-               status = -EBUSY;
+       if ((status = depca_common_init (ioaddr, &dev)))
                goto out;
-       }
-       
-       if (DevicePresent(iobase)) {
-               status = -ENODEV;
-               goto out_release;
-       }
 
-       if (!(dev = init_etherdev (NULL, sizeof (struct depca_private)))) {
-               status = -ENOMEM;
-               goto out_release;
-       }
-               
-       eisa_set_drvdata (edev, dev);
+       /* It would have been nice to get card configuration from the
+        * card. Unfortunately, this register is write-only (shares
+        * it's address with the ethernet prom)... As we don't parse
+        * the EISA configuration structures (yet... :-), just rely on
+        * the ISA probing to sort it out... */
+       
+       depca_shmem_probe (&mem_start);
 
-       if ((status = depca_hw_init(dev, iobase, -1)))
+       dev->base_addr = ioaddr;
+       dev->irq = irq;
+       lp = dev->priv;
+       lp->depca_bus = DEPCA_BUS_EISA;
+       lp->adapter = edev->id.driver_data;
+       lp->mem_start = mem_start;
+       
+       if ((status = depca_hw_init(dev, device)))
                goto out_free;
-
-       num_depcas++;
+       
        return 0;
 
  out_free:
-       kfree (dev);
- out_release:
-       release_region (iobase, DEPCA_TOTAL_SIZE);
+       free_netdev (dev);
+       release_region (ioaddr, DEPCA_TOTAL_SIZE);
  out:
        return status;
 }
+#endif
 
-static int __devexit depca_eisa_remove (struct device *device)
+static int __devexit depca_device_remove (struct device *device)
 {
        struct net_device *dev;
-       struct eisa_device *edev;
        struct depca_private *lp;
+       int bus;
 
-       edev = to_eisa_device (device);
-       dev  = eisa_get_drvdata (edev);
+       dev  = device->driver_data;
        lp   = dev->priv;
 
        unregister_netdev (dev);
        iounmap (lp->sh_mem);
        release_mem_region (lp->mem_start, lp->mem_len);
        release_region (dev->base_addr, DEPCA_TOTAL_SIZE);
-       kfree (dev);
+       bus = lp->depca_bus;
+       free_netdev (dev);
 
        return 0;
 }
-#endif
-
-/*
-** Search the entire 'eth' device list for a fixed probe. If a match isn't
-** found then check for an autoprobe or unused device location. If they
-** are not available then insert a new device structure at the end of
-** the current list.
-*/
-static struct net_device *__init alloc_device(struct net_device *dev, u_long iobase)
-{
-       struct net_device *adev = NULL;
-       int fixed = 0, new_dev = 0;
-
-       num_eth = depca_dev_index(dev->name);
-       if (loading_module)
-               return dev;
-
-       while (1) {
-               if (((dev->base_addr == DEPCA_NDA) || (dev->base_addr == 0)) && !adev) {
-                       adev = dev;
-               } else if ((dev->priv == NULL) && (dev->base_addr == iobase)) {
-                       fixed = 1;
-               } else {
-                       if (dev->next == NULL) {
-                               new_dev = 1;
-                       } else if (strncmp(dev->next->name, "eth", 3) != 0) {
-                               new_dev = 1;
-                       }
-               }
-               if ((dev->next == NULL) || new_dev || fixed)
-                       break;
-               dev = dev->next;
-               num_eth++;
-       }
-       if (adev && !fixed) {
-               dev = adev;
-               num_eth = depca_dev_index(dev->name);
-               new_dev = 0;
-       }
-
-       if (((dev->next == NULL) && ((dev->base_addr != DEPCA_NDA) && (dev->base_addr != 0)) && !fixed) || new_dev) {
-               num_eth++;      /* New device */
-               dev = insert_device(dev, iobase, depca_probe);
-       }
-
-       return dev;
-}
-
-/*
-** If at end of eth device list and can't use current entry, malloc
-** one up. If memory could not be allocated, print an error message.
-*/
-static struct net_device *__init insert_device(struct net_device *dev, u_long iobase, int (*init) (struct net_device *))
-{
-       struct net_device *new;
-
-       new = (struct net_device *) kmalloc(sizeof(struct net_device), GFP_KERNEL);
-       if (new == NULL) {
-               printk("eth%d: Device not initialised, insufficient memory\n", num_eth);
-               return NULL;
-       } else {
-               new->next = dev->next;
-               dev->next = new;
-               dev = dev->next;        /* point to the new device */
-               if (num_eth > 9999) {
-                       sprintf(dev->name, "eth????");  /* New device name */
-               } else {
-                       sprintf(dev->name, "eth%d", num_eth);   /* New device name */
-               }
-               dev->base_addr = iobase;        /* assign the io address */
-               dev->init = init;       /* initialisation routine */
-       }
-
-       return dev;
-}
-
-static int __init depca_dev_index(char *s)
-{
-       int i = 0, j = 0;
-
-       for (; *s; s++) {
-               if (isdigit(*s)) {
-                       j = 1;
-                       i = (i * 10) + (*s - '0');
-               } else if (j)
-                       break;
-       }
-
-       return i;
-}
 
 /*
 ** Look for a particular board name in the on-board Remote Diagnostics
 ** and Boot (readb) ROM. This will also give us a clue to the network RAM
 ** base address.
 */
-static void __init DepcaSignature(char *name, u_long paddr)
+static int __init DepcaSignature(char *name, u_long base_addr)
 {
        u_int i, j, k;
-       const char *signatures[] = DEPCA_SIGNATURE;
        void *ptr;
        char tmpstr[16];
+       u_long prom_addr = base_addr + 0xc000;
+       u_long mem_addr = base_addr + 0x8000; /* 32KB */
+
+       /* Can't reserve the prom region, it is already marked as
+        * used, at least on x86. Instead, reserve a memory region a
+        * board would certainly use. If it works, go ahead. If not,
+        * run like hell... */
+       
+       if (!request_mem_region (mem_addr, 16, depca_string))
+               return unknown;
 
        /* Copy the first 16 bytes of ROM */
-       ptr = ioremap(paddr + 0xc000, 16);
+
+       ptr = ioremap(prom_addr, 16);
        if (ptr == NULL) {
-               printk(KERN_ERR "depca: I/O remap failed at %lx\n", paddr + 0xc000);
-               adapter = unknown;
-               return;
+               printk(KERN_ERR "depca: I/O remap failed at %lx\n", prom_addr);
+               return unknown;
        }
        for (i = 0; i < 16; i++) {
                tmpstr[i] = readb(ptr + i);
        }
        iounmap(ptr);
 
+       release_mem_region (mem_addr, 16);
+
        /* Check if PROM contains a valid string */
-       for (i = 0; *signatures[i] != '\0'; i++) {
-               for (j = 0, k = 0; j < 16 && k < strlen(signatures[i]); j++) {
-                       if (signatures[i][k] == tmpstr[j]) {    /* track signature */
+       for (i = 0; *depca_signature[i] != '\0'; i++) {
+               for (j = 0, k = 0; j < 16 && k < strlen(depca_signature[i]); j++) {
+                       if (depca_signature[i][k] == tmpstr[j]) {       /* track signature */
                                k++;
                        } else {        /* lost signature; begin search again */
                                k = 0;
                        }
                }
-               if (k == strlen(signatures[i]))
+               if (k == strlen(depca_signature[i]))
                        break;
        }
 
        /* Check if name string is valid, provided there's no PROM */
-       if (*name && (i == unknown)) {
-               for (i = 0; *signatures[i] != '\0'; i++) {
-                       if (strcmp(name, signatures[i]) == 0)
+       if (name && *name && (i == unknown)) {
+               for (i = 0; *depca_signature[i] != '\0'; i++) {
+                       if (strcmp(name, depca_signature[i]) == 0)
                                break;
                }
        }
 
-       /* Update search results */
-       strcpy(name, signatures[i]);
-       adapter = i;
-
-       return;
+       return i;
 }
 
 /*
@@ -1773,10 +1769,11 @@ static int __init DevicePresent(u_long ioaddr)
 static int __init get_hw_addr(struct net_device *dev)
 {
        u_long ioaddr = dev->base_addr;
+       struct depca_private *lp = dev->priv;
        int i, k, tmp, status = 0;
        u_short j, x, chksum;
 
-       x = (((adapter == de100) || (adapter == de101)) ? 1 : 0);
+       x = (((lp->adapter == de100) || (lp->adapter == de101)) ? 1 : 0);
 
        for (i = 0, k = 0, j = 0; j < 3; j++) {
                k <<= 1;
@@ -2083,55 +2080,40 @@ static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        return status;
 }
 
-#ifdef MODULE
-static struct net_device thisDepca;
-static int irq = 7;            /* EDIT THESE LINE FOR YOUR CONFIGURATION */
-static int io = 0x200;         /* Or use the irq= io= options to insmod */
-MODULE_PARM(irq, "i");
-MODULE_PARM(io, "i");
-MODULE_PARM_DESC(irq, "DEPCA IRQ number");
-MODULE_PARM_DESC(io, "DEPCA I/O base address");
-
-/* See depca_probe() for autoprobe messages when a module */
-int init_module(void)
+static int __init depca_module_init (void)
 {
-       thisDepca.irq = irq;
-       thisDepca.base_addr = io;
-       thisDepca.init = depca_probe;
+        int err = 0;
 
-       if (register_netdev(&thisDepca) != 0)
-               return -EIO;
-
-       return 0;
+#if CONFIG_MCA
+        err = mca_register_driver (&depca_mca_driver);
+#endif
+#ifdef CONFIG_EISA
+        err |= eisa_driver_register (&depca_eisa_driver);
+#endif
+       err |= driver_register (&depca_isa_driver);
+       depca_platform_probe ();
+       
+        return err;
 }
 
-void cleanup_module(void)
+static void __exit depca_module_exit (void)
 {
-       struct depca_private *lp = thisDepca.priv;
-
-       unregister_netdev(&thisDepca);
-       if (lp) {
-               iounmap(lp->sh_mem);
-               release_mem_region (lp->mem_start, lp->mem_len);
-#ifdef CONFIG_MCA
-               if (lp->mca_slot != -1)
-                       mca_mark_as_unused(lp->mca_slot);
+       int i;
+#if CONFIG_MCA
+        mca_unregister_driver (&depca_mca_driver);
 #endif
-               kfree(lp);
-               thisDepca.priv = NULL;
-       }
-       thisDepca.irq = 0;
+#ifdef CONFIG_EISA
+        eisa_driver_unregister (&depca_eisa_driver);
+#endif
+       driver_unregister (&depca_isa_driver);
 
-       release_region(thisDepca.base_addr, DEPCA_TOTAL_SIZE);
+       for (i = 0; depca_io_ports[i].iobase; i++) {
+               if (depca_io_ports[i].device) {
+                       platform_device_unregister (depca_io_ports[i].device);
+                       depca_io_ports[i].device = NULL;
+               }
+       }
 }
-#endif                         /* MODULE */
-MODULE_LICENSE("GPL");
-\f
 
-/*
- * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c depca.c"
- *
- *  compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c depca.c"
- * End:
- */
+module_init (depca_module_init);
+module_exit (depca_module_exit);