/* Two ranges conflict if one doesn't end before the other starts */ #define ranged_conflict(starta, enda, startb, endb) \
!((*(enda) < *(startb)) || (*(endb) < *(starta)))
/* if the resource doesn't exist, don't complain about it */ if (cannot_compare(res->flags)) return 1;
/* check if the resource is already in use, skip if the
* device is active because it itself may be in use */ if (!dev->active) { if (!request_region(*port, length(port, end), "pnp")) return 0;
release_region(*port, length(port, end));
}
/* check if the resource is reserved */ for (i = 0; i < 8; i++) { int rport = pnp_reserve_io[i << 1]; int rend = pnp_reserve_io[(i << 1) + 1] + rport - 1; if (ranged_conflict(port, end, &rport, &rend)) return 0;
}
/* check for internal conflicts */ for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) { if (tres != res && tres->flags & IORESOURCE_IO) {
tport = &tres->start;
tend = &tres->end; if (ranged_conflict(port, end, tport, tend)) return 0;
}
}
/* check for conflicts with other pnp devices */
pnp_for_each_dev(tdev) { if (tdev == dev) continue; for (i = 0;
(tres = pnp_get_resource(tdev, IORESOURCE_IO, i));
i++) { if (tres->flags & IORESOURCE_IO) { if (cannot_compare(tres->flags)) continue; if (tres->flags & IORESOURCE_WINDOW) continue;
tport = &tres->start;
tend = &tres->end; if (ranged_conflict(port, end, tport, tend)) return 0;
}
}
}
/* if the resource doesn't exist, don't complain about it */ if (cannot_compare(res->flags)) return 1;
/* check if the resource is already in use, skip if the
* device is active because it itself may be in use */ if (!dev->active) { if (!request_mem_region(*addr, length(addr, end), "pnp")) return 0;
release_mem_region(*addr, length(addr, end));
}
/* check if the resource is reserved */ for (i = 0; i < 8; i++) { int raddr = pnp_reserve_mem[i << 1]; int rend = pnp_reserve_mem[(i << 1) + 1] + raddr - 1; if (ranged_conflict(addr, end, &raddr, &rend)) return 0;
}
/* check for internal conflicts */ for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { if (tres != res && tres->flags & IORESOURCE_MEM) {
taddr = &tres->start;
tend = &tres->end; if (ranged_conflict(addr, end, taddr, tend)) return 0;
}
}
/* check for conflicts with other pnp devices */
pnp_for_each_dev(tdev) { if (tdev == dev) continue; for (i = 0;
(tres = pnp_get_resource(tdev, IORESOURCE_MEM, i));
i++) { if (tres->flags & IORESOURCE_MEM) { if (cannot_compare(tres->flags)) continue; if (tres->flags & IORESOURCE_WINDOW) continue;
taddr = &tres->start;
tend = &tres->end; if (ranged_conflict(addr, end, taddr, tend)) return 0;
}
}
}
if (pci->irq == irq) {
pnp_dbg(&pnp->dev, " device %s using irq %d\n",
pci_name(pci), irq); return 1;
}
/* * See pci_setup_device() and ata_pci_sff_activate_host() for * similar IDE legacy detection.
*/
pci_read_config_dword(pci, PCI_CLASS_REVISION, &class); class >>= 8; /* discard revision ID */
progif = class & 0xff; class >>= 8;
if (class == PCI_CLASS_STORAGE_IDE) { /* * Unless both channels are native-PCI mode only, * treat the compatibility IRQs as busy.
*/ if ((progif & 0x5) != 0x5) if (ATA_PRIMARY_IRQ(pci) == irq ||
ATA_SECONDARY_IRQ(pci) == irq) {
pnp_dbg(&pnp->dev, " legacy IDE device %s " "using irq %d\n", pci_name(pci), irq); return 1;
}
}
int pnp_check_irq(struct pnp_dev *dev, struct resource *res)
{ int i; struct pnp_dev *tdev; struct resource *tres;
resource_size_t *irq;
irq = &res->start;
/* if the resource doesn't exist, don't complain about it */ if (cannot_compare(res->flags)) return 1;
/* check if the resource is valid */ if (*irq > 15) return 0;
/* check if the resource is reserved */ for (i = 0; i < 16; i++) { if (pnp_reserve_irq[i] == *irq) return 0;
}
/* check for internal conflicts */ for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) { if (tres != res && tres->flags & IORESOURCE_IRQ) { if (tres->start == *irq) return 0;
}
}
/* check if the resource is being used by a pci device */ if (pci_uses_irq(dev, *irq)) return 0;
/* check if the resource is already in use, skip if the
* device is active because it itself may be in use */ if (!dev->active) { if (request_irq(*irq, pnp_test_handler,
IRQF_PROBE_SHARED, "pnp", NULL)) return 0;
free_irq(*irq, NULL);
}
/* check for conflicts with other pnp devices */
pnp_for_each_dev(tdev) { if (tdev == dev) continue; for (i = 0;
(tres = pnp_get_resource(tdev, IORESOURCE_IRQ, i));
i++) { if (tres->flags & IORESOURCE_IRQ) { if (cannot_compare(tres->flags)) continue; if (tres->start == *irq) return 0;
}
}
}
return 1;
}
#ifdef CONFIG_ISA_DMA_API int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
{ int i; struct pnp_dev *tdev; struct resource *tres;
resource_size_t *dma;
dma = &res->start;
/* if the resource doesn't exist, don't complain about it */ if (cannot_compare(res->flags)) return 1;
/* check if the resource is valid */ if (*dma == 4 || *dma > 7) return 0;
/* check if the resource is reserved */ for (i = 0; i < 8; i++) { if (pnp_reserve_dma[i] == *dma) return 0;
}
/* check for internal conflicts */ for (i = 0; (tres = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) { if (tres != res && tres->flags & IORESOURCE_DMA) { if (tres->start == *dma) return 0;
}
}
/* check if the resource is already in use, skip if the
* device is active because it itself may be in use */ if (!dev->active) { if (request_dma(*dma, "pnp")) return 0;
free_dma(*dma);
}
/* check for conflicts with other pnp devices */
pnp_for_each_dev(tdev) { if (tdev == dev) continue; for (i = 0;
(tres = pnp_get_resource(tdev, IORESOURCE_DMA, i));
i++) { if (tres->flags & IORESOURCE_DMA) { if (cannot_compare(tres->flags)) continue; if (tres->start == *dma) return 0;
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.