diff options
author | ian <ian@FreeBSD.org> | 2014-10-26 04:01:57 +0000 |
---|---|---|
committer | ian <ian@FreeBSD.org> | 2014-10-26 04:01:57 +0000 |
commit | 8526d66c636337d8a561fa54ed24f881c8ad347a (patch) | |
tree | d30aae75ed4f574bdf983f60ce365f26ac1f52c7 /sys/dev/ofw | |
parent | 14eb39a57df6f6895c77b2d794c3b6a68e73542f (diff) | |
download | FreeBSD-src-8526d66c636337d8a561fa54ed24f881c8ad347a.zip FreeBSD-src-8526d66c636337d8a561fa54ed24f881c8ad347a.tar.gz |
MFC r272109, r272181:
Replace multiple nearly-identical copies of code to walk through an FDT
node's interrupts=<...> property creating resource list entries with a
single common implementation. This change makes ofw_bus_intr_to_rl() the
one true copy of that code and removes the copies of it from other places.
This also adds handling of the interrupts-extended property.
Diffstat (limited to 'sys/dev/ofw')
-rw-r--r-- | sys/dev/ofw/ofw_bus_subr.c | 63 | ||||
-rw-r--r-- | sys/dev/ofw/ofw_bus_subr.h | 3 | ||||
-rw-r--r-- | sys/dev/ofw/ofwbus.c | 34 |
3 files changed, 68 insertions, 32 deletions
diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c index 7ddb5e6..cd11693 100644 --- a/sys/dev/ofw/ofw_bus_subr.c +++ b/sys/dev/ofw/ofw_bus_subr.c @@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$"); #include <sys/errno.h> #include <sys/libkern.h> +#include <machine/resource.h> + #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> #include <dev/ofw/openfirm.h> @@ -367,3 +369,64 @@ ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz, return (0); } +int +ofw_bus_intr_to_rl(device_t dev, phandle_t node, struct resource_list *rl) +{ + phandle_t iparent; + uint32_t icells, *intr; + int err, i, irqnum, nintr, rid; + boolean_t extended; + + nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr), + (void **)&intr); + if (nintr > 0) { + if (OF_searchencprop(node, "interrupt-parent", &iparent, + sizeof(iparent)) == -1) { + device_printf(dev, "No interrupt-parent found, " + "assuming direct parent\n"); + iparent = OF_parent(node); + } + if (OF_searchencprop(OF_node_from_xref(iparent), + "#interrupt-cells", &icells, sizeof(icells)) == -1) { + device_printf(dev, "Missing #interrupt-cells " + "property, assuming <1>\n"); + icells = 1; + } + if (icells < 1 || icells > nintr) { + device_printf(dev, "Invalid #interrupt-cells property " + "value <%d>, assuming <1>\n", icells); + icells = 1; + } + extended = false; + } else { + nintr = OF_getencprop_alloc(node, "interrupts-extended", + sizeof(*intr), (void **)&intr); + if (nintr <= 0) + return (0); + extended = true; + } + err = 0; + rid = 0; + for (i = 0; i < nintr; i += icells) { + if (extended) { + iparent = intr[i++]; + if (OF_searchencprop(OF_node_from_xref(iparent), + "#interrupt-cells", &icells, sizeof(icells)) == -1) { + device_printf(dev, "Missing #interrupt-cells " + "property\n"); + err = ENOENT; + break; + } + if (icells < 1 || (i + icells) > nintr) { + device_printf(dev, "Invalid #interrupt-cells " + "property value <%d>\n", icells); + err = ERANGE; + break; + } + } + irqnum = ofw_bus_map_intr(dev, iparent, icells, &intr[i]); + resource_list_add(rl, SYS_RES_IRQ, rid++, irqnum, irqnum, 1); + } + free(intr, M_OFWPROP); + return (err); +} diff --git a/sys/dev/ofw/ofw_bus_subr.h b/sys/dev/ofw/ofw_bus_subr.h index a4d8b92..59f83fc 100644 --- a/sys/dev/ofw/ofw_bus_subr.h +++ b/sys/dev/ofw/ofw_bus_subr.h @@ -72,6 +72,9 @@ int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int, int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *, void *, void *, int, phandle_t *); +/* Routines for parsing device-tree data into resource lists. */ +int ofw_bus_intr_to_rl(device_t, phandle_t, struct resource_list *); + /* Helper to get device status property */ const char *ofw_bus_get_status(device_t dev); int ofw_bus_status_okay(device_t dev); diff --git a/sys/dev/ofw/ofwbus.c b/sys/dev/ofw/ofwbus.c index 5a141af..ac0f788 100644 --- a/sys/dev/ofw/ofwbus.c +++ b/sys/dev/ofw/ofwbus.c @@ -436,11 +436,9 @@ ofwbus_setup_dinfo(device_t dev, phandle_t node) struct ofwbus_softc *sc; struct ofwbus_devinfo *ndi; const char *nodename; - uint32_t *reg, *intr, icells; + uint32_t *reg; uint64_t phys, size; - phandle_t iparent; int i, j, rid; - int nintr; int nreg; sc = device_get_softc(dev); @@ -485,35 +483,7 @@ ofwbus_setup_dinfo(device_t dev, phandle_t node) } free(reg, M_OFWPROP); - nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr), - (void **)&intr); - if (nintr > 0) { - if (OF_searchencprop(node, "interrupt-parent", &iparent, - sizeof(iparent)) == -1) { - device_printf(dev, "No interrupt-parent found, " - "assuming nexus on <%s>\n", nodename); - iparent = 0xffffffff; - } - if (OF_searchencprop(OF_node_from_xref(iparent), - "#interrupt-cells", &icells, sizeof(icells)) == -1) { - device_printf(dev, "Missing #interrupt-cells property, " - "assuming <1> on <%s>\n", nodename); - icells = 1; - } - if (icells < 1 || icells > nintr) { - device_printf(dev, "Invalid #interrupt-cells property " - "value <%d>, assuming <1> on <%s>\n", icells, - nodename); - icells = 1; - } - for (i = 0, rid = 0; i < nintr; i += icells, rid++) { - intr[i] = ofw_bus_map_intr(dev, iparent, icells, - &intr[i]); - resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, rid, intr[i], - intr[i], 1); - } - free(intr, M_OFWPROP); - } + ofw_bus_intr_to_rl(dev, node, &ndi->ndi_rl); return (ndi); } |