1 1.1 christos /* The common simulator framework for GDB, the GNU Debugger. 2 1.1 christos 3 1.1.1.12 christos Copyright 2002-2025 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.1.11 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 weird */ 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