4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <sys/types.h>
28 #include <sys/esunddi.h>
29 #include <sys/promif_impl.h>
32 static pnode_t chosennode
;
33 static pnode_t optionsnode
;
35 static char *gettoken(char *tp
, char *token
);
36 static pnode_t
finddevice(char *path
);
40 * Routines for walking the PROMs devinfo tree
46 promif_set_nodes(pnode_t chosen
, pnode_t options
)
49 optionsnode
= options
;
53 promif_finddevice(void *p
)
55 cell_t
*ci
= (cell_t
*)p
;
60 path
= p1275_cell2ptr(ci
[3]);
62 if (strcmp("/chosen", path
) == 0) {
63 ci
[4] = p1275_dnode2cell(chosennode
);
64 } else if (strcmp("/options", path
) == 0) {
65 ci
[4] = p1275_dnode2cell(optionsnode
);
67 /* only supports known nodes */
77 promif_finddevice(void *p
)
79 cell_t
*ci
= (cell_t
*)p
;
85 * We are passing the cpu pointer (CPU->cpu_id) explicitly to
86 * thread_affinity_set() so that we don't attempt to grab the
87 * cpu_lock internally in thread_affinity_set() and may sleep
89 * It is safe to pass CPU->cpu_id and it will always be valid.
91 thread_affinity_set(curthread
, CPU
->cpu_id
);
92 node
= finddevice(p1275_cell2ptr(ci
[3]));
94 ci
[4] = p1275_dnode2cell(node
);
95 thread_affinity_clear(curthread
);
103 promif_nextnode(void *p
)
105 cell_t
*ci
= (cell_t
*)p
;
110 next
= promif_stree_nextnode(p1275_cell2dnode(ci
[3]));
112 ci
[4] = p1275_dnode2cell(next
);
118 promif_childnode(void *p
)
120 cell_t
*ci
= (cell_t
*)p
;
125 child
= promif_stree_childnode(p1275_cell2dnode(ci
[3]));
127 ci
[4] = p1275_dnode2cell(child
);
133 promif_parentnode(void *p
)
135 cell_t
*ci
= (cell_t
*)p
;
140 parent
= promif_stree_parentnode(p1275_cell2dnode(ci
[3]));
142 ci
[4] = p1275_dnode2cell(parent
);
150 * Get a token from a prom pathname, collecting everything
151 * until a non-comma, non-colon separator is found. Any
152 * options, including the ':' option separator, on the end
153 * of the token are removed.
156 gettoken(char *tp
, char *token
)
158 char *result
= token
;
161 tp
= prom_path_gettoken(tp
, token
);
162 token
+= prom_strlen(token
);
163 if ((*tp
== ',') || (*tp
== ':')) {
171 /* strip off any options from the token */
172 prom_strip_options(result
, result
);
178 * Retrieve the unit address for a node by looking it up
179 * in the corresponding dip. -1 is returned if no unit
180 * address can be determined.
183 get_unit_addr(pnode_t np
, char *paddr
)
188 if ((dip
= e_ddi_nodeid_to_dip(np
)) == NULL
) {
192 if ((addr
= ddi_get_name_addr(dip
)) == NULL
) {
193 ddi_release_devi(dip
);
197 (void) prom_strcpy(paddr
, addr
);
199 ddi_release_devi(dip
);
205 * Get node id of node in prom tree that path identifies
208 finddevice(char *path
)
210 char name
[OBP_MAXPROPNAME
];
211 char addr
[OBP_MAXPROPNAME
];
212 char pname
[OBP_MAXPROPNAME
];
213 char paddr
[OBP_MAXPROPNAME
];
218 CIF_DBG_NODE("finddevice: %s\n", path
);
221 np
= prom_rootnode();
222 device
= OBP_BADNODE
;
224 /* must be a fully specified path */
229 /* get the name from the path */
230 tp
= gettoken(tp
, name
);
234 /* get the address from the path */
237 tp
= gettoken(tp
, addr
);
242 CIF_DBG_NODE("looking for: %s%s%s\n", name
,
243 (*addr
!= '\0') ? "@" : "", addr
);
245 if ((np
= prom_childnode(np
)) == OBP_NONODE
)
248 while (np
!= OBP_NONODE
) {
250 /* get the name from the current node */
251 if (prom_getprop(np
, OBP_NAME
, pname
) < 0)
254 /* get the address from the current node */
255 if (get_unit_addr(np
, paddr
) < 0)
258 /* compare the names and addresses */
259 if ((prom_strcmp(name
, pname
) == 0) &&
260 (prom_strcmp(addr
, paddr
) == 0)) {
261 CIF_DBG_NODE("found dev: %s%s%s (0x%x)\n",
262 pname
, (*paddr
!= '\0') ? "@" : "",
266 CIF_DBG_NODE(" no match: %s%s%s vs %s%s%s\n",
267 name
, (*addr
!= '\0') ? "@" : "", addr
,
268 pname
, (*paddr
!= '\0') ? "@" : "", paddr
);
270 np
= prom_nextnode(np
);
273 /* path does not map to a node */
274 if (np
== OBP_NONODE
)
278 /* found a matching node */
284 * Continue the loop with the
285 * next component of the path.
291 if (device
== OBP_BADNODE
) {
292 CIF_DBG_NODE("device not found\n\n");
294 CIF_DBG_NODE("returning 0x%x\n\n", device
);