pcmcia: deprecate CS_NO_CARD
[safe/jmp/linux-2.6] / drivers / pcmcia / pcmcia_resource.c
index 4884a18..3e01385 100644 (file)
@@ -44,16 +44,17 @@ static u8 pcmcia_used_irq[NR_IRQS];
 #endif
 
 
-#ifdef DEBUG
+#ifdef CONFIG_PCMCIA_DEBUG
 extern int ds_pc_debug;
 
 #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
 
 
@@ -168,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;
@@ -191,90 +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;
-
-
-#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;
-                       if (s->io[0].res) {
-                               config->BasePort1 = s->io[0].res->start;
-                               config->NumPorts1 = s->io[0].res->end - config->BasePort1 + 1;
-                       }
-               }
-               return CS_SUCCESS;
-       }
-#endif
-
-       if (p_dev) {
-               c = p_dev->function_config;
-               config->Function = p_dev->func;
-       } else {
-               c = NULL;
-               config->Function = 0;
-       }
-
-       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;
-       }
-
-       config->Attributes = c->Attributes | CONF_VALID_CLIENT;
-       config->Vcc = s->socket.Vcc;
-       config->Vpp1 = config->Vpp2 = s->socket.Vpp;
-       config->IntType = c->IntType;
-       config->ConfigBase = c->ConfigBase;
-       config->Status = c->Status;
-       config->Pin = c->Pin;
-       config->Copy = c->Copy;
-       config->Option = c->Option;
-       config->ExtStatus = c->ExtStatus;
-       config->Present = 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,
@@ -284,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;
@@ -304,7 +226,7 @@ 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);
 
@@ -319,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);
 
@@ -335,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);
 
@@ -354,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;
 
@@ -369,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 };
@@ -406,7 +336,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
                }
        }
 
-       return CS_SUCCESS;
+       return 0;
 } /* modify_configuration */
 EXPORT_SYMBOL(pcmcia_modify_configuration);
 
@@ -441,7 +371,7 @@ int pcmcia_release_configuration(struct pcmcia_device *p_dev)
                        }
        }
 
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_release_configuration */
 
 
@@ -475,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 */
 
 
@@ -507,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 */
 
 
@@ -536,7 +466,7 @@ int pcmcia_release_window(window_handle_t win)
 
        win->magic = 0;
 
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_release_window */
 EXPORT_SYMBOL(pcmcia_release_window);
 
@@ -551,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;
@@ -651,7 +586,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
 
        c->state |= CONFIG_LOCKED;
        p_dev->_locked = 1;
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_request_configuration */
 EXPORT_SYMBOL(pcmcia_request_configuration);
 
@@ -667,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;
@@ -697,7 +632,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)
        c->io = *req;
        c->state |= CONFIG_IO_REQ;
        p_dev->_io = 1;
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_request_io */
 EXPORT_SYMBOL(pcmcia_request_io);
 
@@ -727,7 +662,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
        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;
@@ -802,8 +737,10 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
        /* 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;
-               printk(KERN_WARNING "pcmcia: request for exclusive IRQ could not be fulfilled.\n");
-               printk(KERN_WARNING "pcmcia: the driver needs updating to supported shared IRQ lines.\n");
+               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;
@@ -816,7 +753,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)
        pcmcia_used_irq[irq]++;
 #endif
 
-       return CS_SUCCESS;
+       return 0;
 } /* pcmcia_request_irq */
 EXPORT_SYMBOL(pcmcia_request_irq);
 
@@ -834,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;
 
@@ -856,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;
@@ -897,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);
 
@@ -909,3 +846,79 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) {
                pcmcia_release_window(p_dev->win);
 }
 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);