Unify the "detach" and REMOVAL_EVENT handlers to one "remove" function.
Old functionality is preserved, for the moment.
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
 This file details changes in 2.6 which affect PCMCIA card driver authors:
 
+* Unify detach and REMOVAL event code (as of 2.6.16)
+        void (*remove)          (struct pcmcia_device *dev);
+
 * Move suspend, resume and reset out of event handler (as of 2.6.16)
        int (*suspend)          (struct pcmcia_device *dev);
        int (*resume)           (struct pcmcia_device *dev);
 
 static dev_info_t dev_info = "bluecard_cs";
 
 static dev_link_t *bluecard_attach(void);
-static void bluecard_detach(dev_link_t *);
+static void bluecard_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list = NULL;
 
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != CS_SUCCESS) {
                cs_error(link->handle, RegisterClient, ret);
-               bluecard_detach(link);
+               bluecard_detach(link->handle);
                return NULL;
        }
 
 }
 
 
-static void bluecard_detach(dev_link_t *link)
+static void bluecard_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        bluecard_info_t *info = link->priv;
        dev_link_t **linkp;
-       int ret;
 
        /* Locate device structure */
        for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
        if (link->state & DEV_CONFIG)
                bluecard_release(link);
 
-       if (link->handle) {
-               ret = pcmcia_deregister_client(link->handle);
-               if (ret != CS_SUCCESS)
-                       cs_error(link->handle, DeregisterClient, ret);
-       }
-
        /* Unlink device structure, free bits */
        *linkp = link->next;
 
 static int bluecard_event(event_t event, int priority, event_callback_args_t *args)
 {
        dev_link_t *link = args->client_data;
-       bluecard_info_t *info = link->priv;
 
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG) {
-                       bluecard_close(info);
-                       bluecard_release(link);
-               }
-               break;
        case CS_EVENT_CARD_INSERTION:
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                bluecard_config(link);
        },
        .attach         = bluecard_attach,
        .event          = bluecard_event,
-       .detach         = bluecard_detach,
+       .remove         = bluecard_detach,
        .id_table       = bluecard_ids,
        .suspend        = bluecard_suspend,
        .resume         = bluecard_resume,
 
 static dev_info_t dev_info = "bt3c_cs";
 
 static dev_link_t *bt3c_attach(void);
-static void bt3c_detach(dev_link_t *);
+static void bt3c_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list = NULL;
 
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != CS_SUCCESS) {
                cs_error(link->handle, RegisterClient, ret);
-               bt3c_detach(link);
+               bt3c_detach(link->handle);
                return NULL;
        }
 
 }
 
 
-static void bt3c_detach(dev_link_t *link)
+static void bt3c_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        bt3c_info_t *info = link->priv;
        dev_link_t **linkp;
-       int ret;
 
        /* Locate device structure */
        for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
        if (link->state & DEV_CONFIG)
                bt3c_release(link);
 
-       if (link->handle) {
-               ret = pcmcia_deregister_client(link->handle);
-               if (ret != CS_SUCCESS)
-                       cs_error(link->handle, DeregisterClient, ret);
-       }
-
        /* Unlink device structure, free bits */
        *linkp = link->next;
 
 static int bt3c_event(event_t event, int priority, event_callback_args_t *args)
 {
        dev_link_t *link = args->client_data;
-       bt3c_info_t *info = link->priv;
 
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG) {
-                       bt3c_close(info);
-                       bt3c_release(link);
-               }
-               break;
        case CS_EVENT_CARD_INSERTION:
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                bt3c_config(link);
        },
        .attach         = bt3c_attach,
        .event          = bt3c_event,
-       .detach         = bt3c_detach,
+       .remove         = bt3c_detach,
        .id_table       = bt3c_ids,
        .suspend        = bt3c_suspend,
        .resume         = bt3c_resume,
 
 static dev_info_t dev_info = "btuart_cs";
 
 static dev_link_t *btuart_attach(void);
-static void btuart_detach(dev_link_t *);
+static void btuart_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list = NULL;
 
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != CS_SUCCESS) {
                cs_error(link->handle, RegisterClient, ret);
-               btuart_detach(link);
+               btuart_detach(link->handle);
                return NULL;
        }
 
 }
 
 
-static void btuart_detach(dev_link_t *link)
+static void btuart_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        btuart_info_t *info = link->priv;
        dev_link_t **linkp;
-       int ret;
 
        /* Locate device structure */
        for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
        if (link->state & DEV_CONFIG)
                btuart_release(link);
 
-       if (link->handle) {
-               ret = pcmcia_deregister_client(link->handle);
-               if (ret != CS_SUCCESS)
-                       cs_error(link->handle, DeregisterClient, ret);
-       }
-
        /* Unlink device structure, free bits */
        *linkp = link->next;
 
 static int btuart_event(event_t event, int priority, event_callback_args_t *args)
 {
        dev_link_t *link = args->client_data;
-       btuart_info_t *info = link->priv;
 
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG) {
-                       btuart_close(info);
-                       btuart_release(link);
-               }
-               break;
        case CS_EVENT_CARD_INSERTION:
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                btuart_config(link);
        },
        .attach         = btuart_attach,
        .event          = btuart_event,
-       .detach         = btuart_detach,
+       .remove         = btuart_detach,
        .id_table       = btuart_ids,
        .suspend        = btuart_suspend,
        .resume         = btuart_resume,
 
 static dev_info_t dev_info = "dtl1_cs";
 
 static dev_link_t *dtl1_attach(void);
-static void dtl1_detach(dev_link_t *);
+static void dtl1_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list = NULL;
 
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != CS_SUCCESS) {
                cs_error(link->handle, RegisterClient, ret);
-               dtl1_detach(link);
+               dtl1_detach(link->handle);
                return NULL;
        }
 
 }
 
 
-static void dtl1_detach(dev_link_t *link)
+static void dtl1_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        dtl1_info_t *info = link->priv;
        dev_link_t **linkp;
-       int ret;
 
        /* Locate device structure */
        for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
        if (link->state & DEV_CONFIG)
                dtl1_release(link);
 
-       if (link->handle) {
-               ret = pcmcia_deregister_client(link->handle);
-               if (ret != CS_SUCCESS)
-                       cs_error(link->handle, DeregisterClient, ret);
-       }
-
        /* Unlink device structure, free bits */
        *linkp = link->next;
 
 static int dtl1_event(event_t event, int priority, event_callback_args_t *args)
 {
        dev_link_t *link = args->client_data;
-       dtl1_info_t *info = link->priv;
 
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG) {
-                       dtl1_close(info);
-                       dtl1_release(link);
-               }
-               break;
        case CS_EVENT_CARD_INSERTION:
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                dtl1_config(link);
        },
        .attach         = dtl1_attach,
        .event          = dtl1_event,
-       .detach         = dtl1_detach,
+       .remove         = dtl1_detach,
        .id_table       = dtl1_ids,
        .suspend        = dtl1_suspend,
        .resume         = dtl1_resume,
 
 #define        T_100MSEC       msecs_to_jiffies(100)
 #define        T_500MSEC       msecs_to_jiffies(500)
 
-static void cm4000_detach(dev_link_t *link);
+static void cm4000_detach(struct pcmcia_device *p_dev);
 static void cm4000_release(dev_link_t *link);
 
 static int major;              /* major number we get from the kernel */
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                cm4000_config(link, devno);
                break;
-       case CS_EVENT_CARD_REMOVAL:
-               DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n");
-               link->state &= ~DEV_PRESENT;
-               stop_monitor(dev);
-               break;
        default:
                DEBUGP(5, dev, "unknown event %.2x\n", event);
                break;
        i = pcmcia_register_client(&link->handle, &client_reg);
        if (i) {
                cs_error(link->handle, RegisterClient, i);
-               cm4000_detach(link);
+               cm4000_detach(link->handle);
                return NULL;
        }
 
        return link;
 }
 
-static void cm4000_detach_by_devno(int devno, dev_link_t * link)
+static void cm4000_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        struct cm4000_dev *dev = link->priv;
+       int devno;
 
-       DEBUGP(3, dev, "-> detach_by_devno(devno=%d)\n", devno);
+       /* find device */
+       for (devno = 0; devno < CM4000_MAX_DEV; devno++)
+               if (dev_table[devno] == link)
+                       break;
+       if (devno == CM4000_MAX_DEV)
+               return;
 
-       if (link->state & DEV_CONFIG) {
-               DEBUGP(5, dev, "device still configured (try to release it)\n");
-               cm4000_release(link);
-       }
+       link->state &= ~DEV_PRESENT;
+       stop_monitor(dev);
 
-       if (link->handle) {
-               pcmcia_deregister_client(link->handle);
-       }
+       if (link->state & DEV_CONFIG)
+               cm4000_release(link);
 
        dev_table[devno] = NULL;
-       kfree(dev);
-       return;
-}
-
-static void cm4000_detach(dev_link_t * link)
-{
-       int i;
+       kfree(dev);
 
-       /* find device */
-       for (i = 0; i < CM4000_MAX_DEV; i++)
-               if (dev_table[i] == link)
-                       break;
-
-       if (i == CM4000_MAX_DEV)
-               return;
-
-       cm4000_detach_by_devno(i, link);
        return;
 }
 
                .name = "cm4000_cs",
                },
        .attach   = cm4000_attach,
-       .detach   = cm4000_detach,
+       .remove   = cm4000_detach,
        .suspend  = cm4000_suspend,
        .resume   = cm4000_resume,
        .event    = cm4000_event,
 
 static void __exit cmm_exit(void)
 {
-       int i;
-
        printk(KERN_INFO MODULE_NAME ": unloading\n");
        pcmcia_unregister_driver(&cm4000_driver);
-       for (i = 0; i < CM4000_MAX_DEV; i++)
-               if (dev_table[i])
-                       cm4000_detach_by_devno(i, dev_table[i]);
        unregister_chrdev(major, DEVICE_NAME);
 };
 
 
 #define POLL_PERIOD                            msecs_to_jiffies(10)
 
 static void reader_release(dev_link_t *link);
-static void reader_detach(dev_link_t *link);
+static void reader_detach(struct pcmcia_device *p_dev);
 
 static int major;
 
                        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                        reader_config(link, devno);
                        break;
-               case CS_EVENT_CARD_REMOVAL:
-                       DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n");
-                       link->state &= ~DEV_PRESENT;
-                       break;
 
                default:
                        DEBUGP(5, dev, "reader_event: unknown event %.2x\n",
        i = pcmcia_register_client(&link->handle, &client_reg);
        if (i) {
                cs_error(link->handle, RegisterClient, i);
-               reader_detach(link);
+               reader_detach(link->handle);
                return NULL;
        }
        init_waitqueue_head(&dev->devq);
        return link;
 }
 
-static void reader_detach_by_devno(int devno, dev_link_t *link)
+static void reader_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        struct reader_dev *dev = link->priv;
-
-       if (link->state & DEV_CONFIG) {
-               DEBUGP(5, dev, "device still configured (try to release it)\n");
-               reader_release(link);
-       }
-
-       pcmcia_deregister_client(link->handle);
-       dev_table[devno] = NULL;
-       DEBUGP(5, dev, "freeing dev=%p\n", dev);
-       cm4040_stop_poll(dev);
-       kfree(dev);
-       return;
-}
-
-static void reader_detach(dev_link_t *link)
-{
-       int i;
+       int devno;
 
        /* find device */
-       for (i = 0; i < CM_MAX_DEV; i++) {
-               if (dev_table[i] == link)
+       for (devno = 0; devno < CM_MAX_DEV; devno++) {
+               if (dev_table[devno] == link)
                        break;
        }
-       if (i == CM_MAX_DEV)
+       if (devno == CM_MAX_DEV)
                return;
 
-       reader_detach_by_devno(i, link);
+       link->state &= ~DEV_PRESENT;
+
+       if (link->state & DEV_CONFIG)
+               reader_release(link);
+
+       dev_table[devno] = NULL;
+       kfree(dev);
+
        return;
 }
 
                .name   = "cm4040_cs",
        },
        .attach         = reader_attach,
-       .detach         = reader_detach,
+       .remove         = reader_detach,
        .suspend        = reader_suspend,
        .resume         = reader_resume,
        .event          = reader_event,
 
 static void __exit cm4040_exit(void)
 {
-       int i;
-
        printk(KERN_INFO MODULE_NAME ": unloading\n");
        pcmcia_unregister_driver(&reader_driver);
-       for (i = 0; i < CM_MAX_DEV; i++) {
-               if (dev_table[i])
-                       reader_detach_by_devno(i, dev_table[i]);
-       }
        unregister_chrdev(major, DEVICE_NAME);
 }
 
 
 static int  mgslpc_event(event_t event, int priority,
                         event_callback_args_t *args);
 static dev_link_t *mgslpc_attach(void);
-static void mgslpc_detach(dev_link_t *);
+static void mgslpc_detach(struct pcmcia_device *p_dev);
 
 static dev_info_t dev_info = "synclink_cs";
 static dev_link_t *dev_list = NULL;
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
            cs_error(link->handle, RegisterClient, ret);
-           mgslpc_detach(link);
+           mgslpc_detach(link->handle);
            return NULL;
     }
 
            pcmcia_release_io(link->handle, &link->io);
     if (link->irq.AssignedIRQ)
            pcmcia_release_irq(link->handle, &link->irq);
-    if (link->state & DEV_STALE_LINK)
-           mgslpc_detach(link);
 }
 
-static void mgslpc_detach(dev_link_t *link)
+static void mgslpc_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
 
     if (debug_level >= DEBUG_LEVEL_INFO)
            printk("mgslpc_detach(0x%p)\n", link);
-    
+
     /* find device */
     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
            if (*linkp == link) break;
            return;
 
     if (link->state & DEV_CONFIG) {
-           /* device is configured/active, mark it so when
-            * release() is called a proper detach() occurs.
-            */
-           if (debug_level >= DEBUG_LEVEL_INFO)
-                   printk(KERN_DEBUG "synclinkpc: detach postponed, '%s' "
-                          "still locked\n", link->dev->dev_name);
-           link->state |= DEV_STALE_LINK;
-           return;
+           ((MGSLPC_INFO *)link->priv)->stop = 1;
+           mgslpc_release((u_long)link);
     }
 
-    /* Break the link with Card Services */
-    if (link->handle)
-           pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, and free it */
     *linkp = link->next;
     mgslpc_remove_device((MGSLPC_INFO *)link->priv);
            printk("mgslpc_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-           link->state &= ~DEV_PRESENT;
-           if (link->state & DEV_CONFIG) {
-                   ((MGSLPC_INFO *)link->priv)->stop = 1;
-                   mgslpc_release((u_long)link);
-           }
-           break;
     case CS_EVENT_CARD_INSERTION:
            link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
            mgslpc_config(link);
        },
        .attach         = mgslpc_attach,
        .event          = mgslpc_event,
-       .detach         = mgslpc_detach,
+       .remove         = mgslpc_detach,
        .id_table       = mgslpc_ids,
        .suspend        = mgslpc_suspend,
        .resume         = mgslpc_resume,
 
 static dev_info_t dev_info = "ide-cs";
 
 static dev_link_t *ide_attach(void);
-static void ide_detach(dev_link_t *);
+static void ide_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list = NULL;
 
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
        cs_error(link->handle, RegisterClient, ret);
-       ide_detach(link);
+       ide_detach(link->handle);
        return NULL;
     }
     
 
 ======================================================================*/
 
-static void ide_detach(dev_link_t *link)
+static void ide_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
-    int ret;
 
     DEBUG(0, "ide_detach(0x%p)\n", link);
     
     if (link->state & DEV_CONFIG)
        ide_release(link);
     
-    if (link->handle) {
-       ret = pcmcia_deregister_client(link->handle);
-       if (ret != CS_SUCCESS)
-           cs_error(link->handle, DeregisterClient, ret);
-    }
-    
     /* Unlink, free device structure */
     *linkp = link->next;
     kfree(link->priv);
     DEBUG(1, "ide_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-       link->state &= ~DEV_PRESENT;
-       if (link->state & DEV_CONFIG)
-               ide_release(link);
-       break;
     case CS_EVENT_CARD_INSERTION:
        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        ide_config(link);
        },
        .attach         = ide_attach,
        .event          = ide_event,
-       .detach         = ide_detach,
+       .remove         = ide_detach,
        .id_table       = ide_ids,
        .suspend        = ide_suspend,
        .resume         = ide_resume,
 
 */
 
 static dev_link_t *avmcs_attach(void);
-static void avmcs_detach(dev_link_t *);
+static void avmcs_detach(struct pcmcia_device *p_dev);
 
 /*
    The dev_info variable is the "key" that is used to match up this
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
        cs_error(link->handle, RegisterClient, ret);
-       avmcs_detach(link);
+       avmcs_detach(link->handle);
        goto err;
     }
     return link;
 
 ======================================================================*/
 
-static void avmcs_detach(dev_link_t *link)
+static void avmcs_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
 
     /* Locate device structure */
     if (*linkp == NULL)
        return;
 
-    /*
-       If the device is currently configured and active, we won't
-       actually delete it yet.  Instead, it is marked so that when
-       the release() function is called, that will trigger a proper
-       detach().
-    */
-    if (link->state & DEV_CONFIG) {
-       link->state |= DEV_STALE_LINK;
-       return;
-    }
+    if (link->state & DEV_CONFIG)
+       avmcs_release(link);
 
-    /* Break the link with Card Services */
-    if (link->handle)
-       pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, free pieces */
     *linkp = link->next;
     kfree(link->priv);
     pcmcia_release_io(link->handle, &link->io);
     pcmcia_release_irq(link->handle, &link->irq);
     link->state &= ~DEV_CONFIG;
-    
-    if (link->state & DEV_STALE_LINK)
-       avmcs_detach(link);
-    
 } /* avmcs_release */
 
 static int avmcs_suspend(struct pcmcia_device *dev)
     dev_link_t *link = args->client_data;
 
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-       link->state &= ~DEV_PRESENT;
-       if (link->state & DEV_CONFIG)
-               avmcs_release(link);
-       break;
     case CS_EVENT_CARD_INSERTION:
        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        avmcs_config(link);
        },
        .attach = avmcs_attach,
        .event  = avmcs_event,
-       .detach = avmcs_detach,
+       .remove = avmcs_detach,
        .id_table = avmcs_ids,
        .suspend= avmcs_suspend,
        .resume = avmcs_resume,
 
 */
 
 static dev_link_t *avma1cs_attach(void);
-static void avma1cs_detach(dev_link_t *);
+static void avma1cs_detach(struct pcmcia_device *p_dev);
 
 /*
    The dev_info variable is the "key" that is used to match up this
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
        cs_error(link->handle, RegisterClient, ret);
-       avma1cs_detach(link);
+       avma1cs_detach(link->handle);
        return NULL;
     }
 
 
 ======================================================================*/
 
-static void avma1cs_detach(dev_link_t *link)
+static void avma1cs_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
 
     DEBUG(0, "avma1cs_detach(0x%p)\n", link);
-    
+
     /* Locate device structure */
     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
        if (*linkp == link) break;
     if (*linkp == NULL)
        return;
 
-    /*
-       If the device is currently configured and active, we won't
-       actually delete it yet.  Instead, it is marked so that when
-       the release() function is called, that will trigger a proper
-       detach().
-    */
-    if (link->state & DEV_CONFIG) {
-#ifdef PCMCIA_DEBUG
-       printk(KERN_DEBUG "avma1_cs: detach postponed, '%s' "
-              "still locked\n", link->dev->dev_name);
-#endif
-       link->state |= DEV_STALE_LINK;
-       return;
-    }
+    if (link->state & DEV_CONFIG)
+           avma1cs_release(link);
 
-    /* Break the link with Card Services */
-    if (link->handle)
-       pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, free pieces */
     *linkp = link->next;
     kfree(link->priv);
     kfree(link);
-    
 } /* avma1cs_detach */
 
 /*======================================================================
     pcmcia_release_io(link->handle, &link->io);
     pcmcia_release_irq(link->handle, &link->irq);
     link->state &= ~DEV_CONFIG;
-    
-    if (link->state & DEV_STALE_LINK)
-       avma1cs_detach(link);
 } /* avma1cs_release */
 
 static int avma1cs_suspend(struct pcmcia_device *dev)
     DEBUG(1, "avma1cs_event(0x%06x)\n", event);
     
     switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-           if (link->state & DEV_CONFIG)
-               avma1cs_release(link);
-           break;
        case CS_EVENT_CARD_INSERTION:
            link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
            avma1cs_config(link);
        },
        .attach         = avma1cs_attach,
        .event          = avma1cs_event,
-       .detach         = avma1cs_detach,
+       .remove         = avma1cs_detach,
        .id_table       = avma1cs_ids,
        .suspend        = avma1cs_suspend,
        .resume         = avma1cs_resume,
 
 */
 
 static dev_link_t *elsa_cs_attach(void);
-static void elsa_cs_detach(dev_link_t *);
+static void elsa_cs_detach(struct pcmcia_device *p_dev);
 
 /*
    The dev_info variable is the "key" that is used to match up this
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
         cs_error(link->handle, RegisterClient, ret);
-        elsa_cs_detach(link);
+        elsa_cs_detach(link->handle);
         return NULL;
     }
 
 
 ======================================================================*/
 
-static void elsa_cs_detach(dev_link_t *link)
+static void elsa_cs_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
     local_info_t *info = link->priv;
-    int ret;
 
     DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
 
     if (*linkp == NULL)
         return;
 
-    if (link->state & DEV_CONFIG)
+    if (link->state & DEV_CONFIG) {
+        ((local_info_t*)link->priv)->busy = 1;
         elsa_cs_release(link);
-
-    /* Break the link with Card Services */
-    if (link->handle) {
-        ret = pcmcia_deregister_client(link->handle);
-       if (ret != CS_SUCCESS)
-           cs_error(link->handle, DeregisterClient, ret);
     }
 
     /* Unlink device structure and free it */
     DEBUG(1, "elsa_cs_event(%d)\n", event);
 
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-        link->state &= ~DEV_PRESENT;
-        if (link->state & DEV_CONFIG) {
-            ((local_info_t*)link->priv)->busy = 1;
-           elsa_cs_release(link);
-        }
-        break;
     case CS_EVENT_CARD_INSERTION:
         link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
         elsa_cs_config(link);
        },
        .attach         = elsa_cs_attach,
        .event          = elsa_cs_event,
-       .detach         = elsa_cs_detach,
+       .remove         = elsa_cs_detach,
        .id_table       = elsa_ids,
        .suspend        = elsa_suspend,
        .resume         = elsa_resume,
 
 */
 
 static dev_link_t *sedlbauer_attach(void);
-static void sedlbauer_detach(dev_link_t *);
+static void sedlbauer_detach(struct pcmcia_device *p_dev);
 
 /*
    You'll also need to prototype all the functions that will actually
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
        cs_error(link->handle, RegisterClient, ret);
-       sedlbauer_detach(link);
+       sedlbauer_detach(link->handle);
        return NULL;
     }
 
 
 ======================================================================*/
 
-static void sedlbauer_detach(dev_link_t *link)
+static void sedlbauer_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
 
     DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
     if (*linkp == NULL)
        return;
 
-    /*
-       If the device is currently configured and active, we won't
-       actually delete it yet.  Instead, it is marked so that when
-       the release() function is called, that will trigger a proper
-       detach().
-    */
     if (link->state & DEV_CONFIG) {
-#ifdef PCMCIA_DEBUG
-       printk(KERN_DEBUG "sedlbauer_cs: detach postponed, '%s' "
-              "still locked\n", link->dev->dev_name);
-#endif
-       link->state |= DEV_STALE_LINK;
-       return;
+       ((local_info_t *)link->priv)->stop = 1;
+       sedlbauer_release(link);
     }
 
-    /* Break the link with Card Services */
-    if (link->handle)
-       pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, and free it */
     *linkp = link->next;
     /* This points to the parent local_info_t struct */
     if (link->irq.AssignedIRQ)
        pcmcia_release_irq(link->handle, &link->irq);
     link->state &= ~DEV_CONFIG;
-    
-    if (link->state & DEV_STALE_LINK)
-       sedlbauer_detach(link);
-    
 } /* sedlbauer_release */
 
 static int sedlbauer_suspend(struct pcmcia_device *p_dev)
     DEBUG(1, "sedlbauer_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-       link->state &= ~DEV_PRESENT;
-       if (link->state & DEV_CONFIG) {
-           ((local_info_t *)link->priv)->stop = 1;
-           sedlbauer_release(link);
-       }
-       break;
     case CS_EVENT_CARD_INSERTION:
        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        sedlbauer_config(link);
        },
        .attach         = sedlbauer_attach,
        .event          = sedlbauer_event,
-       .detach         = sedlbauer_detach,
+       .remove         = sedlbauer_detach,
        .id_table       = sedlbauer_ids,
        .suspend        = sedlbauer_suspend,
        .resume         = sedlbauer_resume,
 
 */
 
 static dev_link_t *teles_attach(void);
-static void teles_detach(dev_link_t *);
+static void teles_detach(struct pcmcia_device *p_dev);
 
 /*
    The dev_info variable is the "key" that is used to match up this
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
         cs_error(link->handle, RegisterClient, ret);
-        teles_detach(link);
+        teles_detach(link->handle);
         return NULL;
     }
 
 
 ======================================================================*/
 
-static void teles_detach(dev_link_t *link)
+static void teles_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
     local_info_t *info = link->priv;
-    int ret;
 
     DEBUG(0, "teles_detach(0x%p)\n", link);
 
     if (*linkp == NULL)
         return;
 
-    if (link->state & DEV_CONFIG)
+    if (link->state & DEV_CONFIG) {
+        info->busy = 1;
         teles_cs_release(link);
-
-    /* Break the link with Card Services */
-    if (link->handle) {
-        ret = pcmcia_deregister_client(link->handle);
-       if (ret != CS_SUCCESS)
-           cs_error(link->handle, DeregisterClient, ret);
     }
 
     /* Unlink device structure and free it */
     DEBUG(1, "teles_cs_event(%d)\n", event);
 
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-        link->state &= ~DEV_PRESENT;
-        if (link->state & DEV_CONFIG) {
-            ((local_info_t*)link->priv)->busy = 1;
-           teles_cs_release(link);
-        }
-        break;
     case CS_EVENT_CARD_INSERTION:
         link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
         teles_cs_config(link);
        },
        .attach         = teles_attach,
        .event          = teles_cs_event,
-       .detach         = teles_detach,
+       .remove         = teles_detach,
        .id_table       = teles_ids,
        .suspend        = teles_suspend,
        .resume         = teles_resume,
 
 
        DEBUG(1, "event=0x%06x", event);
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               DEBUG(2, "EVENT_CARD_REMOVAL");
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG) {
-                       struct pcmciamtd_dev *dev = link->priv;
-                       if(dev->mtd_info) {
-                               del_mtd_device(dev->mtd_info);
-                               info("mtd%d: Removed", dev->mtd_info->index);
-                       }
-                       pcmciamtd_release(link);
-               }
-               break;
        case CS_EVENT_CARD_INSERTION:
                DEBUG(2, "EVENT_CARD_INSERTION");
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
  * when the device is released.
  */
 
-static void pcmciamtd_detach(dev_link_t *link)
+static void pcmciamtd_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
+
        DEBUG(3, "link=0x%p", link);
 
        if(link->state & DEV_CONFIG) {
-               pcmciamtd_release(link);
-       }
+               struct pcmciamtd_dev *dev = link->priv;
+               if(dev->mtd_info) {
+                       del_mtd_device(dev->mtd_info);
+                       info("mtd%d: Removed", dev->mtd_info->index);
+               }
 
-       if (link->handle) {
-               int ret;
-               DEBUG(2, "Deregistering with card services");
-               ret = pcmcia_deregister_client(link->handle);
-               if (ret != CS_SUCCESS)
-                       cs_error(link->handle, DeregisterClient, ret);
+               pcmciamtd_release(link);
        }
-
-       link->state |= DEV_STALE_LINK;
 }
 
 
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != 0) {
                cs_error(link->handle, RegisterClient, ret);
-               pcmciamtd_detach(link);
+               pcmciamtd_detach(link->handle);
                return NULL;
        }
        DEBUG(2, "link = %p", link);
        },
        .attach         = pcmciamtd_attach,
        .event          = pcmciamtd_event,
-       .detach         = pcmciamtd_detach,
+       .remove         = pcmciamtd_detach,
        .owner          = THIS_MODULE,
        .id_table       = pcmciamtd_ids,
        .suspend        = pcmciamtd_suspend,
 
 static dev_info_t dev_info = "3c574_cs";
 
 static dev_link_t *tc574_attach(void);
-static void tc574_detach(dev_link_t *);
+static void tc574_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list;
 
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != 0) {
                cs_error(link->handle, RegisterClient, ret);
-               tc574_detach(link);
+               tc574_detach(link->handle);
                return NULL;
        }
 
 
 */
 
-static void tc574_detach(dev_link_t *link)
+static void tc574_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
        dev_link_t **linkp;
 
        if (link->state & DEV_CONFIG)
                tc574_release(link);
 
-       if (link->handle)
-               pcmcia_deregister_client(link->handle);
-
        /* Unlink device structure, free bits */
        *linkp = link->next;
        free_netdev(dev);
                                           event_callback_args_t *args)
 {
        dev_link_t *link = args->client_data;
-       struct net_device *dev = link->priv;
 
        DEBUG(1, "3c574_event(0x%06x)\n", event);
 
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG)
-                       netif_device_detach(dev);
-               break;
        case CS_EVENT_CARD_INSERTION:
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                tc574_config(link);
        },
        .attach         = tc574_attach,
        .event          = tc574_event,
-       .detach         = tc574_detach,
+       .remove         = tc574_detach,
        .id_table       = tc574_ids,
        .suspend        = tc574_suspend,
        .resume         = tc574_resume,
 
 static dev_info_t dev_info = "3c589_cs";
 
 static dev_link_t *tc589_attach(void);
-static void tc589_detach(dev_link_t *);
+static void tc589_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list;
 
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
        cs_error(link->handle, RegisterClient, ret);
-       tc589_detach(link);
+       tc589_detach(link->handle);
        return NULL;
     }
     
 
 ======================================================================*/
 
-static void tc589_detach(dev_link_t *link)
+static void tc589_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
     dev_link_t **linkp;
     
 
     if (link->state & DEV_CONFIG)
        tc589_release(link);
-    
-    if (link->handle)
-       pcmcia_deregister_client(link->handle);
-    
+
     /* Unlink device structure, free bits */
     *linkp = link->next;
     free_netdev(dev);
                       event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
     
     DEBUG(1, "3c589_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-       link->state &= ~DEV_PRESENT;
-       if (link->state & DEV_CONFIG)
-           netif_device_detach(dev);
-       break;
     case CS_EVENT_CARD_INSERTION:
        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        tc589_config(link);
        },
        .attach         = tc589_attach,
        .event          = tc589_event,
-       .detach         = tc589_detach,
+       .remove         = tc589_detach,
         .id_table       = tc589_ids,
        .suspend        = tc589_suspend,
        .resume         = tc589_resume,
 
                         const u_char *buf, const int start_page);
 
 static dev_link_t *axnet_attach(void);
-static void axnet_detach(dev_link_t *);
+static void axnet_detach(struct pcmcia_device *p_dev);
 
 static dev_info_t dev_info = "axnet_cs";
 static dev_link_t *dev_list;
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
        cs_error(link->handle, RegisterClient, ret);
-       axnet_detach(link);
+       axnet_detach(link->handle);
        return NULL;
     }
 
 
 ======================================================================*/
 
-static void axnet_detach(dev_link_t *link)
+static void axnet_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
     dev_link_t **linkp;
 
     if (link->state & DEV_CONFIG)
        axnet_release(link);
 
-    if (link->handle)
-       pcmcia_deregister_client(link->handle);
-
     /* Unlink device structure, free bits */
     *linkp = link->next;
     free_netdev(dev);
                       event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
 
     DEBUG(2, "axnet_event(0x%06x)\n", event);
 
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-       link->state &= ~DEV_PRESENT;
-       if (link->state & DEV_CONFIG)
-           netif_device_detach(dev);
-       break;
     case CS_EVENT_CARD_INSERTION:
        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        axnet_config(link);
        },
        .attach         = axnet_attach,
        .event          = axnet_event,
-       .detach         = axnet_detach,
+       .remove         = axnet_detach,
        .id_table       = axnet_ids,
        .suspend        = axnet_suspend,
        .resume         = axnet_resume,
 
 static dev_info_t dev_info = "com20020_cs";
 
 static dev_link_t *com20020_attach(void);
-static void com20020_detach(dev_link_t *);
+static void com20020_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list;
 
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
         cs_error(link->handle, RegisterClient, ret);
-        com20020_detach(link);
+        com20020_detach(link->handle);
         return NULL;
     }
 
 
 ======================================================================*/
 
-static void com20020_detach(dev_link_t *link)
+static void com20020_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct com20020_dev_t *info = link->priv;
     dev_link_t **linkp;
     struct net_device *dev; 
     if (link->state & DEV_CONFIG)
         com20020_release(link);
 
-    if (link->handle)
-        pcmcia_deregister_client(link->handle);
-
     /* Unlink device structure, free bits */
     DEBUG(1,"unlinking...\n");
     *linkp = link->next;
                          event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    com20020_dev_t *info = link->priv;
-    struct net_device *dev = info->dev;
 
     DEBUG(1, "com20020_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-        link->state &= ~DEV_PRESENT;
-        if (link->state & DEV_CONFIG)
-            netif_device_detach(dev);
-        break;
     case CS_EVENT_CARD_INSERTION:
         link->state |= DEV_PRESENT;
        com20020_config(link); 
        },
        .attach         = com20020_attach,
        .event          = com20020_event,
-       .detach         = com20020_detach,
+       .remove         = com20020_detach,
        .id_table       = com20020_ids,
        .suspend        = com20020_suspend,
        .resume         = com20020_resume,
 
 static int fmvj18x_event(event_t event, int priority,
                          event_callback_args_t *args);
 static dev_link_t *fmvj18x_attach(void);
-static void fmvj18x_detach(dev_link_t *);
+static void fmvj18x_detach(struct pcmcia_device *p_dev);
 
 /*
     LAN controller(MBH86960A) specific routines
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
        cs_error(link->handle, RegisterClient, ret);
-       fmvj18x_detach(link);
+       fmvj18x_detach(link->handle);
        return NULL;
     }
 
 
 /*====================================================================*/
 
-static void fmvj18x_detach(dev_link_t *link)
+static void fmvj18x_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
     dev_link_t **linkp;
     
     if (link->state & DEV_CONFIG)
        fmvj18x_release(link);
 
-    /* Break the link with Card Services */
-    if (link->handle)
-       pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, free pieces */
     *linkp = link->next;
     free_netdev(dev);
                          event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
 
     DEBUG(1, "fmvj18x_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-       link->state &= ~DEV_PRESENT;
-       if (link->state & DEV_CONFIG)
-           netif_device_detach(dev);
-       break;
     case CS_EVENT_CARD_INSERTION:
        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        fmvj18x_config(link);
        },
        .attach         = fmvj18x_attach,
        .event          = fmvj18x_event,
-       .detach         = fmvj18x_detach,
+       .remove         = fmvj18x_detach,
        .id_table       = fmvj18x_ids,
        .suspend        = fmvj18x_suspend,
        .resume         = fmvj18x_resume,
 
 static dev_info_t dev_info = "ibmtr_cs";
 
 static dev_link_t *ibmtr_attach(void);
-static void ibmtr_detach(dev_link_t *);
+static void ibmtr_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list;
 
     return link;
 
 out_detach:
-    ibmtr_detach(link);
+    ibmtr_detach(link->handle);
     link = NULL;
     goto out;
 } /* ibmtr_attach */
 
 ======================================================================*/
 
-static void ibmtr_detach(dev_link_t *link)
+static void ibmtr_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct ibmtr_dev_t *info = link->priv;
     dev_link_t **linkp;
     struct net_device *dev;
     if (link->state & DEV_CONFIG)
         ibmtr_release(link);
 
-    if (link->handle)
-        pcmcia_deregister_client(link->handle);
-
     /* Unlink device structure, free bits */
     *linkp = link->next;
     free_netdev(dev);
                        event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    ibmtr_dev_t *info = link->priv;
-    struct net_device *dev = info->dev;
 
     DEBUG(1, "ibmtr_event(0x%06x)\n", event);
 
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-        link->state &= ~DEV_PRESENT;
-        if (link->state & DEV_CONFIG) {
-           /* set flag to bypass normal interrupt code */
-           struct tok_info *priv = netdev_priv(dev);
-           priv->sram_phys |= 1;
-           netif_device_detach(dev);
-        }
-        break;
     case CS_EVENT_CARD_INSERTION:
         link->state |= DEV_PRESENT;
        ibmtr_config(link);
        },
        .attach         = ibmtr_attach,
        .event          = ibmtr_event,
-       .detach         = ibmtr_detach,
+       .remove         = ibmtr_detach,
        .id_table       = ibmtr_ids,
        .suspend        = ibmtr_suspend,
        .resume         = ibmtr_resume,
 
 
 
 static dev_link_t *nmclan_attach(void);
-static void nmclan_detach(dev_link_t *);
+static void nmclan_detach(struct pcmcia_device *p_dev);
 
 /* ----------------------------------------------------------------------------
 nmclan_attach
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
        cs_error(link->handle, RegisterClient, ret);
-       nmclan_detach(link);
+       nmclan_detach(link->handle);
        return NULL;
     }
 
        when the device is released.
 ---------------------------------------------------------------------------- */
 
-static void nmclan_detach(dev_link_t *link)
+static void nmclan_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
     dev_link_t **linkp;
 
     if (link->state & DEV_CONFIG)
        nmclan_release(link);
 
-    if (link->handle)
-       pcmcia_deregister_client(link->handle);
-
     /* Unlink device structure, free bits */
     *linkp = link->next;
     free_netdev(dev);
                       event_callback_args_t *args)
 {
   dev_link_t *link = args->client_data;
-  struct net_device *dev = link->priv;
 
   DEBUG(1, "nmclan_event(0x%06x)\n", event);
 
   switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-      link->state &= ~DEV_PRESENT;
-      if (link->state & DEV_CONFIG)
-       netif_device_detach(dev);
-      break;
     case CS_EVENT_CARD_INSERTION:
       link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
       nmclan_config(link);
        },
        .attach         = nmclan_attach,
        .event          = nmclan_event,
-       .detach         = nmclan_detach,
+       .remove         = nmclan_detach,
        .id_table       = nmclan_ids,
        .suspend        = nmclan_suspend,
        .resume         = nmclan_resume,
 
                            int stop_pg);
 
 static dev_link_t *pcnet_attach(void);
-static void pcnet_detach(dev_link_t *);
+static void pcnet_detach(struct pcmcia_device *p_dev);
 
 static dev_info_t dev_info = "pcnet_cs";
 static dev_link_t *dev_list;
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
        cs_error(link->handle, RegisterClient, ret);
-       pcnet_detach(link);
+       pcnet_detach(link->handle);
        return NULL;
     }
 
 
 ======================================================================*/
 
-static void pcnet_detach(dev_link_t *link)
+static void pcnet_detach(struct pcmcia_device *p_dev)
 {
-    struct net_device *dev = link->priv;
-    dev_link_t **linkp;
-
-    DEBUG(0, "pcnet_detach(0x%p)\n", link);
+       dev_link_t *link = dev_to_instance(p_dev);
+       struct net_device *dev = link->priv;
+       dev_link_t **linkp;
 
-    /* Locate device structure */
-    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-       if (*linkp == link) break;
-    if (*linkp == NULL)
-       return;
+       DEBUG(0, "pcnet_detach(0x%p)\n", link);
 
-    if (link->dev)
-       unregister_netdev(dev);
+       /* Locate device structure */
+       for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+               if (*linkp == link) break;
+       if (*linkp == NULL)
+               return;
 
-    if (link->state & DEV_CONFIG)
-       pcnet_release(link);
+       if (link->dev)
+               unregister_netdev(dev);
 
-    if (link->handle)
-       pcmcia_deregister_client(link->handle);
+       if (link->state & DEV_CONFIG)
+               pcnet_release(link);
 
-    /* Unlink device structure, free bits */
-    *linkp = link->next;
-    free_netdev(dev);
+       /* Unlink device structure, free bits */
+       *linkp = link->next;
+       free_netdev(dev);
 } /* pcnet_detach */
 
 /*======================================================================
                       event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
 
     DEBUG(2, "pcnet_event(0x%06x)\n", event);
 
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-       link->state &= ~DEV_PRESENT;
-       if (link->state & DEV_CONFIG)
-           netif_device_detach(dev);
-       break;
     case CS_EVENT_CARD_INSERTION:
        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        pcnet_config(link);
        },
        .attach         = pcnet_attach,
        .event          = pcnet_event,
-       .detach         = pcnet_detach,
+       .remove         = pcnet_detach,
        .owner          = THIS_MODULE,
        .id_table       = pcnet_ids,
        .suspend        = pcnet_suspend,
 
 /*====================================================================*/
 
 static dev_link_t *smc91c92_attach(void);
-static void smc91c92_detach(dev_link_t *);
+static void smc91c92_detach(struct pcmcia_device *p_dev);
 static void smc91c92_config(dev_link_t *link);
 static void smc91c92_release(dev_link_t *link);
 static int smc91c92_event(event_t event, int priority,
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
        cs_error(link->handle, RegisterClient, ret);
-       smc91c92_detach(link);
+       smc91c92_detach(link->handle);
        return NULL;
     }
 
 
 ======================================================================*/
 
-static void smc91c92_detach(dev_link_t *link)
+static void smc91c92_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
     dev_link_t **linkp;
 
     if (link->state & DEV_CONFIG)
        smc91c92_release(link);
 
-    if (link->handle)
-       pcmcia_deregister_client(link->handle);
-
     /* Unlink device structure, free bits */
     *linkp = link->next;
     free_netdev(dev);
                          event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
 
     DEBUG(1, "smc91c92_event(0x%06x)\n", event);
 
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-       link->state &= ~DEV_PRESENT;
-       if (link->state & DEV_CONFIG)
-           netif_device_detach(dev);
-       break;
     case CS_EVENT_CARD_INSERTION:
        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        smc91c92_config(link);
        },
        .attach         = smc91c92_attach,
        .event          = smc91c92_event,
-       .detach         = smc91c92_detach,
+       .remove         = smc91c92_detach,
        .id_table       = smc91c92_ids,
        .suspend        = smc91c92_suspend,
        .resume         = smc91c92_resume,
 
  */
 
 static dev_link_t *xirc2ps_attach(void);
-static void xirc2ps_detach(dev_link_t *);
+static void xirc2ps_detach(struct pcmcia_device *p_dev);
 
 /****************
  * You'll also need to prototype all the functions that will actually
     client_reg.event_callback_args.client_data = link;
     if ((err = pcmcia_register_client(&link->handle, &client_reg))) {
        cs_error(link->handle, RegisterClient, err);
-       xirc2ps_detach(link);
+       xirc2ps_detach(link->handle);
        return NULL;
     }
 
  */
 
 static void
-xirc2ps_detach(dev_link_t * link)
+xirc2ps_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
     dev_link_t **linkp;
 
     if (link->dev)
        unregister_netdev(dev);
 
-    /*
-     * If the device is currently configured and active, we won't
-     * actually delete it yet. Instead, it is marked so that when
-     * the release() function is called, that will trigger a proper
-     * detach().
-     */
     if (link->state & DEV_CONFIG)
        xirc2ps_release(link);
 
-    /* Break the link with Card Services */
-    if (link->handle)
-       pcmcia_deregister_client(link->handle);
-
     /* Unlink device structure, free it */
     *linkp = link->next;
     free_netdev(dev);
              event_callback_args_t * args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
 
     DEBUG(0, "event(%d)\n", (int)event);
 
     switch (event) {
-    case CS_EVENT_REGISTRATION_COMPLETE:
-       DEBUG(0, "registration complete\n");
-       break;
-    case CS_EVENT_CARD_REMOVAL:
-       link->state &= ~DEV_PRESENT;
-       if (link->state & DEV_CONFIG)
-           netif_device_detach(dev);
-       break;
     case CS_EVENT_CARD_INSERTION:
        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        xirc2ps_config(link);
        },
        .attach         = xirc2ps_attach,
        .event          = xirc2ps_event,
-       .detach         = xirc2ps_detach,
+       .remove         = xirc2ps_detach,
        .id_table       = xirc2ps_ids,
        .suspend        = xirc2ps_suspend,
        .resume         = xirc2ps_resume,
 
 */
 
 static dev_link_t *airo_attach(void);
-static void airo_detach(dev_link_t *);
+static void airo_detach(struct pcmcia_device *p_dev);
 
 /*
    You'll also need to prototype all the functions that will actually
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != 0) {
                cs_error(link->handle, RegisterClient, ret);
-               airo_detach(link);
+               airo_detach(link->handle);
                return NULL;
        }
        
   
   ======================================================================*/
 
-static void airo_detach(dev_link_t *link)
+static void airo_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        dev_link_t **linkp;
        
        DEBUG(0, "airo_detach(0x%p)\n", link);
        if ( ((local_info_t*)link->priv)->eth_dev ) {
                stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 );
        }
-       ((local_info_t*)link->priv)->eth_dev = NULL;   
-       
-       /* Break the link with Card Services */
-       if (link->handle)
-               pcmcia_deregister_client(link->handle);
-       
-       
-       
+       ((local_info_t*)link->priv)->eth_dev = NULL;
+
        /* Unlink device structure, free pieces */
        *linkp = link->next;
        kfree(link->priv);
                      event_callback_args_t *args)
 {
        dev_link_t *link = args->client_data;
-       local_info_t *local = link->priv;
-       
+
        DEBUG(1, "airo_event(0x%06x)\n", event);
-       
+
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG) {
-                       netif_device_detach(local->eth_dev);
-                       airo_release(link);
-               }
-               break;
        case CS_EVENT_CARD_INSERTION:
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                airo_config(link);
        },
        .attach         = airo_attach,
        .event          = airo_event,
-       .detach         = airo_detach,
+       .remove         = airo_detach,
        .id_table       = airo_ids,
        .suspend        = airo_suspend,
        .resume         = airo_resume,
 
 */
 
 static dev_link_t *atmel_attach(void);
-static void atmel_detach(dev_link_t *);
+static void atmel_detach(struct pcmcia_device *p_dev);
 
 /*
    You'll also need to prototype all the functions that will actually
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != 0) {
                cs_error(link->handle, RegisterClient, ret);
-               atmel_detach(link);
+               atmel_detach(link->handle);
                return NULL;
        }
        
   
   ======================================================================*/
 
-static void atmel_detach(dev_link_t *link)
+static void atmel_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        dev_link_t **linkp;
        
        DEBUG(0, "atmel_detach(0x%p)\n", link);
        if (link->state & DEV_CONFIG)
                atmel_release(link);
                
-       /* Break the link with Card Services */
-       if (link->handle)
-               pcmcia_deregister_client(link->handle);
-
        /* Unlink device structure, free pieces */
        *linkp = link->next;
        kfree(link->priv);
                      event_callback_args_t *args)
 {
        dev_link_t *link = args->client_data;
-       local_info_t *local = link->priv;
-       
+
        DEBUG(1, "atmel_event(0x%06x)\n", event);
-       
+
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG) {
-                       netif_device_detach(local->eth_dev);
-                       atmel_release(link);
-               }
-               break;
        case CS_EVENT_CARD_INSERTION:
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                atmel_config(link);
         },
        .attach         = atmel_attach,
        .event          = atmel_event,
-       .detach         = atmel_detach,
+       .remove         = atmel_detach,
        .id_table       = atmel_ids,
        .suspend        = atmel_suspend,
        .resume         = atmel_resume,
 
 
 
 
-static void prism2_detach(dev_link_t *link);
+static void prism2_detach(struct pcmcia_device *p_dev);
 static void prism2_release(u_long arg);
 static int prism2_event(event_t event, int priority,
                        event_callback_args_t *args);
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != CS_SUCCESS) {
                cs_error(link->handle, RegisterClient, ret);
-               prism2_detach(link);
+               prism2_detach(link->handle);
                return NULL;
        }
        return link;
 }
 
 
-static void prism2_detach(dev_link_t *link)
+static void prism2_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        dev_link_t **linkp;
 
        PDEBUG(DEBUG_FLOW, "prism2_detach\n");
                prism2_release((u_long)link);
        }
 
-       if (link->handle) {
-               int res = pcmcia_deregister_client(link->handle);
-               if (res) {
-                       printk("CardService(DeregisterClient) => %d\n", res);
-                       cs_error(link->handle, DeregisterClient, res);
-               }
-       }
-
        *linkp = link->next;
        /* release net devices */
        if (link->priv) {
                        event_callback_args_t *args)
 {
        dev_link_t *link = args->client_data;
-       struct net_device *dev = (struct net_device *) link->priv;
 
        switch (event) {
        case CS_EVENT_CARD_INSERTION:
                }
                break;
 
-       case CS_EVENT_CARD_REMOVAL:
-               PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_REMOVAL\n", dev_info);
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG) {
-                       netif_stop_queue(dev);
-                       netif_device_detach(dev);
-                       prism2_release((u_long) link);
-               }
-               break;
-
        default:
                PDEBUG(DEBUG_EXTRA, "%s: prism2_event() - unknown event %d\n",
                       dev_info, event);
                .name   = "hostap_cs",
        },
        .attach         = prism2_attach,
-       .detach         = prism2_detach,
+       .remove         = prism2_detach,
        .owner          = THIS_MODULE,
        .event          = prism2_event,
        .id_table       = hostap_cs_ids,
 
 static void netwave_pcmcia_config(dev_link_t *arg); /* Runs after card 
                                                                                                           insertion */
 static dev_link_t *netwave_attach(void);     /* Create instance */
-static void netwave_detach(dev_link_t *);    /* Destroy instance */
+static void netwave_detach(struct pcmcia_device *p_dev);    /* Destroy instance */
 
 /* Hardware configuration */
 static void netwave_doreset(kio_addr_t iobase, u_char __iomem *ramBase);
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
        cs_error(link->handle, RegisterClient, ret);
-       netwave_detach(link);
+       netwave_detach(link->handle);
        return NULL;
     }
 
  *    structures are freed.  Otherwise, the structures will be freed
  *    when the device is released.
  */
-static void netwave_detach(dev_link_t *link)
+static void netwave_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     struct net_device *dev = link->priv;
     dev_link_t **linkp;
 
        */
     if (link->state & DEV_CONFIG)
        netwave_release(link);
-       
-    /* Break the link with Card Services */
-    if (link->handle)
-       pcmcia_deregister_client(link->handle);
-    
+
     /* Locate device structure */
     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
        if (*linkp == link) break;
                         event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
-       
+
     DEBUG(1, "netwave_event(0x%06x)\n", event);
-  
-    switch (event) {
-    case CS_EVENT_REGISTRATION_COMPLETE:
-       DEBUG(0, "netwave_cs: registration complete\n");
-       break;
 
-    case CS_EVENT_CARD_REMOVAL:
-       link->state &= ~DEV_PRESENT;
-       if (link->state & DEV_CONFIG) {
-           netif_device_detach(dev);
-           netwave_release(link);
-       }
-       break;
+    switch (event) {
     case CS_EVENT_CARD_INSERTION:
        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        netwave_pcmcia_config( link);
        },
        .attach         = netwave_attach,
        .event          = netwave_event,
-       .detach         = netwave_detach,
+       .remove         = netwave_detach,
        .id_table       = netwave_ids,
        .suspend        = netwave_suspend,
        .resume         = netwave_resume,
 
 /********************************************************************/
 
 static void orinoco_cs_release(dev_link_t *link);
-static void orinoco_cs_detach(dev_link_t *link);
+static void orinoco_cs_detach(struct pcmcia_device *p_dev);
 
 /********************************************************************/
 /* Device methods                                                  */
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != CS_SUCCESS) {
                cs_error(link->handle, RegisterClient, ret);
-               orinoco_cs_detach(link);
+               orinoco_cs_detach(link->handle);
                return NULL;
        }
 
  * are freed.  Otherwise, the structures will be freed when the device
  * is released.
  */
-static void orinoco_cs_detach(dev_link_t *link)
+static void orinoco_cs_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        dev_link_t **linkp;
        struct net_device *dev = link->priv;
 
        if (link->state & DEV_CONFIG)
                orinoco_cs_release(link);
 
-       /* Break the link with Card Services */
-       if (link->handle)
-               pcmcia_deregister_client(link->handle);
-
        /* Unlink device structure, and free it */
        *linkp = link->next;
        DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
                       event_callback_args_t * args)
 {
        dev_link_t *link = args->client_data;
-       struct net_device *dev = link->priv;
-       struct orinoco_private *priv = netdev_priv(dev);
-       int err = 0;
 
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG) {
-                       unsigned long flags;
-
-                       spin_lock_irqsave(&priv->lock, flags);
-                       netif_device_detach(dev);
-                       priv->hw_unavailable++;
-                       spin_unlock_irqrestore(&priv->lock, flags);
-               }
-               break;
-
        case CS_EVENT_CARD_INSERTION:
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                orinoco_cs_config(link);
                break;
        }
 
-       return err;
+       return 0;
 }                              /* orinoco_cs_event */
 
 /********************************************************************/
                .name   = DRIVER_NAME,
        },
        .attach         = orinoco_cs_attach,
-       .detach         = orinoco_cs_detach,
+       .remove         = orinoco_cs_detach,
        .event          = orinoco_cs_event,
        .id_table       = orinoco_cs_ids,
        .suspend        = orinoco_cs_suspend,
 
 static void ray_release(dev_link_t *link);
 static int ray_event(event_t event, int priority, event_callback_args_t *args);
 static dev_link_t *ray_attach(void);
-static void ray_detach(dev_link_t *);
+static void ray_detach(struct pcmcia_device *p_dev);
 
 /***** Prototypes indicated by device structure ******************************/
 static int ray_dev_close(struct net_device *dev);
     if (ret != 0) {
         printk("ray_cs ray_attach RegisterClient unhappy - detaching\n");
         cs_error(link->handle, RegisterClient, ret);
-        ray_detach(link);
+        ray_detach(link->handle);
         return NULL;
     }
     DEBUG(2,"ray_cs ray_attach ending\n");
     structures are freed.  Otherwise, the structures will be freed
     when the device is released.
 =============================================================================*/
-static void ray_detach(dev_link_t *link)
+static void ray_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
+    struct net_device *dev;
+    ray_dev_t *local;
 
     DEBUG(1, "ray_detach(0x%p)\n", link);
     
     if (*linkp == NULL)
         return;
 
-    /* If the device is currently configured and active, we won't
-      actually delete it yet.  Instead, it is marked so that when
-      the release() function is called, that will trigger a proper
-      detach().
-    */
-    if (link->state & DEV_CONFIG)
-        ray_release(link);
+    dev = link->priv;
+
+    if (link->state & DEV_CONFIG) {
+           ray_release(link);
+
+           local = (ray_dev_t *)dev->priv;
+            del_timer(&local->timer);
+    }
 
-    /* Break the link with Card Services */
-    if (link->handle)
-        pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, free pieces */
     *linkp = link->next;
     if (link->priv) {
-        struct net_device *dev = link->priv;
        if (link->dev) unregister_netdev(dev);
         free_netdev(dev);
     }
                      event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
-    ray_dev_t *local = (ray_dev_t *)dev->priv;
     DEBUG(1, "ray_event(0x%06x)\n", event);
-    
+
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-        link->state &= ~DEV_PRESENT;
-        netif_device_detach(dev);
-        if (link->state & DEV_CONFIG) {
-           ray_release(link);
-            del_timer(&local->timer);
-        }
-        break;
     case CS_EVENT_CARD_INSERTION:
         link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
         ray_config(link);
        },
        .attach         = ray_attach,
        .event          = ray_event,
-       .detach         = ray_detach,
+       .remove         = ray_detach,
        .id_table       = ray_ids,
        .suspend        = ray_suspend,
        .resume         = ray_resume,
 
 /********************************************************************/
 
 static void spectrum_cs_release(dev_link_t *link);
-static void spectrum_cs_detach(dev_link_t *link);
+static void spectrum_cs_detach(struct pcmcia_device *p_dev);
 
 /********************************************************************/
 /* Firmware downloader                                             */
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != CS_SUCCESS) {
                cs_error(link->handle, RegisterClient, ret);
-               spectrum_cs_detach(link);
+               spectrum_cs_detach(link->handle);
                return NULL;
        }
 
  * are freed.  Otherwise, the structures will be freed when the device
  * is released.
  */
-static void spectrum_cs_detach(dev_link_t *link)
+static void spectrum_cs_detach(struct pcmcia_device *p_dev)
 {
-       dev_link_t **linkp;
+       dev_link_t *link = dev_to_instance(p_dev);
        struct net_device *dev = link->priv;
 
-       /* Locate device structure */
-       for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-               if (*linkp == link)
-                       break;
-
-       BUG_ON(*linkp == NULL);
-
        if (link->state & DEV_CONFIG)
                spectrum_cs_release(link);
 
-       /* Break the link with Card Services */
-       if (link->handle)
-               pcmcia_deregister_client(link->handle);
-
-       /* Unlink device structure, and free it */
-       *linkp = link->next;
        DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
        if (link->dev) {
                DEBUG(0, PFX "About to unregister net device %p\n",
                       event_callback_args_t * args)
 {
        dev_link_t *link = args->client_data;
-       struct net_device *dev = link->priv;
-       struct orinoco_private *priv = netdev_priv(dev);
 
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG) {
-                       unsigned long flags;
-
-                       spin_lock_irqsave(&priv->lock, flags);
-                       netif_device_detach(dev);
-                       priv->hw_unavailable++;
-                       spin_unlock_irqrestore(&priv->lock, flags);
-               }
-               break;
-
        case CS_EVENT_CARD_INSERTION:
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                spectrum_cs_config(link);
                .name   = DRIVER_NAME,
        },
        .attach         = spectrum_cs_attach,
-       .detach         = spectrum_cs_detach,
+       .remove         = spectrum_cs_detach,
        .suspend        = spectrum_cs_suspend,
        .resume         = spectrum_cs_resume,
        .event          = spectrum_cs_event,
 
   if(ret != 0)
     {
       cs_error(link->handle, RegisterClient, ret);
-      wavelan_detach(link);
+      wavelan_detach(link->handle);
       return NULL;
     }
 
  * is released.
  */
 static void
-wavelan_detach(dev_link_t *    link)
+wavelan_detach(struct pcmcia_device *p_dev)
 {
+   dev_link_t *link = dev_to_instance(p_dev);
+
 #ifdef DEBUG_CALLBACK_TRACE
   printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link);
 #endif
       wv_pcmcia_release(link);
     }
 
-  /* Break the link with Card Services */
-  if(link->handle)
-    pcmcia_deregister_client(link->handle);
-    
   /* Remove the interface data from the linked list */
   if(dev_list == link)
     dev_list = link->next;
 
     switch(event)
       {
-      case CS_EVENT_REGISTRATION_COMPLETE:
-#ifdef DEBUG_CONFIG_INFO
-       printk(KERN_DEBUG "wavelan_cs: registration complete\n");
-#endif
-       break;
-
-      case CS_EVENT_CARD_REMOVAL:
-       /* Oups ! The card is no more there */
-       link->state &= ~DEV_PRESENT;
-       if(link->state & DEV_CONFIG)
-         {
-           /* Accept no more transmissions */
-           netif_device_detach(dev);
-
-           /* Release the card */
-           wv_pcmcia_release(link);
-         }
-       break;
-
       case CS_EVENT_CARD_INSERTION:
        /* Reset and configure the card */
        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        },
        .attach         = wavelan_attach,
        .event          = wavelan_event,
-       .detach         = wavelan_detach,
+       .remove         = wavelan_detach,
        .id_table       = wavelan_ids,
        .suspend        = wavelan_suspend,
        .resume         = wavelan_resume,
 
 static dev_link_t *
        wavelan_attach(void);           /* Create a new device */
 static void
-       wavelan_detach(dev_link_t *);   /* Destroy a removed device */
+       wavelan_detach(struct pcmcia_device *p_dev);    /* Destroy a removed device */
 static int
        wavelan_event(event_t,          /* Manage pcmcia events */
                      int,
 
  * Services. If it has been released, all local data structures are freed.
  * Otherwise, the structures will be freed when the device is released.
  */
-static void wl3501_detach(dev_link_t *link)
+static void wl3501_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        dev_link_t **linkp;
+       struct net_device *dev = link->priv;
 
        /* Locate device structure */
        for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next)
         * function is called, that will trigger a proper detach(). */
 
        if (link->state & DEV_CONFIG) {
-#ifdef PCMCIA_DEBUG
-               printk(KERN_DEBUG "wl3501_cs: detach postponed, '%s' "
-                      "still locked\n", link->dev->dev_name);
-#endif
-               goto out;
-       }
+               while (link->open > 0)
+                       wl3501_close(dev);
 
-       /* Break the link with Card Services */
-       if (link->handle)
-               pcmcia_deregister_client(link->handle);
+               netif_device_detach(dev);
+               wl3501_release(link);
+       }
 
        /* Unlink device structure, free pieces */
        *linkp = link->next;
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret) {
                cs_error(link->handle, RegisterClient, ret);
-               wl3501_detach(link);
+               wl3501_detach(link->handle);
                link = NULL;
        }
 out:
 static int wl3501_event(event_t event, int pri, event_callback_args_t *args)
 {
        dev_link_t *link = args->client_data;
-       struct net_device *dev = link->priv;
 
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG) {
-                       while (link->open > 0)
-                               wl3501_close(dev);
-                       netif_device_detach(dev);
-                       wl3501_release(link);
-               }
-               break;
        case CS_EVENT_CARD_INSERTION:
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                wl3501_config(link);
        },
        .attach         = wl3501_attach,
        .event          = wl3501_event,
-       .detach         = wl3501_detach,
+       .remove         = wl3501_detach,
        .id_table       = wl3501_ids,
        .suspend        = wl3501_suspend,
        .resume         = wl3501_resume,
 
 } parport_info_t;
 
 static dev_link_t *parport_attach(void);
-static void parport_detach(dev_link_t *);
+static void parport_detach(struct pcmcia_device *p_dev);
 static void parport_config(dev_link_t *link);
 static void parport_cs_release(dev_link_t *);
 static int parport_event(event_t event, int priority,
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != CS_SUCCESS) {
        cs_error(link->handle, RegisterClient, ret);
-       parport_detach(link);
+       parport_detach(link->handle);
        return NULL;
     }
     
 
 ======================================================================*/
 
-static void parport_detach(dev_link_t *link)
+static void parport_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
-    int ret;
 
     DEBUG(0, "parport_detach(0x%p)\n", link);
-    
+
     /* Locate device structure */
     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
        if (*linkp == link) break;
 
     if (link->state & DEV_CONFIG)
        parport_cs_release(link);
-    
-    if (link->handle) {
-       ret = pcmcia_deregister_client(link->handle);
-       if (ret != CS_SUCCESS)
-           cs_error(link->handle, DeregisterClient, ret);
-    }
-    
+
     /* Unlink, free device structure */
     *linkp = link->next;
     kfree(link->priv);
-    
 } /* parport_detach */
 
 /*======================================================================
     DEBUG(1, "parport_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-       link->state &= ~DEV_PRESENT;
-       if (link->state & DEV_CONFIG)
-               parport_cs_release(link);
-       break;
     case CS_EVENT_CARD_INSERTION:
        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        parport_config(link);
        },
        .attach         = parport_attach,
        .event          = parport_event,
-       .detach         = parport_detach,
+       .remove         = parport_detach,
        .id_table       = parport_ids,
        .suspend        = parport_suspend,
        .resume         = parport_resume,
 
 
 spinlock_t pcmcia_dev_list_lock;
 
-static int unbind_request(struct pcmcia_socket *s);
-
 /*====================================================================*/
 
 /* code which was in cs.c before */
        unsigned int i;
        u32 hash;
 
-       if (!p_drv->attach || !p_drv->event || !p_drv->detach)
+       if (!p_drv->attach || !p_drv->event || !p_drv->remove)
                printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback "
                       "function\n", p_drv->drv.name);
 
 {
        struct pcmcia_device *p_dev;
        struct pcmcia_driver *p_drv;
+       int i;
 
        /* detach the "instance" */
        p_dev = to_pcmcia_dev(dev);
        p_drv = to_pcmcia_drv(dev->driver);
 
+       /* the likely, new path */
+       if (p_drv && p_drv->remove) {
+               p_drv->remove(p_dev);
+
+               /* check for proper unloading */
+               if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
+                       printk(KERN_INFO "pcmcia: driver %s did not release config properly\n",
+                              p_drv->drv.name);
+
+               for (i = 0; i < MAX_WIN; i++)
+                       if (p_dev->state & CLIENT_WIN_REQ(i))
+                               printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n",
+                                      p_drv->drv.name);
+
+               /* undo pcmcia_register_client */
+               p_dev->state = CLIENT_UNBOUND;
+               pcmcia_put_dev(p_dev);
+
+               /* references from pcmcia_probe_device */
+               pcmcia_put_dev(p_dev);
+               module_put(p_drv->owner);
+
+               return 0;
+       }
+
+       /* old path */
        if (p_drv) {
                if ((p_drv->detach) && (p_dev->instance)) {
+                       printk(KERN_INFO "pcmcia: using deprecated detach mechanism. Fix the driver!\n");
+
                        p_drv->detach(p_dev->instance);
                        /* from pcmcia_probe_device */
                        put_device(&p_dev->dev);
 }
 
 
+/*
+ * Removes a PCMCIA card from the device tree and socket list.
+ */
+static void pcmcia_card_remove(struct pcmcia_socket *s)
+{
+       struct pcmcia_device    *p_dev;
+       unsigned long           flags;
+
+       ds_dbg(2, "unbind_request(%d)\n", s->sock);
+
+       s->device_count = 0;
+
+       for (;;) {
+               /* unregister all pcmcia_devices registered with this socket*/
+               spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
+               if (list_empty(&s->devices_list)) {
+                       spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+                       return;
+               }
+               p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
+               list_del(&p_dev->socket_device_list);
+               p_dev->state |= CLIENT_STALE;
+               spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
+
+               device_unregister(&p_dev->dev);
+       }
+
+       return;
+} /* unbind_request */
+
 
 /*
  * pcmcia_device_query -- determine information about a pcmcia device
 
        case CS_EVENT_CARD_REMOVAL:
                s->pcmcia_state.present = 0;
-               send_event(skt, event, priority);
-               unbind_request(skt);
+               send_event(skt, event, priority);
+               pcmcia_card_remove(skt);
                handle_event(skt, event);
                break;
        
 EXPORT_SYMBOL(pcmcia_register_client);
 
 
-/* unbind _all_ devices attached to a given pcmcia_bus_socket. The
- * drivers have been called with EVENT_CARD_REMOVAL before.
- */
-static int unbind_request(struct pcmcia_socket *s)
-{
-       struct pcmcia_device    *p_dev;
-       unsigned long           flags;
-
-       ds_dbg(2, "unbind_request(%d)\n", s->sock);
-
-       s->device_count = 0;
-
-       for (;;) {
-               /* unregister all pcmcia_devices registered with this socket*/
-               spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
-               if (list_empty(&s->devices_list)) {
-                       spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-                       return 0;
-               }
-               p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
-               list_del(&p_dev->socket_device_list);
-               p_dev->state |= CLIENT_STALE;
-               spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
-
-               device_unregister(&p_dev->dev);
-       }
-
-       return 0;
-} /* unbind_request */
-
 int pcmcia_deregister_client(struct pcmcia_device *p_dev)
 {
        struct pcmcia_socket *s;
 
                         event_callback_args_t *args);
 
 static dev_link_t *aha152x_attach(void);
-static void aha152x_detach(dev_link_t *);
+static void aha152x_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list;
 static dev_info_t dev_info = "aha152x_cs";
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
        cs_error(link->handle, RegisterClient, ret);
-       aha152x_detach(link);
+       aha152x_detach(link->handle);
        return NULL;
     }
     
 
 /*====================================================================*/
 
-static void aha152x_detach(dev_link_t *link)
+static void aha152x_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
 
     DEBUG(0, "aha152x_detach(0x%p)\n", link);
     if (link->state & DEV_CONFIG)
        aha152x_release_cs(link);
 
-    if (link->handle)
-       pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, free bits */
     *linkp = link->next;
     kfree(link->priv);
     DEBUG(0, "aha152x_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-       link->state &= ~DEV_PRESENT;
-       if (link->state & DEV_CONFIG)
-           aha152x_release_cs(link);
-       break;
     case CS_EVENT_CARD_INSERTION:
        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        aha152x_config_cs(link);
        },
        .attach         = aha152x_attach,
        .event          = aha152x_event,
-       .detach         = aha152x_detach,
+       .remove         = aha152x_detach,
        .id_table       = aha152x_ids,
        .suspend        = aha152x_suspend,
        .resume         = aha152x_resume,
 
                        event_callback_args_t *args);
 
 static dev_link_t *fdomain_attach(void);
-static void fdomain_detach(dev_link_t *);
+static void fdomain_detach(struct pcmcia_device *p_dev);
 
 
 static dev_link_t *dev_list = NULL;
     ret = pcmcia_register_client(&link->handle, &client_reg);
     if (ret != 0) {
        cs_error(link->handle, RegisterClient, ret);
-       fdomain_detach(link);
+       fdomain_detach(link->handle);
        return NULL;
     }
     
 
 /*====================================================================*/
 
-static void fdomain_detach(dev_link_t *link)
+static void fdomain_detach(struct pcmcia_device *p_dev)
 {
+    dev_link_t *link = dev_to_instance(p_dev);
     dev_link_t **linkp;
 
     DEBUG(0, "fdomain_detach(0x%p)\n", link);
     if (link->state & DEV_CONFIG)
        fdomain_release(link);
 
-    if (link->handle)
-       pcmcia_deregister_client(link->handle);
-    
     /* Unlink device structure, free bits */
     *linkp = link->next;
     kfree(link->priv);
     DEBUG(1, "fdomain_event(0x%06x)\n", event);
     
     switch (event) {
-    case CS_EVENT_CARD_REMOVAL:
-       link->state &= ~DEV_PRESENT;
-       if (link->state & DEV_CONFIG)
-           fdomain_release(link);
-       break;
     case CS_EVENT_CARD_INSERTION:
        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        fdomain_config(link);
        },
        .attach         = fdomain_attach,
        .event          = fdomain_event,
-       .detach         = fdomain_detach,
+       .remove         = fdomain_detach,
        .id_table       = fdomain_ids,
        .suspend        = fdomain_suspend,
        .resume         = fdomain_resume,
 
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != CS_SUCCESS) {
                cs_error(link->handle, RegisterClient, ret);
-               nsp_cs_detach(link);
+               nsp_cs_detach(link->handle);
                return NULL;
        }
 
     structures are freed.  Otherwise, the structures will be freed
     when the device is released.
 ======================================================================*/
-static void nsp_cs_detach(dev_link_t *link)
+static void nsp_cs_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        dev_link_t **linkp;
 
        nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);
                return;
        }
 
-       if (link->state & DEV_CONFIG)
+       if (link->state & DEV_CONFIG) {
+               ((scsi_info_t *)link->priv)->stop = 1;
                nsp_cs_release(link);
-
-       /* Break the link with Card Services */
-       if (link->handle) {
-               pcmcia_deregister_client(link->handle);
        }
 
        /* Unlink device structure, free bits */
        nsp_dbg(NSP_DEBUG_INIT, "in, event=0x%08x", event);
 
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               nsp_dbg(NSP_DEBUG_INIT, "event: remove");
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG) {
-                       ((scsi_info_t *)link->priv)->stop = 1;
-                       nsp_cs_release(link);
-               }
-               break;
-
        case CS_EVENT_CARD_INSERTION:
                nsp_dbg(NSP_DEBUG_INIT, "event: insert");
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        },
        .attach         = nsp_cs_attach,
        .event          = nsp_cs_event,
-       .detach         = nsp_cs_detach,
+       .remove         = nsp_cs_detach,
        .id_table       = nsp_cs_ids,
        .suspend        = nsp_cs_suspend,
        .resume         = nsp_cs_resume,
 
 
 /* Card service functions */
 static dev_link_t *nsp_cs_attach (void);
-static void        nsp_cs_detach (dev_link_t *link);
+static void        nsp_cs_detach (struct pcmcia_device *p_dev);
 static void        nsp_cs_release(dev_link_t *link);
 static void        nsp_cs_config (dev_link_t *link);
 static int         nsp_cs_event  (event_t event, int priority, event_callback_args_t *args);
 
 static int qlogic_event(event_t event, int priority, event_callback_args_t * args);
 
 static dev_link_t *qlogic_attach(void);
-static void qlogic_detach(dev_link_t *);
+static void qlogic_detach(struct pcmcia_device *p_dev);
 
 
 static dev_link_t *dev_list = NULL;
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != 0) {
                cs_error(link->handle, RegisterClient, ret);
-               qlogic_detach(link);
+               qlogic_detach(link->handle);
                return NULL;
        }
 
 
 /*====================================================================*/
 
-static void qlogic_detach(dev_link_t * link)
+static void qlogic_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        dev_link_t **linkp;
 
        DEBUG(0, "qlogic_detach(0x%p)\n", link);
        if (link->state & DEV_CONFIG)
                qlogic_release(link);
 
-       if (link->handle)
-               pcmcia_deregister_client(link->handle);
-
        /* Unlink device structure, free bits */
        *linkp = link->next;
        kfree(link->priv);
        DEBUG(1, "qlogic_event(0x%06x)\n", event);
 
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG)
-                       qlogic_release(link);
-               break;
        case CS_EVENT_CARD_INSERTION:
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                qlogic_config(link);
        },
        .attach         = qlogic_attach,
        .event          = qlogic_event,
-       .detach         = qlogic_detach,
+       .remove         = qlogic_detach,
        .id_table       = qlogic_ids,
        .suspend        = qlogic_suspend,
        .resume         = qlogic_resume,
 
        DEBUG(1, "SYM53C500_event(0x%06x)\n", event);
 
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG)
-                       SYM53C500_release(link);
-               break;
        case CS_EVENT_CARD_INSERTION:
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                SYM53C500_config(link);
 } /* SYM53C500_event */
 
 static void
-SYM53C500_detach(dev_link_t *link)
+SYM53C500_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        dev_link_t **linkp;
 
        DEBUG(0, "SYM53C500_detach(0x%p)\n", link);
        if (link->state & DEV_CONFIG)
                SYM53C500_release(link);
 
-       if (link->handle)
-               pcmcia_deregister_client(link->handle);
-
        /* Unlink device structure, free bits. */
        *linkp = link->next;
        kfree(link->priv);
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != 0) {
                cs_error(link->handle, RegisterClient, ret);
-               SYM53C500_detach(link);
+               SYM53C500_detach(link->handle);
                return NULL;
        }
 
        },
        .attach         = SYM53C500_attach,
        .event          = SYM53C500_event,
-       .detach         = SYM53C500_detach,
+       .remove         = SYM53C500_detach,
        .id_table       = sym53c500_ids,
        .suspend        = sym53c500_suspend,
        .resume         = sym53c500_resume,
 
 static dev_info_t dev_info = "serial_cs";
 
 static dev_link_t *serial_attach(void);
-static void serial_detach(dev_link_t *);
+static void serial_detach(struct pcmcia_device *p_dev);
 
 static dev_link_t *dev_list = NULL;
 
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != CS_SUCCESS) {
                cs_error(link->handle, RegisterClient, ret);
-               serial_detach(link);
+               serial_detach(link->handle);
                return NULL;
        }
 
 
 ======================================================================*/
 
-static void serial_detach(dev_link_t * link)
+static void serial_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        struct serial_info *info = link->priv;
        dev_link_t **linkp;
-       int ret;
 
        DEBUG(0, "serial_detach(0x%p)\n", link);
 
         */
        serial_remove(link);
 
-       if (link->handle) {
-               ret = pcmcia_deregister_client(link->handle);
-               if (ret != CS_SUCCESS)
-                       cs_error(link->handle, DeregisterClient, ret);
-       }
-
        /* Unlink device structure, free bits */
        *linkp = link->next;
        kfree(info);
        DEBUG(1, "serial_event(0x%06x)\n", event);
 
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               serial_remove(link);
-               break;
 
        case CS_EVENT_CARD_INSERTION:
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        },
        .attach         = serial_attach,
        .event          = serial_event,
-       .detach         = serial_detach,
+       .remove         = serial_detach,
        .id_table       = serial_ids,
        .suspend        = serial_suspend,
        .resume         = serial_resume,
 
 } ixj_info_t;
 
 static dev_link_t *ixj_attach(void);
-static void ixj_detach(dev_link_t *);
+static void ixj_detach(struct pcmcia_device *p_dev);
 static void ixj_config(dev_link_t * link);
 static void ixj_cs_release(dev_link_t * link);
 static int ixj_event(event_t event, int priority, event_callback_args_t * args);
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != CS_SUCCESS) {
                cs_error(link->handle, RegisterClient, ret);
-               ixj_detach(link);
+               ixj_detach(link->handle);
                return NULL;
        }
        return link;
 }
 
-static void ixj_detach(dev_link_t * link)
+static void ixj_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        dev_link_t **linkp;
-       int ret;
+
        DEBUG(0, "ixj_detach(0x%p)\n", link);
        for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
                if (*linkp == link)
        link->state &= ~DEV_RELEASE_PENDING;
        if (link->state & DEV_CONFIG)
                ixj_cs_release(link);
-       if (link->handle) {
-               ret = pcmcia_deregister_client(link->handle);
-               if (ret != CS_SUCCESS)
-                       cs_error(link->handle, DeregisterClient, ret);
-       }
+
        /* Unlink device structure, free bits */
        *linkp = link->next;
         kfree(link->priv);
        dev_link_t *link = args->client_data;
        DEBUG(1, "ixj_event(0x%06x)\n", event);
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG) {
-                       link->state |= DEV_RELEASE_PENDING;
-                       ixj_cs_release(link);
-               }
-               break;
        case CS_EVENT_CARD_INSERTION:
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                ixj_config(link);
        },
        .attach         = ixj_attach,
        .event          = ixj_event,
-       .detach         = ixj_detach,
+       .remove         = ixj_detach,
        .id_table       = ixj_ids,
        .suspend        = ixj_suspend,
        .resume         = ixj_resume,
 
        dev_node_t              node;
 } local_info_t;
 
+static void sl811_cs_release(dev_link_t * link);
+
 /*====================================================================*/
 
 static void release_platform_dev(struct device * dev)
 
 /*====================================================================*/
 
-static void sl811_cs_detach(dev_link_t *link)
+static void sl811_cs_detach(struct pcmcia_device *p_dev)
 {
+       dev_link_t *link = dev_to_instance(p_dev);
        dev_link_t **linkp;
 
        DBG(0, "sl811_cs_detach(0x%p)\n", link);
        if (*linkp == NULL)
                return;
 
-       /* Break the link with Card Services */
-       if (link->handle)
-               pcmcia_deregister_client(link->handle);
+       link->state &= ~DEV_PRESENT;
+       if (link->state & DEV_CONFIG)
+               sl811_cs_release(link);
 
        /* Unlink device structure, and free it */
        *linkp = link->next;
 
        DBG(0, "sl811_cs_release(0x%p)\n", link);
 
-       if (link->open) {
-               DBG(1, "sl811_cs: release postponed, '%s' still open\n",
-                   link->dev->dev_name);
-               link->state |= DEV_STALE_CONFIG;
-               return;
-       }
-
        /* Unlink the device chain */
        link->dev = NULL;
 
        if (link->irq.AssignedIRQ)
                pcmcia_release_irq(link->handle, &link->irq);
        link->state &= ~DEV_CONFIG;
-
-       if (link->state & DEV_STALE_LINK)
-               sl811_cs_detach(link);
 }
 
 static void sl811_cs_config(dev_link_t *link)
        DBG(1, "sl811_cs_event(0x%06x)\n", event);
 
        switch (event) {
-       case CS_EVENT_CARD_REMOVAL:
-               link->state &= ~DEV_PRESENT;
-               if (link->state & DEV_CONFIG)
-                       sl811_cs_release(link);
-               break;
-
        case CS_EVENT_CARD_INSERTION:
                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                sl811_cs_config(link);
        ret = pcmcia_register_client(&link->handle, &client_reg);
        if (ret != CS_SUCCESS) {
                cs_error(link->handle, RegisterClient, ret);
-               sl811_cs_detach(link);
+               sl811_cs_detach(link->handle);
                return NULL;
        }
 
        },
        .attach         = sl811_cs_attach,
        .event          = sl811_cs_event,
-       .detach         = sl811_cs_detach,
+       .remove         = sl811_cs_detach,
        .id_table       = sl811_ids,
        .suspend        = sl811_suspend,
        .resume         = sl811_resume,
 
                                 event_callback_args_t *);
        void                    (*detach)(dev_link_t *);
 
+       void (*remove)          (struct pcmcia_device *dev);
+
        int (*suspend)          (struct pcmcia_device *dev);
        int (*resume)           (struct pcmcia_device *dev);