aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/ofw/openfirm.c
diff options
context:
space:
mode:
authorNathan Whitehorn <nwhitehorn@FreeBSD.org>2013-09-15 14:19:17 +0000
committerNathan Whitehorn <nwhitehorn@FreeBSD.org>2013-09-15 14:19:17 +0000
commitc088841850a3cf9119a942bab99c3ae2bf723911 (patch)
treefe3ff164532f1f65b1e3f0ea2a314284c1f99fe8 /sys/dev/ofw/openfirm.c
parentc775ab573d1384fa8598eb48b06aa63f0d6aab20 (diff)
downloadsrc-c088841850a3cf9119a942bab99c3ae2bf723911.tar.gz
src-c088841850a3cf9119a942bab99c3ae2bf723911.zip
Add a kernel interface (OF_xref_phandle()) for systems where phandles
used as cross-references in the device tree and phandles as used by the Open Firmware client interface are in different namespaces. This include IBM pSeries hardware as well as FDT systems. FDT certainly abuses ihandles for this purpose and should be modified to use this API eventually. This changes no behavior on systems where FreeBSD already worked. Reviewed by: marius Approved by: re (kib) MFC after: 2 weeks
Notes
Notes: svn path=/head/; revision=255596
Diffstat (limited to 'sys/dev/ofw/openfirm.c')
-rw-r--r--sys/dev/ofw/openfirm.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/sys/dev/ofw/openfirm.c b/sys/dev/ofw/openfirm.c
index d63edcebff9d..0760854079c7 100644
--- a/sys/dev/ofw/openfirm.c
+++ b/sys/dev/ofw/openfirm.c
@@ -386,6 +386,48 @@ OF_package_to_path(phandle_t package, char *buf, size_t len)
return (OFW_PACKAGE_TO_PATH(ofw_obj, package, buf, len));
}
+/* Look up effective phandle (see FDT/PAPR spec) */
+static phandle_t
+OF_child_xref_phandle(phandle_t parent, phandle_t xref)
+{
+ phandle_t child, rxref;
+
+ /*
+ * Recursively descend from parent, looking for a node with a property
+ * named either "phandle", "ibm,phandle", or "linux,phandle" that
+ * matches the xref we are looking for.
+ */
+
+ for (child = OF_child(parent); child != 0; child = OF_peer(child)) {
+ rxref = OF_child_xref_phandle(child, xref);
+ if (rxref != -1)
+ return (rxref);
+
+ if (OF_getprop(child, "phandle", &rxref, sizeof(rxref)) == -1 &&
+ OF_getprop(child, "ibm,phandle", &rxref,
+ sizeof(rxref)) == -1 && OF_getprop(child,
+ "linux,phandle", &rxref, sizeof(rxref)) == -1)
+ continue;
+
+ if (rxref == xref)
+ return (child);
+ }
+
+ return (-1);
+}
+
+phandle_t
+OF_xref_phandle(phandle_t xref)
+{
+ phandle_t node;
+
+ node = OF_child_xref_phandle(OF_peer(0), xref);
+ if (node == -1)
+ return (xref);
+
+ return (node);
+}
+
/* Call the method in the scope of a given instance. */
int
OF_call_method(const char *method, ihandle_t instance, int nargs, int nreturns,