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