Sun Jan 24 17:44:16 2021 UTC ()
Implement of_match_compat_data() using device_compatible_match_strlist().
Implement of_search_compatible() using device_compatible_lookup_strlist().


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

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

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