diff options
author | tmm <tmm@FreeBSD.org> | 2002-03-24 02:11:06 +0000 |
---|---|---|
committer | tmm <tmm@FreeBSD.org> | 2002-03-24 02:11:06 +0000 |
commit | 521e80e7004d21d31b68b84f1038865ad8513c5b (patch) | |
tree | 38a7ef1596d0873fd81c61d83dd216b08b60752f /sys/sparc64/pci | |
parent | 587f263c4d8db119551ac4d9518abee9498ebd04 (diff) | |
download | FreeBSD-src-521e80e7004d21d31b68b84f1038865ad8513c5b.zip FreeBSD-src-521e80e7004d21d31b68b84f1038865ad8513c5b.tar.gz |
Make the OpenFirmware interrupt mapping code more generic, to reduce
the bus-dependent code and to be able to support more systems. The core
of the new code is mostly obtained from NetBSD.
Kluge the interrupt routing methods of the psycho and apb drivers so
that an intline of 0 can be handled for now; real routing is still not
possible (all intline registers are preinitialized instead); this will
require a sparc64-specific adaption of the driver for generic PCI-PCI
bridges with a custom routing method to work right.
Diffstat (limited to 'sys/sparc64/pci')
-rw-r--r-- | sys/sparc64/pci/apb.c | 26 | ||||
-rw-r--r-- | sys/sparc64/pci/ofw_pci.c | 116 | ||||
-rw-r--r-- | sys/sparc64/pci/ofw_pci.h | 15 | ||||
-rw-r--r-- | sys/sparc64/pci/psycho.c | 33 | ||||
-rw-r--r-- | sys/sparc64/pci/psychovar.h | 3 |
5 files changed, 66 insertions, 127 deletions
diff --git a/sys/sparc64/pci/apb.c b/sys/sparc64/pci/apb.c index 52a5270..4f01630 100644 --- a/sys/sparc64/pci/apb.c +++ b/sys/sparc64/pci/apb.c @@ -46,8 +46,13 @@ #include <sys/malloc.h> #include <sys/bus.h> +#include <dev/ofw/openfirm.h> +#include <dev/ofw/ofw_pci.h> + #include <machine/resource.h> +#include <sparc64/pci/ofw_pci.h> + #include <pci/pcivar.h> #include <pci/pcireg.h> @@ -343,12 +348,27 @@ apb_write_config(device_t dev, int b, int s, int f, int reg, u_int32_t val, } /* - * Route an interrupt across a PCI bridge - the APB does not route interrupts, - * and routing of interrupts that are not preinitialized is not supported yet. + * Route an interrupt across a PCI bridge - we need to rely on the firmware + * here. */ static int apb_route_interrupt(device_t pcib, device_t dev, int pin) { - panic("apb_route_interrupt"); + /* + * XXX: ugly loathsome hack: + * We can't use ofw_pci_route_intr() here; the device passed may be + * the one of a bridge, so the original device can't be recovered. + * + * We need to use the firmware to route interrupts, however it has + * no interface which could be used to interpret intpins; instead, + * all assignments are done by device. + * + * The MI pci code will try to reroute interrupts of 0, although they + * are correct; all other interrupts are preinitialized, so if we + * get here, the intline is either 0 (so return 0), or we hit a + * device which was not preinitialized (e.g. hotplugged stuff), in + * which case we are lost. + */ + return (0); } diff --git a/sys/sparc64/pci/ofw_pci.c b/sys/sparc64/pci/ofw_pci.c index f56efaf..636c9f9 100644 --- a/sys/sparc64/pci/ofw_pci.c +++ b/sys/sparc64/pci/ofw_pci.c @@ -50,66 +50,15 @@ #include "pcib_if.h" -/* - * Find the interrupt-map properties for a node. This might not be a property - * of the parent, because there may be bridges in between, so go up through the - * tree to find it. - * This seems to be only needed for PCI systems, so it has not been moved to - * ofw_bus.c - */ -int -ofw_pci_find_imap(phandle_t node, struct ofw_pci_imap **imap, - struct ofw_pci_imap_msk *imapmsk) -{ - int nimap; - - nimap = -1; - while ((node = OF_parent(node)) != 0) { - if ((nimap = OF_getprop_alloc(node, "interrupt-map", - sizeof(**imap), (void **)imap)) == -1 || - OF_getprop(node, "interrupt-map-mask", - imapmsk, sizeof(*imapmsk)) == -1) { - if (*imap != NULL) { - free(*imap, M_OFWPROP); - *imap = NULL; - } - nimap = -1; - } else - break; - } - return (nimap); -} - -/* - * Route an interrupt using the firmware nodes. Returns 255 for interrupts - * that cannot be routed (suitable for the PCI code). - */ -int -ofw_pci_route_intr2(int intr, struct ofw_pci_register *pcir, - struct ofw_pci_imap *imap, int nimap, struct ofw_pci_imap_msk *imapmsk) -{ - char regm[12]; - int cintr; - - cintr = ofw_bus_route_intr(intr, pcir, sizeof(*pcir), 12, 1, imap, - nimap, imapmsk, regm); - if (cintr == -1) - return (255); - else - return (cintr); -} - -int -ofw_pci_route_intr(phandle_t node, struct ofw_pci_register *pcir, - struct ofw_pci_imap *intrmap, int nintrmap, - struct ofw_pci_imap_msk *intrmapmsk) +u_int32_t +ofw_pci_route_intr(phandle_t node) { - int intr; + u_int32_t rv; - if (OF_getprop(node, "interrupts", &intr, sizeof(intr)) == -1) + rv = ofw_bus_route_intr(node, ORIP_NOINT); + if (rv == ORIR_NOTFOUND) return (255); - - return (ofw_pci_route_intr2(intr, pcir, intrmap, nintrmap, intrmapmsk)); + return (rv); } #define OFW_PCI_PCIBUS "pci" @@ -119,10 +68,8 @@ ofw_pci_route_intr(phandle_t node, struct ofw_pci_register *pcir, * of attached devices using firmware information. */ void -ofw_pci_init_intr(device_t dev, phandle_t bus, struct ofw_pci_imap *intrmap, - int nintrmap, struct ofw_pci_imap_msk *intrmapmsk) +ofw_pci_init_intr(device_t dev, phandle_t bus) { - struct ofw_pci_imap_msk lintrmapmsk; struct ofw_pci_register pcir; phandle_t node; char type[32]; @@ -146,40 +93,19 @@ ofw_pci_init_intr(device_t dev, phandle_t bus, struct ofw_pci_imap *intrmap, * deep, so recursion is feasible. */ #ifdef OFW_PCI_DEBUG - device_printf(dev, __func__": descending to " - "subordinate PCI bus\n"); + device_printf(dev, "%s: descending to " + "subordinate PCI bus\n", __func__); #endif - ofw_pci_init_intr(dev, node, NULL, 0, NULL); + ofw_pci_init_intr(dev, node); } else { if (OF_getprop(node, "reg", &pcir, sizeof(pcir)) == -1) panic("ofw_pci_route_intr: OF_getprop failed"); - /* - * If we didn't get interrupt map properties passed, - * try to find them now. On some systems, buses that - * have no non-bridge children have no such properties, - * so only try to find them at need. - */ - if (intrmap == NULL) { - nintrmap = OF_getprop_alloc(bus, - "interrupt-map", sizeof(*intrmap), - (void **)&intrmap); - if (nintrmap == -1 || - OF_getprop(bus, "interrupt-map-mask", - &lintrmapmsk, sizeof(lintrmapmsk)) == -1) { - printf("ofw_pci_init_intr: could not get " - "interrupt map properties\n"); - if (nintrmap != -1) - free(intrmap, M_OFWPROP); - return; - } - intrmapmsk = &lintrmapmsk; - freemap = 1; - } - if ((intr = ofw_pci_route_intr(node, &pcir, intrmap, - nintrmap, intrmapmsk)) != 255) { + + if ((intr = ofw_pci_route_intr(node)) != 255) { #ifdef OFW_PCI_DEBUG - device_printf(dev, __func__": mapping intr for " + device_printf(dev, "%s: mapping intr for " "%d/%d/%d to %d (preset was %d)\n", + __func__, OFW_PCI_PHYS_HI_BUS(pcir.phys_hi), OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi), OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi), @@ -189,7 +115,6 @@ ofw_pci_init_intr(device_t dev, phandle_t bus, struct ofw_pci_imap *intrmap, OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi), OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi), PCIR_INTLINE, 1)); - #endif /* OFW_PCI_DEBUG */ PCIB_WRITE_CONFIG(dev, OFW_PCI_PHYS_HI_BUS(pcir.phys_hi), @@ -198,8 +123,9 @@ ofw_pci_init_intr(device_t dev, phandle_t bus, struct ofw_pci_imap *intrmap, PCIR_INTLINE, intr, 1); } else { #ifdef OFW_PCI_DEBUG - device_printf(dev, __func__": no interrupt " + device_printf(dev, "%s: no interrupt " "mapping found for %d/%d/%d (preset %d)\n", + __func__, OFW_PCI_PHYS_HI_BUS(pcir.phys_hi), OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi), OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi), @@ -218,8 +144,6 @@ ofw_pci_init_intr(device_t dev, phandle_t bus, struct ofw_pci_imap *intrmap, } } } while ((node = OF_peer(node)) != 0); - if (freemap) - free(intrmap, M_OFWPROP); } phandle_t @@ -268,3 +192,11 @@ ofw_pci_find_node(int bus, int slot, int func) } return (0); } + +phandle_t +ofw_pci_node(device_t dev) +{ + + return (ofw_pci_find_node(pci_get_bus(dev), pci_get_slot(dev), + pci_get_function(dev))); +} diff --git a/sys/sparc64/pci/ofw_pci.h b/sys/sparc64/pci/ofw_pci.h index dc453be..862df92 100644 --- a/sys/sparc64/pci/ofw_pci.h +++ b/sys/sparc64/pci/ofw_pci.h @@ -56,18 +56,9 @@ struct ofw_pci_imap_msk { u_int32_t intr; }; -int ofw_pci_find_imap(phandle_t, struct ofw_pci_imap **, - struct ofw_pci_imap_msk *); -int ofw_pci_route_intr2(int, struct ofw_pci_register *, - struct ofw_pci_imap *, int, struct ofw_pci_imap_msk *); -int ofw_pci_route_intr(phandle_t, struct ofw_pci_register *, - struct ofw_pci_imap *, int, struct ofw_pci_imap_msk *); -void ofw_pci_init_intr(device_t, phandle_t, struct ofw_pci_imap *, int, - struct ofw_pci_imap_msk *); +u_int32_t ofw_pci_route_intr(phandle_t); +void ofw_pci_init_intr(device_t, phandle_t); phandle_t ofw_pci_find_node(int, int, int); -int ofw_pci_dev_iterate_node(device_t, phandle_t, uintptr_t *, int, int *, - int *, uintptr_t *, uintptr_t *); -int ofw_pci_dev_iterate(device_t, uintptr_t *, int, int *, int *, uintptr_t *, - uintptr_t *); +phandle_t ofw_pci_node(device_t); #endif /* ! _SPARC64_PCI_OFW_PCI_H_ */ diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c index 54edab5..bd26e84 100644 --- a/sys/sparc64/pci/psycho.c +++ b/sys/sparc64/pci/psycho.c @@ -478,16 +478,6 @@ psycho_attach(device_t dev) /* XXX: register as root dma tag (kluge). */ sparc64_root_dma_tag = sc->sc_dmat; - if ((sc->sc_nintrmap = OF_getprop_alloc(sc->sc_node, "interrupt-map", - sizeof(*sc->sc_intrmap), (void **)&sc->sc_intrmap)) == -1 || - OF_getprop(sc->sc_node, "interrupt-map-mask", &sc->sc_intrmapmsk, - sizeof(sc->sc_intrmapmsk)) == -1) { - if (sc->sc_intrmap != NULL) { - free(sc->sc_intrmap, M_OFWPROP); - sc->sc_intrmap = NULL; - } - } - /* Register the softc, this is needed for paired psychos. */ if (psycho_ndevs < sizeof(psycho_softcs) / sizeof(psycho_softcs[0])) psycho_softcs[psycho_ndevs] = sc; @@ -617,8 +607,7 @@ psycho_attach(device_t dev) * at least on some models, and we probably shouldn't trust that * the firmware uses the same model as this driver if it does. */ - ofw_pci_init_intr(dev, sc->sc_node, sc->sc_intrmap, sc->sc_nintrmap, - &sc->sc_intrmapmsk); + ofw_pci_init_intr(dev, sc->sc_node); device_add_child(dev, "pci", device_get_unit(dev)); return (bus_generic_attach(dev)); @@ -966,14 +955,24 @@ psycho_write_config(device_t dev, u_int bus, u_int slot, u_int func, static int psycho_route_interrupt(device_t bus, device_t dev, int pin) { + int intline; /* - * Since we preinitialize all interrupt line registers, this should not - * happen for any built-in device. - * Devices on bridges that route interrupts cannot work now - the - * interrupt pin mappings are not known from the firmware... + * XXX: ugly loathsome hack: + * We can't use ofw_pci_route_intr() here; the device passed may be + * the one of a bridge, so the original device can't be recovered. + * + * We need to use the firmware to route interrupts, however it has + * no interface which could be used to interpret intpins; instead, + * all assignments are done by device. + * + * The MI pci code will try to reroute interrupts of 0, although they + * are correct; all other interrupts are preinitialized, so if we + * get here, the intline is either 0 (so return 0), or we hit a + * device which was not preinitialized (e.g. hotplugged stuff), in + * which case we are lost. */ - panic("psycho_route_interrupt"); + return (0); } static int diff --git a/sys/sparc64/pci/psychovar.h b/sys/sparc64/pci/psychovar.h index 25ca9c1..cee7c77 100644 --- a/sys/sparc64/pci/psychovar.h +++ b/sys/sparc64/pci/psychovar.h @@ -74,9 +74,6 @@ struct psycho_softc { */ struct upa_ranges *sc_range; int sc_nrange; - struct ofw_pci_imap *sc_intrmap; - int sc_nintrmap; - struct ofw_pci_imap_msk sc_intrmapmsk; /* our tags */ bus_space_tag_t sc_cfgt; |