Sun Jan 24 19:38:37 2021 UTC ()
Rewrite of_compatible() using strlist_match().


(thorpej)
diff -r1.46 -r1.47 src/sys/dev/ofw/ofw_subr.c

cvs diff -r1.46 -r1.47 src/sys/dev/ofw/ofw_subr.c (switch to unified diff)

--- src/sys/dev/ofw/ofw_subr.c 2021/01/24 17:44:16 1.46
+++ src/sys/dev/ofw/ofw_subr.c 2021/01/24 19:38:37 1.47
@@ -1,670 +1,641 @@ @@ -1,670 +1,641 @@
1/* $NetBSD: ofw_subr.c,v 1.46 2021/01/24 17:44:16 thorpej Exp $ */ 1/* $NetBSD: ofw_subr.c,v 1.47 2021/01/24 19:38:37 thorpej Exp $ */
2 2
3/* 3/*
4 * Copyright 1998 4 * Copyright 1998
5 * Digital Equipment Corporation. All rights reserved. 5 * Digital Equipment Corporation. All rights reserved.
6 * 6 *
7 * This software is furnished under license and may be used and 7 * This software is furnished under license and may be used and
8 * copied only in accordance with the following terms and conditions. 8 * copied only in accordance with the following terms and conditions.
9 * Subject to these conditions, you may download, copy, install, 9 * Subject to these conditions, you may download, copy, install,
10 * use, modify and distribute this software in source and/or binary 10 * use, modify and distribute this software in source and/or binary
11 * form. No title or ownership is transferred hereby. 11 * form. No title or ownership is transferred hereby.
12 * 12 *
13 * 1) Any source code used, modified or distributed must reproduce 13 * 1) Any source code used, modified or distributed must reproduce
14 * and retain this copyright notice and list of conditions as 14 * and retain this copyright notice and list of conditions as
15 * they appear in the source file. 15 * they appear in the source file.
16 * 16 *
17 * 2) No right is granted to use any trade name, trademark, or logo of 17 * 2) No right is granted to use any trade name, trademark, or logo of
18 * Digital Equipment Corporation. Neither the "Digital Equipment 18 * Digital Equipment Corporation. Neither the "Digital Equipment
19 * Corporation" name nor any trademark or logo of Digital Equipment 19 * Corporation" name nor any trademark or logo of Digital Equipment
20 * Corporation may be used to endorse or promote products derived 20 * Corporation may be used to endorse or promote products derived
21 * from this software without the prior written permission of 21 * from this software without the prior written permission of
22 * Digital Equipment Corporation. 22 * Digital Equipment Corporation.
23 * 23 *
24 * 3) This software is provided "AS-IS" and any express or implied 24 * 3) This software is provided "AS-IS" and any express or implied
25 * warranties, including but not limited to, any implied warranties 25 * warranties, including but not limited to, any implied warranties
26 * of merchantability, fitness for a particular purpose, or 26 * of merchantability, fitness for a particular purpose, or
27 * non-infringement are disclaimed. In no event shall DIGITAL be 27 * non-infringement are disclaimed. In no event shall DIGITAL be
28 * liable for any damages whatsoever, and in particular, DIGITAL 28 * liable for any damages whatsoever, and in particular, DIGITAL
29 * shall not be liable for special, indirect, consequential, or 29 * shall not be liable for special, indirect, consequential, or
30 * incidental damages or damages for lost profits, loss of 30 * incidental damages or damages for lost profits, loss of
31 * revenue or loss of use, whether such damages arise in contract, 31 * revenue or loss of use, whether such damages arise in contract,
32 * negligence, tort, under statute, in equity, at law or otherwise, 32 * negligence, tort, under statute, in equity, at law or otherwise,
33 * even if advised of the possibility of such damage. 33 * even if advised of the possibility of such damage.
34 */ 34 */
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37__KERNEL_RCSID(0, "$NetBSD: ofw_subr.c,v 1.46 2021/01/24 17:44:16 thorpej Exp $"); 37__KERNEL_RCSID(0, "$NetBSD: ofw_subr.c,v 1.47 2021/01/24 19:38:37 thorpej Exp $");
38 38
39#include <sys/param.h> 39#include <sys/param.h>
40#include <sys/device.h> 40#include <sys/device.h>
41#include <sys/kmem.h> 41#include <sys/kmem.h>
42#include <sys/systm.h> 42#include <sys/systm.h>
43#include <sys/malloc.h> 43#include <sys/malloc.h>
44#include <dev/ofw/openfirm.h> 44#include <dev/ofw/openfirm.h>
45 45
46#define OFW_MAX_STACK_BUF_SIZE 256 46#define OFW_MAX_STACK_BUF_SIZE 256
47#define OFW_PATH_BUF_SIZE 512 47#define OFW_PATH_BUF_SIZE 512
48 48
49/* 49/*
50 * int of_decode_int(p) 50 * int of_decode_int(p)
51 * 51 *
52 * This routine converts OFW encoded-int datums 52 * This routine converts OFW encoded-int datums
53 * into the integer format of the host machine. 53 * into the integer format of the host machine.
54 * 54 *
55 * It is primarily used to convert integer properties 55 * It is primarily used to convert integer properties
56 * returned by the OF_getprop routine. 56 * returned by the OF_getprop routine.
57 * 57 *
58 * Arguments: 58 * Arguments:
59 * p pointer to unsigned char array which is an 59 * p pointer to unsigned char array which is an
60 * OFW-encoded integer. 60 * OFW-encoded integer.
61 * 61 *
62 * Return Value: 62 * Return Value:
63 * Decoded integer value of argument p. 63 * Decoded integer value of argument p.
64 * 64 *
65 * Side Effects: 65 * Side Effects:
66 * None. 66 * None.
67 */ 67 */
68int 68int
69of_decode_int(const unsigned char *p) 69of_decode_int(const unsigned char *p)
70{ 70{
71 unsigned int i = *p++ << 8; 71 unsigned int i = *p++ << 8;
72 i = (i + *p++) << 8; 72 i = (i + *p++) << 8;
73 i = (i + *p++) << 8; 73 i = (i + *p++) << 8;
74 return (i + *p); 74 return (i + *p);
75} 75}
76 76
77/* 77/*
78 * int of_compatible(phandle, strings) 78 * int of_compatible(phandle, strings)
79 * 79 *
80 * This routine checks an OFW node's "compatible" entry to see if 80 * This routine checks an OFW node's "compatible" entry to see if
81 * it matches any of the provided strings. 81 * it matches any of the provided strings.
82 * 82 *
83 * It should be used when determining whether a driver can drive 83 * It should be used when determining whether a driver can drive
84 * a particular device. 84 * a particular device.
85 * 85 *
86 * Arguments: 86 * Arguments:
87 * phandle OFW phandle of device to be checked for 87 * phandle OFW phandle of device to be checked for
88 * compatibility. 88 * compatibility.
89 * strings Array of containing expected "compatibility" 89 * strings Array of containing expected "compatibility"
90 * property values, presence of any of which 90 * property values, presence of any of which
91 * indicates compatibility. 91 * indicates compatibility.
92 * 92 *
93 * Return Value: 93 * Return Value:
94 * -1 if none of the strings are found in phandle's "compatibility" 94 * -1 if none of the strings are found in phandle's "compatibility"
95 * property, or the reverse index of the matching string in the 95 * property, or the reverse index of the matching string in the
96 * phandle's "compatibility" property. 96 * phandle's "compatibility" property.
97 * 97 *
98 * Side Effects: 98 * Side Effects:
99 * None. 99 * None.
100 */ 100 */
101int 101int
102of_compatible(int phandle, const char * const *strings) 102of_compatible(int phandle, const char * const *strings)
103{ 103{
 104 char *prop, propbuf[OFW_MAX_STACK_BUF_SIZE];
 105 const char *cp;
 106 int proplen, match, rv = -1;
104 107
105 int len, olen, allocated, nstr, cstr, rv; 108 proplen = OF_getproplen(phandle, "compatible");
106 char *buf, sbuf[OFW_MAX_STACK_BUF_SIZE]; 109 if (proplen <= 0) {
107 const char *sp, *nsp; 110 return -1;
108 
109 len = OF_getproplen(phandle, "compatible"); 
110 if (len <= 0) 
111 return (-1); 
112 
113 if (len > sizeof(sbuf)) { 
114 buf = malloc(len, M_TEMP, M_WAITOK); 
115 allocated = 1; 
116 } else { 
117 buf = sbuf; 
118 allocated = 0; 
119 } 111 }
120 112
121 /* 'compatible' size should not change. */ 113 prop = kmem_tmpbuf_alloc(proplen, propbuf, sizeof(propbuf), KM_SLEEP);
122 if (OF_getprop(phandle, "compatible", buf, len) != len) { 114
123 rv = -1; 115 if (OF_getprop(phandle, "compatible", prop, proplen) != proplen) {
124 goto out; 116 goto out;
125 } 117 }
126 118
127 /* count 'compatible' strings */ 119 for (; (cp = *strings) != NULL; strings++) {
128 sp = buf; 120 if ((match = strlist_match(prop, proplen, cp)) != 0) {
129 nstr = 0; 121 rv = match - 1;
130 olen = len; 122 break;
131 while (len && (nsp = memchr(sp, 0, len)) != NULL) { 123 }
132 nsp++; /* skip over NUL char */ 124 }
133 len -= (nsp - sp); 125
134 sp = nsp; 126 out:
135 nstr++; 127 kmem_tmpbuf_free(prop, proplen, propbuf);
136 } 128 return rv;
137 len = olen; 
138 
139 sp = buf; 
140 rv = nstr; 
141 while (len && (nsp = memchr(sp, 0, len)) != NULL) { 
142 rv--; 
143 /* look for a match among the strings provided */ 
144 for (cstr = 0; strings[cstr] != NULL; cstr++) 
145 if (strcmp(sp, strings[cstr]) == 0) 
146 goto out; 
147 
148 nsp++; /* skip over NUL char */ 
149 len -= (nsp - sp); 
150 sp = nsp; 
151 } 
152 rv = -1; 
153 
154out: 
155 if (allocated) 
156 free(buf, M_TEMP); 
157 return (rv); 
158} 129}
159 130
160/* 131/*
161 * int of_match_compatible(phandle, strings) 132 * int of_match_compatible(phandle, strings)
162 * 133 *
163 * This routine checks an OFW node's "compatible" entry to see if 134 * This routine checks an OFW node's "compatible" entry to see if
164 * it matches any of the provided strings. 135 * it matches any of the provided strings.
165 * 136 *
166 * It should be used when determining whether a driver can drive 137 * It should be used when determining whether a driver can drive
167 * a particular device. 138 * a particular device.
168 * 139 *
169 * Arguments: 140 * Arguments:
170 * phandle OFW phandle of device to be checked for 141 * phandle OFW phandle of device to be checked for
171 * compatibility. 142 * compatibility.
172 * strings Array of containing expected "compatibility" 143 * strings Array of containing expected "compatibility"
173 * property values, presence of any of which 144 * property values, presence of any of which
174 * indicates compatibility. 145 * indicates compatibility.
175 * 146 *
176 * Return Value: 147 * Return Value:
177 * 0 if none of the strings are found in phandle's "compatibility" 148 * 0 if none of the strings are found in phandle's "compatibility"
178 * property, or a positive number based on the reverse index of the 149 * property, or a positive number based on the reverse index of the
179 * matching string in the phandle's "compatibility" property, plus 1. 150 * matching string in the phandle's "compatibility" property, plus 1.
180 * 151 *
181 * Side Effects: 152 * Side Effects:
182 * None. 153 * None.
183 */ 154 */
184int 155int
185of_match_compatible(int phandle, const char * const *strings) 156of_match_compatible(int phandle, const char * const *strings)
186{ 157{
187 return of_compatible(phandle, strings) + 1; 158 return of_compatible(phandle, strings) + 1;
188} 159}
189 160
190/* 161/*
191 * int of_match_compat_data(phandle, compat_data) 162 * int of_match_compat_data(phandle, compat_data)
192 * 163 *
193 * This routine searches an array of compat_data structures for a 164 * This routine searches an array of compat_data structures for a
194 * matching "compatible" entry matching the supplied OFW node. 165 * matching "compatible" entry matching the supplied OFW node.
195 * 166 *
196 * It should be used when determining whether a driver can drive 167 * It should be used when determining whether a driver can drive
197 * a particular device. 168 * a particular device.
198 * 169 *
199 * Arguments: 170 * Arguments:
200 * phandle OFW phandle of device to be checked for 171 * phandle OFW phandle of device to be checked for
201 * compatibility. 172 * compatibility.
202 * compat_data Array of possible compat entry strings and 173 * compat_data Array of possible compat entry strings and
203 * associated metadata. The last entry in the 174 * associated metadata. The last entry in the
204 * list should have a "compat" of NULL to terminate 175 * list should have a "compat" of NULL to terminate
205 * the list. 176 * the list.
206 * 177 *
207 * Return Value: 178 * Return Value:
208 * 0 if none of the strings are found in phandle's "compatibility" 179 * 0 if none of the strings are found in phandle's "compatibility"
209 * property, or a positive number based on the reverse index of the 180 * property, or a positive number based on the reverse index of the
210 * matching string in the phandle's "compatibility" property, plus 1. 181 * matching string in the phandle's "compatibility" property, plus 1.
211 * 182 *
212 * Side Effects: 183 * Side Effects:
213 * None. 184 * None.
214 */ 185 */
215int 186int
216of_match_compat_data(int phandle, 187of_match_compat_data(int phandle,
217 const struct device_compatible_entry *compat_data) 188 const struct device_compatible_entry *compat_data)
218{ 189{
219 char *prop, propbuf[OFW_MAX_STACK_BUF_SIZE]; 190 char *prop, propbuf[OFW_MAX_STACK_BUF_SIZE];
220 int proplen, match = 0; 191 int proplen, match = 0;
221 192
222 proplen = OF_getproplen(phandle, "compatible"); 193 proplen = OF_getproplen(phandle, "compatible");
223 if (proplen <= 0) { 194 if (proplen <= 0) {
224 return 0; 195 return 0;
225 } 196 }
226 197
227 prop = kmem_tmpbuf_alloc(proplen, propbuf, sizeof(propbuf), KM_SLEEP); 198 prop = kmem_tmpbuf_alloc(proplen, propbuf, sizeof(propbuf), KM_SLEEP);
228 199
229 if (OF_getprop(phandle, "compatible", prop, proplen) != proplen) { 200 if (OF_getprop(phandle, "compatible", prop, proplen) != proplen) {
230 goto out; 201 goto out;
231 } 202 }
232 203
233 match = device_compatible_match_strlist(prop, proplen, compat_data); 204 match = device_compatible_match_strlist(prop, proplen, compat_data);
234 205
235 out: 206 out:
236 kmem_tmpbuf_free(prop, proplen, propbuf); 207 kmem_tmpbuf_free(prop, proplen, propbuf);
237 return match; 208 return match;
238} 209}
239 210
240/* 211/*
241 * const struct device_compatible_entry *of_search_compatible(phandle, 212 * const struct device_compatible_entry *of_search_compatible(phandle,
242 * compat_data) 213 * compat_data)
243 * 214 *
244 * This routine searches an array of compat_data structures for a 215 * This routine searches an array of compat_data structures for a
245 * matching "compatible" entry matching the supplied OFW node. 216 * matching "compatible" entry matching the supplied OFW node.
246 * 217 *
247 * Arguments: 218 * Arguments:
248 * phandle OFW phandle of device to be checked for 219 * phandle OFW phandle of device to be checked for
249 * compatibility. 220 * compatibility.
250 * compat_data Array of possible compat entry strings and 221 * compat_data Array of possible compat entry strings and
251 * associated metadata. The last entry in the 222 * associated metadata. The last entry in the
252 * list should have a "compat" of NULL to terminate 223 * list should have a "compat" of NULL to terminate
253 * the list. 224 * the list.
254 * 225 *
255 * Return Value: 226 * Return Value:
256 * The first matching compat_data entry in the array. If no matches 227 * The first matching compat_data entry in the array. If no matches
257 * are found, NULL is returned. 228 * are found, NULL is returned.
258 * 229 *
259 * Side Effects: 230 * Side Effects:
260 * None. 231 * None.
261 */ 232 */
262const struct device_compatible_entry * 233const struct device_compatible_entry *
263of_search_compatible(int phandle, 234of_search_compatible(int phandle,
264 const struct device_compatible_entry *compat_data) 235 const struct device_compatible_entry *compat_data)
265{ 236{
266 char *prop, propbuf[OFW_MAX_STACK_BUF_SIZE]; 237 char *prop, propbuf[OFW_MAX_STACK_BUF_SIZE];
267 const struct device_compatible_entry *match = NULL; 238 const struct device_compatible_entry *match = NULL;
268 int proplen; 239 int proplen;
269 240
270 proplen = OF_getproplen(phandle, "compatible"); 241 proplen = OF_getproplen(phandle, "compatible");
271 if (proplen <= 0) { 242 if (proplen <= 0) {
272 return 0; 243 return 0;
273 } 244 }
274 245
275 prop = kmem_tmpbuf_alloc(proplen, propbuf, sizeof(propbuf), KM_SLEEP); 246 prop = kmem_tmpbuf_alloc(proplen, propbuf, sizeof(propbuf), KM_SLEEP);
276 247
277 if (OF_getprop(phandle, "compatible", prop, proplen) != proplen) { 248 if (OF_getprop(phandle, "compatible", prop, proplen) != proplen) {
278 goto out; 249 goto out;
279 } 250 }
280 251
281 match = device_compatible_lookup_strlist(prop, proplen, compat_data); 252 match = device_compatible_lookup_strlist(prop, proplen, compat_data);
282 253
283 out: 254 out:
284 kmem_tmpbuf_free(prop, proplen, propbuf); 255 kmem_tmpbuf_free(prop, proplen, propbuf);
285 return match; 256 return match;
286} 257}
287 258
288/* 259/*
289 * int of_packagename(phandle, buf, bufsize) 260 * int of_packagename(phandle, buf, bufsize)
290 * 261 *
291 * This routine places the last component of an OFW node's name 262 * This routine places the last component of an OFW node's name
292 * into a user-provided buffer. 263 * into a user-provided buffer.
293 * 264 *
294 * It can be used during autoconfiguration to make printing of 265 * It can be used during autoconfiguration to make printing of
295 * device names more informative. 266 * device names more informative.
296 * 267 *
297 * Arguments: 268 * Arguments:
298 * phandle OFW phandle of device whose name name is 269 * phandle OFW phandle of device whose name name is
299 * desired. 270 * desired.
300 * buf Buffer to contain device name, provided by 271 * buf Buffer to contain device name, provided by
301 * caller. (For now, must be at least 4 272 * caller. (For now, must be at least 4
302 * bytes long.) 273 * bytes long.)
303 * bufsize Length of buffer referenced by 'buf', in 274 * bufsize Length of buffer referenced by 'buf', in
304 * bytes. 275 * bytes.
305 * 276 *
306 * Return Value: 277 * Return Value:
307 * -1 if the device path name could not be obtained or would 278 * -1 if the device path name could not be obtained or would
308 * not fit in the allocated temporary buffer, or zero otherwise 279 * not fit in the allocated temporary buffer, or zero otherwise
309 * (meaning that the leaf node name was successfully extracted). 280 * (meaning that the leaf node name was successfully extracted).
310 * 281 *
311 * Side Effects: 282 * Side Effects:
312 * If the leaf node name was successfully extracted, 'buf' is 283 * If the leaf node name was successfully extracted, 'buf' is
313 * filled in with at most 'bufsize' bytes of the leaf node 284 * filled in with at most 'bufsize' bytes of the leaf node
314 * name. If the leaf node was not successfully extracted, a 285 * name. If the leaf node was not successfully extracted, a
315 * somewhat meaningful string is placed in the buffer. In 286 * somewhat meaningful string is placed in the buffer. In
316 * either case, the contents of 'buf' will be NUL-terminated. 287 * either case, the contents of 'buf' will be NUL-terminated.
317 */ 288 */
318int 289int
319of_packagename(int phandle, char *buf, int bufsize) 290of_packagename(int phandle, char *buf, int bufsize)
320{ 291{
321 char *pbuf; 292 char *pbuf;
322 const char *lastslash; 293 const char *lastslash;
323 int l, rv; 294 int l, rv;
324 295
325 pbuf = malloc(OFW_PATH_BUF_SIZE, M_TEMP, M_WAITOK); 296 pbuf = malloc(OFW_PATH_BUF_SIZE, M_TEMP, M_WAITOK);
326 l = OF_package_to_path(phandle, pbuf, OFW_PATH_BUF_SIZE); 297 l = OF_package_to_path(phandle, pbuf, OFW_PATH_BUF_SIZE);
327 298
328 /* check that we could get the name, and that it's not too long. */ 299 /* check that we could get the name, and that it's not too long. */
329 if (l < 0 || 300 if (l < 0 ||
330 (l == OFW_PATH_BUF_SIZE && pbuf[OFW_PATH_BUF_SIZE - 1] != '\0')) { 301 (l == OFW_PATH_BUF_SIZE && pbuf[OFW_PATH_BUF_SIZE - 1] != '\0')) {
331 if (bufsize >= 25) 302 if (bufsize >= 25)
332 snprintf(buf, bufsize, "??? (phandle 0x%x)", phandle); 303 snprintf(buf, bufsize, "??? (phandle 0x%x)", phandle);
333 else if (bufsize >= 4) 304 else if (bufsize >= 4)
334 strlcpy(buf, "???", bufsize); 305 strlcpy(buf, "???", bufsize);
335 else 306 else
336 panic("of_packagename: bufsize = %d is silly", 307 panic("of_packagename: bufsize = %d is silly",
337 bufsize); 308 bufsize);
338 rv = -1; 309 rv = -1;
339 } else { 310 } else {
340 pbuf[l] = '\0'; 311 pbuf[l] = '\0';
341 lastslash = strrchr(pbuf, '/'); 312 lastslash = strrchr(pbuf, '/');
342 strlcpy(buf, (lastslash == NULL) ? pbuf : (lastslash + 1), 313 strlcpy(buf, (lastslash == NULL) ? pbuf : (lastslash + 1),
343 bufsize); 314 bufsize);
344 rv = 0; 315 rv = 0;
345 } 316 }
346 317
347 free(pbuf, M_TEMP); 318 free(pbuf, M_TEMP);
348 return (rv); 319 return (rv);
349} 320}
350 321
351/*  322/*
352 * Find the first child of a given node that matches name. Does not recurse. 323 * Find the first child of a given node that matches name. Does not recurse.
353 */ 324 */
354int 325int
355of_find_firstchild_byname(int node, const char *name) 326of_find_firstchild_byname(int node, const char *name)
356{ 327{
357 char namex[32];  328 char namex[32];
358 int nn; 329 int nn;
359  330
360 for (nn = OF_child(node); nn; nn = OF_peer(nn)) { 331 for (nn = OF_child(node); nn; nn = OF_peer(nn)) {
361 memset(namex, 0, sizeof(namex)); 332 memset(namex, 0, sizeof(namex));
362 if (OF_getprop(nn, "name", namex, sizeof(namex)) == -1) 333 if (OF_getprop(nn, "name", namex, sizeof(namex)) == -1)
363 continue; 334 continue;
364 if (strcmp(name, namex) == 0) 335 if (strcmp(name, namex) == 0)
365 return nn; 336 return nn;
366 } 337 }
367 return -1; 338 return -1;
368} 339}
369 340
370/* 341/*
371 * Find a child node that is compatible with str. Recurses, starting at node. 342 * Find a child node that is compatible with str. Recurses, starting at node.
372 */ 343 */
373int 344int
374of_find_bycompat(int node, const char *str) 345of_find_bycompat(int node, const char *str)
375{ 346{
376 const char * compatible[] = { str, NULL }; 347 const char * compatible[] = { str, NULL };
377 int child, ret; 348 int child, ret;
378 349
379 for (child = OF_child(node); child; child = OF_peer(child)) { 350 for (child = OF_child(node); child; child = OF_peer(child)) {
380 if (of_match_compatible(child, compatible) != 0) 351 if (of_match_compatible(child, compatible) != 0)
381 return child; 352 return child;
382 ret = of_find_bycompat(child, str); 353 ret = of_find_bycompat(child, str);
383 if (ret != -1) 354 if (ret != -1)
384 return ret; 355 return ret;
385 } 356 }
386 357
387 return -1; 358 return -1;
388} 359}
389 360
390/* 361/*
391 * Find a give node by name. Recurses, and seems to walk upwards too. 362 * Find a give node by name. Recurses, and seems to walk upwards too.
392 */ 363 */
393 364
394int 365int
395of_getnode_byname(int start, const char *target) 366of_getnode_byname(int start, const char *target)
396{ 367{
397 int node, next; 368 int node, next;
398 char name[64]; 369 char name[64];
399 370
400 if (start == 0) 371 if (start == 0)
401 start = OF_peer(0); 372 start = OF_peer(0);
402 373
403 for (node = start; node; node = next) { 374 for (node = start; node; node = next) {
404 memset(name, 0, sizeof name); 375 memset(name, 0, sizeof name);
405 OF_getprop(node, "name", name, sizeof name - 1); 376 OF_getprop(node, "name", name, sizeof name - 1);
406 if (strcmp(name, target) == 0) 377 if (strcmp(name, target) == 0)
407 break; 378 break;
408 379
409 if ((next = OF_child(node)) != 0) 380 if ((next = OF_child(node)) != 0)
410 continue; 381 continue;
411 382
412 while (node) { 383 while (node) {
413 if ((next = OF_peer(node)) != 0) 384 if ((next = OF_peer(node)) != 0)
414 break; 385 break;
415 node = OF_parent(node); 386 node = OF_parent(node);
416 } 387 }
417 } 388 }
418 389
419 /* XXX is this correct? */ 390 /* XXX is this correct? */
420 return node; 391 return node;
421} 392}
422 393
423/* 394/*
424 * Create a uint32_t integer property from an OFW node property. 395 * Create a uint32_t integer property from an OFW node property.
425 */ 396 */
426 397
427boolean_t 398boolean_t
428of_to_uint32_prop(prop_dictionary_t dict, int node, const char *ofname, 399of_to_uint32_prop(prop_dictionary_t dict, int node, const char *ofname,
429 const char *propname) 400 const char *propname)
430{ 401{
431 uint32_t prop; 402 uint32_t prop;
432 403
433 if (OF_getprop(node, ofname, &prop, sizeof(prop)) != sizeof(prop)) 404 if (OF_getprop(node, ofname, &prop, sizeof(prop)) != sizeof(prop))
434 return FALSE; 405 return FALSE;
435 406
436 return(prop_dictionary_set_uint32(dict, propname, prop)); 407 return(prop_dictionary_set_uint32(dict, propname, prop));
437} 408}
438 409
439/* 410/*
440 * Create a data property from an OFW node property. Max size of 256bytes. 411 * Create a data property from an OFW node property. Max size of 256bytes.
441 */ 412 */
442 413
443boolean_t 414boolean_t
444of_to_dataprop(prop_dictionary_t dict, int node, const char *ofname, 415of_to_dataprop(prop_dictionary_t dict, int node, const char *ofname,
445 const char *propname) 416 const char *propname)
446{ 417{
447 int len; 418 int len;
448 uint8_t prop[256]; 419 uint8_t prop[256];
449 420
450 len = OF_getprop(node, ofname, prop, 256); 421 len = OF_getprop(node, ofname, prop, 256);
451 if (len < 1) 422 if (len < 1)
452 return FALSE; 423 return FALSE;
453 424
454 return prop_dictionary_set_data(dict, propname, prop, len); 425 return prop_dictionary_set_data(dict, propname, prop, len);
455} 426}
456 427
457/* 428/*
458 * look at output-device, see if there's a Sun-typical video mode specifier as 429 * look at output-device, see if there's a Sun-typical video mode specifier as
459 * in screen:r1024x768x60 attached. If found copy it into *buffer, otherwise 430 * in screen:r1024x768x60 attached. If found copy it into *buffer, otherwise
460 * return NULL 431 * return NULL
461 */ 432 */
462 433
463char * 434char *
464of_get_mode_string(char *buffer, int len) 435of_get_mode_string(char *buffer, int len)
465{ 436{
466 int options; 437 int options;
467 char *pos, output_device[256]; 438 char *pos, output_device[256];
468 439
469 /* 440 /*
470 * finally, let's see if there's a video mode specified in 441 * finally, let's see if there's a video mode specified in
471 * output-device and pass it on so there's at least some way 442 * output-device and pass it on so there's at least some way
472 * to program video modes 443 * to program video modes
473 */ 444 */
474 options = OF_finddevice("/options"); 445 options = OF_finddevice("/options");
475 if ((options == 0) || (options == -1)) 446 if ((options == 0) || (options == -1))
476 return NULL; 447 return NULL;
477 if (OF_getprop(options, "output-device", output_device, 256) == 0) 448 if (OF_getprop(options, "output-device", output_device, 256) == 0)
478 return NULL; 449 return NULL;
479 450
480 /* find the mode string if there is one */ 451 /* find the mode string if there is one */
481 pos = strstr(output_device, ":r"); 452 pos = strstr(output_device, ":r");
482 if (pos == NULL) 453 if (pos == NULL)
483 return NULL; 454 return NULL;
484 strncpy(buffer, pos + 2, len); 455 strncpy(buffer, pos + 2, len);
485 return buffer; 456 return buffer;
486} 457}
487 458
488/* 459/*
489 * Iterate over the subtree of a i2c controller node. 460 * Iterate over the subtree of a i2c controller node.
490 * Add all sub-devices into an array as part of the controller's 461 * Add all sub-devices into an array as part of the controller's
491 * device properties. 462 * device properties.
492 * This is used by the i2c bus attach code to do direct configuration. 463 * This is used by the i2c bus attach code to do direct configuration.
493 */ 464 */
494void 465void
495of_enter_i2c_devs(prop_dictionary_t props, int ofnode, size_t cell_size, 466of_enter_i2c_devs(prop_dictionary_t props, int ofnode, size_t cell_size,
496 int addr_shift) 467 int addr_shift)
497{ 468{
498 int node, len; 469 int node, len;
499 char name[32]; 470 char name[32];
500 uint64_t reg64; 471 uint64_t reg64;
501 uint32_t reg32; 472 uint32_t reg32;
502 uint64_t addr; 473 uint64_t addr;
503 prop_array_t array = NULL; 474 prop_array_t array = NULL;
504 prop_dictionary_t dev; 475 prop_dictionary_t dev;
505 476
506 for (node = OF_child(ofnode); node; node = OF_peer(node)) { 477 for (node = OF_child(ofnode); node; node = OF_peer(node)) {
507 if (OF_getprop(node, "name", name, sizeof(name)) <= 0) 478 if (OF_getprop(node, "name", name, sizeof(name)) <= 0)
508 continue; 479 continue;
509 len = OF_getproplen(node, "reg"); 480 len = OF_getproplen(node, "reg");
510 addr = 0; 481 addr = 0;
511 if (cell_size == 8 && len >= sizeof(reg64)) { 482 if (cell_size == 8 && len >= sizeof(reg64)) {
512 if (OF_getprop(node, "reg", &reg64, sizeof(reg64)) 483 if (OF_getprop(node, "reg", &reg64, sizeof(reg64))
513 < sizeof(reg64)) 484 < sizeof(reg64))
514 continue; 485 continue;
515 addr = be64toh(reg64); 486 addr = be64toh(reg64);
516 /* 487 /*
517 * The i2c bus number (0 or 1) is encoded in bit 33 488 * The i2c bus number (0 or 1) is encoded in bit 33
518 * of the register, but we encode it in bit 8 of 489 * of the register, but we encode it in bit 8 of
519 * i2c_addr_t. 490 * i2c_addr_t.
520 */ 491 */
521 if (addr & 0x100000000) 492 if (addr & 0x100000000)
522 addr = (addr & 0xff) | 0x100; 493 addr = (addr & 0xff) | 0x100;
523 } else if (cell_size == 4 && len >= sizeof(reg32)) { 494 } else if (cell_size == 4 && len >= sizeof(reg32)) {
524 if (OF_getprop(node, "reg", &reg32, sizeof(reg32)) 495 if (OF_getprop(node, "reg", &reg32, sizeof(reg32))
525 < sizeof(reg32)) 496 < sizeof(reg32))
526 continue; 497 continue;
527 addr = be32toh(reg32); 498 addr = be32toh(reg32);
528 } else { 499 } else {
529 continue; 500 continue;
530 } 501 }
531 addr >>= addr_shift; 502 addr >>= addr_shift;
532 if (addr == 0) continue; 503 if (addr == 0) continue;
533 504
534 if (array == NULL) 505 if (array == NULL)
535 array = prop_array_create(); 506 array = prop_array_create();
536 507
537 dev = prop_dictionary_create(); 508 dev = prop_dictionary_create();
538 prop_dictionary_set_string(dev, "name", name); 509 prop_dictionary_set_string(dev, "name", name);
539 prop_dictionary_set_uint32(dev, "addr", addr); 510 prop_dictionary_set_uint32(dev, "addr", addr);
540 prop_dictionary_set_uint64(dev, "cookie", node); 511 prop_dictionary_set_uint64(dev, "cookie", node);
541 of_to_dataprop(dev, node, "compatible", "compatible"); 512 of_to_dataprop(dev, node, "compatible", "compatible");
542 prop_array_add(array, dev); 513 prop_array_add(array, dev);
543 prop_object_release(dev); 514 prop_object_release(dev);
544 } 515 }
545 516
546 if (array != NULL) { 517 if (array != NULL) {
547 prop_dictionary_set(props, "i2c-child-devices", array); 518 prop_dictionary_set(props, "i2c-child-devices", array);
548 prop_object_release(array); 519 prop_object_release(array);
549 } 520 }
550} 521}
551 522
552void 523void
553of_enter_spi_devs(prop_dictionary_t props, int ofnode, size_t cell_size) 524of_enter_spi_devs(prop_dictionary_t props, int ofnode, size_t cell_size)
554{ 525{
555 int node, len; 526 int node, len;
556 char name[32]; 527 char name[32];
557 uint64_t reg64; 528 uint64_t reg64;
558 uint32_t reg32; 529 uint32_t reg32;
559 uint32_t slave; 530 uint32_t slave;
560 u_int32_t maxfreq; 531 u_int32_t maxfreq;
561 prop_array_t array = NULL; 532 prop_array_t array = NULL;
562 prop_dictionary_t dev; 533 prop_dictionary_t dev;
563 int mode; 534 int mode;
564 535
565 for (node = OF_child(ofnode); node; node = OF_peer(node)) { 536 for (node = OF_child(ofnode); node; node = OF_peer(node)) {
566 if (OF_getprop(node, "name", name, sizeof(name)) <= 0) 537 if (OF_getprop(node, "name", name, sizeof(name)) <= 0)
567 continue; 538 continue;
568 len = OF_getproplen(node, "reg"); 539 len = OF_getproplen(node, "reg");
569 slave = 0; 540 slave = 0;
570 if (cell_size == 8 && len >= sizeof(reg64)) { 541 if (cell_size == 8 && len >= sizeof(reg64)) {
571 if (OF_getprop(node, "reg", &reg64, sizeof(reg64)) 542 if (OF_getprop(node, "reg", &reg64, sizeof(reg64))
572 < sizeof(reg64)) 543 < sizeof(reg64))
573 continue; 544 continue;
574 slave = be64toh(reg64); 545 slave = be64toh(reg64);
575 } else if (cell_size == 4 && len >= sizeof(reg32)) { 546 } else if (cell_size == 4 && len >= sizeof(reg32)) {
576 if (OF_getprop(node, "reg", &reg32, sizeof(reg32)) 547 if (OF_getprop(node, "reg", &reg32, sizeof(reg32))
577 < sizeof(reg32)) 548 < sizeof(reg32))
578 continue; 549 continue;
579 slave = be32toh(reg32); 550 slave = be32toh(reg32);
580 } else { 551 } else {
581 continue; 552 continue;
582 } 553 }
583 if (of_getprop_uint32(node, "spi-max-frequency", &maxfreq)) { 554 if (of_getprop_uint32(node, "spi-max-frequency", &maxfreq)) {
584 maxfreq = 0; 555 maxfreq = 0;
585 } 556 }
586 mode = ((int)of_hasprop(node, "cpol") << 1) | (int)of_hasprop(node, "cpha"); 557 mode = ((int)of_hasprop(node, "cpol") << 1) | (int)of_hasprop(node, "cpha");
587 558
588 if (array == NULL) 559 if (array == NULL)
589 array = prop_array_create(); 560 array = prop_array_create();
590 561
591 dev = prop_dictionary_create(); 562 dev = prop_dictionary_create();
592 prop_dictionary_set_string(dev, "name", name); 563 prop_dictionary_set_string(dev, "name", name);
593 prop_dictionary_set_uint32(dev, "slave", slave); 564 prop_dictionary_set_uint32(dev, "slave", slave);
594 prop_dictionary_set_uint32(dev, "mode", mode); 565 prop_dictionary_set_uint32(dev, "mode", mode);
595 if (maxfreq > 0) 566 if (maxfreq > 0)
596 prop_dictionary_set_uint32(dev, "spi-max-frequency", maxfreq); 567 prop_dictionary_set_uint32(dev, "spi-max-frequency", maxfreq);
597 prop_dictionary_set_uint64(dev, "cookie", node); 568 prop_dictionary_set_uint64(dev, "cookie", node);
598 of_to_dataprop(dev, node, "compatible", "compatible"); 569 of_to_dataprop(dev, node, "compatible", "compatible");
599 prop_array_add(array, dev); 570 prop_array_add(array, dev);
600 prop_object_release(dev); 571 prop_object_release(dev);
601 } 572 }
602 573
603 if (array != NULL) { 574 if (array != NULL) {
604 prop_dictionary_set(props, "spi-child-devices", array); 575 prop_dictionary_set(props, "spi-child-devices", array);
605 prop_object_release(array); 576 prop_object_release(array);
606 } 577 }
607} 578}
608 579
609 580
610/* 581/*
611 * Returns true if the specified property is present. 582 * Returns true if the specified property is present.
612 */ 583 */
613bool 584bool
614of_hasprop(int node, const char *prop) 585of_hasprop(int node, const char *prop)
615{ 586{
616 return OF_getproplen(node, prop) >= 0; 587 return OF_getproplen(node, prop) >= 0;
617} 588}
618 589
619/* 590/*
620 * Get the value of a uint32 property, compensating for host byte order. 591 * Get the value of a uint32 property, compensating for host byte order.
621 * Returns 0 on success, non-zero on failure. 592 * Returns 0 on success, non-zero on failure.
622 */ 593 */
623int 594int
624of_getprop_uint32(int node, const char *prop, uint32_t *val) 595of_getprop_uint32(int node, const char *prop, uint32_t *val)
625{ 596{
626 uint32_t v; 597 uint32_t v;
627 int len; 598 int len;
628 599
629 len = OF_getprop(node, prop, &v, sizeof(v)); 600 len = OF_getprop(node, prop, &v, sizeof(v));
630 if (len != sizeof(v)) 601 if (len != sizeof(v))
631 return -1; 602 return -1;
632 603
633 *val = be32toh(v); 604 *val = be32toh(v);
634 return 0; 605 return 0;
635} 606}
636 607
637int 608int
638of_getprop_uint32_array(int node, const char *prop, uint32_t *array, int n) 609of_getprop_uint32_array(int node, const char *prop, uint32_t *array, int n)
639{ 610{
640 uint32_t *v = array; 611 uint32_t *v = array;
641 int len; 612 int len;
642 613
643 len = OF_getprop(node, prop, array, n * sizeof(*v)); 614 len = OF_getprop(node, prop, array, n * sizeof(*v));
644 if (len < (int)(n * sizeof(*v))) 615 if (len < (int)(n * sizeof(*v)))
645 return -1; 616 return -1;
646 617
647 for (; n > 0; n--) { 618 for (; n > 0; n--) {
648 BE32TOH(*v); 619 BE32TOH(*v);
649 v++; 620 v++;
650 } 621 }
651 622
652 return 0; 623 return 0;
653} 624}
654/* 625/*
655 * Get the value of a uint64 property, compensating for host byte order. 626 * Get the value of a uint64 property, compensating for host byte order.
656 * Returns 0 on success, non-zero on failure. 627 * Returns 0 on success, non-zero on failure.
657 */ 628 */
658int 629int
659of_getprop_uint64(int node, const char *prop, uint64_t *val) 630of_getprop_uint64(int node, const char *prop, uint64_t *val)
660{ 631{
661 uint64_t v; 632 uint64_t v;
662 int len; 633 int len;
663 634
664 len = OF_getprop(node, prop, &v, sizeof(v)); 635 len = OF_getprop(node, prop, &v, sizeof(v));
665 if (len != sizeof(v)) 636 if (len != sizeof(v))
666 return -1; 637 return -1;
667 638
668 *val = be64toh(v); 639 *val = be64toh(v);
669 return 0; 640 return 0;
670} 641}