Index: dev/acpica/acpi_pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/acpica/acpi_pci.c,v retrieving revision 1.2 diff -u -r1.2 acpi_pci.c --- dev/acpica/acpi_pci.c 4 Sep 2002 03:13:15 -0000 1.2 +++ dev/acpica/acpi_pci.c 12 Sep 2002 20:52:49 -0000 @@ -79,7 +79,7 @@ DEVMETHOD(device_attach, acpi_pci_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_resume, pci_resume), /* Bus interface */ DEVMETHOD(bus_print_child, pci_print_child), Index: dev/pci/pci.c =================================================================== RCS file: /home/ncvs/src/sys/dev/pci/pci.c,v retrieving revision 1.200 diff -u -r1.200 pci.c --- dev/pci/pci.c 4 Sep 2002 03:53:21 -0000 1.200 +++ dev/pci/pci.c 13 Sep 2002 03:01:40 -0000 @@ -73,7 +73,7 @@ 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 bus, device_t pcib, device_t dev); static int pci_probe(device_t dev); static int pci_attach(device_t dev); static void pci_load_vendor_data(void); @@ -81,6 +81,8 @@ int *device, char **desc); static char *pci_describe_device(device_t dev); static int pci_modevent(module_t mod, int what, void *arg); +static int pci_add_pir_record(device_t dev, device_t pcib, + device_t child, int intpin); static device_method_t pci_methods[] = { /* Device interface */ @@ -88,7 +90,7 @@ DEVMETHOD(device_attach, pci_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_resume, pci_resume), /* Bus interface */ DEVMETHOD(bus_print_child, pci_print_child), @@ -740,13 +742,13 @@ } static void -pci_add_resources(device_t pcib, device_t dev) +pci_add_resources(device_t bus, device_t pcib, device_t dev) { struct pci_devinfo *dinfo = device_get_ivars(dev); pcicfgregs *cfg = &dinfo->cfg; struct resource_list *rl = &dinfo->resources; struct pci_quirk *q; - int b, i, f, s; + int b, i, irq, f, s; b = cfg->bus; s = cfg->slot; @@ -762,14 +764,17 @@ } if (cfg->intpin > 0 && PCI_INTERRUPT_VALID(cfg->intline)) { -#ifdef __ia64__ /* - * Re-route interrupts on ia64 so that we can get the - * I/O SAPIC interrupt numbers (the BIOS leaves legacy - * PIC interrupt numbers in the intline registers). + * Try to re-route interrupts. Sometimes the BIOS or + * firmware may leave bogus values in these registers. + * If the re-route fails, then just stick with what we + * have. */ - cfg->intline = PCIB_ROUTE_INTERRUPT(pcib, dev, cfg->intpin); -#endif + irq = PCIB_ROUTE_INTERRUPT(pcib, dev, cfg->intpin); + if (PCI_INTERRUPT_VALID(irq)) { + cfg->intline = irq; + pci_add_pir_record(bus, pcib, dev, cfg->intpin); + } resource_list_add(rl, SYS_RES_IRQ, 0, cfg->intline, cfg->intline, 1); } @@ -807,7 +812,7 @@ 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(bus, pcib, dinfo->cfg.dev); pci_print_verbose(dinfo); } @@ -1310,6 +1315,8 @@ cfg->intline, 1); resource_list_add(rl, SYS_RES_IRQ, 0, cfg->intline, cfg->intline, 1); + pci_add_pir_record(dev, device_get_parent(dev), + child, cfg->intpin); } } } @@ -1408,3 +1415,69 @@ return (0); } + +struct pci_interrupt_routing_record { + STAILQ_ENTRY(pci_interrupt_routing_record) pir_list; + device_t dev; + device_t pcib; + device_t child; + int intpin; +}; + +static STAILQ_HEAD(, pci_interrupt_routing_record) pir_head; +static int pir_head_initted = 0; + +static int +pci_add_pir_record(device_t dev, device_t pcib, device_t child, int intpin) +{ + struct pci_interrupt_routing_record *record; + + record = malloc(sizeof(struct pci_interrupt_routing_record), + M_DEVBUF, M_NOWAIT); + if (record == NULL) { + return (ENOMEM); + } + + record->dev = dev; + record->pcib = pcib; + record->child = child; + record->intpin = intpin; + + if (!pir_head_initted) { + STAILQ_INIT(&pir_head); + pir_head_initted = 1; + } + + STAILQ_INSERT_TAIL(&pir_head, record, pir_list); + + return (0); +} + +int +pci_resume(device_t dev) +{ + struct pci_interrupt_routing_record *record; + struct pci_devinfo *dinfo; + pcicfgregs *cfg; + + if (pir_head_initted) { + STAILQ_FOREACH(record, &pir_head, pir_list) { + if (record->dev != dev) { + continue; + } + + dinfo = device_get_ivars(record->child); + cfg = &dinfo->cfg; + + cfg->intline = PCIB_ROUTE_INTERRUPT(record->pcib, + record->child, record->intpin); + if (PCI_INTERRUPT_VALID(cfg->intline)) { + pci_write_config(record->child, PCIR_INTLINE, + cfg->intline, 1); + } + } + } + + return (bus_generic_resume(dev)); +} + Index: dev/pci/pci_private.h =================================================================== RCS file: /home/ncvs/src/sys/dev/pci/pci_private.h,v retrieving revision 1.4 diff -u -r1.4 pci_private.h --- dev/pci/pci_private.h 4 Sep 2002 03:13:16 -0000 1.4 +++ dev/pci/pci_private.h 12 Sep 2002 20:55:39 -0000 @@ -68,5 +68,6 @@ size_t size); void pci_print_verbose(struct pci_devinfo *dinfo); int pci_freecfg(struct pci_devinfo *dinfo); +int pci_resume(device_t dev); #endif /* _PCI_PRIVATE_H_ */