summaryrefslogtreecommitdiffstats
path: root/sys/dev/ofw
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2009-01-03 19:38:47 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2009-01-03 19:38:47 +0000
commit4ca12119c31e0cd42b3cb4b28dd898b8218290dc (patch)
tree098db494b106fc2ba6859a08899f153876ecd41f /sys/dev/ofw
parent6299d1e736cea0af7a3dba4c67151b374fa64885 (diff)
downloadFreeBSD-src-4ca12119c31e0cd42b3cb4b28dd898b8218290dc.zip
FreeBSD-src-4ca12119c31e0cd42b3cb4b28dd898b8218290dc.tar.gz
Fix the OFW interrupt map parser to use its own idea of the number of interrupt
cells in the map, instead of using a value passed to it and then panicing if it disagrees. This fixes interrupt map parsing for PCI bridges on some Apple Uninorth PCI controllers. Reported by: marcel Tested on: G4 iBook, Sun Ultra 5
Diffstat (limited to 'sys/dev/ofw')
-rw-r--r--sys/dev/ofw/ofw_bus_subr.c23
-rw-r--r--sys/dev/ofw/openfirm.c17
-rw-r--r--sys/dev/ofw/openfirm.h2
3 files changed, 24 insertions, 18 deletions
diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c
index 19de2b97..1cc5207 100644
--- a/sys/dev/ofw/ofw_bus_subr.c
+++ b/sys/dev/ofw/ofw_bus_subr.c
@@ -146,18 +146,6 @@ ofw_bus_gen_get_type(device_t bus, device_t dev)
return (obd->obd_type);
}
-static int
-ofw_bus_searchprop(phandle_t node, char *propname, void *buf, int buflen)
-{
- int rv;
-
- for (; node != 0; node = OF_parent(node)) {
- if ((rv = OF_getprop(node, propname, buf, buflen)) != -1)
- return (rv);
- }
- return (-1);
-}
-
void
ofw_bus_setup_iinfo(phandle_t node, struct ofw_bus_iinfo *ii, int intrsz)
{
@@ -249,17 +237,16 @@ ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz,
mptr = imap;
i = imapsz;
- tsz = physsz + intrsz + sizeof(phandle_t) + rintrsz;
while (i > 0) {
- KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map"));
bcopy(mptr + physsz + intrsz, &parent, sizeof(parent));
- if (ofw_bus_searchprop(parent, "#interrupt-cells",
+ if (OF_searchprop(parent, "#interrupt-cells",
&pintrsz, sizeof(pintrsz)) == -1)
pintrsz = 1; /* default */
pintrsz *= sizeof(pcell_t);
- if (pintrsz != rintrsz)
- panic("ofw_bus_search_intrmap: expected interrupt cell "
- "size incorrect: %d > %d", rintrsz, pintrsz);
+
+ /* Compute the map stride size */
+ tsz = physsz + intrsz + sizeof(phandle_t) + pintrsz;
+ KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map"));
/*
* XXX: Apple hardware uses a second cell to set information
diff --git a/sys/dev/ofw/openfirm.c b/sys/dev/ofw/openfirm.c
index c7b2203..4c33c9f 100644
--- a/sys/dev/ofw/openfirm.c
+++ b/sys/dev/ofw/openfirm.c
@@ -220,6 +220,23 @@ OF_getprop(phandle_t package, const char *propname, void *buf, size_t buflen)
}
/*
+ * Resursively search the node and its parent for the given property, working
+ * downward from the node to the device tree root. Returns the value of the
+ * first match.
+ */
+ssize_t
+OF_searchprop(phandle_t node, char *propname, void *buf, size_t len)
+{
+ ssize_t rv;
+
+ for (; node != 0; node = OF_parent(node)) {
+ if ((rv = OF_getprop(node, propname, buf, len)) != -1)
+ return (rv);
+ }
+ return (-1);
+}
+
+/*
* Store the value of a property of a package into newly allocated memory
* (using the M_OFWPROP malloc pool and M_WAITOK). elsz is the size of a
* single element, the number of elements is return in number.
diff --git a/sys/dev/ofw/openfirm.h b/sys/dev/ofw/openfirm.h
index 08a0544..614c4b2 100644
--- a/sys/dev/ofw/openfirm.h
+++ b/sys/dev/ofw/openfirm.h
@@ -104,6 +104,8 @@ phandle_t OF_parent(phandle_t node);
ssize_t OF_getproplen(phandle_t node, const char *propname);
ssize_t OF_getprop(phandle_t node, const char *propname, void *buf,
size_t len);
+ssize_t OF_searchprop(phandle_t node, char *propname, void *buf,
+ size_t len);
ssize_t OF_getprop_alloc(phandle_t node, const char *propname,
int elsz, void **buf);
int OF_nextprop(phandle_t node, const char *propname, char *buf,
OpenPOWER on IntegriCloud