hw-tree.c revision 1.1.1.10 1 1.1 christos /* The common simulator framework for GDB, the GNU Debugger.
2 1.1 christos
3 1.1.1.10 christos Copyright 2002-2024 Free Software Foundation, Inc.
4 1.1 christos
5 1.1 christos Contributed by Andrew Cagney and Red Hat.
6 1.1 christos
7 1.1 christos This file is part of GDB.
8 1.1 christos
9 1.1 christos This program is free software; you can redistribute it and/or modify
10 1.1 christos it under the terms of the GNU General Public License as published by
11 1.1 christos the Free Software Foundation; either version 3 of the License, or
12 1.1 christos (at your option) any later version.
13 1.1 christos
14 1.1 christos This program is distributed in the hope that it will be useful,
15 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
16 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 1.1 christos GNU General Public License for more details.
18 1.1 christos
19 1.1 christos You should have received a copy of the GNU General Public License
20 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 1.1 christos
22 1.1.1.9 christos /* This must come before any other includes. */
23 1.1.1.9 christos #include "defs.h"
24 1.1.1.9 christos
25 1.1.1.9 christos #include <ctype.h>
26 1.1.1.9 christos #include <stdarg.h>
27 1.1.1.9 christos #include <stdlib.h>
28 1.1.1.9 christos #include <string.h>
29 1.1 christos
30 1.1 christos #include "hw-main.h"
31 1.1 christos #include "hw-base.h"
32 1.1 christos #include "hw-tree.h"
33 1.1 christos
34 1.1 christos #include "sim-io.h"
35 1.1 christos #include "sim-assert.h"
36 1.1 christos
37 1.1 christos /* manipulate/lookup device names */
38 1.1 christos
39 1.1 christos typedef struct _name_specifier
40 1.1 christos {
41 1.1 christos
42 1.1 christos /* components in the full length name */
43 1.1 christos char *path;
44 1.1 christos char *property;
45 1.1 christos char *value;
46 1.1 christos
47 1.1 christos /* current device */
48 1.1 christos char *family;
49 1.1 christos char *name;
50 1.1 christos char *unit;
51 1.1 christos char *args;
52 1.1 christos
53 1.1 christos /* previous device */
54 1.1 christos char *last_name;
55 1.1 christos char *last_family;
56 1.1 christos char *last_unit;
57 1.1 christos char *last_args;
58 1.1 christos
59 1.1 christos /* work area */
60 1.1 christos char buf[1024];
61 1.1 christos
62 1.1 christos } name_specifier;
63 1.1 christos
64 1.1 christos
65 1.1 christos
66 1.1 christos /* Given a device specifier, break it up into its main components:
67 1.1 christos path (and if present) property name and property value. */
68 1.1 christos
69 1.1 christos static int
70 1.1 christos split_device_specifier (struct hw *current,
71 1.1 christos const char *device_specifier,
72 1.1 christos name_specifier *spec)
73 1.1 christos {
74 1.1 christos char *chp = NULL;
75 1.1 christos
76 1.1 christos /* expand any leading alias if present */
77 1.1 christos if (current != NULL
78 1.1 christos && *device_specifier != '\0'
79 1.1 christos && *device_specifier != '.'
80 1.1 christos && *device_specifier != '/')
81 1.1 christos {
82 1.1 christos struct hw *aliases = hw_tree_find_device (current, "/aliases");
83 1.1 christos char alias[32];
84 1.1 christos int len = 0;
85 1.1 christos while (device_specifier[len] != '\0'
86 1.1 christos && device_specifier[len] != '/'
87 1.1 christos && device_specifier[len] != ':'
88 1.1 christos && !isspace (device_specifier[len]))
89 1.1 christos {
90 1.1 christos alias[len] = device_specifier[len];
91 1.1 christos len++;
92 1.1.1.2 christos if (len >= sizeof (alias))
93 1.1 christos hw_abort (NULL, "split_device_specifier: buffer overflow");
94 1.1 christos }
95 1.1 christos alias[len] = '\0';
96 1.1 christos if (aliases != NULL
97 1.1 christos && hw_find_property (aliases, alias))
98 1.1 christos {
99 1.1.1.2 christos strcpy (spec->buf, hw_find_string_property (aliases, alias));
100 1.1 christos strcat (spec->buf, device_specifier + len);
101 1.1 christos }
102 1.1 christos else
103 1.1 christos {
104 1.1 christos strcpy (spec->buf, device_specifier);
105 1.1 christos }
106 1.1 christos }
107 1.1 christos else
108 1.1 christos {
109 1.1.1.2 christos strcpy (spec->buf, device_specifier);
110 1.1 christos }
111 1.1 christos
112 1.1 christos /* check no overflow */
113 1.1.1.2 christos if (strlen (spec->buf) >= sizeof (spec->buf))
114 1.1 christos hw_abort (NULL, "split_device_specifier: buffer overflow\n");
115 1.1 christos
116 1.1 christos /* strip leading spaces */
117 1.1 christos chp = spec->buf;
118 1.1.1.2 christos while (*chp != '\0' && isspace (*chp))
119 1.1 christos chp++;
120 1.1 christos if (*chp == '\0')
121 1.1 christos return 0;
122 1.1 christos
123 1.1 christos /* find the path and terminate it with null */
124 1.1 christos spec->path = chp;
125 1.1.1.2 christos while (*chp != '\0' && !isspace (*chp))
126 1.1 christos chp++;
127 1.1 christos if (*chp != '\0')
128 1.1 christos {
129 1.1 christos *chp = '\0';
130 1.1 christos chp++;
131 1.1 christos }
132 1.1 christos
133 1.1 christos /* and any value */
134 1.1.1.2 christos while (*chp != '\0' && isspace (*chp))
135 1.1 christos chp++;
136 1.1 christos spec->value = chp;
137 1.1 christos
138 1.1 christos /* now go back and chop the property off of the path */
139 1.1 christos if (spec->value[0] == '\0')
140 1.1 christos {
141 1.1 christos spec->property = NULL; /*not a property*/
142 1.1 christos spec->value = NULL;
143 1.1 christos }
144 1.1 christos else if (spec->value[0] == '>'
145 1.1 christos || spec->value[0] == '<')
146 1.1 christos {
147 1.1 christos /* an interrupt spec */
148 1.1 christos spec->property = NULL;
149 1.1 christos }
150 1.1 christos else
151 1.1 christos {
152 1.1.1.2 christos chp = strrchr (spec->path, '/');
153 1.1 christos if (chp == NULL)
154 1.1 christos {
155 1.1 christos spec->property = spec->path;
156 1.1.1.2 christos spec->path = strchr (spec->property, '\0');
157 1.1 christos }
158 1.1 christos else
159 1.1 christos {
160 1.1 christos *chp = '\0';
161 1.1 christos spec->property = chp+1;
162 1.1 christos }
163 1.1 christos }
164 1.1 christos
165 1.1 christos /* and mark the rest as invalid */
166 1.1 christos spec->name = NULL;
167 1.1 christos spec->family = NULL;
168 1.1 christos spec->unit = NULL;
169 1.1 christos spec->args = NULL;
170 1.1 christos spec->last_name = NULL;
171 1.1 christos spec->last_family = NULL;
172 1.1 christos spec->last_unit = NULL;
173 1.1 christos spec->last_args = NULL;
174 1.1 christos
175 1.1 christos return 1;
176 1.1 christos }
177 1.1 christos
178 1.1 christos
179 1.1 christos /* given a device specifier break it up into its main components -
180 1.1 christos path and property name - assuming that the last `device' is a
181 1.1 christos property name. */
182 1.1 christos
183 1.1 christos static int
184 1.1 christos split_property_specifier (struct hw *current,
185 1.1 christos const char *property_specifier,
186 1.1 christos name_specifier *spec)
187 1.1 christos {
188 1.1 christos if (split_device_specifier (current, property_specifier, spec))
189 1.1 christos {
190 1.1 christos if (spec->property == NULL)
191 1.1 christos {
192 1.1 christos /* force the last name to be a property name */
193 1.1 christos char *chp = strrchr (spec->path, '/');
194 1.1 christos if (chp == NULL)
195 1.1 christos {
196 1.1 christos spec->property = spec->path;
197 1.1 christos spec->path = strrchr (spec->property, '\0');;
198 1.1 christos }
199 1.1 christos else
200 1.1 christos {
201 1.1 christos *chp = '\0';
202 1.1 christos spec->property = chp + 1;
203 1.1 christos }
204 1.1 christos }
205 1.1 christos return 1;
206 1.1 christos }
207 1.1 christos else
208 1.1 christos return 0;
209 1.1 christos }
210 1.1 christos
211 1.1 christos
212 1.1 christos /* device the next device name and split it up, return 0 when no more
213 1.1 christos names to struct hw */
214 1.1 christos
215 1.1 christos static int
216 1.1 christos split_device_name (name_specifier *spec)
217 1.1 christos {
218 1.1 christos char *chp;
219 1.1 christos /* remember what came before */
220 1.1 christos spec->last_name = spec->name;
221 1.1 christos spec->last_family = spec->family;
222 1.1 christos spec->last_unit = spec->unit;
223 1.1 christos spec->last_args = spec->args;
224 1.1 christos /* finished? */
225 1.1 christos if (spec->path[0] == '\0')
226 1.1 christos {
227 1.1 christos spec->name = NULL;
228 1.1 christos spec->family = NULL;
229 1.1 christos spec->unit = NULL;
230 1.1 christos spec->args = NULL;
231 1.1 christos return 0;
232 1.1 christos }
233 1.1 christos /* break the current device spec from the path */
234 1.1 christos spec->name = spec->path;
235 1.1 christos chp = strchr (spec->name, '/');
236 1.1 christos if (chp == NULL)
237 1.1 christos spec->path = strchr (spec->name, '\0');
238 1.1 christos else
239 1.1 christos {
240 1.1 christos spec->path = chp+1;
241 1.1 christos *chp = '\0';
242 1.1 christos }
243 1.1 christos /* break out the base */
244 1.1 christos if (spec->name[0] == '(')
245 1.1 christos {
246 1.1.1.2 christos chp = strchr (spec->name, ')');
247 1.1 christos if (chp == NULL)
248 1.1 christos {
249 1.1 christos spec->family = spec->name;
250 1.1 christos }
251 1.1 christos else
252 1.1 christos {
253 1.1 christos *chp = '\0';
254 1.1 christos spec->family = spec->name + 1;
255 1.1 christos spec->name = chp + 1;
256 1.1 christos }
257 1.1 christos }
258 1.1 christos else
259 1.1 christos {
260 1.1 christos spec->family = spec->name;
261 1.1 christos }
262 1.1 christos /* now break out the unit */
263 1.1.1.2 christos chp = strchr (spec->name, '@');
264 1.1 christos if (chp == NULL)
265 1.1 christos {
266 1.1 christos spec->unit = NULL;
267 1.1 christos chp = spec->name;
268 1.1 christos }
269 1.1 christos else
270 1.1 christos {
271 1.1 christos *chp = '\0';
272 1.1 christos chp += 1;
273 1.1 christos spec->unit = chp;
274 1.1 christos }
275 1.1 christos /* finally any args */
276 1.1.1.2 christos chp = strchr (chp, ':');
277 1.1 christos if (chp == NULL)
278 1.1 christos spec->args = NULL;
279 1.1 christos else
280 1.1 christos {
281 1.1 christos *chp = '\0';
282 1.1 christos spec->args = chp+1;
283 1.1 christos }
284 1.1 christos return 1;
285 1.1 christos }
286 1.1 christos
287 1.1 christos
288 1.1 christos /* device the value, returning the next non-space token */
289 1.1 christos
290 1.1 christos static char *
291 1.1 christos split_value (name_specifier *spec)
292 1.1 christos {
293 1.1 christos char *token;
294 1.1 christos if (spec->value == NULL)
295 1.1 christos return NULL;
296 1.1 christos /* skip leading white space */
297 1.1 christos while (isspace (spec->value[0]))
298 1.1 christos spec->value++;
299 1.1 christos if (spec->value[0] == '\0')
300 1.1 christos {
301 1.1 christos spec->value = NULL;
302 1.1 christos return NULL;
303 1.1 christos }
304 1.1 christos token = spec->value;
305 1.1 christos /* find trailing space */
306 1.1 christos while (spec->value[0] != '\0' && !isspace (spec->value[0]))
307 1.1 christos spec->value++;
308 1.1 christos /* chop this value out */
309 1.1 christos if (spec->value[0] != '\0')
310 1.1 christos {
311 1.1 christos spec->value[0] = '\0';
312 1.1 christos spec->value++;
313 1.1 christos }
314 1.1 christos return token;
315 1.1 christos }
316 1.1 christos
317 1.1 christos
318 1.1 christos
319 1.1 christos /* traverse the path specified by spec starting at current */
320 1.1 christos
321 1.1 christos static struct hw *
322 1.1 christos split_find_device (struct hw *current,
323 1.1 christos name_specifier *spec)
324 1.1 christos {
325 1.1 christos /* strip off (and process) any leading ., .., ./ and / */
326 1.1 christos while (1)
327 1.1 christos {
328 1.1 christos if (strncmp (spec->path, "/", strlen ("/")) == 0)
329 1.1 christos {
330 1.1 christos /* cd /... */
331 1.1 christos while (current != NULL && hw_parent (current) != NULL)
332 1.1 christos current = hw_parent (current);
333 1.1 christos spec->path += strlen ("/");
334 1.1 christos }
335 1.1 christos else if (strncmp (spec->path, "./", strlen ("./")) == 0)
336 1.1 christos {
337 1.1 christos /* cd ./... */
338 1.1 christos spec->path += strlen ("./");
339 1.1 christos }
340 1.1 christos else if (strncmp (spec->path, "../", strlen ("../")) == 0)
341 1.1 christos {
342 1.1 christos /* cd ../... */
343 1.1 christos if (current != NULL && hw_parent (current) != NULL)
344 1.1 christos current = hw_parent (current);
345 1.1 christos spec->path += strlen ("../");
346 1.1 christos }
347 1.1 christos else if (strcmp (spec->path, ".") == 0)
348 1.1 christos {
349 1.1 christos /* cd . */
350 1.1 christos spec->path += strlen (".");
351 1.1 christos }
352 1.1 christos else if (strcmp (spec->path, "..") == 0)
353 1.1 christos {
354 1.1 christos /* cd .. */
355 1.1 christos if (current != NULL && hw_parent (current) != NULL)
356 1.1 christos current = hw_parent (current);
357 1.1 christos spec->path += strlen ("..");
358 1.1 christos }
359 1.1 christos else
360 1.1 christos break;
361 1.1 christos }
362 1.1 christos
363 1.1 christos /* now go through the path proper */
364 1.1 christos
365 1.1 christos if (current == NULL)
366 1.1 christos {
367 1.1 christos split_device_name (spec);
368 1.1 christos return NULL;
369 1.1 christos }
370 1.1 christos
371 1.1 christos while (split_device_name (spec))
372 1.1 christos {
373 1.1 christos struct hw *child;
374 1.1 christos for (child = hw_child (current);
375 1.1 christos child != NULL; child = hw_sibling (child))
376 1.1 christos {
377 1.1 christos if (strcmp (spec->name, hw_name (child)) == 0)
378 1.1 christos {
379 1.1 christos if (spec->unit == NULL)
380 1.1 christos break;
381 1.1 christos else
382 1.1 christos {
383 1.1 christos hw_unit phys;
384 1.1 christos hw_unit_decode (current, spec->unit, &phys);
385 1.1 christos if (memcmp (&phys, hw_unit_address (child),
386 1.1 christos sizeof (hw_unit)) == 0)
387 1.1 christos break;
388 1.1 christos }
389 1.1 christos }
390 1.1 christos }
391 1.1 christos if (child == NULL)
392 1.1 christos return current; /* search failed */
393 1.1 christos current = child;
394 1.1 christos }
395 1.1 christos
396 1.1 christos return current;
397 1.1 christos }
398 1.1 christos
399 1.1 christos
400 1.1 christos static struct hw *
401 1.1 christos split_fill_path (struct hw *current,
402 1.1 christos const char *device_specifier,
403 1.1 christos name_specifier *spec)
404 1.1 christos {
405 1.1 christos /* break it up */
406 1.1 christos if (!split_device_specifier (current, device_specifier, spec))
407 1.1 christos hw_abort (current, "error parsing %s\n", device_specifier);
408 1.1 christos
409 1.1 christos /* fill our tree with its contents */
410 1.1 christos current = split_find_device (current, spec);
411 1.1 christos
412 1.1 christos /* add any additional devices as needed */
413 1.1 christos if (spec->name != NULL)
414 1.1 christos {
415 1.1 christos do
416 1.1 christos {
417 1.1 christos if (current != NULL && !hw_finished_p (current))
418 1.1 christos hw_finish (current);
419 1.1 christos current = hw_create (NULL,
420 1.1 christos current,
421 1.1 christos spec->family,
422 1.1 christos spec->name,
423 1.1 christos spec->unit,
424 1.1 christos spec->args);
425 1.1 christos }
426 1.1 christos while (split_device_name (spec));
427 1.1 christos }
428 1.1 christos
429 1.1 christos return current;
430 1.1 christos }
431 1.1 christos
432 1.1 christos
433 1.1 christos /* <non-white-space> */
435 1.1 christos
436 1.1.1.2 christos static const char *
437 1.1 christos skip_token (const char *chp)
438 1.1.1.2 christos {
439 1.1 christos while (!isspace (*chp) && *chp != '\0')
440 1.1.1.2 christos chp++;
441 1.1 christos while (isspace (*chp) && *chp != '\0')
442 1.1 christos chp++;
443 1.1 christos return chp;
444 1.1 christos }
445 1.1 christos
446 1.1 christos
447 1.1 christos /* count the number of entries */
448 1.1 christos
449 1.1 christos static int
450 1.1 christos count_entries (struct hw *current,
451 1.1 christos const char *property_name,
452 1.1 christos const char *property_value,
453 1.1 christos int modulo)
454 1.1 christos {
455 1.1 christos const char *chp = property_value;
456 1.1 christos int nr_entries = 0;
457 1.1 christos while (*chp != '\0')
458 1.1 christos {
459 1.1 christos nr_entries += 1;
460 1.1 christos chp = skip_token (chp);
461 1.1 christos }
462 1.1 christos if ((nr_entries % modulo) != 0)
463 1.1 christos {
464 1.1 christos hw_abort (current, "incorrect number of entries for %s property %s, should be multiple of %d",
465 1.1 christos property_name, property_value, modulo);
466 1.1 christos }
467 1.1 christos return nr_entries / modulo;
468 1.1 christos }
469 1.1 christos
470 1.1 christos
471 1.1 christos
472 1.1 christos /* parse: <address> ::= <token> ; device dependant */
473 1.1 christos
474 1.1 christos static const char *
475 1.1 christos parse_address (struct hw *current,
476 1.1 christos struct hw *bus,
477 1.1 christos const char *chp,
478 1.1 christos hw_unit *address)
479 1.1 christos {
480 1.1 christos if (hw_unit_decode (bus, chp, address) < 0)
481 1.1 christos hw_abort (current, "invalid unit address in %s", chp);
482 1.1 christos return skip_token (chp);
483 1.1 christos }
484 1.1 christos
485 1.1 christos
486 1.1 christos /* parse: <size> ::= <number> { "," <number> } ; */
487 1.1 christos
488 1.1 christos static const char *
489 1.1 christos parse_size (struct hw *current,
490 1.1 christos struct hw *bus,
491 1.1 christos const char *chp,
492 1.1 christos hw_unit *size)
493 1.1 christos {
494 1.1 christos int i;
495 1.1 christos int nr;
496 1.1.1.2 christos const char *curr = chp;
497 1.1 christos memset (size, 0, sizeof (*size));
498 1.1 christos /* parse the numeric list */
499 1.1 christos size->nr_cells = hw_unit_nr_size_cells (bus);
500 1.1 christos nr = 0;
501 1.1 christos while (1)
502 1.1 christos {
503 1.1 christos char *next;
504 1.1 christos size->cells[nr] = strtoul (curr, &next, 0);
505 1.1 christos if (curr == next)
506 1.1 christos hw_abort (current, "Problem parsing <size> %s", chp);
507 1.1 christos nr += 1;
508 1.1 christos if (next[0] != ',')
509 1.1 christos break;
510 1.1 christos if (nr == size->nr_cells)
511 1.1 christos hw_abort (current, "Too many values in <size> %s", chp);
512 1.1 christos curr = next + 1;
513 1.1 christos }
514 1.1 christos ASSERT (nr > 0 && nr <= size->nr_cells);
515 1.1 christos /* right align the numbers */
516 1.1 christos for (i = 1; i <= size->nr_cells; i++)
517 1.1 christos {
518 1.1 christos if (i <= nr)
519 1.1 christos size->cells[size->nr_cells - i] = size->cells[nr - i];
520 1.1 christos else
521 1.1 christos size->cells[size->nr_cells - i] = 0;
522 1.1 christos }
523 1.1 christos return skip_token (chp);
524 1.1 christos }
525 1.1 christos
526 1.1 christos
527 1.1 christos /* parse: <reg> ::= { <address> <size> } ; */
528 1.1 christos
529 1.1 christos static void
530 1.1 christos parse_reg_property (struct hw *current,
531 1.1 christos const char *property_name,
532 1.1 christos const char *property_value)
533 1.1 christos {
534 1.1 christos int nr_regs;
535 1.1 christos int reg_nr;
536 1.1 christos reg_property_spec *regs;
537 1.1 christos const char *chp;
538 1.1 christos
539 1.1 christos /* determine the number of reg entries by counting tokens */
540 1.1 christos nr_regs = count_entries (current, property_name, property_value, 2);
541 1.1 christos
542 1.1 christos /* create working space */
543 1.1 christos regs = zalloc (nr_regs * sizeof (*regs));
544 1.1 christos
545 1.1 christos /* fill it in */
546 1.1 christos chp = property_value;
547 1.1 christos for (reg_nr = 0; reg_nr < nr_regs; reg_nr++)
548 1.1.1.2 christos {
549 1.1 christos chp = parse_address (current, hw_parent (current),
550 1.1.1.2 christos chp, ®s[reg_nr].address);
551 1.1 christos chp = parse_size (current, hw_parent (current),
552 1.1 christos chp, ®s[reg_nr].size);
553 1.1 christos }
554 1.1 christos
555 1.1 christos /* create it */
556 1.1 christos hw_add_reg_array_property (current, property_name,
557 1.1 christos regs, nr_regs);
558 1.1 christos
559 1.1 christos free (regs);
560 1.1 christos }
561 1.1 christos
562 1.1 christos
563 1.1 christos /* { <child-address> <parent-address> <child-size> }* */
564 1.1 christos
565 1.1 christos static void
566 1.1 christos parse_ranges_property (struct hw *current,
567 1.1 christos const char *property_name,
568 1.1 christos const char *property_value)
569 1.1 christos {
570 1.1 christos int nr_ranges;
571 1.1 christos int range_nr;
572 1.1 christos range_property_spec *ranges;
573 1.1 christos const char *chp;
574 1.1 christos
575 1.1 christos /* determine the number of ranges specified */
576 1.1 christos nr_ranges = count_entries (current, property_name, property_value, 3);
577 1.1 christos
578 1.1.1.2 christos /* create a property of that size */
579 1.1 christos ranges = zalloc (nr_ranges * sizeof (*ranges));
580 1.1 christos
581 1.1 christos /* fill it in */
582 1.1 christos chp = property_value;
583 1.1 christos for (range_nr = 0; range_nr < nr_ranges; range_nr++)
584 1.1 christos {
585 1.1 christos chp = parse_address (current, current,
586 1.1.1.2 christos chp, &ranges[range_nr].child_address);
587 1.1 christos chp = parse_address (current, hw_parent (current),
588 1.1 christos chp, &ranges[range_nr].parent_address);
589 1.1 christos chp = parse_size (current, current,
590 1.1 christos chp, &ranges[range_nr].size);
591 1.1 christos }
592 1.1 christos
593 1.1 christos /* create it */
594 1.1 christos hw_add_range_array_property (current, property_name, ranges, nr_ranges);
595 1.1 christos
596 1.1 christos free (ranges);
597 1.1 christos }
598 1.1 christos
599 1.1 christos
600 1.1 christos /* <integer> ... */
601 1.1 christos
602 1.1 christos static void
603 1.1 christos parse_integer_property (struct hw *current,
604 1.1 christos const char *property_name,
605 1.1 christos const char *property_value)
606 1.1 christos {
607 1.1 christos int nr_entries;
608 1.1 christos unsigned_cell words[1024];
609 1.1 christos /* integer or integer array? */
610 1.1 christos nr_entries = 0;
611 1.1 christos while (1)
612 1.1 christos {
613 1.1 christos char *end;
614 1.1 christos words[nr_entries] = strtoul (property_value, &end, 0);
615 1.1 christos if (property_value == end)
616 1.1 christos break;
617 1.1 christos nr_entries += 1;
618 1.1 christos if (nr_entries * sizeof (words[0]) >= sizeof (words))
619 1.1 christos hw_abort (current, "buffer overflow");
620 1.1 christos property_value = end;
621 1.1 christos }
622 1.1 christos if (nr_entries == 0)
623 1.1 christos hw_abort (current, "error parsing integer property %s (%s)",
624 1.1 christos property_name, property_value);
625 1.1 christos else if (nr_entries == 1)
626 1.1 christos hw_add_integer_property (current, property_name, words[0]);
627 1.1 christos else
628 1.1 christos {
629 1.1 christos int i;
630 1.1 christos for (i = 0; i < nr_entries; i++)
631 1.1 christos {
632 1.1 christos H2BE (words[i]);
633 1.1 christos }
634 1.1 christos /* perhaps integer array property is better */
635 1.1.1.2 christos hw_add_array_property (current, property_name, words,
636 1.1 christos sizeof (words[0]) * nr_entries);
637 1.1 christos }
638 1.1 christos }
639 1.1 christos
640 1.1 christos
641 1.1 christos /* <string> ... */
642 1.1 christos
643 1.1 christos static void
644 1.1 christos parse_string_property (struct hw *current,
645 1.1 christos const char *property_name,
646 1.1 christos const char *property_value)
647 1.1 christos {
648 1.1 christos char **strings;
649 1.1 christos const char *chp;
650 1.1 christos int nr_strings;
651 1.1 christos int approx_nr_strings;
652 1.1 christos
653 1.1 christos /* get an estimate as to the number of strings by counting double
654 1.1 christos quotes */
655 1.1 christos approx_nr_strings = 2;
656 1.1 christos for (chp = property_value; *chp; chp++)
657 1.1 christos {
658 1.1 christos if (*chp == '"')
659 1.1 christos approx_nr_strings++;
660 1.1 christos }
661 1.1 christos approx_nr_strings = (approx_nr_strings) / 2;
662 1.1 christos
663 1.1.1.2 christos /* create a string buffer for that many (plus a null) */
664 1.1 christos strings = (char**) zalloc ((approx_nr_strings + 1) * sizeof (char*));
665 1.1 christos
666 1.1 christos /* now find all the strings */
667 1.1 christos chp = property_value;
668 1.1 christos nr_strings = 0;
669 1.1 christos while (1)
670 1.1 christos {
671 1.1 christos
672 1.1 christos /* skip leading space */
673 1.1 christos while (*chp != '\0' && isspace (*chp))
674 1.1 christos chp += 1;
675 1.1 christos if (*chp == '\0')
676 1.1 christos break;
677 1.1 christos
678 1.1 christos /* copy it in */
679 1.1 christos if (*chp == '"')
680 1.1 christos {
681 1.1 christos /* a quoted string - watch for '\' et al. */
682 1.1 christos /* estimate the size and allocate space for it */
683 1.1 christos int pos;
684 1.1 christos chp++;
685 1.1 christos pos = 0;
686 1.1 christos while (chp[pos] != '\0' && chp[pos] != '"')
687 1.1 christos {
688 1.1 christos if (chp[pos] == '\\' && chp[pos+1] != '\0')
689 1.1 christos pos += 2;
690 1.1 christos else
691 1.1 christos pos += 1;
692 1.1 christos }
693 1.1 christos strings[nr_strings] = zalloc (pos + 1);
694 1.1 christos /* copy the string over */
695 1.1 christos pos = 0;
696 1.1 christos while (*chp != '\0' && *chp != '"')
697 1.1 christos {
698 1.1 christos if (*chp == '\\' && *(chp+1) != '\0')
699 1.1 christos {
700 1.1 christos strings[nr_strings][pos] = *(chp+1);
701 1.1 christos chp += 2;
702 1.1 christos pos++;
703 1.1 christos }
704 1.1 christos else
705 1.1 christos {
706 1.1 christos strings[nr_strings][pos] = *chp;
707 1.1 christos chp += 1;
708 1.1 christos pos++;
709 1.1 christos }
710 1.1 christos }
711 1.1 christos if (*chp != '\0')
712 1.1 christos chp++;
713 1.1 christos strings[nr_strings][pos] = '\0';
714 1.1 christos }
715 1.1 christos else
716 1.1 christos {
717 1.1 christos /* copy over a single unquoted token */
718 1.1.1.2 christos int len = 0;
719 1.1 christos while (chp[len] != '\0' && !isspace (chp[len]))
720 1.1.1.2 christos len++;
721 1.1.1.2 christos strings[nr_strings] = zalloc (len + 1);
722 1.1 christos strncpy (strings[nr_strings], chp, len);
723 1.1 christos strings[nr_strings][len] = '\0';
724 1.1 christos chp += len;
725 1.1 christos }
726 1.1 christos nr_strings++;
727 1.1 christos if (nr_strings > approx_nr_strings)
728 1.1 christos hw_abort (current, "String property %s badly formatted",
729 1.1 christos property_name);
730 1.1 christos }
731 1.1 christos ASSERT (strings[nr_strings] == NULL); /* from zalloc */
732 1.1 christos
733 1.1 christos /* install it */
734 1.1 christos if (nr_strings == 0)
735 1.1 christos hw_add_string_property (current, property_name, "");
736 1.1 christos else if (nr_strings == 1)
737 1.1 christos hw_add_string_property (current, property_name, strings[0]);
738 1.1 christos else
739 1.1 christos {
740 1.1 christos const char **specs = (const char**) strings; /* stop a bogus error */
741 1.1 christos hw_add_string_array_property (current, property_name,
742 1.1 christos specs, nr_strings);
743 1.1 christos }
744 1.1 christos
745 1.1 christos /* flush the created string */
746 1.1 christos while (nr_strings > 0)
747 1.1 christos {
748 1.1 christos nr_strings--;
749 1.1 christos free (strings[nr_strings]);
750 1.1.1.2 christos }
751 1.1 christos free (strings);
752 1.1 christos }
753 1.1 christos
754 1.1 christos
755 1.1 christos /* <path-to-ihandle-device> */
756 1.1 christos
757 1.1 christos #if NOT_YET
758 1.1 christos static void
759 1.1 christos parse_ihandle_property (struct hw *current,
760 1.1 christos const char *property,
761 1.1 christos const char *value)
762 1.1 christos {
763 1.1 christos ihandle_runtime_property_spec ihandle;
764 1.1 christos
765 1.1 christos /* pass the full path */
766 1.1 christos ihandle.full_path = value;
767 1.1 christos
768 1.1 christos /* save this ready for the ihandle create */
769 1.1 christos hw_add_ihandle_runtime_property (current, property,
770 1.1 christos &ihandle);
771 1.1 christos }
772 1.1 christos #endif
773 1.1 christos
774 1.1 christos
775 1.1 christos struct hw *
776 1.1 christos hw_tree_create (SIM_DESC sd,
777 1.1 christos const char *family)
778 1.1 christos {
779 1.1 christos return hw_create (sd, NULL, family, family, NULL, NULL);
780 1.1 christos }
781 1.1 christos
782 1.1 christos void
783 1.1 christos hw_tree_delete (struct hw *me)
784 1.1 christos {
785 1.1 christos /* Need to allow devices to disapear under our feet */
786 1.1 christos while (hw_child (me) != NULL)
787 1.1 christos {
788 1.1 christos hw_tree_delete (hw_child (me));
789 1.1 christos }
790 1.1 christos hw_delete (me);
791 1.1 christos }
792 1.1 christos
793 1.1 christos
794 1.1 christos struct hw *
795 1.1 christos hw_tree_parse (struct hw *current,
796 1.1 christos const char *fmt,
797 1.1 christos ...)
798 1.1 christos {
799 1.1 christos va_list ap;
800 1.1 christos va_start (ap, fmt);
801 1.1 christos current = hw_tree_vparse (current, fmt, ap);
802 1.1 christos va_end (ap);
803 1.1 christos return current;
804 1.1 christos }
805 1.1 christos
806 1.1 christos struct hw *
807 1.1 christos hw_tree_vparse (struct hw *current,
808 1.1 christos const char *fmt,
809 1.1 christos va_list ap)
810 1.1 christos {
811 1.1 christos char device_specifier[1024];
812 1.1 christos name_specifier spec;
813 1.1 christos
814 1.1 christos /* format the path */
815 1.1 christos vsprintf (device_specifier, fmt, ap);
816 1.1 christos if (strlen (device_specifier) >= sizeof (device_specifier))
817 1.1 christos hw_abort (NULL, "device_tree_add_deviced: buffer overflow\n");
818 1.1 christos
819 1.1 christos /* construct the tree down to the final struct hw */
820 1.1 christos current = split_fill_path (current, device_specifier, &spec);
821 1.1 christos
822 1.1 christos /* is there an interrupt spec */
823 1.1 christos if (spec.property == NULL
824 1.1 christos && spec.value != NULL)
825 1.1 christos {
826 1.1 christos char *op = split_value (&spec);
827 1.1 christos switch (op[0])
828 1.1 christos {
829 1.1 christos case '>':
830 1.1 christos {
831 1.1 christos char *my_port_name = split_value (&spec);
832 1.1 christos int my_port;
833 1.1 christos char *dest_port_name = split_value (&spec);
834 1.1 christos int dest_port;
835 1.1 christos name_specifier dest_spec;
836 1.1 christos char *dest_hw_name = split_value (&spec);
837 1.1 christos struct hw *dest;
838 1.1 christos /* find my name */
839 1.1 christos if (!hw_finished_p (current))
840 1.1 christos hw_finish (current);
841 1.1 christos my_port = hw_port_decode (current, my_port_name, output_port);
842 1.1 christos /* find the dest device and port */
843 1.1 christos dest = split_fill_path (current, dest_hw_name, &dest_spec);
844 1.1 christos if (!hw_finished_p (dest))
845 1.1 christos hw_finish (dest);
846 1.1 christos dest_port = hw_port_decode (dest, dest_port_name,
847 1.1 christos input_port);
848 1.1 christos /* connect the two */
849 1.1 christos hw_port_attach (current,
850 1.1 christos my_port,
851 1.1 christos dest,
852 1.1.1.10 christos dest_port,
853 1.1 christos permanent_object);
854 1.1 christos break;
855 1.1 christos }
856 1.1 christos default:
857 1.1 christos hw_abort (current, "unreconised interrupt spec %s\n", spec.value);
858 1.1 christos break;
859 1.1 christos }
860 1.1 christos }
861 1.1 christos
862 1.1 christos /* is there a property */
863 1.1 christos if (spec.property != NULL)
864 1.1 christos {
865 1.1 christos if (strcmp (spec.value, "true") == 0)
866 1.1 christos hw_add_boolean_property (current, spec.property, 1);
867 1.1 christos else if (strcmp (spec.value, "false") == 0)
868 1.1 christos hw_add_boolean_property (current, spec.property, 0);
869 1.1 christos else
870 1.1 christos {
871 1.1 christos const struct hw_property *property;
872 1.1 christos switch (spec.value[0])
873 1.1 christos {
874 1.1 christos #if NOT_YET
875 1.1 christos case '*':
876 1.1 christos {
877 1.1 christos parse_ihandle_property (current, spec.property, spec.value + 1);
878 1.1 christos break;
879 1.1 christos }
880 1.1 christos #endif
881 1.1 christos case '[':
882 1.1.1.9 christos {
883 1.1 christos uint8_t words[1024];
884 1.1 christos char *curr = spec.value + 1;
885 1.1 christos int nr_words = 0;
886 1.1 christos while (1)
887 1.1 christos {
888 1.1 christos char *next;
889 1.1 christos words[nr_words] = H2BE_1 (strtoul (curr, &next, 0));
890 1.1 christos if (curr == next)
891 1.1 christos break;
892 1.1 christos curr = next;
893 1.1 christos nr_words += 1;
894 1.1 christos }
895 1.1.1.2 christos hw_add_array_property (current, spec.property,
896 1.1 christos words, sizeof (words[0]) * nr_words);
897 1.1 christos break;
898 1.1 christos }
899 1.1 christos case '"':
900 1.1 christos {
901 1.1 christos parse_string_property (current, spec.property, spec.value);
902 1.1 christos break;
903 1.1 christos }
904 1.1 christos case '!':
905 1.1 christos {
906 1.1 christos spec.value++;
907 1.1 christos property = hw_tree_find_property (current, spec.value);
908 1.1 christos if (property == NULL)
909 1.1 christos hw_abort (current, "property %s not found\n", spec.value);
910 1.1 christos hw_add_duplicate_property (current,
911 1.1 christos spec.property,
912 1.1 christos property);
913 1.1 christos break;
914 1.1 christos }
915 1.1 christos default:
916 1.1 christos {
917 1.1 christos if (strcmp (spec.property, "reg") == 0
918 1.1 christos || strcmp (spec.property, "assigned-addresses") == 0
919 1.1 christos || strcmp (spec.property, "alternate-reg") == 0)
920 1.1 christos {
921 1.1 christos parse_reg_property (current, spec.property, spec.value);
922 1.1 christos }
923 1.1 christos else if (strcmp (spec.property, "ranges") == 0)
924 1.1 christos {
925 1.1 christos parse_ranges_property (current, spec.property, spec.value);
926 1.1.1.2 christos }
927 1.1.1.2 christos else if (isdigit (spec.value[0])
928 1.1.1.2 christos || (spec.value[0] == '-' && isdigit (spec.value[1]))
929 1.1 christos || (spec.value[0] == '+' && isdigit (spec.value[1])))
930 1.1.1.2 christos {
931 1.1 christos parse_integer_property (current, spec.property, spec.value);
932 1.1 christos }
933 1.1.1.2 christos else
934 1.1 christos parse_string_property (current, spec.property, spec.value);
935 1.1 christos break;
936 1.1 christos }
937 1.1 christos }
938 1.1 christos }
939 1.1 christos }
940 1.1 christos return current;
941 1.1 christos }
942 1.1 christos
943 1.1 christos
944 1.1 christos static void
945 1.1 christos finish_hw_tree (struct hw *me,
946 1.1 christos void *data)
947 1.1 christos {
948 1.1 christos if (!hw_finished_p (me))
949 1.1 christos hw_finish (me);
950 1.1 christos }
951 1.1 christos
952 1.1 christos void
953 1.1 christos hw_tree_finish (struct hw *root)
954 1.1 christos {
955 1.1 christos hw_tree_traverse (root, finish_hw_tree, NULL, NULL);
956 1.1 christos }
957 1.1 christos
958 1.1 christos
959 1.1 christos
960 1.1 christos void
961 1.1 christos hw_tree_traverse (struct hw *root,
962 1.1 christos hw_tree_traverse_function *prefix,
963 1.1 christos hw_tree_traverse_function *postfix,
964 1.1 christos void *data)
965 1.1 christos {
966 1.1 christos struct hw *child;
967 1.1 christos if (prefix != NULL)
968 1.1 christos prefix (root, data);
969 1.1 christos for (child = hw_child (root);
970 1.1 christos child != NULL;
971 1.1 christos child = hw_sibling (child))
972 1.1 christos {
973 1.1 christos hw_tree_traverse (child, prefix, postfix, data);
974 1.1 christos }
975 1.1 christos if (postfix != NULL)
976 1.1 christos postfix (root, data);
977 1.1 christos }
978 1.1 christos
979 1.1 christos
980 1.1 christos
981 1.1 christos struct printer
983 1.1 christos {
984 1.1 christos hw_tree_print_callback *print;
985 1.1 christos void *file;
986 1.1 christos };
987 1.1 christos
988 1.1 christos static void
989 1.1 christos print_address (struct hw *bus,
990 1.1 christos const hw_unit *phys,
991 1.1 christos struct printer *p)
992 1.1.1.2 christos {
993 1.1 christos char unit[32];
994 1.1 christos hw_unit_encode (bus, phys, unit, sizeof (unit));
995 1.1 christos p->print (p->file, " %s", unit);
996 1.1 christos }
997 1.1 christos
998 1.1 christos static void
999 1.1 christos print_size (struct hw *bus,
1000 1.1 christos const hw_unit *size,
1001 1.1 christos struct printer *p)
1002 1.1 christos {
1003 1.1 christos int i;
1004 1.1 christos for (i = 0; i < size->nr_cells; i++)
1005 1.1 christos if (size->cells[i] != 0)
1006 1.1 christos break;
1007 1.1 christos if (i < size->nr_cells)
1008 1.1 christos {
1009 1.1 christos p->print (p->file, " 0x%lx", (unsigned long) size->cells[i]);
1010 1.1 christos i++;
1011 1.1 christos for (; i < size->nr_cells; i++)
1012 1.1 christos p->print (p->file, ",0x%lx", (unsigned long) size->cells[i]);
1013 1.1 christos }
1014 1.1 christos else
1015 1.1 christos p->print (p->file, " 0");
1016 1.1 christos }
1017 1.1 christos
1018 1.1 christos static void
1019 1.1 christos print_reg_property (struct hw *me,
1020 1.1 christos const struct hw_property *property,
1021 1.1 christos struct printer *p)
1022 1.1 christos {
1023 1.1 christos int reg_nr;
1024 1.1 christos reg_property_spec reg;
1025 1.1 christos for (reg_nr = 0;
1026 1.1 christos hw_find_reg_array_property (me, property->name, reg_nr, ®);
1027 1.1 christos reg_nr++)
1028 1.1 christos {
1029 1.1 christos print_address (hw_parent (me), ®.address, p);
1030 1.1 christos print_size (me, ®.size, p);
1031 1.1 christos }
1032 1.1 christos }
1033 1.1 christos
1034 1.1 christos static void
1035 1.1 christos print_ranges_property (struct hw *me,
1036 1.1 christos const struct hw_property *property,
1037 1.1 christos struct printer *p)
1038 1.1 christos {
1039 1.1 christos int range_nr;
1040 1.1 christos range_property_spec range;
1041 1.1 christos for (range_nr = 0;
1042 1.1 christos hw_find_range_array_property (me, property->name, range_nr, &range);
1043 1.1 christos range_nr++)
1044 1.1 christos {
1045 1.1 christos print_address (me, &range.child_address, p);
1046 1.1 christos print_address (hw_parent (me), &range.parent_address, p);
1047 1.1 christos print_size (me, &range.size, p);
1048 1.1 christos }
1049 1.1 christos }
1050 1.1 christos
1051 1.1 christos static void
1052 1.1 christos print_string (struct hw *me,
1053 1.1 christos const char *string,
1054 1.1 christos struct printer *p)
1055 1.1 christos {
1056 1.1 christos p->print (p->file, " \"");
1057 1.1 christos while (*string != '\0')
1058 1.1 christos {
1059 1.1 christos switch (*string)
1060 1.1 christos {
1061 1.1 christos case '"':
1062 1.1 christos p->print (p->file, "\\\"");
1063 1.1 christos break;
1064 1.1 christos case '\\':
1065 1.1 christos p->print (p->file, "\\\\");
1066 1.1 christos break;
1067 1.1 christos default:
1068 1.1 christos p->print (p->file, "%c", *string);
1069 1.1 christos break;
1070 1.1 christos }
1071 1.1 christos string++;
1072 1.1 christos }
1073 1.1 christos p->print (p->file, "\"");
1074 1.1 christos }
1075 1.1 christos
1076 1.1 christos static void
1077 1.1 christos print_string_array_property (struct hw *me,
1078 1.1 christos const struct hw_property *property,
1079 1.1 christos struct printer *p)
1080 1.1 christos {
1081 1.1 christos int nr;
1082 1.1 christos string_property_spec string;
1083 1.1 christos for (nr = 0;
1084 1.1 christos hw_find_string_array_property (me, property->name, nr, &string);
1085 1.1 christos nr++)
1086 1.1 christos {
1087 1.1 christos print_string (me, string, p);
1088 1.1 christos }
1089 1.1 christos }
1090 1.1 christos
1091 1.1 christos static void
1092 1.1 christos print_properties (struct hw *me,
1093 1.1 christos struct printer *p)
1094 1.1 christos {
1095 1.1 christos const struct hw_property *property;
1096 1.1 christos for (property = hw_find_property (me, NULL);
1097 1.1 christos property != NULL;
1098 1.1 christos property = hw_next_property (property))
1099 1.1 christos {
1100 1.1 christos if (hw_parent (me) == NULL)
1101 1.1 christos p->print (p->file, "/%s", property->name);
1102 1.1 christos else
1103 1.1 christos p->print (p->file, "%s/%s", hw_path (me), property->name);
1104 1.1 christos if (property->original != NULL)
1105 1.1 christos {
1106 1.1 christos p->print (p->file, " !");
1107 1.1 christos p->print (p->file, "%s/%s",
1108 1.1 christos hw_path (property->original->owner),
1109 1.1 christos property->original->name);
1110 1.1 christos }
1111 1.1 christos else
1112 1.1 christos {
1113 1.1 christos switch (property->type)
1114 1.1 christos {
1115 1.1 christos case array_property:
1116 1.1 christos {
1117 1.1 christos if ((property->sizeof_array % sizeof (signed_cell)) == 0)
1118 1.1 christos {
1119 1.1 christos unsigned_cell *w = (unsigned_cell*) property->array;
1120 1.1 christos int cell_nr;
1121 1.1 christos for (cell_nr = 0;
1122 1.1 christos cell_nr < (property->sizeof_array / sizeof (unsigned_cell));
1123 1.1 christos cell_nr++)
1124 1.1 christos {
1125 1.1 christos p->print (p->file, " 0x%lx", (unsigned long) BE2H_cell (w[cell_nr]));
1126 1.1 christos }
1127 1.1 christos }
1128 1.1.1.9 christos else
1129 1.1 christos {
1130 1.1 christos uint8_t *w = (uint8_t*)property->array;
1131 1.1 christos p->print (p->file, " [");
1132 1.1 christos while ((char*)w - (char*)property->array < property->sizeof_array)
1133 1.1 christos {
1134 1.1 christos p->print (p->file, " 0x%2x", BE2H_1 (*w));
1135 1.1 christos w++;
1136 1.1 christos }
1137 1.1 christos }
1138 1.1 christos break;
1139 1.1 christos }
1140 1.1.1.2 christos case boolean_property:
1141 1.1 christos {
1142 1.1 christos int b = hw_find_boolean_property (me, property->name);
1143 1.1 christos p->print (p->file, " %s", b ? "true" : "false");
1144 1.1 christos break;
1145 1.1 christos }
1146 1.1 christos #if NOT_YET
1147 1.1 christos case ihandle_property:
1148 1.1 christos {
1149 1.1 christos if (property->array != NULL)
1150 1.1.1.2 christos {
1151 1.1 christos device_instance *instance = hw_find_ihandle_property (me, property->name);
1152 1.1 christos p->print (p->file, " *%s", device_instance_path (instance));
1153 1.1 christos }
1154 1.1 christos else
1155 1.1 christos {
1156 1.1 christos /* not yet initialized, ask the device for the path */
1157 1.1 christos ihandle_runtime_property_spec spec;
1158 1.1 christos hw_find_ihandle_runtime_property (me, property->name, &spec);
1159 1.1 christos p->print (p->file, " *%s", spec.full_path);
1160 1.1 christos }
1161 1.1 christos break;
1162 1.1 christos }
1163 1.1 christos #endif
1164 1.1 christos case integer_property:
1165 1.1 christos {
1166 1.1 christos unsigned_word w = hw_find_integer_property (me, property->name);
1167 1.1 christos p->print (p->file, " 0x%lx", (unsigned long)w);
1168 1.1 christos break;
1169 1.1 christos }
1170 1.1 christos case range_array_property:
1171 1.1 christos {
1172 1.1 christos print_ranges_property (me, property, p);
1173 1.1 christos break;
1174 1.1 christos }
1175 1.1 christos case reg_array_property:
1176 1.1 christos {
1177 1.1 christos print_reg_property (me, property, p);
1178 1.1 christos break;
1179 1.1 christos }
1180 1.1 christos case string_property:
1181 1.1 christos {
1182 1.1 christos const char *s = hw_find_string_property (me, property->name);
1183 1.1 christos print_string (me, s, p);
1184 1.1 christos break;
1185 1.1 christos }
1186 1.1 christos case string_array_property:
1187 1.1 christos {
1188 1.1 christos print_string_array_property (me, property, p);
1189 1.1 christos break;
1190 1.1 christos }
1191 1.1 christos }
1192 1.1 christos }
1193 1.1 christos p->print (p->file, "\n");
1194 1.1 christos }
1195 1.1 christos }
1196 1.1 christos
1197 1.1 christos static void
1198 1.1 christos print_interrupts (struct hw *me,
1199 1.1 christos int my_port,
1200 1.1 christos struct hw *dest,
1201 1.1 christos int dest_port,
1202 1.1 christos void *data)
1203 1.1 christos {
1204 1.1 christos struct printer *p = data;
1205 1.1.1.2 christos char src[32];
1206 1.1.1.2 christos char dst[32];
1207 1.1 christos hw_port_encode (me, my_port, src, sizeof (src), output_port);
1208 1.1 christos hw_port_encode (dest, dest_port, dst, sizeof (dst), input_port);
1209 1.1 christos p->print (p->file,
1210 1.1 christos "%s > %s %s %s\n",
1211 1.1 christos hw_path (me),
1212 1.1 christos src, dst,
1213 1.1 christos hw_path (dest));
1214 1.1 christos }
1215 1.1 christos
1216 1.1 christos static void
1217 1.1 christos print_device (struct hw *me,
1218 1.1 christos void *data)
1219 1.1 christos {
1220 1.1 christos struct printer *p = data;
1221 1.1 christos p->print (p->file, "%s\n", hw_path (me));
1222 1.1 christos print_properties (me, p);
1223 1.1 christos hw_port_traverse (me, print_interrupts, data);
1224 1.1 christos }
1225 1.1 christos
1226 1.1 christos void
1227 1.1 christos hw_tree_print (struct hw *root,
1228 1.1 christos hw_tree_print_callback *print,
1229 1.1 christos void *file)
1230 1.1 christos {
1231 1.1 christos struct printer p;
1232 1.1 christos p.print = print;
1233 1.1 christos p.file = file;
1234 1.1 christos hw_tree_traverse (root,
1235 1.1 christos print_device, NULL,
1236 1.1 christos &p);
1237 1.1 christos }
1238 1.1 christos
1239 1.1 christos
1240 1.1 christos
1241 1.1.1.2 christos #if NOT_YET
1243 1.1 christos device_instance *
1244 1.1 christos tree_instance (struct hw *root,
1245 1.1 christos const char *device_specifier)
1246 1.1 christos {
1247 1.1.1.2 christos /* find the device node */
1248 1.1 christos struct hw *me;
1249 1.1.1.2 christos name_specifier spec;
1250 1.1 christos if (!split_device_specifier (root, device_specifier, &spec))
1251 1.1 christos return NULL;
1252 1.1 christos me = split_find_device (root, &spec);
1253 1.1.1.2 christos if (spec.name != NULL)
1254 1.1 christos return NULL;
1255 1.1 christos /* create the instance */
1256 1.1 christos return device_create_instance (me, device_specifier, spec.last_args);
1257 1.1 christos }
1258 1.1 christos #endif
1259 1.1 christos
1260 1.1 christos struct hw *
1261 1.1 christos hw_tree_find_device (struct hw *root,
1262 1.1 christos const char *path_to_device)
1263 1.1 christos {
1264 1.1 christos struct hw *node;
1265 1.1 christos name_specifier spec;
1266 1.1 christos
1267 1.1 christos /* parse the path */
1268 1.1 christos split_device_specifier (root, path_to_device, &spec);
1269 1.1 christos if (spec.value != NULL)
1270 1.1 christos return NULL; /* something wierd */
1271 1.1 christos
1272 1.1 christos /* now find it */
1273 1.1 christos node = split_find_device (root, &spec);
1274 1.1 christos if (spec.name != NULL)
1275 1.1 christos return NULL; /* not a leaf */
1276 1.1 christos
1277 1.1 christos return node;
1278 1.1 christos }
1279 1.1 christos
1280 1.1 christos
1281 1.1 christos const struct hw_property *
1282 1.1 christos hw_tree_find_property (struct hw *root,
1283 1.1 christos const char *path_to_property)
1284 1.1 christos {
1285 1.1 christos name_specifier spec;
1286 1.1 christos if (!split_property_specifier (root, path_to_property, &spec))
1287 1.1 christos hw_abort (root, "Invalid property path %s", path_to_property);
1288 1.1 christos root = split_find_device (root, &spec);
1289 1.1 christos if (spec.name != NULL)
1290 1.1 christos return NULL; /* not a leaf */
1291 1.1 christos return hw_find_property (root, spec.property);
1292 1.1 christos }
1293 1.1 christos
1294 1.1 christos int
1295 1.1 christos hw_tree_find_boolean_property (struct hw *root,
1296 1.1 christos const char *path_to_property)
1297 1.1 christos {
1298 1.1 christos name_specifier spec;
1299 1.1 christos if (!split_property_specifier (root, path_to_property, &spec))
1300 1.1 christos hw_abort (root, "Invalid property path %s", path_to_property);
1301 1.1 christos root = split_find_device (root, &spec);
1302 1.1 christos if (spec.name != NULL)
1303 1.1 christos hw_abort (root, "device \"%s\" not found (property \"%s\")",
1304 1.1 christos spec.name, path_to_property);
1305 1.1 christos return hw_find_boolean_property (root, spec.property);
1306 1.1 christos }
1307 1.1 christos
1308 1.1 christos signed_cell
1309 1.1 christos hw_tree_find_integer_property (struct hw *root,
1310 1.1 christos const char *path_to_property)
1311 1.1 christos {
1312 1.1 christos name_specifier spec;
1313 1.1 christos if (!split_property_specifier (root, path_to_property, &spec))
1314 1.1 christos hw_abort (root, "Invalid property path %s", path_to_property);
1315 1.1 christos root = split_find_device (root, &spec);
1316 1.1 christos if (spec.name != NULL)
1317 1.1 christos hw_abort (root, "device \"%s\" not found (property \"%s\")",
1318 1.1 christos spec.name, path_to_property);
1319 1.1 christos return hw_find_integer_property (root, spec.property);
1320 1.1 christos }
1321 1.1 christos
1322 1.1 christos #if NOT_YET
1323 1.1 christos device_instance *
1324 1.1 christos hw_tree_find_ihandle_property (struct hw *root,
1325 1.1 christos const char *path_to_property)
1326 1.1 christos {
1327 1.1 christos struct hw *root;
1328 1.1 christos name_specifier spec;
1329 1.1 christos if (!split_property_specifier (root, path_to_property, &spec))
1330 1.1 christos hw_abort (root, "Invalid property path %s", path_to_property);
1331 1.1 christos root = split_find_device (root, &spec);
1332 1.1 christos if (spec.name != NULL)
1333 1.1 christos hw_abort (root, "device \"%s\" not found (property \"%s\")",
1334 1.1 christos spec.name, path_to_property);
1335 1.1 christos return hw_find_ihandle_property (root, spec.property);
1336 1.1 christos }
1337 1.1 christos #endif
1338 1.1 christos
1339 1.1 christos const char *
1340 1.1 christos hw_tree_find_string_property (struct hw *root,
1341 1.1 christos const char *path_to_property)
1342 1.1 christos {
1343 1.1 christos name_specifier spec;
1344 1.1 christos if (!split_property_specifier (root, path_to_property, &spec))
1345 1.1 christos hw_abort (root, "Invalid property path %s", path_to_property);
1346 1.1 christos root = split_find_device (root, &spec);
1347 1.1 christos if (spec.name != NULL)
1348 1.1 christos hw_abort (root, "device \"%s\" not found (property \"%s\")",
1349 spec.name, path_to_property);
1350 return hw_find_string_property (root, spec.property);
1351 }
1352