Index: sys/dev/ofw/ofw_bus_subr.h =================================================================== --- sys/dev/ofw/ofw_bus_subr.h +++ sys/dev/ofw/ofw_bus_subr.h @@ -101,4 +101,7 @@ /* Helper routine for checking existence of a prop */ int ofw_bus_has_prop(device_t, const char *); +/* Helper to search for a child with a given compat prop */ +phandle_t ofw_bus_find_compatible(phandle_t, const char *); + #endif /* !_DEV_OFW_OFW_BUS_SUBR_H_ */ Index: sys/dev/ofw/ofw_bus_subr.c =================================================================== --- sys/dev/ofw/ofw_bus_subr.c +++ sys/dev/ofw/ofw_bus_subr.c @@ -176,37 +176,47 @@ return (0); } -int -ofw_bus_is_compatible(device_t dev, const char *onecompat) +static int +ofw_bus_node_is_compatible(phandle_t node, const char *onecompat) { - phandle_t node; - const char *compat; - int len, onelen, l; + int len, onelen, l, ret; + char *compat; - if ((compat = ofw_bus_get_compat(dev)) == NULL) - return (0); - - if ((node = ofw_bus_get_node(dev)) == -1) - return (0); - - /* Get total 'compatible' prop len */ - if ((len = OF_getproplen(node, "compatible")) <= 0) + len = OF_getprop_alloc(node, "compatible", 1, (void **)&compat); + if (len <= 0) return (0); onelen = strlen(onecompat); + ret = 0; while (len > 0) { if (strlen(compat) == onelen && - strncasecmp(compat, onecompat, onelen) == 0) + strncasecmp(compat, onecompat, onelen) == 0) { /* Found it. */ - return (1); + ret = 1; + break; + } /* Slide to the next sub-string. */ l = strlen(compat) + 1; compat += l; len -= l; } - return (0); + + free(compat, M_OFWPROP); + + return (ret); +} + +int +ofw_bus_is_compatible(device_t dev, const char *onecompat) +{ + phandle_t node; + + if ((node = ofw_bus_get_node(dev)) == -1) + return (0); + + return (ofw_bus_node_is_compatible(node, onecompat)); } int @@ -487,3 +497,22 @@ return (err); } +phandle_t +ofw_bus_find_compatible(phandle_t node, const char *compat) +{ + phandle_t child, ret; + + /* + * Traverse all children of 'start' node, and find first with + * matching 'compatible' property. + */ + for (child = OF_child(node); child != 0; child = OF_peer(child)) { + if (ofw_bus_node_is_compatible(child, compat)) + return (child); + + ret = ofw_bus_find_compatible(child, compat); + if (ret != 0) + return (ret); + } + return (0); +}