11ae08745Sheppo /*
21ae08745Sheppo * CDDL HEADER START
31ae08745Sheppo *
41ae08745Sheppo * The contents of this file are subject to the terms of the
51ae08745Sheppo * Common Development and Distribution License (the "License").
61ae08745Sheppo * You may not use this file except in compliance with the License.
71ae08745Sheppo *
81ae08745Sheppo * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91ae08745Sheppo * or http://www.opensolaris.org/os/licensing.
101ae08745Sheppo * See the License for the specific language governing permissions
111ae08745Sheppo * and limitations under the License.
121ae08745Sheppo *
131ae08745Sheppo * When distributing Covered Code, include this CDDL HEADER in each
141ae08745Sheppo * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151ae08745Sheppo * If applicable, add the following below this CDDL HEADER, with the
161ae08745Sheppo * fields enclosed by brackets "[]" replaced with your own identifying
171ae08745Sheppo * information: Portions Copyright [yyyy] [name of copyright owner]
181ae08745Sheppo *
191ae08745Sheppo * CDDL HEADER END
201ae08745Sheppo */
211ae08745Sheppo
221ae08745Sheppo /*
23*de81a4f4Sjm22469 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
241ae08745Sheppo * Use is subject to license terms.
251ae08745Sheppo */
261ae08745Sheppo
271ae08745Sheppo #pragma ident "%Z%%M% %I% %E% SMI"
281ae08745Sheppo
291ae08745Sheppo #include <sys/promif_impl.h>
301ae08745Sheppo #include <sys/kmem.h>
311ae08745Sheppo #include <sys/machsystm.h>
321ae08745Sheppo
331ae08745Sheppo /*
341ae08745Sheppo * A property attached to a node in the kernel's
351ae08745Sheppo * shadow copy of the PROM device tree.
361ae08745Sheppo */
371ae08745Sheppo typedef struct prom_prop {
381ae08745Sheppo struct prom_prop *pp_next;
391ae08745Sheppo char *pp_name;
401ae08745Sheppo int pp_len;
411ae08745Sheppo void *pp_val;
421ae08745Sheppo } prom_prop_t;
431ae08745Sheppo
441ae08745Sheppo /*
451ae08745Sheppo * A node in the kernel's shadow copy of the PROM
461ae08745Sheppo * device tree.
471ae08745Sheppo */
481ae08745Sheppo typedef struct prom_node {
491ae08745Sheppo pnode_t pn_nodeid;
501ae08745Sheppo struct prom_prop *pn_propp;
511ae08745Sheppo struct prom_node *pn_parent;
521ae08745Sheppo struct prom_node *pn_child;
531ae08745Sheppo struct prom_node *pn_sibling;
541ae08745Sheppo } prom_node_t;
551ae08745Sheppo
561ae08745Sheppo static prom_node_t *promif_root;
571ae08745Sheppo
581ae08745Sheppo static prom_node_t *find_node(pnode_t nodeid);
591ae08745Sheppo static prom_node_t *find_node_work(prom_node_t *np, pnode_t node);
601ae08745Sheppo static int getproplen(prom_node_t *pnp, char *name);
611ae08745Sheppo static void *getprop(prom_node_t *pnp, char *name);
621ae08745Sheppo static char *nextprop(prom_node_t *pnp, char *name);
631ae08745Sheppo
641ae08745Sheppo #ifndef _KMDB
651ae08745Sheppo static void create_prop(prom_node_t *pnp, char *name, void *val, int len);
661ae08745Sheppo static prom_node_t *create_node(prom_node_t *parent, pnode_t node);
671ae08745Sheppo static void create_peers(prom_node_t *pnp, pnode_t node);
681ae08745Sheppo static void create_children(prom_node_t *pnp, pnode_t parent);
691ae08745Sheppo #endif
701ae08745Sheppo
711ae08745Sheppo /*
721ae08745Sheppo * Hooks for kmdb for accessing the PROM shadow tree. The driver portion
731ae08745Sheppo * of kmdb will retrieve the root of the tree and pass it down to the
741ae08745Sheppo * debugger portion of kmdb. As the kmdb debugger is standalone, it has
751ae08745Sheppo * its own promif_root pointer that it will be set to the value passed by
761ae08745Sheppo * the driver so that kmdb points to the shadow tree maintained by the kernel.
771ae08745Sheppo * So the "get" function is in the kernel while the "set" function is in kmdb.
781ae08745Sheppo */
791ae08745Sheppo #ifdef _KMDB
801ae08745Sheppo void
promif_stree_setroot(void * root)811ae08745Sheppo promif_stree_setroot(void *root)
821ae08745Sheppo {
831ae08745Sheppo promif_root = (prom_node_t *)root;
841ae08745Sheppo }
851ae08745Sheppo #else
861ae08745Sheppo void *
promif_stree_getroot(void)871ae08745Sheppo promif_stree_getroot(void)
881ae08745Sheppo {
891ae08745Sheppo return (promif_root);
901ae08745Sheppo }
911ae08745Sheppo #endif
921ae08745Sheppo
931ae08745Sheppo /*
941ae08745Sheppo * Interfaces used internally by promif functions.
951ae08745Sheppo * These hide all accesses to the shadow tree.
961ae08745Sheppo */
971ae08745Sheppo
981ae08745Sheppo pnode_t
promif_stree_parentnode(pnode_t nodeid)991ae08745Sheppo promif_stree_parentnode(pnode_t nodeid)
1001ae08745Sheppo {
1011ae08745Sheppo prom_node_t *pnp;
1021ae08745Sheppo
1031ae08745Sheppo pnp = find_node(nodeid);
1041ae08745Sheppo if (pnp && pnp->pn_parent) {
1051ae08745Sheppo return (pnp->pn_parent->pn_nodeid);
1061ae08745Sheppo }
1071ae08745Sheppo
1081ae08745Sheppo return (OBP_NONODE);
1091ae08745Sheppo }
1101ae08745Sheppo
1111ae08745Sheppo pnode_t
promif_stree_childnode(pnode_t nodeid)1121ae08745Sheppo promif_stree_childnode(pnode_t nodeid)
1131ae08745Sheppo {
1141ae08745Sheppo prom_node_t *pnp;
1151ae08745Sheppo
1161ae08745Sheppo pnp = find_node(nodeid);
1171ae08745Sheppo if (pnp && pnp->pn_child)
1181ae08745Sheppo return (pnp->pn_child->pn_nodeid);
1191ae08745Sheppo
1201ae08745Sheppo return (OBP_NONODE);
1211ae08745Sheppo }
1221ae08745Sheppo
1231ae08745Sheppo pnode_t
promif_stree_nextnode(pnode_t nodeid)1241ae08745Sheppo promif_stree_nextnode(pnode_t nodeid)
1251ae08745Sheppo {
1261ae08745Sheppo prom_node_t *pnp;
1271ae08745Sheppo
1281ae08745Sheppo /*
1291ae08745Sheppo * Note: next(0) returns the root node
1301ae08745Sheppo */
1311ae08745Sheppo pnp = find_node(nodeid);
1321ae08745Sheppo if (pnp && (nodeid == OBP_NONODE))
1331ae08745Sheppo return (pnp->pn_nodeid);
1341ae08745Sheppo if (pnp && pnp->pn_sibling)
1351ae08745Sheppo return (pnp->pn_sibling->pn_nodeid);
1361ae08745Sheppo
1371ae08745Sheppo return (OBP_NONODE);
1381ae08745Sheppo }
1391ae08745Sheppo
1401ae08745Sheppo int
promif_stree_getproplen(pnode_t nodeid,char * name)1411ae08745Sheppo promif_stree_getproplen(pnode_t nodeid, char *name)
1421ae08745Sheppo {
1431ae08745Sheppo prom_node_t *pnp;
1441ae08745Sheppo
1451ae08745Sheppo pnp = find_node(nodeid);
1461ae08745Sheppo if (pnp == NULL)
1471ae08745Sheppo return (-1);
1481ae08745Sheppo
1491ae08745Sheppo return (getproplen(pnp, name));
1501ae08745Sheppo }
1511ae08745Sheppo
1521ae08745Sheppo int
promif_stree_getprop(pnode_t nodeid,char * name,void * value)1531ae08745Sheppo promif_stree_getprop(pnode_t nodeid, char *name, void *value)
1541ae08745Sheppo {
1551ae08745Sheppo prom_node_t *pnp;
1561ae08745Sheppo void *prop;
1571ae08745Sheppo int len;
1581ae08745Sheppo
1591ae08745Sheppo pnp = find_node(nodeid);
1601ae08745Sheppo if (pnp == NULL) {
1611ae08745Sheppo prom_printf("find_node: no node?\n");
1621ae08745Sheppo return (-1);
1631ae08745Sheppo }
1641ae08745Sheppo
1651ae08745Sheppo len = getproplen(pnp, name);
1661ae08745Sheppo if (len > 0) {
1671ae08745Sheppo prop = getprop(pnp, name);
1681ae08745Sheppo bcopy(prop, value, len);
1691ae08745Sheppo } else {
1701ae08745Sheppo prom_printf("find_node: getproplen: %d\n", len);
1711ae08745Sheppo }
1721ae08745Sheppo
1731ae08745Sheppo return (len);
1741ae08745Sheppo }
1751ae08745Sheppo
1761ae08745Sheppo char *
promif_stree_nextprop(pnode_t nodeid,char * name,char * next)1771ae08745Sheppo promif_stree_nextprop(pnode_t nodeid, char *name, char *next)
1781ae08745Sheppo {
1791ae08745Sheppo prom_node_t *pnp;
1801ae08745Sheppo char *propname;
1811ae08745Sheppo
1821ae08745Sheppo next[0] = '\0';
1831ae08745Sheppo
1841ae08745Sheppo pnp = find_node(nodeid);
1851ae08745Sheppo if (pnp == NULL)
1861ae08745Sheppo return (NULL);
1871ae08745Sheppo
1881ae08745Sheppo propname = nextprop(pnp, name);
1891ae08745Sheppo if (propname == NULL)
1901ae08745Sheppo return (next);
1911ae08745Sheppo
1921ae08745Sheppo (void) prom_strcpy(next, propname);
1931ae08745Sheppo
1941ae08745Sheppo return (next);
1951ae08745Sheppo }
1961ae08745Sheppo
1971ae08745Sheppo static prom_node_t *
find_node_work(prom_node_t * np,pnode_t node)1981ae08745Sheppo find_node_work(prom_node_t *np, pnode_t node)
1991ae08745Sheppo {
2001ae08745Sheppo prom_node_t *nnp;
201c3bc9566Sae112802 prom_node_t *snp;
2021ae08745Sheppo
203c3bc9566Sae112802 for (snp = np; snp != NULL; snp = snp->pn_sibling) {
204c3bc9566Sae112802 if (snp->pn_nodeid == node)
205c3bc9566Sae112802 return (snp);
2061ae08745Sheppo
207c3bc9566Sae112802 if (snp->pn_child)
208c3bc9566Sae112802 if ((nnp = find_node_work(snp->pn_child, node)) != NULL)
2091ae08745Sheppo return (nnp);
210c3bc9566Sae112802 }
2111ae08745Sheppo
2121ae08745Sheppo return (NULL);
2131ae08745Sheppo }
2141ae08745Sheppo
2151ae08745Sheppo static prom_node_t *
find_node(pnode_t nodeid)2161ae08745Sheppo find_node(pnode_t nodeid)
2171ae08745Sheppo {
2181ae08745Sheppo
2191ae08745Sheppo if (nodeid == OBP_NONODE)
2201ae08745Sheppo return (promif_root);
2211ae08745Sheppo
2221ae08745Sheppo if (promif_root == NULL)
2231ae08745Sheppo return (NULL);
2241ae08745Sheppo
2251ae08745Sheppo return (find_node_work(promif_root, nodeid));
2261ae08745Sheppo }
2271ae08745Sheppo
2281ae08745Sheppo static int
getproplen(prom_node_t * pnp,char * name)2291ae08745Sheppo getproplen(prom_node_t *pnp, char *name)
2301ae08745Sheppo {
2311ae08745Sheppo struct prom_prop *propp;
2321ae08745Sheppo
2331ae08745Sheppo for (propp = pnp->pn_propp; propp != NULL; propp = propp->pp_next)
2341ae08745Sheppo if (prom_strcmp(propp->pp_name, name) == 0)
2351ae08745Sheppo return (propp->pp_len);
2361ae08745Sheppo
2371ae08745Sheppo return (-1);
2381ae08745Sheppo }
2391ae08745Sheppo
2401ae08745Sheppo static void *
getprop(prom_node_t * np,char * name)2411ae08745Sheppo getprop(prom_node_t *np, char *name)
2421ae08745Sheppo {
2431ae08745Sheppo struct prom_prop *propp;
2441ae08745Sheppo
2451ae08745Sheppo for (propp = np->pn_propp; propp != NULL; propp = propp->pp_next)
2461ae08745Sheppo if (prom_strcmp(propp->pp_name, name) == 0)
2471ae08745Sheppo return (propp->pp_val);
2481ae08745Sheppo
2491ae08745Sheppo return (NULL);
2501ae08745Sheppo }
2511ae08745Sheppo
2521ae08745Sheppo static char *
nextprop(prom_node_t * pnp,char * name)2531ae08745Sheppo nextprop(prom_node_t *pnp, char *name)
2541ae08745Sheppo {
2551ae08745Sheppo struct prom_prop *propp;
2561ae08745Sheppo
2571ae08745Sheppo /*
2581ae08745Sheppo * getting next of NULL or a null string returns the first prop name
2591ae08745Sheppo */
2601ae08745Sheppo if (name == NULL || *name == '\0')
2611ae08745Sheppo if (pnp->pn_propp)
2621ae08745Sheppo return (pnp->pn_propp->pp_name);
2631ae08745Sheppo
2641ae08745Sheppo for (propp = pnp->pn_propp; propp != NULL; propp = propp->pp_next)
2651ae08745Sheppo if (prom_strcmp(propp->pp_name, name) == 0)
2661ae08745Sheppo if (propp->pp_next)
2671ae08745Sheppo return (propp->pp_next->pp_name);
2681ae08745Sheppo
2691ae08745Sheppo return (NULL);
2701ae08745Sheppo }
2711ae08745Sheppo
2721ae08745Sheppo #ifndef _KMDB
2731ae08745Sheppo
2741ae08745Sheppo int
promif_stree_setprop(pnode_t nodeid,char * name,void * value,int len)2751ae08745Sheppo promif_stree_setprop(pnode_t nodeid, char *name, void *value, int len)
2761ae08745Sheppo {
2771ae08745Sheppo prom_node_t *pnp;
2781ae08745Sheppo struct prom_prop *prop;
2791ae08745Sheppo
2801ae08745Sheppo pnp = find_node(nodeid);
2811ae08745Sheppo if (pnp == NULL) {
2821ae08745Sheppo prom_printf("find_node: no node?\n");
2831ae08745Sheppo return (-1);
2841ae08745Sheppo }
2851ae08745Sheppo
2861ae08745Sheppo /*
2871ae08745Sheppo * If a property with this name exists, replace the existing
2881ae08745Sheppo * value.
2891ae08745Sheppo */
2901ae08745Sheppo for (prop = pnp->pn_propp; prop; prop = prop->pp_next)
2911ae08745Sheppo if (prom_strcmp(prop->pp_name, name) == 0) {
292a47315d7Sjm22469 /*
293a47315d7Sjm22469 * Make sure we don't get dispatched onto a
294a47315d7Sjm22469 * different cpu if we happen to sleep. See
295a47315d7Sjm22469 * kern_postprom().
296a47315d7Sjm22469 */
297*de81a4f4Sjm22469 thread_affinity_set(curthread, CPU->cpu_id);
298*de81a4f4Sjm22469 kmem_free(prop->pp_val, prop->pp_len);
299a47315d7Sjm22469
300*de81a4f4Sjm22469 prop->pp_val = NULL;
301*de81a4f4Sjm22469 if (len > 0) {
302*de81a4f4Sjm22469 prop->pp_val = kmem_zalloc(len, KM_SLEEP);
3031ae08745Sheppo bcopy(value, prop->pp_val, len);
3041ae08745Sheppo }
305*de81a4f4Sjm22469 thread_affinity_clear(curthread);
3061ae08745Sheppo prop->pp_len = len;
3071ae08745Sheppo return (len);
3081ae08745Sheppo }
3091ae08745Sheppo
3101ae08745Sheppo return (-1);
3111ae08745Sheppo }
3121ae08745Sheppo
3131ae08745Sheppo /*
3141ae08745Sheppo * Create a promif private copy of boot's device tree.
3151ae08745Sheppo */
3161ae08745Sheppo void
promif_stree_init(void)3171ae08745Sheppo promif_stree_init(void)
3181ae08745Sheppo {
3191ae08745Sheppo pnode_t node;
3201ae08745Sheppo prom_node_t *pnp;
3211ae08745Sheppo
3221ae08745Sheppo node = prom_rootnode();
3231ae08745Sheppo promif_root = pnp = create_node(OBP_NONODE, node);
3241ae08745Sheppo
3251ae08745Sheppo create_peers(pnp, node);
3261ae08745Sheppo create_children(pnp, node);
3271ae08745Sheppo }
3281ae08745Sheppo
3291ae08745Sheppo static void
create_children(prom_node_t * pnp,pnode_t parent)3301ae08745Sheppo create_children(prom_node_t *pnp, pnode_t parent)
3311ae08745Sheppo {
3321ae08745Sheppo prom_node_t *cnp;
3331ae08745Sheppo pnode_t child;
3341ae08745Sheppo
3351ae08745Sheppo _NOTE(CONSTCOND)
3361ae08745Sheppo while (1) {
3371ae08745Sheppo child = prom_childnode(parent);
3381ae08745Sheppo if (child == 0)
3391ae08745Sheppo break;
3401ae08745Sheppo if (prom_getproplen(child, "name") <= 0) {
3411ae08745Sheppo parent = child;
3421ae08745Sheppo continue;
3431ae08745Sheppo }
3441ae08745Sheppo cnp = create_node(pnp, child);
3451ae08745Sheppo pnp->pn_child = cnp;
3461ae08745Sheppo create_peers(cnp, child);
3471ae08745Sheppo pnp = cnp;
3481ae08745Sheppo parent = child;
3491ae08745Sheppo }
3501ae08745Sheppo }
3511ae08745Sheppo
3521ae08745Sheppo static void
create_peers(prom_node_t * np,pnode_t node)3531ae08745Sheppo create_peers(prom_node_t *np, pnode_t node)
3541ae08745Sheppo {
3551ae08745Sheppo prom_node_t *pnp;
3561ae08745Sheppo pnode_t peer;
3571ae08745Sheppo
3581ae08745Sheppo _NOTE(CONSTCOND)
3591ae08745Sheppo while (1) {
3601ae08745Sheppo peer = prom_nextnode(node);
3611ae08745Sheppo if (peer == 0)
3621ae08745Sheppo break;
3631ae08745Sheppo if (prom_getproplen(peer, "name") <= 0) {
3641ae08745Sheppo node = peer;
3651ae08745Sheppo continue;
3661ae08745Sheppo }
3671ae08745Sheppo pnp = create_node(np->pn_parent, peer);
3681ae08745Sheppo np->pn_sibling = pnp;
3691ae08745Sheppo create_children(pnp, peer);
3701ae08745Sheppo np = pnp;
3711ae08745Sheppo node = peer;
3721ae08745Sheppo }
3731ae08745Sheppo }
3741ae08745Sheppo
3751ae08745Sheppo static prom_node_t *
create_node(prom_node_t * parent,pnode_t node)3761ae08745Sheppo create_node(prom_node_t *parent, pnode_t node)
3771ae08745Sheppo {
3781ae08745Sheppo prom_node_t *pnp;
3791ae08745Sheppo char prvname[OBP_MAXPROPNAME];
3801ae08745Sheppo char propname[OBP_MAXPROPNAME];
3811ae08745Sheppo int proplen;
3821ae08745Sheppo void *propval;
3831ae08745Sheppo
384a47315d7Sjm22469 /*
385a47315d7Sjm22469 * Make sure we don't get dispatched onto a different
386a47315d7Sjm22469 * cpu if we happen to sleep. See kern_postprom().
387a47315d7Sjm22469 */
388*de81a4f4Sjm22469 thread_affinity_set(curthread, CPU->cpu_id);
389a47315d7Sjm22469
3901ae08745Sheppo pnp = kmem_zalloc(sizeof (prom_node_t), KM_SLEEP);
3911ae08745Sheppo pnp->pn_nodeid = node;
3921ae08745Sheppo pnp->pn_parent = parent;
3931ae08745Sheppo
3941ae08745Sheppo prvname[0] = '\0';
3951ae08745Sheppo
3961ae08745Sheppo _NOTE(CONSTCOND)
3971ae08745Sheppo while (1) {
3981ae08745Sheppo (void) prom_nextprop(node, prvname, propname);
3991ae08745Sheppo if (prom_strlen(propname) == 0)
4001ae08745Sheppo break;
4011ae08745Sheppo if ((proplen = prom_getproplen(node, propname)) == -1)
4021ae08745Sheppo continue;
4031ae08745Sheppo propval = NULL;
4041ae08745Sheppo if (proplen != 0) {
4051ae08745Sheppo propval = kmem_zalloc(proplen, KM_SLEEP);
4061ae08745Sheppo (void) prom_getprop(node, propname, propval);
4071ae08745Sheppo }
4081ae08745Sheppo create_prop(pnp, propname, propval, proplen);
4091ae08745Sheppo
4101ae08745Sheppo (void) prom_strcpy(prvname, propname);
4111ae08745Sheppo }
4121ae08745Sheppo
413a47315d7Sjm22469 thread_affinity_clear(curthread);
414a47315d7Sjm22469
4151ae08745Sheppo return (pnp);
4161ae08745Sheppo }
4171ae08745Sheppo
4181ae08745Sheppo static void
create_prop(prom_node_t * pnp,char * name,void * val,int len)4191ae08745Sheppo create_prop(prom_node_t *pnp, char *name, void *val, int len)
4201ae08745Sheppo {
4211ae08745Sheppo struct prom_prop *prop;
4221ae08745Sheppo struct prom_prop *newprop;
4231ae08745Sheppo
424a47315d7Sjm22469 /*
425a47315d7Sjm22469 * Make sure we don't get dispatched onto a different
426a47315d7Sjm22469 * cpu if we happen to sleep. See kern_postprom().
427a47315d7Sjm22469 */
428*de81a4f4Sjm22469 thread_affinity_set(curthread, CPU->cpu_id);
4291ae08745Sheppo newprop = kmem_zalloc(sizeof (*newprop), KM_SLEEP);
4301ae08745Sheppo newprop->pp_name = kmem_zalloc(prom_strlen(name) + 1, KM_SLEEP);
431a47315d7Sjm22469 thread_affinity_clear(curthread);
432a47315d7Sjm22469
4331ae08745Sheppo (void) prom_strcpy(newprop->pp_name, name);
4341ae08745Sheppo newprop->pp_val = val;
4351ae08745Sheppo newprop->pp_len = len;
4361ae08745Sheppo
4371ae08745Sheppo if (pnp->pn_propp == NULL) {
4381ae08745Sheppo pnp->pn_propp = newprop;
4391ae08745Sheppo return;
4401ae08745Sheppo }
4411ae08745Sheppo
4421ae08745Sheppo /* move to the end of the prop list */
4431ae08745Sheppo for (prop = pnp->pn_propp; prop->pp_next != NULL; prop = prop->pp_next)
4441ae08745Sheppo /* empty */;
4451ae08745Sheppo
4461ae08745Sheppo /* append the new prop */
4471ae08745Sheppo prop->pp_next = newprop;
4481ae08745Sheppo }
4491ae08745Sheppo
4501ae08745Sheppo static void
promif_dump_tree(prom_node_t * pnp)4511ae08745Sheppo promif_dump_tree(prom_node_t *pnp)
4521ae08745Sheppo {
4531ae08745Sheppo int i;
4541ae08745Sheppo static int level = 0;
4551ae08745Sheppo
4561ae08745Sheppo if (pnp == NULL)
4571ae08745Sheppo return;
4581ae08745Sheppo
4591ae08745Sheppo for (i = 0; i < level; i++) {
4601ae08745Sheppo prom_printf(" ");
4611ae08745Sheppo }
4621ae08745Sheppo
4631ae08745Sheppo prom_printf("Node 0x%x (parent=0x%x, sibling=0x%x)\n", pnp->pn_nodeid,
4641ae08745Sheppo (pnp->pn_parent) ? pnp->pn_parent->pn_nodeid : 0,
4651ae08745Sheppo (pnp->pn_sibling) ? pnp->pn_sibling->pn_nodeid : 0);
4661ae08745Sheppo
4671ae08745Sheppo if (pnp->pn_child != NULL) {
4681ae08745Sheppo level++;
4691ae08745Sheppo promif_dump_tree(pnp->pn_child);
4701ae08745Sheppo level--;
4711ae08745Sheppo }
4721ae08745Sheppo
4731ae08745Sheppo if (pnp->pn_sibling != NULL)
4741ae08745Sheppo promif_dump_tree(pnp->pn_sibling);
4751ae08745Sheppo }
4761ae08745Sheppo
4771ae08745Sheppo #endif
478