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