dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / arch / x86 / kernel / promif / prom_emul.c
blob5497d9eab8462ee85ad969c9da6732fe93228cfe
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
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);
41 static void
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);
50 q->pp_len = len;
51 switch (flags) {
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);
66 break;
69 if (pnp->pn_propp == NULL) {
70 pnp->pn_propp = q;
71 return;
74 for (p = pnp->pn_propp; p->pp_next != NULL; p = p->pp_next)
75 /* empty */;
77 p->pp_next = q;
80 static prom_node_t *
81 promif_create_node(dev_info_t *dip)
83 prom_node_t *pnp;
84 ddi_prop_t *hwprop;
85 char *nodename;
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);
101 return (pnp);
104 static void promif_create_children(prom_node_t *, dev_info_t *);
106 static void
107 promif_create_peers(prom_node_t *pnp, dev_info_t *dip)
109 dev_info_t *ndip = ddi_get_next_sibling(dip);
111 while (ndip) {
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);
119 static void
120 promif_create_children(prom_node_t *pnp, dev_info_t *dip)
122 dev_info_t *cdip = ddi_get_child(dip);
124 while (cdip) {
125 pnp->pn_child = promif_create_node(cdip);
126 promif_create_peers(pnp->pn_child, cdip);
127 pnp = pnp->pn_child;
128 cdip = ddi_get_child(cdip);
132 void
133 promif_create_device_tree(void)
135 promif_top = promif_create_node(ddi_root_node());
136 promif_create_children(promif_top, ddi_root_node());
139 static prom_node_t *
140 find_node_work(prom_node_t *pnp, pnode_t n)
142 prom_node_t *qnp;
144 if (pnp->pn_nodeid == n)
145 return (pnp);
147 if (pnp->pn_child)
148 if ((qnp = find_node_work(pnp->pn_child, n)) != NULL)
149 return (qnp);
151 if (pnp->pn_sibling)
152 if ((qnp = find_node_work(pnp->pn_sibling, n)) != NULL)
153 return (qnp);
155 return (NULL);
158 static prom_node_t *
159 promif_find_node(pnode_t nodeid)
161 if (nodeid == OBP_NONODE)
162 return (promif_top);
164 if (promif_top == NULL)
165 return (NULL);
167 return (find_node_work(promif_top, nodeid));
170 pnode_t
171 promif_nextnode(pnode_t nodeid)
173 prom_node_t *pnp;
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);
184 return (OBP_NONODE);
187 pnode_t
188 promif_childnode(pnode_t nodeid)
190 prom_node_t *pnp;
192 pnp = promif_find_node(nodeid);
193 if (pnp && pnp->pn_child)
194 return (pnp->pn_child->pn_nodeid);
196 return (OBP_NONODE);
200 * Retrieve a PROM property (len and value)
203 static int
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);
212 return (-1);
216 promif_getproplen(pnode_t nodeid, char *name)
218 prom_node_t *pnp;
220 pnp = promif_find_node(nodeid);
221 if (pnp == NULL)
222 return (-1);
224 return (getproplen(pnp, name));
227 static void *
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);
236 return (NULL);
240 promif_getprop(pnode_t nodeid, char *name, void *value)
242 prom_node_t *pnp;
243 void *v;
244 int len;
246 pnp = promif_find_node(nodeid);
247 if (pnp == NULL)
248 return (-1);
250 len = getproplen(pnp, name);
251 if (len > 0) {
252 v = getprop(pnp, name);
253 bcopy(v, value, len);
255 return (len);
258 static char *
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')
267 if (pnp->pn_propp)
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)
272 if (propp->pp_next)
273 return (propp->pp_next->pp_name);
275 return (NULL);
278 char *
279 promif_nextprop(pnode_t nodeid, char *name, char *next)
281 prom_node_t *pnp;
282 char *s;
284 next[0] = '\0';
286 pnp = promif_find_node(nodeid);
287 if (pnp == NULL)
288 return (NULL);
290 s = nextprop(pnp, name);
291 if (s == NULL)
292 return (next);
294 (void) strcpy(next, s);
295 return (next);