X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fpnp%2Fquirks.c;h=1ff3bb585ab2b0b5f0bb88f8477fe334c26c726a;hb=5c2cec143ac54c1960e54bc320fa7d13ac8e0f4a;hp=37993206ae5dd149d98672345ef5d16c6c21743c;hpb=6f58d79598c184dc4f18ceddfaa5fa7483bce0a5;p=linux-2.6 diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index 37993206ae..1ff3bb585a 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -49,8 +49,11 @@ static void quirk_awe32_resources(struct pnp_dev *dev) port2->max += 0x400; port3->min += 0x800; port3->max += 0x800; + dev_info(&dev->dev, + "AWE32 quirk - added ioports 0x%lx and 0x%lx\n", + (unsigned long)port2->min, + (unsigned long)port3->min); } - printk(KERN_INFO "pnp: AWE32 quirk - adding two ports\n"); } static void quirk_cmi8330_resources(struct pnp_dev *dev) @@ -73,7 +76,8 @@ static void quirk_cmi8330_resources(struct pnp_dev *dev) IORESOURCE_DMA_8BIT) dma->map = 0x000A; } - printk(KERN_INFO "pnp: CMI8330 quirk - fixing interrupts and dma\n"); + dev_info(&dev->dev, "CMI8330 quirk - forced possible IRQs to 5, 7, 10 " + "and DMA channels to 1, 3\n"); } static void quirk_sb16audio_resources(struct pnp_dev *dev) @@ -104,16 +108,123 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev) changed = 1; } if (changed) - printk(KERN_INFO - "pnp: SB audio device quirk - increasing port range\n"); + dev_info(&dev->dev, "SB audio device quirk - increased port range\n"); } +static struct pnp_option *quirk_isapnp_mpu_options(struct pnp_dev *dev) +{ + struct pnp_option *head = NULL; + struct pnp_option *prev = NULL; + struct pnp_option *res; + + /* + * Build a functional IRQ-less variant of each MPU option. + */ + + for (res = dev->dependent; res; res = res->next) { + struct pnp_option *curr; + struct pnp_port *port; + struct pnp_port *copy; + + port = res->port; + if (!port || !res->irq) + continue; + + copy = pnp_alloc(sizeof *copy); + if (!copy) + break; + + copy->min = port->min; + copy->max = port->max; + copy->align = port->align; + copy->size = port->size; + copy->flags = port->flags; + + curr = pnp_build_option(PNP_RES_PRIORITY_FUNCTIONAL); + if (!curr) { + kfree(copy); + break; + } + curr->port = copy; + + if (prev) + prev->next = curr; + else + head = curr; + prev = curr; + } + if (head) + dev_info(&dev->dev, "adding IRQ-less MPU options\n"); + + return head; +} + +static void quirk_ad1815_mpu_resources(struct pnp_dev *dev) +{ + struct pnp_option *res; + struct pnp_irq *irq; + + /* + * Distribute the independent IRQ over the dependent options + */ + + res = dev->independent; + if (!res) + return; + + irq = res->irq; + if (!irq || irq->next) + return; + + res = dev->dependent; + if (!res) + return; + + while (1) { + struct pnp_irq *copy; + + copy = pnp_alloc(sizeof *copy); + if (!copy) + break; + + memcpy(copy->map, irq->map, sizeof copy->map); + copy->flags = irq->flags; + + copy->next = res->irq; /* Yes, this is NULL */ + res->irq = copy; + + if (!res->next) + break; + res = res->next; + } + kfree(irq); + + res->next = quirk_isapnp_mpu_options(dev); + + res = dev->independent; + res->irq = NULL; +} + +static void quirk_isapnp_mpu_resources(struct pnp_dev *dev) +{ + struct pnp_option *res; + + res = dev->dependent; + if (!res) + return; + + while (res->next) + res = res->next; + + res->next = quirk_isapnp_mpu_options(dev); +} #include static void quirk_system_pci_resources(struct pnp_dev *dev) { struct pci_dev *pdev = NULL; + struct resource *res; resource_size_t pnp_start, pnp_end, pci_start, pci_end; int i, j; @@ -134,13 +245,15 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) pci_start = pci_resource_start(pdev, i); pci_end = pci_resource_end(pdev, i); - for (j = 0; j < PNP_MAX_MEM; j++) { - if (!pnp_mem_valid(dev, j) || - pnp_mem_len(dev, j) == 0) + for (j = 0; + (res = pnp_get_resource(dev, IORESOURCE_MEM, j)); + j++) { + if (res->flags & IORESOURCE_UNSET || + (res->start == 0 && res->end == 0)) continue; - pnp_start = pnp_mem_start(dev, j); - pnp_end = pnp_mem_end(dev, j); + pnp_start = res->start; + pnp_end = res->end; /* * If the PNP region doesn't overlap the PCI @@ -173,7 +286,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev) pci_name(pdev), i, (unsigned long long) pci_start, (unsigned long long) pci_end); - pnp_mem_flags(dev, j) = 0; + res->flags |= IORESOURCE_DISABLED; } } } @@ -199,6 +312,11 @@ static struct pnp_fixup pnp_fixups[] = { {"CTL0043", quirk_sb16audio_resources}, {"CTL0044", quirk_sb16audio_resources}, {"CTL0045", quirk_sb16audio_resources}, + /* Add IRQ-less MPU options */ + {"ADS7151", quirk_ad1815_mpu_resources}, + {"ADS7181", quirk_isapnp_mpu_resources}, + {"AZT0002", quirk_isapnp_mpu_resources}, + /* PnP resources that might overlap PCI BARs */ {"PNP0c01", quirk_system_pci_resources}, {"PNP0c02", quirk_system_pci_resources}, {""} @@ -206,20 +324,15 @@ static struct pnp_fixup pnp_fixups[] = { void pnp_fixup_device(struct pnp_dev *dev) { - int i = 0; - void (*quirk)(struct pnp_dev *); - - while (*pnp_fixups[i].id) { - if (compare_pnp_id(dev->id, pnp_fixups[i].id)) { - quirk = pnp_fixups[i].quirk_function; + struct pnp_fixup *f; + for (f = pnp_fixups; *f->id; f++) { + if (!compare_pnp_id(dev->id, f->id)) + continue; #ifdef DEBUG - dev_dbg(&dev->dev, "calling quirk 0x%p", quirk); - print_fn_descriptor_symbol(": %s()\n", - (unsigned long) *quirk); + dev_dbg(&dev->dev, "%s: calling ", f->id); + print_fn_descriptor_symbol("%s\n", f->quirk_function); #endif - (*quirk)(dev); - } - i++; + f->quirk_function(dev); } }