4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/promif.h>
30 #include <sys/promimpl.h>
33 * Routines for walking the PROMs devinfo tree
36 prom_nextnode(pnode_t nodeid
)
40 ci
[0] = p1275_ptr2cell("peer"); /* Service name */
41 ci
[1] = (cell_t
)1; /* #argument cells */
42 ci
[2] = (cell_t
)1; /* #result cells */
43 ci
[3] = p1275_dnode2cell(nodeid
); /* Arg1: input phandle */
44 ci
[4] = p1275_dnode2cell(OBP_NONODE
); /* Res1: Prime result */
47 (void) p1275_cif_handler(&ci
);
50 return (p1275_cell2dnode(ci
[4])); /* Res1: peer phandle */
54 prom_childnode(pnode_t nodeid
)
58 ci
[0] = p1275_ptr2cell("child"); /* Service name */
59 ci
[1] = (cell_t
)1; /* #argument cells */
60 ci
[2] = (cell_t
)1; /* #result cells */
61 ci
[3] = p1275_dnode2cell(nodeid
); /* Arg1: input phandle */
62 ci
[4] = p1275_dnode2cell(OBP_NONODE
); /* Res1: Prime result */
65 (void) p1275_cif_handler(&ci
);
68 return (p1275_cell2dnode(ci
[4])); /* Res1: child phandle */
72 * prom_walk_devs() implements a generic walker for the OBP tree; this
73 * implementation uses an explicitly managed stack in order to save the
74 * overhead of a recursive implementation.
77 prom_walk_devs(pnode_t node
, int (*cb
)(pnode_t
, void *, void *), void *arg
,
80 pnode_t stack
[OBP_STACKDEPTH
];
83 if (node
== OBP_NONODE
|| node
== OBP_BADNODE
) {
84 prom_panic("Invalid node specified as root of prom tree walk");
90 pnode_t curnode
= stack
[stackidx
];
94 * We're out of stuff to do at this level, bump back up a level
95 * in the tree, and move to the next node; if the new level
96 * will be level -1, we're done.
98 if (curnode
== OBP_NONODE
|| curnode
== OBP_BADNODE
) {
104 stack
[stackidx
] = prom_nextnode(stack
[stackidx
]);
108 switch ((*cb
)(curnode
, arg
, result
)) {
110 case PROM_WALK_TERMINATE
:
113 case PROM_WALK_CONTINUE
:
115 * If curnode has a child, traverse to it,
116 * otherwise move to curnode's sibling.
118 child
= prom_childnode(curnode
);
119 if (child
!= OBP_NONODE
&& child
!= OBP_BADNODE
) {
121 stack
[stackidx
] = child
;
124 prom_nextnode(stack
[stackidx
]);
129 prom_panic("unrecognized walk directive");
135 * prom_findnode_bydevtype() searches the prom device subtree rooted at 'node'
136 * and returns the first node whose device type property matches the type
137 * supplied in 'devtype'.
140 bytype_cb(pnode_t node
, void *arg
, void *result
)
142 if (prom_devicetype(node
, (char *)arg
)) {
143 *((pnode_t
*)result
) = node
;
144 return (PROM_WALK_TERMINATE
);
146 return (PROM_WALK_CONTINUE
);
150 prom_findnode_bydevtype(pnode_t node
, char *devtype
)
152 pnode_t result
= OBP_NONODE
;
153 prom_walk_devs(node
, bytype_cb
, devtype
, &result
);
159 * prom_findnode_byname() searches the prom device subtree rooted at 'node' and
160 * returns the first node whose name matches the name supplied in 'name'.
163 byname_cb(pnode_t node
, void *arg
, void *result
)
165 if (prom_getnode_byname(node
, (char *)arg
)) {
166 *((pnode_t
*)result
) = node
;
167 return (PROM_WALK_TERMINATE
);
169 return (PROM_WALK_CONTINUE
);
173 prom_findnode_byname(pnode_t node
, char *name
)
175 pnode_t result
= OBP_NONODE
;
176 prom_walk_devs(node
, byname_cb
, name
, &result
);
181 * Return the root nodeid.
182 * Calling prom_nextnode(0) returns the root nodeid.
187 static pnode_t rootnode
;
189 return (rootnode
? rootnode
: (rootnode
= prom_nextnode(OBP_NONODE
)));
193 prom_parentnode(pnode_t nodeid
)
197 ci
[0] = p1275_ptr2cell("parent"); /* Service name */
198 ci
[1] = (cell_t
)1; /* #argument cells */
199 ci
[2] = (cell_t
)1; /* #result cells */
200 ci
[3] = p1275_dnode2cell(nodeid
); /* Arg1: input phandle */
201 ci
[4] = p1275_dnode2cell(OBP_NONODE
); /* Res1: Prime result */
204 (void) p1275_cif_handler(&ci
);
207 return (p1275_cell2dnode(ci
[4])); /* Res1: parent phandle */
211 prom_finddevice(char *path
)
214 #ifdef PROM_32BIT_ADDRS
218 if ((uintptr_t)path
> (uint32_t)-1) {
220 len
= prom_strlen(opath
) + 1; /* include terminating NUL */
221 path
= promplat_alloc(len
);
223 return (OBP_BADNODE
);
225 (void) prom_strcpy(path
, opath
);
231 ci
[0] = p1275_ptr2cell("finddevice"); /* Service name */
232 ci
[1] = (cell_t
)1; /* #argument cells */
233 ci
[2] = (cell_t
)1; /* #result cells */
234 ci
[3] = p1275_ptr2cell(path
); /* Arg1: pathname */
235 ci
[4] = p1275_dnode2cell(OBP_BADNODE
); /* Res1: Prime result */
237 (void) p1275_cif_handler(&ci
);
241 #ifdef PROM_32BIT_ADDRS
243 promplat_free(path
, len
);
246 return ((pnode_t
)p1275_cell2dnode(ci
[4])); /* Res1: phandle */
250 prom_chosennode(void)
252 static pnode_t chosen
;
258 node
= prom_finddevice("/chosen");
260 if (node
!= OBP_BADNODE
)
261 return (chosen
= node
);
263 prom_fatal_error("prom_chosennode: Can't find </chosen>\n");
267 * gcc doesn't recognize "NOTREACHED" and puts the warning.
268 * To surpress it, returning an integer value is required.
274 * Returns the nodeid of /aliases.
275 * /aliases exists in OBP >= 2.4 and in Open Firmware.
276 * Returns OBP_BADNODE if it doesn't exist.
279 prom_alias_node(void)
284 node
= prom_finddevice("/aliases");
289 * Returns the nodeid of /options.
290 * Returns OBP_BADNODE if it doesn't exist.
293 prom_optionsnode(void)
298 node
= prom_finddevice("/options");