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>
31 #include <sys/prom_emul.h>
32 #include <sys/obpdefs.h>
33 #include <sys/sunddi.h>
35 static prom_node_t
*promif_top
;
37 static prom_node_t
*promif_find_node(pnode_t nodeid
);
38 static int getproplen(prom_node_t
*pnp
, char *name
);
39 static void *getprop(prom_node_t
*pnp
, char *name
);
42 promif_create_prop(prom_node_t
*pnp
, char *name
, void *val
, int len
, int flags
)
44 struct prom_prop
*p
, *q
;
46 q
= kmem_zalloc(sizeof (*q
), KM_SLEEP
);
47 q
->pp_name
= kmem_zalloc(strlen(name
) + 1, KM_SLEEP
);
48 (void) strcpy(q
->pp_name
, name
);
49 q
->pp_val
= kmem_alloc(len
, KM_SLEEP
);
52 case DDI_PROP_TYPE_INT
:
53 case DDI_PROP_TYPE_INT64
:
55 * Technically, we need byte-swapping to conform to 1275.
56 * However, the old x86 prom simulator used little endian
57 * representation, so we don't swap here either.
59 * NOTE: this is inconsistent with ddi_prop_lookup_*()
60 * which does byte-swapping when looking up prom properties.
61 * Since all kernel nodes are SID nodes, drivers no longer
62 * access PROM properties on x86.
64 default: /* no byte swapping */
65 (void) bcopy(val
, q
->pp_val
, len
);
69 if (pnp
->pn_propp
== NULL
) {
74 for (p
= pnp
->pn_propp
; p
->pp_next
!= NULL
; p
= p
->pp_next
)
81 promif_create_node(dev_info_t
*dip
)
87 pnp
= kmem_zalloc(sizeof (prom_node_t
), KM_SLEEP
);
88 pnp
->pn_nodeid
= DEVI(dip
)->devi_nodeid
;
90 hwprop
= DEVI(dip
)->devi_hw_prop_ptr
;
91 while (hwprop
!= NULL
) {
92 /* need to encode to proper endianness */
93 promif_create_prop(pnp
, hwprop
->prop_name
, hwprop
->prop_val
,
94 hwprop
->prop_len
, hwprop
->prop_flags
& DDI_PROP_TYPE_MASK
);
95 hwprop
= hwprop
->prop_next
;
97 nodename
= ddi_node_name(dip
);
98 promif_create_prop(pnp
, "name", nodename
, strlen(nodename
) + 1,
99 DDI_PROP_TYPE_STRING
);
104 static void promif_create_children(prom_node_t
*, dev_info_t
*);
107 promif_create_peers(prom_node_t
*pnp
, dev_info_t
*dip
)
109 dev_info_t
*ndip
= ddi_get_next_sibling(dip
);
112 pnp
->pn_sibling
= promif_create_node(ndip
);
113 promif_create_children(pnp
->pn_sibling
, ndip
);
114 pnp
= pnp
->pn_sibling
;
115 ndip
= ddi_get_next_sibling(ndip
);
120 promif_create_children(prom_node_t
*pnp
, dev_info_t
*dip
)
122 dev_info_t
*cdip
= ddi_get_child(dip
);
125 pnp
->pn_child
= promif_create_node(cdip
);
126 promif_create_peers(pnp
->pn_child
, cdip
);
128 cdip
= ddi_get_child(cdip
);
133 promif_create_device_tree(void)
135 promif_top
= promif_create_node(ddi_root_node());
136 promif_create_children(promif_top
, ddi_root_node());
140 find_node_work(prom_node_t
*pnp
, pnode_t n
)
144 if (pnp
->pn_nodeid
== n
)
148 if ((qnp
= find_node_work(pnp
->pn_child
, n
)) != NULL
)
152 if ((qnp
= find_node_work(pnp
->pn_sibling
, n
)) != NULL
)
159 promif_find_node(pnode_t nodeid
)
161 if (nodeid
== OBP_NONODE
)
164 if (promif_top
== NULL
)
167 return (find_node_work(promif_top
, nodeid
));
171 promif_nextnode(pnode_t nodeid
)
176 * Note: next(0) returns the root node
178 pnp
= promif_find_node(nodeid
);
179 if (pnp
&& (nodeid
== OBP_NONODE
))
180 return (pnp
->pn_nodeid
);
181 if (pnp
&& pnp
->pn_sibling
)
182 return (pnp
->pn_sibling
->pn_nodeid
);
188 promif_childnode(pnode_t nodeid
)
192 pnp
= promif_find_node(nodeid
);
193 if (pnp
&& pnp
->pn_child
)
194 return (pnp
->pn_child
->pn_nodeid
);
200 * Retrieve a PROM property (len and value)
204 getproplen(prom_node_t
*pnp
, char *name
)
206 struct prom_prop
*propp
;
208 for (propp
= pnp
->pn_propp
; propp
!= NULL
; propp
= propp
->pp_next
)
209 if (strcmp(propp
->pp_name
, name
) == 0)
210 return (propp
->pp_len
);
216 promif_getproplen(pnode_t nodeid
, char *name
)
220 pnp
= promif_find_node(nodeid
);
224 return (getproplen(pnp
, name
));
228 getprop(prom_node_t
*pnp
, char *name
)
230 struct prom_prop
*propp
;
232 for (propp
= pnp
->pn_propp
; propp
!= NULL
; propp
= propp
->pp_next
)
233 if (strcmp(propp
->pp_name
, name
) == 0)
234 return (propp
->pp_val
);
240 promif_getprop(pnode_t nodeid
, char *name
, void *value
)
246 pnp
= promif_find_node(nodeid
);
250 len
= getproplen(pnp
, name
);
252 v
= getprop(pnp
, name
);
253 bcopy(v
, value
, len
);
259 nextprop(prom_node_t
*pnp
, char *name
)
261 struct prom_prop
*propp
;
264 * getting next of NULL or a null string returns the first prop name
266 if (name
== NULL
|| *name
== '\0')
268 return (pnp
->pn_propp
->pp_name
);
270 for (propp
= pnp
->pn_propp
; propp
!= NULL
; propp
= propp
->pp_next
)
271 if (strcmp(propp
->pp_name
, name
) == 0)
273 return (propp
->pp_next
->pp_name
);
279 promif_nextprop(pnode_t nodeid
, char *name
, char *next
)
286 pnp
= promif_find_node(nodeid
);
290 s
= nextprop(pnp
, name
);
294 (void) strcpy(next
, s
);