]> err.no Git - linux-2.6/blobdiff - drivers/pnp/resource.c
PNP: make resource assignment functions return 0 (success) or -EBUSY (failure)
[linux-2.6] / drivers / pnp / resource.c
index 390b50096e30890f57d6cf6f55dc730d18013b47..391828c7f2079a6a0a3727ae5a1f7fdfdbbc4f2a 100644 (file)
@@ -98,13 +98,13 @@ int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
                int i;
 
                for (i = 0; i < 16; i++)
-                       if (test_bit(i, data->map))
+                       if (test_bit(i, data->map.bits))
                                pcibios_penalize_isa_irq(i, 0);
        }
 #endif
 
 #ifdef DEBUG
-       bitmap_scnprintf(buf, sizeof(buf), data->map, PNP_IRQ_NR);
+       bitmap_scnprintf(buf, sizeof(buf), data->map.bits, PNP_IRQ_NR);
        dev_dbg(&dev->dev, "  irq bitmask %s flags %#x\n", buf,
                data->flags);
 #endif
@@ -143,8 +143,11 @@ int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option,
                option->port = data;
 
        dev_dbg(&dev->dev, "  io  "
-               "min %#x max %#x align %d size %d flags %#x\n",
-               data->min, data->max, data->align, data->size, data->flags);
+               "min %#llx max %#llx align %lld size %lld flags %#x\n",
+               (unsigned long long) data->min,
+               (unsigned long long) data->max,
+               (unsigned long long) data->align,
+               (unsigned long long) data->size, data->flags);
        return 0;
 }
 
@@ -162,8 +165,11 @@ int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option,
                option->mem = data;
 
        dev_dbg(&dev->dev, "  mem "
-               "min %#x max %#x align %d size %d flags %#x\n",
-               data->min, data->max, data->align, data->size, data->flags);
+               "min %#llx max %#llx align %lld size %lld flags %#x\n",
+               (unsigned long long) data->min,
+               (unsigned long long) data->max,
+               (unsigned long long) data->align,
+               (unsigned long long) data->size, data->flags);
        return 0;
 }
 
@@ -237,7 +243,7 @@ void pnp_free_option(struct pnp_option *option)
        !((*(enda) < *(startb)) || (*(endb) < *(starta)))
 
 #define cannot_compare(flags) \
-((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED))
+((flags) & IORESOURCE_DISABLED)
 
 int pnp_check_port(struct pnp_dev *dev, struct resource *res)
 {
@@ -499,81 +505,37 @@ int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
 #endif
 }
 
-struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
-                                         unsigned int type, unsigned int num)
+int pnp_resource_type(struct resource *res)
 {
-       struct pnp_resource_table *res = dev->res;
-
-       switch (type) {
-       case IORESOURCE_IO:
-               if (num >= PNP_MAX_PORT)
-                       return NULL;
-               return &res->port[num];
-       case IORESOURCE_MEM:
-               if (num >= PNP_MAX_MEM)
-                       return NULL;
-               return &res->mem[num];
-       case IORESOURCE_IRQ:
-               if (num >= PNP_MAX_IRQ)
-                       return NULL;
-               return &res->irq[num];
-       case IORESOURCE_DMA:
-               if (num >= PNP_MAX_DMA)
-                       return NULL;
-               return &res->dma[num];
-       }
-       return NULL;
+       return res->flags & (IORESOURCE_IO  | IORESOURCE_MEM |
+                            IORESOURCE_IRQ | IORESOURCE_DMA);
 }
 
 struct resource *pnp_get_resource(struct pnp_dev *dev,
                                  unsigned int type, unsigned int num)
 {
        struct pnp_resource *pnp_res;
+       struct resource *res;
 
-       pnp_res = pnp_get_pnp_resource(dev, type, num);
-       if (pnp_res)
-               return &pnp_res->res;
-
+       list_for_each_entry(pnp_res, &dev->resources, list) {
+               res = &pnp_res->res;
+               if (pnp_resource_type(res) == type && num-- == 0)
+                       return res;
+       }
        return NULL;
 }
 EXPORT_SYMBOL(pnp_get_resource);
 
-static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev, int type)
+static struct pnp_resource *pnp_new_resource(struct pnp_dev *dev)
 {
        struct pnp_resource *pnp_res;
-       int i;
 
-       switch (type) {
-       case IORESOURCE_IO:
-               for (i = 0; i < PNP_MAX_PORT; i++) {
-                       pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, i);
-                       if (pnp_res && !pnp_resource_valid(&pnp_res->res))
-                               return pnp_res;
-               }
-               break;
-       case IORESOURCE_MEM:
-               for (i = 0; i < PNP_MAX_MEM; i++) {
-                       pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, i);
-                       if (pnp_res && !pnp_resource_valid(&pnp_res->res))
-                               return pnp_res;
-               }
-               break;
-       case IORESOURCE_IRQ:
-               for (i = 0; i < PNP_MAX_IRQ; i++) {
-                       pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, i);
-                       if (pnp_res && !pnp_resource_valid(&pnp_res->res))
-                               return pnp_res;
-               }
-               break;
-       case IORESOURCE_DMA:
-               for (i = 0; i < PNP_MAX_DMA; i++) {
-                       pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, i);
-                       if (pnp_res && !pnp_resource_valid(&pnp_res->res))
-                               return pnp_res;
-               }
-               break;
-       }
-       return NULL;
+       pnp_res = kzalloc(sizeof(struct pnp_resource), GFP_KERNEL);
+       if (!pnp_res)
+               return NULL;
+
+       list_add_tail(&pnp_res->list, &dev->resources);
+       return pnp_res;
 }
 
 struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
@@ -581,15 +543,10 @@ struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
 {
        struct pnp_resource *pnp_res;
        struct resource *res;
-       static unsigned char warned;
 
-       pnp_res = pnp_new_resource(dev, IORESOURCE_IRQ);
+       pnp_res = pnp_new_resource(dev);
        if (!pnp_res) {
-               if (!warned) {
-                       dev_err(&dev->dev, "can't add resource for IRQ %d\n",
-                               irq);
-                       warned = 1;
-               }
+               dev_err(&dev->dev, "can't add resource for IRQ %d\n", irq);
                return NULL;
        }
 
@@ -607,15 +564,10 @@ struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
 {
        struct pnp_resource *pnp_res;
        struct resource *res;
-       static unsigned char warned;
 
-       pnp_res = pnp_new_resource(dev, IORESOURCE_DMA);
+       pnp_res = pnp_new_resource(dev);
        if (!pnp_res) {
-               if (!warned) {
-                       dev_err(&dev->dev, "can't add resource for DMA %d\n",
-                               dma);
-                       warned = 1;
-               }
+               dev_err(&dev->dev, "can't add resource for DMA %d\n", dma);
                return NULL;
        }
 
@@ -634,16 +586,12 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
 {
        struct pnp_resource *pnp_res;
        struct resource *res;
-       static unsigned char warned;
 
-       pnp_res = pnp_new_resource(dev, IORESOURCE_IO);
+       pnp_res = pnp_new_resource(dev);
        if (!pnp_res) {
-               if (!warned) {
-                       dev_err(&dev->dev, "can't add resource for IO "
-                               "%#llx-%#llx\n",(unsigned long long) start,
-                               (unsigned long long) end);
-                       warned = 1;
-               }
+               dev_err(&dev->dev, "can't add resource for IO %#llx-%#llx\n",
+                       (unsigned long long) start,
+                       (unsigned long long) end);
                return NULL;
        }
 
@@ -663,16 +611,12 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
 {
        struct pnp_resource *pnp_res;
        struct resource *res;
-       static unsigned char warned;
 
-       pnp_res = pnp_new_resource(dev, IORESOURCE_MEM);
+       pnp_res = pnp_new_resource(dev);
        if (!pnp_res) {
-               if (!warned) {
-                       dev_err(&dev->dev, "can't add resource for MEM "
-                               "%#llx-%#llx\n",(unsigned long long) start,
-                               (unsigned long long) end);
-                       warned = 1;
-               }
+               dev_err(&dev->dev, "can't add resource for MEM %#llx-%#llx\n",
+                       (unsigned long long) start,
+                       (unsigned long long) end);
                return NULL;
        }
 
@@ -686,6 +630,68 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
        return pnp_res;
 }
 
+static int pnp_possible_option(struct pnp_option *option, int type,
+                              resource_size_t start, resource_size_t size)
+{
+       struct pnp_option *tmp;
+       struct pnp_port *port;
+       struct pnp_mem *mem;
+       struct pnp_irq *irq;
+       struct pnp_dma *dma;
+
+       if (!option)
+               return 0;
+
+       for (tmp = option; tmp; tmp = tmp->next) {
+               switch (type) {
+               case IORESOURCE_IO:
+                       for (port = tmp->port; port; port = port->next) {
+                               if (port->min == start && port->size == size)
+                                       return 1;
+                       }
+                       break;
+               case IORESOURCE_MEM:
+                       for (mem = tmp->mem; mem; mem = mem->next) {
+                               if (mem->min == start && mem->size == size)
+                                       return 1;
+                       }
+                       break;
+               case IORESOURCE_IRQ:
+                       for (irq = tmp->irq; irq; irq = irq->next) {
+                               if (start < PNP_IRQ_NR &&
+                                   test_bit(start, irq->map.bits))
+                                       return 1;
+                       }
+                       break;
+               case IORESOURCE_DMA:
+                       for (dma = tmp->dma; dma; dma = dma->next) {
+                               if (dma->map & (1 << start))
+                                       return 1;
+                       }
+                       break;
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * Determine whether the specified resource is a possible configuration
+ * for this device.
+ */
+int pnp_possible_config(struct pnp_dev *dev, int type, resource_size_t start,
+                       resource_size_t size)
+{
+       if (pnp_possible_option(dev->independent, type, start, size))
+               return 1;
+
+       if (pnp_possible_option(dev->dependent, type, start, size))
+               return 1;
+
+       return 0;
+}
+EXPORT_SYMBOL(pnp_possible_config);
+
 /* format is: pnp_reserve_irq=irq1[,irq2] .... */
 static int __init pnp_setup_reserve_irq(char *str)
 {