From 3920999db7a352f899447e41d4fae2c7a1f7442b Mon Sep 17 00:00:00 2001 From: Thomas Moestl Date: Tue, 1 Jul 2003 14:08:33 +0000 Subject: [PATCH] Add a new PCI interface method, assign_interrupt, to determine the interrupt to be used for a device. This is intended solely for internal use of PCI bus implementations, and exists so that PCI bus drivers implementing special interrupt assignment methods which require additional work at the bus level to work right can be easily derived from the generic driver (or any other one) without resorting to hacks. It will be used in the sparc64 ofw_pcibus driver, which will be committed shortly. Make use of this method in the generic implementation, and add it to the method table of bus drivers derived from the PCI one. Reviewed by: imp, -hackers --- sys/dev/acpica/acpi_pci.c | 1 + sys/dev/cardbus/cardbus.c | 1 + sys/dev/pci/pci.c | 23 +++++++++++++++++------ sys/dev/pci/pci_if.m | 5 +++++ sys/dev/pci/pci_private.h | 1 + 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/sys/dev/acpica/acpi_pci.c b/sys/dev/acpica/acpi_pci.c index 2448b62db75..04319b6f312 100644 --- a/sys/dev/acpica/acpi_pci.c +++ b/sys/dev/acpica/acpi_pci.c @@ -111,6 +111,7 @@ static device_method_t acpi_pci_methods[] = { /* XXX: We should override these two. */ DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method), DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method), + DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method), { 0, 0 } }; diff --git a/sys/dev/cardbus/cardbus.c b/sys/dev/cardbus/cardbus.c index 155971285a7..5c34c85d112 100644 --- a/sys/dev/cardbus/cardbus.c +++ b/sys/dev/cardbus/cardbus.c @@ -387,6 +387,7 @@ static device_method_t cardbus_methods[] = { DEVMETHOD(pci_disable_io, pci_disable_io_method), DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method), DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method), + DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method), {0,0} }; diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index 71865a81690..f4681f14c3a 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -70,7 +70,8 @@ static int pci_porten(device_t pcib, int b, int s, int f); static int pci_memen(device_t pcib, int b, int s, int f); static int pci_add_map(device_t pcib, int b, int s, int f, int reg, struct resource_list *rl); -static void pci_add_resources(device_t pcib, device_t dev); +static void pci_add_resources(device_t pcib, device_t bus, + device_t dev); static int pci_probe(device_t dev); static int pci_attach(device_t dev); static void pci_load_vendor_data(void); @@ -119,6 +120,7 @@ static device_method_t pci_methods[] = { DEVMETHOD(pci_disable_io, pci_disable_io_method), DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method), DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method), + DEVMETHOD(pci_assign_interrupt, pci_assign_interrupt_method), { 0, 0 } }; @@ -776,7 +778,7 @@ pci_add_map(device_t pcib, int b, int s, int f, int reg, } static void -pci_add_resources(device_t pcib, device_t dev) +pci_add_resources(device_t pcib, device_t bus, device_t dev) { struct pci_devinfo *dinfo = device_get_ivars(dev); pcicfgregs *cfg = &dinfo->cfg; @@ -805,7 +807,7 @@ pci_add_resources(device_t pcib, device_t dev) * If the re-route fails, then just stick with what we * have. */ - irq = PCIB_ROUTE_INTERRUPT(pcib, dev, cfg->intpin); + irq = PCI_ASSIGN_INTERRUPT(bus, dev); if (PCI_INTERRUPT_VALID(irq)) { pci_write_config(dev, PCIR_INTLINE, irq, 1); cfg->intline = irq; @@ -855,7 +857,7 @@ pci_add_child(device_t bus, struct pci_devinfo *dinfo) pcib = device_get_parent(bus); dinfo->cfg.dev = device_add_child(bus, NULL, -1); device_set_ivars(dinfo->cfg.dev, dinfo); - pci_add_resources(pcib, dinfo->cfg.dev); + pci_add_resources(pcib, bus, dinfo->cfg.dev); pci_print_verbose(dinfo); } @@ -1356,8 +1358,7 @@ pci_alloc_resource(device_t dev, device_t child, int type, int *rid, */ if (!PCI_INTERRUPT_VALID(cfg->intline) && (cfg->intpin != 0)) { - cfg->intline = PCIB_ROUTE_INTERRUPT( - device_get_parent(dev), child, cfg->intpin); + cfg->intline = PCI_ASSIGN_INTERRUPT(dev, child); if (PCI_INTERRUPT_VALID(cfg->intline)) { pci_write_config(child, PCIR_INTLINE, cfg->intline, 1); @@ -1479,6 +1480,16 @@ pci_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf, return (0); } +int +pci_assign_interrupt_method(device_t dev, device_t child) +{ + struct pci_devinfo *dinfo = device_get_ivars(child); + pcicfgregs *cfg = &dinfo->cfg; + + return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, + cfg->intpin)); +} + static int pci_modevent(module_t mod, int what, void *arg) { diff --git a/sys/dev/pci/pci_if.m b/sys/dev/pci/pci_if.m index bd1956507d6..635005dc1bc 100644 --- a/sys/dev/pci/pci_if.m +++ b/sys/dev/pci/pci_if.m @@ -77,3 +77,8 @@ METHOD int disable_io { device_t child; int space; }; + +METHOD int assign_interrupt { + device_t dev; + device_t child; +}; diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h index f0387d068fe..fb85e601156 100644 --- a/sys/dev/pci/pci_private.h +++ b/sys/dev/pci/pci_private.h @@ -72,4 +72,5 @@ int pci_child_location_str_method(device_t cbdev, device_t child, char *buf, size_t buflen); int pci_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf, size_t buflen); +int pci_assign_interrupt_method(device_t dev, device_t child); #endif /* _PCI_PRIVATE_H_ */