static loff_t vme_user_llseek(struct file *, loff_t, int);
 static long vme_user_unlocked_ioctl(struct file *, unsigned int, unsigned long);
 
+static int vme_user_match(struct vme_dev *);
 static int __devinit vme_user_probe(struct vme_dev *);
 static int __devexit vme_user_remove(struct vme_dev *);
 
 
 static struct vme_driver vme_user_driver = {
        .name = driver_name,
+       .match = vme_user_match,
        .probe = vme_user_probe,
        .remove = __devexit_p(vme_user_remove),
 };
 static int __init vme_user_init(void)
 {
        int retval = 0;
-       int i;
-       struct vme_device_id *ids;
 
        printk(KERN_INFO "VME User Space Access Driver\n");
 
                bus_num = USER_BUS_MAX;
        }
 
-
-       /* Dynamically create the bind table based on module parameters */
-       ids = kzalloc(sizeof(struct vme_device_id) * (bus_num + 1), GFP_KERNEL);
-       if (ids == NULL) {
-               printk(KERN_ERR "%s: Unable to allocate ID table\n",
-                       driver_name);
-               retval = -ENOMEM;
-               goto err_id;
-       }
-
-       for (i = 0; i < bus_num; i++) {
-               ids[i].bus = bus[i];
-               /*
-                * We register the driver against the slot occupied by *this*
-                * card, since it's really a low level way of controlling
-                * the VME bridge
-                */
-               ids[i].slot = VME_SLOT_CURRENT;
-       }
-
-       vme_user_driver.bind_table = ids;
-
-       retval = vme_register_driver(&vme_user_driver);
+       /*
+        * Here we just register the maximum number of devices we can and
+        * leave vme_user_match() to allow only 1 to go through to probe().
+        * This way, if we later want to allow multiple user access devices,
+        * we just change the code in vme_user_match().
+        */
+       retval = vme_register_driver(&vme_user_driver, VME_MAX_SLOTS);
        if (retval != 0)
                goto err_reg;
 
        return retval;
 
 err_reg:
-       kfree(ids);
-err_id:
 err_nocard:
        return retval;
 }
 
+static int vme_user_match(struct vme_dev *vdev)
+{
+       if (vdev->id.num >= USER_BUS_MAX)
+               return 0;
+       return 1;
+}
+
 /*
  * In this simple access driver, the old behaviour is being preserved as much
  * as practical. We will therefore reserve the buffers and request the images
 static void __exit vme_user_exit(void)
 {
        vme_unregister_driver(&vme_user_driver);
-
-       kfree(vme_user_driver.bind_table);
 }
 
 
 
                if ((vme_bus_numbers & (1 << i)) == 0) {
                        vme_bus_numbers |= (1 << i);
                        bridge->num = i;
+                       INIT_LIST_HEAD(&bridge->devices);
                        list_add_tail(&bridge->bus_list, &vme_bus_list);
                        ret = 0;
                        break;
 
 static void vme_remove_bus(struct vme_bridge *bridge)
 {
+       struct vme_dev *vdev;
+       struct vme_dev *tmp;
+
        mutex_lock(&vme_buses_lock);
        vme_bus_numbers &= ~(1 << bridge->num);
+       list_for_each_entry_safe(vdev, tmp, &bridge->devices, bridge_list) {
+               list_del(&vdev->drv_list);
+               list_del(&vdev->bridge_list);
+               device_unregister(&vdev->dev);
+       }
        list_del(&bridge->bus_list);
        mutex_unlock(&vme_buses_lock);
 }
 
 int vme_register_bridge(struct vme_bridge *bridge)
 {
-       struct vme_dev *vdev;
-       int retval;
-       int i;
+       return vme_add_bus(bridge);
+}
+EXPORT_SYMBOL(vme_register_bridge);
 
-       retval = vme_add_bus(bridge);
-       if (retval)
-               return retval;
+void vme_unregister_bridge(struct vme_bridge *bridge)
+{
+       vme_remove_bus(bridge);
+}
+EXPORT_SYMBOL(vme_unregister_bridge);
 
-       /* This creates 32 vme "slot" devices. This equates to a slot for each
-        * ID available in a system conforming to the ANSI/VITA 1-1994
-        * specification.
-        */
-       for (i = 0; i < VME_SLOTS_MAX; i++) {
-               bridge->dev[i] = kzalloc(sizeof(struct vme_dev), GFP_KERNEL);
-               if (!bridge->dev[i]) {
-                       retval = -ENOMEM;
+/* - Driver Registration --------------------------------------------------- */
+
+static int __vme_register_driver_bus(struct vme_driver *drv,
+       struct vme_bridge *bridge, unsigned int ndevs)
+{
+       int err;
+       unsigned int i;
+       struct vme_dev *vdev;
+       struct vme_dev *tmp;
+
+       for (i = 0; i < ndevs; i++) {
+               vdev = kzalloc(sizeof(struct vme_dev), GFP_KERNEL);
+               if (!vdev) {
+                       err = -ENOMEM;
                        goto err_devalloc;
                }
-               vdev = bridge->dev[i];
-               memset(vdev, 0, sizeof(struct vme_dev));
-
+               vdev->id.num = i;
                vdev->id.bus = bridge->num;
                vdev->id.slot = i + 1;
                vdev->bridge = bridge;
+               vdev->dev.platform_data = drv;
+               vdev->dev.release = vme_dev_release;
                vdev->dev.parent = bridge->parent;
                vdev->dev.bus = &vme_bus_type;
-               vdev->dev.release = vme_dev_release;
-               /*
-                * We save a pointer to the bridge in platform_data so that we
-                * can get to it later. We keep driver_data for use by the
-                * driver that binds against the slot
-                */
-               vdev->dev.platform_data = bridge;
-               dev_set_name(&vdev->dev, "vme-%x.%x", bridge->num, i + 1);
+               dev_set_name(&vdev->dev, "%s.%u-%u", drv->name, vdev->id.bus,
+                       vdev->id.num);
 
-               retval = device_register(&vdev->dev);
-               if (retval)
+               err = device_register(&vdev->dev);
+               if (err)
                        goto err_reg;
-       }
 
-       return retval;
+               if (vdev->dev.platform_data) {
+                       list_add_tail(&vdev->drv_list, &drv->devices);
+                       list_add_tail(&vdev->bridge_list, &bridge->devices);
+               } else
+                       device_unregister(&vdev->dev);
+       }
+       return 0;
 
 err_reg:
        kfree(vdev);
 err_devalloc:
-       while (--i >= 0) {
-               vdev = bridge->dev[i];
+       list_for_each_entry_safe(vdev, tmp, &drv->devices, drv_list) {
+               list_del(&vdev->drv_list);
+               list_del(&vdev->bridge_list);
                device_unregister(&vdev->dev);
        }
-       vme_remove_bus(bridge);
-       return retval;
+       return err;
 }
-EXPORT_SYMBOL(vme_register_bridge);
 
-void vme_unregister_bridge(struct vme_bridge *bridge)
+static int __vme_register_driver(struct vme_driver *drv, unsigned int ndevs)
 {
-       int i;
-       struct vme_dev *vdev;
-
+       struct vme_bridge *bridge;
+       int err = 0;
 
-       for (i = 0; i < VME_SLOTS_MAX; i++) {
-               vdev = bridge->dev[i];
-               device_unregister(&vdev->dev);
+       mutex_lock(&vme_buses_lock);
+       list_for_each_entry(bridge, &vme_bus_list, bus_list) {
+               /*
+                * This cannot cause trouble as we already have vme_buses_lock
+                * and if the bridge is removed, it will have to go through
+                * vme_unregister_bridge() to do it (which calls remove() on
+                * the bridge which in turn tries to acquire vme_buses_lock and
+                * will have to wait). The probe() called after device
+                * registration in __vme_register_driver below will also fail
+                * as the bridge is being removed (since the probe() calls
+                * vme_bridge_get()).
+                */
+               err = __vme_register_driver_bus(drv, bridge, ndevs);
+               if (err)
+                       break;
        }
-       vme_remove_bus(bridge);
+       mutex_unlock(&vme_buses_lock);
+       return err;
 }
-EXPORT_SYMBOL(vme_unregister_bridge);
-
-
-/* - Driver Registration --------------------------------------------------- */
 
-int vme_register_driver(struct vme_driver *drv)
+int vme_register_driver(struct vme_driver *drv, unsigned int ndevs)
 {
+       int err;
+
        drv->driver.name = drv->name;
        drv->driver.bus = &vme_bus_type;
+       INIT_LIST_HEAD(&drv->devices);
+
+       err = driver_register(&drv->driver);
+       if (err)
+               return err;
 
-       return driver_register(&drv->driver);
+       err = __vme_register_driver(drv, ndevs);
+       if (err)
+               driver_unregister(&drv->driver);
+
+       return err;
 }
 EXPORT_SYMBOL(vme_register_driver);
 
 void vme_unregister_driver(struct vme_driver *drv)
 {
+       struct vme_dev *dev, *dev_tmp;
+
+       mutex_lock(&vme_buses_lock);
+       list_for_each_entry_safe(dev, dev_tmp, &drv->devices, drv_list) {
+               list_del(&dev->drv_list);
+               list_del(&dev->bridge_list);
+               device_unregister(&dev->dev);
+       }
+       mutex_unlock(&vme_buses_lock);
+
        driver_unregister(&drv->driver);
 }
 EXPORT_SYMBOL(vme_unregister_driver);
 
 /* - Bus Registration ------------------------------------------------------ */
 
-static struct vme_driver *dev_to_vme_driver(struct device *dev)
-{
-       if (dev->driver == NULL)
-               printk(KERN_ERR "Bugger dev->driver is NULL\n");
-
-       return container_of(dev->driver, struct vme_driver, driver);
-}
-
 static int vme_bus_match(struct device *dev, struct device_driver *drv)
 {
-       struct vme_dev *vdev;
-       struct vme_bridge *bridge;
-       struct vme_driver *driver;
-       int i, num;
-
-       vdev = dev_to_vme_dev(dev);
-       bridge = vdev->bridge;
-       driver = container_of(drv, struct vme_driver, driver);
+       struct vme_driver *vme_drv;
 
-       num = vdev->id.slot;
-       if (num <= 0 || num >= VME_SLOTS_MAX)
-               goto err_dev;
-
-       if (driver->bind_table == NULL) {
-               dev_err(dev, "Bind table NULL\n");
-               goto err_table;
-       }
+       vme_drv = container_of(drv, struct vme_driver, driver);
 
-       i = 0;
-       while ((driver->bind_table[i].bus != 0) ||
-               (driver->bind_table[i].slot != 0)) {
+       if (dev->platform_data == vme_drv) {
+               struct vme_dev *vdev = dev_to_vme_dev(dev);
 
-               if (bridge->num == driver->bind_table[i].bus) {
-                       if (num == driver->bind_table[i].slot)
-                               return 1;
+               if (vme_drv->match && vme_drv->match(vdev))
+                       return 1;
 
-                       if (driver->bind_table[i].slot == VME_SLOT_ALL)
-                               return 1;
-
-                       if ((driver->bind_table[i].slot == VME_SLOT_CURRENT) &&
-                               (num == vme_slot_get(vdev)))
-                               return 1;
-               }
-               i++;
+               dev->platform_data = NULL;
        }
-
-err_dev:
-err_table:
        return 0;
 }
 
 static int vme_bus_probe(struct device *dev)
 {
-       struct vme_driver *driver;
-       struct vme_dev *vdev;
        int retval = -ENODEV;
+       struct vme_driver *driver;
+       struct vme_dev *vdev = dev_to_vme_dev(dev);
 
-       driver = dev_to_vme_driver(dev);
-       vdev = dev_to_vme_dev(dev);
+       driver = dev->platform_data;
 
        if (driver->probe != NULL)
                retval = driver->probe(vdev);
 
 static int vme_bus_remove(struct device *dev)
 {
-       struct vme_driver *driver;
-       struct vme_dev *vdev;
        int retval = -ENODEV;
+       struct vme_driver *driver;
+       struct vme_dev *vdev = dev_to_vme_dev(dev);
 
-       driver = dev_to_vme_driver(dev);
-       vdev = dev_to_vme_dev(dev);
+       driver = dev->platform_data;
 
        if (driver->remove != NULL)
                retval = driver->remove(vdev);
 
 
 extern struct bus_type vme_bus_type;
 
+/* VME_MAX_BRIDGES comes from the type of vme_bus_numbers */
+#define VME_MAX_BRIDGES                (sizeof(unsigned int)*8)
+#define VME_MAX_SLOTS          32
+
 #define VME_SLOT_CURRENT       -1
 #define VME_SLOT_ALL           -2
 
 /**
  * VME device identifier structure
+ * @num: The device ID (ranges from 0 to N-1 for N devices)
  * @bus: The bus ID of the bus the device is on
  * @slot: The slot this device is plugged into
  */
 struct vme_device_id {
+       int num;
        int bus;
        int slot;
 };
  * @id: The ID of the device (currently the bus and slot number)
  * @bridge: Pointer to the bridge device this device is on
  * @dev: Internal device structure
+ * @drv_list: List of devices (per driver)
+ * @bridge_list: List of devices (per bridge)
  */
 struct vme_dev {
        struct vme_device_id id;
        struct vme_bridge *bridge;
        struct device dev;
+       struct list_head drv_list;
+       struct list_head bridge_list;
 };
 
 struct vme_driver {
        struct list_head node;
        const char *name;
-       const struct vme_device_id *bind_table;
-       int (*probe)  (struct vme_dev *);
-       int (*remove) (struct vme_dev *);
-       void (*shutdown) (void);
-       struct device_driver    driver;
+       int (*match)(struct vme_dev *);
+       int (*probe)(struct vme_dev *);
+       int (*remove)(struct vme_dev *);
+       void (*shutdown)(void);
+       struct device_driver driver;
+       struct list_head devices;
 };
 
 void *vme_alloc_consistent(struct vme_resource *, size_t, dma_addr_t *);
 
 int vme_slot_get(struct vme_dev *);
 
-int vme_register_driver(struct vme_driver *);
+int vme_register_driver(struct vme_driver *, unsigned int);
 void vme_unregister_driver(struct vme_driver *);
 
 
 
 
        struct vme_driver {
                struct list_head node;
-               char *name;
-               const struct vme_device_id *bind_table;
-               int (*probe)  (struct vme_dev *);
-               int (*remove) (struct vme_dev *);
-               void (*shutdown) (void);
-               struct device_driver    driver;
+               const char *name;
+               int (*match)(struct vme_dev *);
+               int (*probe)(struct vme_dev *);
+               int (*remove)(struct vme_dev *);
+               void (*shutdown)(void);
+               struct device_driver driver;
+               struct list_head devices;
+               unsigned int ndev;
        };
 
-At the minimum, the '.name', '.probe' and '.bind_table' elements of this
-structure should be correctly set. The '.name' element is a pointer to a string
-holding the device driver's name. The '.probe' element should contain a pointer
-to the probe routine.
+At the minimum, the '.name', '.match' and '.probe' elements of this structure
+should be correctly set. The '.name' element is a pointer to a string holding
+the device driver's name.
 
-The arguments of the probe routine are as follows:
+The '.match' function allows controlling the number of devices that need to
+be registered. The match function should return 1 if a device should be
+probed and 0 otherwise. This example match function (from vme_user.c) limits
+the number of devices probed to one:
 
-       probe(struct vme_dev *dev);
+       #define USER_BUS_MAX    1
+       ...
+       static int vme_user_match(struct vme_dev *vdev)
+       {
+               if (vdev->id.num >= USER_BUS_MAX)
+                       return 0;
+               return 1;
+       }
 
-The device structure looks like the following:
+The '.probe' element should contain a pointer to the probe routine. The
+probe routine is passed a 'struct vme_dev' pointer as an argument. The
+'struct vme_dev' structure looks like the following:
 
        struct vme_dev {
                struct vme_device_id id;
        struct vme_device_id {
                int bus;
                int slot;
+               int num;
        };
 
-'bus' is the number of the bus the device being probed is on. 'slot' refers
-to the specific slot on the VME bus.
-
-The '.bind_table' is a pointer to an array of type 'vme_device_id':
-
-       struct vme_device_id {
-               int bus;
-               int slot;
-       };
-
-Each structure in this array should provide a bus and slot number where the core
-should probe, using the driver's probe routine, for a device on the specified
-VME bus.
-
-The VME subsystem supports a single VME driver per 'slot'. There are considered
-to be 32 slots per bus, one for each slot-ID as defined in the ANSI/VITA 1-1994
-specification and are analogious to the physical slots on the VME backplane.
+Here, 'bus' is the number of the bus the device being probed is on. 'slot'
+refers to the specific slot on the VME bus. The 'num' field refers to the
+sequential device ID for this specific driver.
 
 A function is also provided to unregister the driver from the VME core and is
 usually called from the device driver's exit routine: