pcmcia: deprecate CS_NO_CARD
[safe/jmp/linux-2.6] / drivers / pcmcia / pcmcia_resource.c
index dbf167c..3e01385 100644 (file)
 #include <linux/pci.h>
 #include <linux/device.h>
 
-#define IN_CARD_SERVICES
 #include <pcmcia/cs_types.h>
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
-#include <pcmcia/bulkmem.h>
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/ds.h>
@@ -46,17 +44,17 @@ static u8 pcmcia_used_irq[NR_IRQS];
 #endif
 
 
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
 extern int ds_pc_debug;
-#define cs_socket_name(skt)    ((skt)->dev.class_id)
 
 #define ds_dbg(skt, lvl, fmt, arg...) do {                     \
        if (ds_pc_debug >= lvl)                                 \
-               printk(KERN_DEBUG "pcmcia_resource: %s: " fmt,  \
-                       cs_socket_name(skt) , ## arg);          \
+               dev_printk(KERN_DEBUG, &skt->dev,               \
+                          "pcmcia_resource: " fmt,             \
+                          ## arg);                             \
 } while (0)
 #else
-#define ds_dbg(lvl, fmt, arg...) do { } while (0)
+#define ds_dbg(skt, lvl, fmt, arg...) do { } while (0)
 #endif
 
 
@@ -66,29 +64,28 @@ extern int ds_pc_debug;
  * Special stuff for managing IO windows, because they are scarce
  */
 
-static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
-                         ioaddr_t num, u_int lines)
+static int alloc_io_space(struct pcmcia_socket *s, u_int attr,
+                         unsigned int *base, unsigned int num, u_int lines)
 {
        int i;
-       kio_addr_t try, align;
+       unsigned int try, align;
 
        align = (*base) ? (lines ? 1<<lines : 0) : 1;
        if (align && (align < num)) {
                if (*base) {
-                       ds_dbg(s, 0, "odd IO request: num %#x align %#lx\n",
+                       ds_dbg(s, 0, "odd IO request: num %#x align %#x\n",
                               num, align);
                        align = 0;
                } else
                        while (align && (align < num)) align <<= 1;
        }
        if (*base & ~(align-1)) {
-               ds_dbg(s, 0, "odd IO request: base %#x align %#lx\n",
+               ds_dbg(s, 0, "odd IO request: base %#x align %#x\n",
                       *base, align);
                align = 0;
        }
        if ((s->features & SS_CAP_STATIC_MAP) && s->io_offset) {
                *base = s->io_offset | (*base & 0x0fff);
-               s->io[0].res->flags = (s->io[0].res->flags & ~IORESOURCE_BITS) | (attr & IORESOURCE_BITS);
                return 0;
        }
        /* Check for an already-allocated window that must conflict with
@@ -96,7 +93,7 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
         * potential conflicts, just the most obvious ones.
         */
        for (i = 0; i < MAX_IO_WIN; i++)
-               if ((s->io[i].res) &&
+               if ((s->io[i].res) && *base &&
                    ((s->io[i].res->start & (align-1)) == *base))
                        return 1;
        for (i = 0; i < MAX_IO_WIN; i++) {
@@ -134,8 +131,8 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
 } /* alloc_io_space */
 
 
-static void release_io_space(struct pcmcia_socket *s, ioaddr_t base,
-                            ioaddr_t num)
+static void release_io_space(struct pcmcia_socket *s, unsigned int base,
+                            unsigned int num)
 {
        int i;
 
@@ -172,7 +169,7 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
        u_char val;
 
        if (!p_dev || !p_dev->function_config)
-               return CS_NO_CARD;
+               return -EINVAL;
 
        s = p_dev->socket;
        c = p_dev->function_config;
@@ -195,76 +192,11 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,
                return CS_BAD_ARGS;
                break;
        }
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_access_configuration_register */
 EXPORT_SYMBOL(pcmcia_access_configuration_register);
 
 
-int pccard_get_configuration_info(struct pcmcia_socket *s,
-                                 struct pcmcia_device *p_dev,
-                                 config_info_t *config)
-{
-       config_t *c;
-
-       if (!(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
-
-       config->Function = p_dev->func;
-
-#ifdef CONFIG_CARDBUS
-       if (s->state & SOCKET_CARDBUS) {
-               memset(config, 0, sizeof(config_info_t));
-               config->Vcc = s->socket.Vcc;
-               config->Vpp1 = config->Vpp2 = s->socket.Vpp;
-               config->Option = s->cb_dev->subordinate->number;
-               if (s->state & SOCKET_CARDBUS_CONFIG) {
-                       config->Attributes = CONF_VALID_CLIENT;
-                       config->IntType = INT_CARDBUS;
-                       config->AssignedIRQ = s->irq.AssignedIRQ;
-                       if (config->AssignedIRQ)
-                               config->Attributes |= CONF_ENABLE_IRQ;
-                       config->BasePort1 = s->io[0].res->start;
-                       config->NumPorts1 = s->io[0].res->end - config->BasePort1 + 1;
-               }
-               return CS_SUCCESS;
-       }
-#endif
-
-       c = (p_dev) ? p_dev->function_config : NULL;
-
-       if ((c == NULL) || !(c->state & CONFIG_LOCKED)) {
-               config->Attributes = 0;
-               config->Vcc = s->socket.Vcc;
-               config->Vpp1 = config->Vpp2 = s->socket.Vpp;
-               return CS_SUCCESS;
-       }
-
-       /* !!! This is a hack !!! */
-       memcpy(&config->Attributes, &c->Attributes, sizeof(config_t));
-       config->Attributes |= CONF_VALID_CLIENT;
-       config->CardValues = c->CardValues;
-       config->IRQAttributes = c->irq.Attributes;
-       config->AssignedIRQ = s->irq.AssignedIRQ;
-       config->BasePort1 = c->io.BasePort1;
-       config->NumPorts1 = c->io.NumPorts1;
-       config->Attributes1 = c->io.Attributes1;
-       config->BasePort2 = c->io.BasePort2;
-       config->NumPorts2 = c->io.NumPorts2;
-       config->Attributes2 = c->io.Attributes2;
-       config->IOAddrLines = c->io.IOAddrLines;
-
-       return CS_SUCCESS;
-} /* pccard_get_configuration_info */
-
-int pcmcia_get_configuration_info(struct pcmcia_device *p_dev,
-                                 config_info_t *config)
-{
-       return pccard_get_configuration_info(p_dev->socket, p_dev,
-                                            config);
-}
-EXPORT_SYMBOL(pcmcia_get_configuration_info);
-
-
 /** pcmcia_get_window
  */
 int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle,
@@ -274,7 +206,7 @@ int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle,
        int w;
 
        if (!s || !(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
+               return -ENODEV;
        for (w = idx; w < MAX_WIN; w++)
                if (s->state & SOCKET_WIN_REQ(w))
                        break;
@@ -294,79 +226,11 @@ int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle,
        if (win->ctl.flags & MAP_USE_WAIT)
                req->Attributes |= WIN_USE_WAIT;
        *handle = win;
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_get_window */
 EXPORT_SYMBOL(pcmcia_get_window);
 
 
-/** pccard_get_status
- *
- * Get the current socket state bits.  We don't support the latched
- * SocketState yet: I haven't seen any point for it.
- */
-
-int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev,
-                     cs_status_t *status)
-{
-       config_t *c;
-       int val;
-
-       s->ops->get_status(s, &val);
-       status->CardState = status->SocketState = 0;
-       status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0;
-       status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0;
-       status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0;
-       status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0;
-       if (s->state & SOCKET_SUSPEND)
-               status->CardState |= CS_EVENT_PM_SUSPEND;
-       if (!(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
-
-       c = (p_dev) ? p_dev->function_config : NULL;
-
-       if ((c != NULL) && (c->state & CONFIG_LOCKED) &&
-           (c->IntType & (INT_MEMORY_AND_IO | INT_ZOOMED_VIDEO))) {
-               u_char reg;
-               if (c->CardValues & PRESENT_PIN_REPLACE) {
-                       pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, &reg);
-                       status->CardState |=
-                               (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0;
-                       status->CardState |=
-                               (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0;
-                       status->CardState |=
-                               (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0;
-                       status->CardState |=
-                               (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0;
-               } else {
-                       /* No PRR?  Then assume we're always ready */
-                       status->CardState |= CS_EVENT_READY_CHANGE;
-               }
-               if (c->CardValues & PRESENT_EXT_STATUS) {
-                       pcmcia_read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, &reg);
-                       status->CardState |=
-                               (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0;
-               }
-               return CS_SUCCESS;
-       }
-       status->CardState |=
-               (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0;
-       status->CardState |=
-               (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0;
-       status->CardState |=
-               (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0;
-       status->CardState |=
-               (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0;
-       return CS_SUCCESS;
-} /* pccard_get_status */
-
-int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status)
-{
-       return pccard_get_status(p_dev->socket, p_dev, status);
-}
-EXPORT_SYMBOL(pcmcia_get_status);
-
-
-
 /** pcmcia_get_mem_page
  *
  * Change the card address of an already open memory window.
@@ -377,7 +241,7 @@ int pcmcia_get_mem_page(window_handle_t win, memreq_t *req)
                return CS_BAD_HANDLE;
        req->Page = 0;
        req->CardOffset = win->ctl.card_start;
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_get_mem_page */
 EXPORT_SYMBOL(pcmcia_get_mem_page);
 
@@ -393,7 +257,7 @@ int pcmcia_map_mem_page(window_handle_t win, memreq_t *req)
        win->ctl.card_start = req->CardOffset;
        if (s->ops->set_mem_map(s, &win->ctl) != 0)
                return CS_BAD_OFFSET;
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_map_mem_page */
 EXPORT_SYMBOL(pcmcia_map_mem_page);
 
@@ -412,7 +276,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
        c = p_dev->function_config;
 
        if (!(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
+               return -ENODEV;
        if (!(c->state & CONFIG_LOCKED))
                return CS_CONFIGURATION_LOCKED;
 
@@ -427,20 +291,28 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
                s->ops->set_socket(s, &s->socket);
        }
 
-       if (mod->Attributes & CONF_VCC_CHANGE_VALID)
-               return CS_BAD_VCC;
+       if (mod->Attributes & CONF_VCC_CHANGE_VALID) {
+               ds_dbg(s, 0, "changing Vcc is not allowed at this time\n");
+               return -EINVAL;
+       }
 
        /* We only allow changing Vpp1 and Vpp2 to the same value */
        if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
            (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
                if (mod->Vpp1 != mod->Vpp2)
-                       return CS_BAD_VPP;
+                       ds_dbg(s, 0, "Vpp1 and Vpp2 must be the same\n");
+                       return -EINVAL;
                s->socket.Vpp = mod->Vpp1;
-               if (s->ops->set_socket(s, &s->socket))
-                       return CS_BAD_VPP;
+               if (s->ops->set_socket(s, &s->socket)) {
+                       dev_printk(KERN_WARNING, &s->dev,
+                                  "Unable to set VPP\n");
+                       return -EIO;
+               }
        } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
-                  (mod->Attributes & CONF_VPP2_CHANGE_VALID))
-               return CS_BAD_VPP;
+                  (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
+               ds_dbg(s, 0, "changing Vcc is not allowed at this time\n");
+               return -EINVAL;
+       }
 
        if (mod->Attributes & CONF_IO_CHANGE_WIDTH) {
                pccard_io_map io_off = { 0, 0, 0, 0, 1 };
@@ -464,7 +336,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
                }
        }
 
-       return CS_SUCCESS;
+       return 0;
 } /* modify_configuration */
 EXPORT_SYMBOL(pcmcia_modify_configuration);
 
@@ -476,8 +348,8 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
        config_t *c = p_dev->function_config;
        int i;
 
-       if (p_dev->p_state & CLIENT_CONFIG_LOCKED) {
-               p_dev->p_state &= ~CLIENT_CONFIG_LOCKED;
+       if (p_dev->_locked) {
+               p_dev->_locked = 0;
                if (--(s->lock_count) == 0) {
                        s->socket.flags = SS_OUTPUT_ENA;   /* Is this correct? */
                        s->socket.Vpp = 0;
@@ -499,7 +371,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
                        }
        }
 
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_release_configuration */
 
 
@@ -516,10 +388,10 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
        struct pcmcia_socket *s = p_dev->socket;
        config_t *c = p_dev->function_config;
 
-       if (!(p_dev->p_state & CLIENT_IO_REQ))
+       if (!p_dev->_io )
                return CS_BAD_HANDLE;
 
-       p_dev->p_state &= ~CLIENT_IO_REQ;
+       p_dev->_io = 0;
 
        if ((c->io.BasePort1 != req->BasePort1) ||
            (c->io.NumPorts1 != req->NumPorts1) ||
@@ -533,7 +405,7 @@ static int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req)
        if (req->NumPorts2)
                release_io_space(s, req->BasePort2, req->NumPorts2);
 
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_release_io */
 
 
@@ -542,9 +414,9 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
        struct pcmcia_socket *s = p_dev->socket;
        config_t *c= p_dev->function_config;
 
-       if (!(p_dev->p_state & CLIENT_IRQ_REQ))
+       if (!p_dev->_irq)
                return CS_BAD_HANDLE;
-       p_dev->p_state &= ~CLIENT_IRQ_REQ;
+       p_dev->_irq = 0;
 
        if (c->state & CONFIG_LOCKED)
                return CS_CONFIGURATION_LOCKED;
@@ -565,7 +437,7 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)
        pcmcia_used_irq[req->AssignedIRQ]--;
 #endif
 
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_release_irq */
 
 
@@ -576,7 +448,7 @@ int pcmcia_release_window(window_handle_t win)
        if ((win == NULL) || (win->magic != WINDOW_MAGIC))
                return CS_BAD_HANDLE;
        s = win->sock;
-       if (!(win->handle->p_state & CLIENT_WIN_REQ(win->index)))
+       if (!(win->handle->_win & CLIENT_WIN_REQ(win->index)))
                return CS_BAD_HANDLE;
 
        /* Shut down memory window */
@@ -590,11 +462,11 @@ int pcmcia_release_window(window_handle_t win)
                kfree(win->ctl.res);
                win->ctl.res = NULL;
        }
-       win->handle->p_state &= ~CLIENT_WIN_REQ(win->index);
+       win->handle->_win &= ~CLIENT_WIN_REQ(win->index);
 
        win->magic = 0;
 
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_release_window */
 EXPORT_SYMBOL(pcmcia_release_window);
 
@@ -609,18 +481,23 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
        pccard_io_map iomap;
 
        if (!(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
+               return -ENODEV;;
 
-       if (req->IntType & INT_CARDBUS)
-               return CS_UNSUPPORTED_MODE;
+       if (req->IntType & INT_CARDBUS) {
+               ds_dbg(p_dev->socket, 0, "IntType may not be INT_CARDBUS\n");
+               return -EINVAL;
+       }
        c = p_dev->function_config;
        if (c->state & CONFIG_LOCKED)
                return CS_CONFIGURATION_LOCKED;
 
        /* Do power control.  We don't allow changes in Vcc. */
        s->socket.Vpp = req->Vpp;
-       if (s->ops->set_socket(s, &s->socket))
-               return CS_BAD_VPP;
+       if (s->ops->set_socket(s, &s->socket)) {
+               dev_printk(KERN_WARNING, &s->dev,
+                          "Unable to set socket state\n");
+               return -EINVAL;
+       }
 
        /* Pick memory or I/O card, DMA mode, interrupt */
        c->IntType = req->IntType;
@@ -708,8 +585,8 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
        }
 
        c->state |= CONFIG_LOCKED;
-       p_dev->p_state |= CLIENT_CONFIG_LOCKED;
-       return CS_SUCCESS;
+       p_dev->_locked = 1;
+       return 0;
 } /* pcmcia_request_configuration */
 EXPORT_SYMBOL(pcmcia_request_configuration);
 
@@ -725,10 +602,10 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
        config_t *c;
 
        if (!(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
+               return -ENODEV;
 
        if (!req)
-               return CS_UNSUPPORTED_MODE;
+               return -EINVAL;
        c = p_dev->function_config;
        if (c->state & CONFIG_LOCKED)
                return CS_CONFIGURATION_LOCKED;
@@ -754,8 +631,8 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
 
        c->io = *req;
        c->state |= CONFIG_IO_REQ;
-       p_dev->p_state |= CLIENT_IO_REQ;
-       return CS_SUCCESS;
+       p_dev->_io = 1;
+       return 0;
 } /* pcmcia_request_io */
 EXPORT_SYMBOL(pcmcia_request_io);
 
@@ -771,7 +648,7 @@ EXPORT_SYMBOL(pcmcia_request_io);
  */
 
 #ifdef CONFIG_PCMCIA_PROBE
-static irqreturn_t test_action(int cpl, void *dev_id, struct pt_regs *regs)
+static irqreturn_t test_action(int cpl, void *dev_id)
 {
        return IRQ_NONE;
 }
@@ -782,16 +659,33 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
        struct pcmcia_socket *s = p_dev->socket;
        config_t *c;
        int ret = CS_IN_USE, irq = 0;
+       int type;
 
        if (!(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
+               return -ENODEV;
        c = p_dev->function_config;
        if (c->state & CONFIG_LOCKED)
                return CS_CONFIGURATION_LOCKED;
        if (c->state & CONFIG_IRQ_REQ)
                return CS_IN_USE;
 
+       /* Decide what type of interrupt we are registering */
+       type = 0;
+       if (s->functions > 1)           /* All of this ought to be handled higher up */
+               type = IRQF_SHARED;
+       if (req->Attributes & IRQ_TYPE_DYNAMIC_SHARING)
+               type = IRQF_SHARED;
+
 #ifdef CONFIG_PCMCIA_PROBE
+
+#ifdef IRQ_NOAUTOEN
+       /* if the underlying IRQ infrastructure allows for it, only allocate
+        * the IRQ, but do not enable it
+        */
+       if (!(req->Attributes & IRQ_HANDLE_PRESENT))
+               type |= IRQ_NOAUTOEN;
+#endif /* IRQ_NOAUTOEN */
+
        if (s->irq.AssignedIRQ != 0) {
                /* If the interrupt is already assigned, it must be the same */
                irq = s->irq.AssignedIRQ;
@@ -816,9 +710,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
                         * marked as used by the kernel resource management core */
                        ret = request_irq(irq,
                                          (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action,
-                                         ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
-                                          (s->functions > 1) ||
-                                          (irq == s->pci_irq)) ? SA_SHIRQ : 0,
+                                         type,
                                          p_dev->devname,
                                          (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data);
                        if (!ret) {
@@ -833,30 +725,35 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
        if (ret && !s->irq.AssignedIRQ) {
                if (!s->pci_irq)
                        return ret;
+               type = IRQF_SHARED;
                irq = s->pci_irq;
        }
 
-       if (ret && req->Attributes & IRQ_HANDLE_PRESENT) {
-               if (request_irq(irq, req->Handler,
-                               ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
-                                (s->functions > 1) ||
-                                (irq == s->pci_irq)) ? SA_SHIRQ : 0,
-                               p_dev->devname, req->Instance))
+       if (ret && (req->Attributes & IRQ_HANDLE_PRESENT)) {
+               if (request_irq(irq, req->Handler, type,  p_dev->devname, req->Instance))
                        return CS_IN_USE;
        }
 
+       /* Make sure the fact the request type was overridden is passed back */
+       if (type == IRQF_SHARED && !(req->Attributes & IRQ_TYPE_DYNAMIC_SHARING)) {
+               req->Attributes |= IRQ_TYPE_DYNAMIC_SHARING;
+               dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: "
+                       "request for exclusive IRQ could not be fulfilled.\n");
+               dev_printk(KERN_WARNING, &p_dev->dev, "pcmcia: the driver "
+                       "needs updating to supported shared IRQ lines.\n");
+       }
        c->irq.Attributes = req->Attributes;
        s->irq.AssignedIRQ = req->AssignedIRQ = irq;
        s->irq.Config++;
 
        c->state |= CONFIG_IRQ_REQ;
-       p_dev->p_state |= CLIENT_IRQ_REQ;
+       p_dev->_irq = 1;
 
 #ifdef CONFIG_PCMCIA_PROBE
        pcmcia_used_irq[irq]++;
 #endif
 
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_request_irq */
 EXPORT_SYMBOL(pcmcia_request_irq);
 
@@ -874,7 +771,7 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
        int w;
 
        if (!(s->state & SOCKET_PRESENT))
-               return CS_NO_CARD;
+               return -ENODEV;
        if (req->Attributes & (WIN_PAGED | WIN_SHARED))
                return CS_BAD_ATTRIBUTE;
 
@@ -896,7 +793,7 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
        for (w = 0; w < MAX_WIN; w++)
                if (!(s->state & SOCKET_WIN_REQ(w))) break;
        if (w == MAX_WIN)
-               return CS_OUT_OF_RESOURCE;
+               return CS_IN_USE;
 
        win = &s->win[w];
        win->magic = WINDOW_MAGIC;
@@ -910,7 +807,7 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
                if (!win->ctl.res)
                        return CS_IN_USE;
        }
-       (*p_dev)->p_state |= CLIENT_WIN_REQ(w);
+       (*p_dev)->_win |= CLIENT_WIN_REQ(w);
 
        /* Configure the socket controller */
        win->ctl.map = w+1;
@@ -937,7 +834,7 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h
        }
        *wh = win;
 
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_request_window */
 EXPORT_SYMBOL(pcmcia_request_window);
 
@@ -945,9 +842,83 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) {
        pcmcia_release_configuration(p_dev);
        pcmcia_release_io(p_dev, &p_dev->io);
        pcmcia_release_irq(p_dev, &p_dev->irq);
-       if (&p_dev->win)
+       if (p_dev->win)
                pcmcia_release_window(p_dev->win);
-
-       p_dev->dev_node = NULL;
 }
 EXPORT_SYMBOL(pcmcia_disable_device);
+
+
+struct pcmcia_cfg_mem {
+       tuple_t tuple;
+       cisparse_t parse;
+       u8 buf[256];
+       cistpl_cftable_entry_t dflt;
+};
+
+/**
+ * pcmcia_loop_config() - loop over configuration options
+ * @p_dev:     the struct pcmcia_device which we need to loop for.
+ * @conf_check:        function to call for each configuration option.
+ *             It gets passed the struct pcmcia_device, the CIS data
+ *             describing the configuration option, and private data
+ *             being passed to pcmcia_loop_config()
+ * @priv_data: private data to be passed to the conf_check function.
+ *
+ * pcmcia_loop_config() loops over all configuration options, and calls
+ * the driver-specific conf_check() for each one, checking whether
+ * it is a valid one.
+ */
+int pcmcia_loop_config(struct pcmcia_device *p_dev,
+                      int      (*conf_check)   (struct pcmcia_device *p_dev,
+                                                cistpl_cftable_entry_t *cfg,
+                                                cistpl_cftable_entry_t *dflt,
+                                                unsigned int vcc,
+                                                void *priv_data),
+                      void *priv_data)
+{
+       struct pcmcia_cfg_mem *cfg_mem;
+
+       tuple_t *tuple;
+       int ret = -ENODEV;
+       unsigned int vcc;
+
+       cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL);
+       if (cfg_mem == NULL)
+               return -ENOMEM;
+
+       /* get the current Vcc setting */
+       vcc = p_dev->socket->socket.Vcc;
+
+       tuple = &cfg_mem->tuple;
+       tuple->TupleData = cfg_mem->buf;
+       tuple->TupleDataMax = 255;
+       tuple->TupleOffset = 0;
+       tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
+       tuple->Attributes = 0;
+
+       ret = pcmcia_get_first_tuple(p_dev, tuple);
+       while (!ret) {
+               cistpl_cftable_entry_t *cfg = &cfg_mem->parse.cftable_entry;
+
+               if (pcmcia_get_tuple_data(p_dev, tuple))
+                       goto next_entry;
+
+               if (pcmcia_parse_tuple(p_dev, tuple, &cfg_mem->parse))
+                       goto next_entry;
+
+               /* default values */
+               p_dev->conf.ConfigIndex = cfg->index;
+               if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
+                       cfg_mem->dflt = *cfg;
+
+               ret = conf_check(p_dev, cfg, &cfg_mem->dflt, vcc, priv_data);
+               if (!ret)
+                       break;
+
+next_entry:
+               ret = pcmcia_get_next_tuple(p_dev, tuple);
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(pcmcia_loop_config);