diff --git a/sys/dev/ofw/ofw_bus.h b/sys/dev/ofw/ofw_bus.h index 3f4fbae9754..1ea48456126 100644 --- a/sys/dev/ofw/ofw_bus.h +++ b/sys/dev/ofw/ofw_bus.h @@ -70,4 +70,16 @@ ofw_bus_get_type(device_t dev) return (OFW_BUS_GET_TYPE(device_get_parent(dev), dev)); } +static __inline int +ofw_bus_map_intr(device_t dev, phandle_t iparent, int irq) +{ + return (OFW_BUS_MAP_INTR(dev, dev, iparent, irq)); +} + +static __inline int +ofw_bus_config_intr(device_t dev, int irq, int sense) +{ + return (OFW_BUS_CONFIG_INTR(dev, dev, irq, sense)); +} + #endif /* !_DEV_OFW_OFW_BUS_H_ */ diff --git a/sys/dev/ofw/ofw_bus_if.m b/sys/dev/ofw/ofw_bus_if.m index 46fa281118d..e2466b4b68f 100644 --- a/sys/dev/ofw/ofw_bus_if.m +++ b/sys/dev/ofw/ofw_bus_if.m @@ -56,6 +56,8 @@ CODE { static ofw_bus_get_name_t ofw_bus_default_get_name; static ofw_bus_get_node_t ofw_bus_default_get_node; static ofw_bus_get_type_t ofw_bus_default_get_type; + static ofw_bus_map_intr_t ofw_bus_default_map_intr; + static ofw_bus_config_intr_t ofw_bus_default_config_intr; static const struct ofw_bus_devinfo * ofw_bus_default_get_devinfo(device_t bus, device_t dev) @@ -98,6 +100,31 @@ CODE { return (NULL); } + + int + ofw_bus_default_map_intr(device_t bus, device_t dev, phandle_t iparent, + int irq) + { + /* Propagate up the bus hierarchy until someone handles it. */ + if (device_get_parent(bus) != NULL) + return OFW_BUS_MAP_INTR(device_get_parent(bus), dev, + iparent, irq); + + /* If that fails, then assume a one-domain system */ + return (irq); + } + + int + ofw_bus_default_config_intr(device_t bus, device_t dev, int irq, + int sense) + { + /* Propagate up the bus hierarchy until someone handles it. */ + if (device_get_parent(bus) != NULL) + return OFW_BUS_CONFIG_INTR(device_get_parent(bus), dev, + irq, sense); + + return (ENXIO); + } }; # Get the ofw_bus_devinfo struct for the device dev on the bus. Used for bus @@ -143,3 +170,22 @@ METHOD const char * get_type { device_t bus; device_t dev; } DEFAULT ofw_bus_default_get_type; + +# Map an (interrupt parent, IRQ) pair to a unique system-wide interrupt number. +METHOD int map_intr { + device_t bus; + device_t dev; + phandle_t iparent; + int irq; +} DEFAULT ofw_bus_default_map_intr; + +# Configure an interrupt using the device-tree encoded sense key (the second +# value in the interrupts property if interrupt-cells is 2). IRQ should be +# encoded as from ofw_bus_map_intr(). +METHOD int config_intr { + device_t bus; + device_t dev; + int irq; + int sense; +} DEFAULT ofw_bus_default_config_intr; + diff --git a/sys/powerpc/ofw/ofw_pci.c b/sys/powerpc/ofw/ofw_pci.c index f3e9e784b2c..957a8caed2f 100644 --- a/sys/powerpc/ofw/ofw_pci.c +++ b/sys/powerpc/ofw/ofw_pci.c @@ -272,7 +272,7 @@ ofw_pci_route_interrupt(device_t bus, device_t dev, int pin) if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), &iparent, maskbuf)) - return (MAP_IRQ(iparent, mintr)); + return (ofw_bus_map_intr(dev, iparent, mintr)); /* Maybe it's a real interrupt, not an intpin */ if (pin > 4) diff --git a/sys/powerpc/ofw/ofw_pcib_pci.c b/sys/powerpc/ofw/ofw_pcib_pci.c index fb0a488be85..6e3faeafb32 100644 --- a/sys/powerpc/ofw/ofw_pcib_pci.c +++ b/sys/powerpc/ofw/ofw_pcib_pci.c @@ -157,7 +157,7 @@ ofw_pcib_pci_route_interrupt(device_t bridge, device_t dev, int intpin) * it again on higher levels - that causes problems * in some cases, and never seems to be required. */ - return (MAP_IRQ(iparent, mintr)); + return (ofw_bus_map_intr(dev, iparent, mintr)); } } else if (intpin >= 1 && intpin <= 4) { /* diff --git a/sys/powerpc/ofw/ofw_pcibus.c b/sys/powerpc/ofw/ofw_pcibus.c index b78793e304f..63c327c2efa 100644 --- a/sys/powerpc/ofw/ofw_pcibus.c +++ b/sys/powerpc/ofw/ofw_pcibus.c @@ -218,15 +218,13 @@ ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno) OF_getprop(OF_xref_phandle(iparent), "#interrupt-cells", &icells, sizeof(icells)); - intr[0] = MAP_IRQ(iparent, intr[0]); + intr[0] = ofw_bus_map_intr(dev, iparent, + intr[0]); } - if (iparent != 0 && icells > 1) { - powerpc_config_intr(intr[0], - (intr[1] & 1) ? INTR_TRIGGER_LEVEL : - INTR_TRIGGER_EDGE, - INTR_POLARITY_LOW); - } + if (iparent != 0 && icells > 1) + ofw_bus_config_intr(dev, intr[0], + intr[1]); resource_list_add(&dinfo->opd_dinfo.resources, SYS_RES_IRQ, 0, intr[0], intr[0], 1); @@ -343,12 +341,13 @@ ofw_pcibus_assign_interrupt(device_t dev, device_t child) isz = OF_getprop(node, "AAPL,interrupts", &intr, sizeof(intr)); if (isz == sizeof(intr)) - return ((iparent == -1) ? intr : MAP_IRQ(iparent, intr)); + return ((iparent == -1) ? intr : ofw_bus_map_intr(dev, iparent, + intr)); isz = OF_getprop(node, "interrupts", &intr, sizeof(intr)); if (isz == sizeof(intr)) { if (iparent != -1) - intr = MAP_IRQ(iparent, intr); + intr = ofw_bus_map_intr(dev, iparent, intr); } else { /* No property: our best guess is the intpin. */ intr = pci_get_intpin(child); diff --git a/sys/powerpc/powerpc/nexus.c b/sys/powerpc/powerpc/nexus.c index 16b6c2dbd3e..855684ec2eb 100644 --- a/sys/powerpc/powerpc/nexus.c +++ b/sys/powerpc/powerpc/nexus.c @@ -96,6 +96,8 @@ static bus_get_resource_list_t nexus_get_resource_list; static bus_bind_intr_t nexus_bind_intr; #endif static bus_config_intr_t nexus_config_intr; +static ofw_bus_map_intr_t nexus_ofw_map_intr; +static ofw_bus_config_intr_t nexus_ofw_config_intr; static ofw_bus_get_devinfo_t nexus_get_devinfo; static int nexus_inlist(const char *, const char *const *); @@ -141,6 +143,8 @@ static device_method_t nexus_methods[] = { DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name), DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node), DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type), + DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr), + DEVMETHOD(ofw_bus_config_intr, nexus_ofw_config_intr), DEVMETHOD_END }; @@ -370,6 +374,21 @@ nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, return (powerpc_config_intr(irq, trig, pol)); } +static int +nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int irq) +{ + return (MAP_IRQ(iparent, irq)); +} + +static int +nexus_ofw_config_intr(device_t dev, device_t child, int irq, int sense) +{ + + return (bus_generic_config_intr(child, irq, (sense & 1) ? + INTR_TRIGGER_LEVEL : INTR_TRIGGER_EDGE, + INTR_POLARITY_LOW)); +} + static struct resource * nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) @@ -600,14 +619,11 @@ nexus_setup_dinfo(device_t dev, phandle_t node) OF_searchprop(iparent, "#interrupt-cells", &icells, sizeof(icells)); for (i = 0; i < nintr; i+= icells) { - intr[i] = MAP_IRQ(iparent, intr[i]); + intr[i] = ofw_bus_map_intr(dev, iparent, intr[i]); resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i], intr[i], 1); - if (icells > 1) { - powerpc_config_intr(intr[i], (intr[i+1] & 1) ? - INTR_TRIGGER_LEVEL : INTR_TRIGGER_EDGE, - INTR_POLARITY_LOW); - } + if (icells > 1) + ofw_bus_config_intr(dev, intr[i], intr[i+1]); } free(intr, M_OFWPROP); } diff --git a/sys/powerpc/pseries/vdevice.c b/sys/powerpc/pseries/vdevice.c index 8ddd531e5e3..54cd5ddc6be 100644 --- a/sys/powerpc/pseries/vdevice.c +++ b/sys/powerpc/pseries/vdevice.c @@ -156,7 +156,8 @@ vdevice_attach(device_t dev) for (i = 0; i < nintr; i += icells) { u_int irq = intr[i]; if (iparent != -1) - irq = MAP_IRQ(iparent, intr[i]); + irq = ofw_bus_map_intr(dev, iparent, + intr[i]); resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ, i, irq, irq, i);