PageRenderTime 53ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/sim/ppc/tree.c

https://github.com/rofl0r/gdb
C | 1306 lines | 1100 code | 101 blank | 105 comment | 214 complexity | d293d5f3a45a20b98b363353dd13f19b MD5 | raw file
  1. /* This file is part of the program psim.
  2. Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. #ifndef _PARSE_C_
  16. #define _PARSE_C_
  17. #include <stdio.h>
  18. #include <stdarg.h>
  19. #include "basics.h"
  20. #include "device.h"
  21. #include "tree.h"
  22. #ifdef HAVE_STDLIB_H
  23. #include <stdlib.h>
  24. #endif
  25. #ifdef HAVE_STRING_H
  26. #include <string.h>
  27. #else
  28. #ifdef HAVE_STRINGS_H
  29. #include <strings.h>
  30. #endif
  31. #endif
  32. #include <ctype.h>
  33. #include "libiberty.h"
  34. /* manipulate/lookup device names */
  35. typedef struct _name_specifier {
  36. /* components in the full length name */
  37. char *path;
  38. char *property;
  39. char *value;
  40. /* current device */
  41. char *name;
  42. char *base;
  43. char *unit;
  44. char *args;
  45. /* previous device */
  46. char *last_name;
  47. char *last_base;
  48. char *last_unit;
  49. char *last_args;
  50. /* work area */
  51. char buf[1024];
  52. } name_specifier;
  53. /* Given a device specifier, break it up into its main components:
  54. path (and if present) property name and property value. */
  55. STATIC_INLINE_TREE\
  56. (int)
  57. split_device_specifier(device *current,
  58. const char *device_specifier,
  59. name_specifier *spec)
  60. {
  61. char *chp = NULL;
  62. /* expand any leading alias if present */
  63. if (current != NULL
  64. && *device_specifier != '\0'
  65. && *device_specifier != '.'
  66. && *device_specifier != '/') {
  67. device *aliases = tree_find_device(current, "/aliases");
  68. char alias[32];
  69. int len = 0;
  70. while (device_specifier[len] != '\0'
  71. && device_specifier[len] != '/'
  72. && device_specifier[len] != ':'
  73. && !isspace(device_specifier[len])) {
  74. alias[len] = device_specifier[len];
  75. len++;
  76. if (len >= sizeof(alias))
  77. error("split_device_specifier: buffer overflow");
  78. }
  79. alias[len] = '\0';
  80. if (aliases != NULL
  81. && device_find_property(aliases, alias)) {
  82. strcpy(spec->buf, device_find_string_property(aliases, alias));
  83. strcat(spec->buf, device_specifier + len);
  84. }
  85. else {
  86. strcpy(spec->buf, device_specifier);
  87. }
  88. }
  89. else {
  90. strcpy(spec->buf, device_specifier);
  91. }
  92. /* check no overflow */
  93. if (strlen(spec->buf) >= sizeof(spec->buf))
  94. error("split_device_specifier: buffer overflow\n");
  95. /* strip leading spaces */
  96. chp = spec->buf;
  97. while (*chp != '\0' && isspace(*chp))
  98. chp++;
  99. if (*chp == '\0')
  100. return 0;
  101. /* find the path and terminate it with null */
  102. spec->path = chp;
  103. while (*chp != '\0' && !isspace(*chp))
  104. chp++;
  105. if (*chp != '\0') {
  106. *chp = '\0';
  107. chp++;
  108. }
  109. /* and any value */
  110. while (*chp != '\0' && isspace(*chp))
  111. chp++;
  112. spec->value = chp;
  113. /* now go back and chop the property off of the path */
  114. if (spec->value[0] == '\0') {
  115. spec->property = NULL; /*not a property*/
  116. spec->value = NULL;
  117. }
  118. else if (spec->value[0] == '>'
  119. || spec->value[0] == '<') {
  120. /* an interrupt spec */
  121. spec->property = NULL;
  122. }
  123. else {
  124. chp = strrchr(spec->path, '/');
  125. if (chp == NULL) {
  126. spec->property = spec->path;
  127. spec->path = strchr(spec->property, '\0');
  128. }
  129. else {
  130. *chp = '\0';
  131. spec->property = chp+1;
  132. }
  133. }
  134. /* and mark the rest as invalid */
  135. spec->name = NULL;
  136. spec->base = NULL;
  137. spec->unit = NULL;
  138. spec->args = NULL;
  139. spec->last_name = NULL;
  140. spec->last_base = NULL;
  141. spec->last_unit = NULL;
  142. spec->last_args = NULL;
  143. return 1;
  144. }
  145. /* given a device specifier break it up into its main components -
  146. path and property name - assuming that the last `device' is a
  147. property name. */
  148. STATIC_INLINE_DEVICE\
  149. (int)
  150. split_property_specifier(device *current,
  151. const char *property_specifier,
  152. name_specifier *spec)
  153. {
  154. if (split_device_specifier(current, property_specifier, spec)) {
  155. if (spec->property == NULL) {
  156. /* force the last name to be a property name */
  157. char *chp = strrchr(spec->path, '/');
  158. if (chp == NULL) {
  159. spec->property = spec->path;
  160. spec->path = strrchr(spec->property, '\0');;
  161. }
  162. else {
  163. *chp = '\0';
  164. spec->property = chp+1;
  165. }
  166. }
  167. return 1;
  168. }
  169. else
  170. return 0;
  171. }
  172. /* device the next device name and split it up, return 0 when no more
  173. names to device */
  174. STATIC_INLINE_TREE\
  175. (int)
  176. split_device_name(name_specifier *spec)
  177. {
  178. char *chp;
  179. /* remember what came before */
  180. spec->last_name = spec->name;
  181. spec->last_base = spec->base;
  182. spec->last_unit = spec->unit;
  183. spec->last_args = spec->args;
  184. /* finished? */
  185. if (spec->path[0] == '\0') {
  186. spec->name = NULL;
  187. spec->base = NULL;
  188. spec->unit = NULL;
  189. spec->args = NULL;
  190. return 0;
  191. }
  192. /* break the current device spec from the path */
  193. spec->name = spec->path;
  194. chp = strchr(spec->name, '/');
  195. if (chp == NULL)
  196. spec->path = strchr(spec->name, '\0');
  197. else {
  198. spec->path = chp+1;
  199. *chp = '\0';
  200. }
  201. /* break out the base */
  202. if (spec->name[0] == '(') {
  203. chp = strchr(spec->name, ')');
  204. if (chp == NULL) {
  205. spec->base = spec->name;
  206. }
  207. else {
  208. *chp = '\0';
  209. spec->base = spec->name + 1;
  210. spec->name = chp + 1;
  211. }
  212. }
  213. else {
  214. spec->base = spec->name;
  215. }
  216. /* now break out the unit */
  217. chp = strchr(spec->name, '@');
  218. if (chp == NULL) {
  219. spec->unit = NULL;
  220. chp = spec->name;
  221. }
  222. else {
  223. *chp = '\0';
  224. chp += 1;
  225. spec->unit = chp;
  226. }
  227. /* finally any args */
  228. chp = strchr(chp, ':');
  229. if (chp == NULL)
  230. spec->args = NULL;
  231. else {
  232. *chp = '\0';
  233. spec->args = chp+1;
  234. }
  235. return 1;
  236. }
  237. /* device the value, returning the next non-space token */
  238. STATIC_INLINE_TREE\
  239. (char *)
  240. split_value(name_specifier *spec)
  241. {
  242. char *token;
  243. if (spec->value == NULL)
  244. return NULL;
  245. /* skip leading white space */
  246. while (isspace(spec->value[0]))
  247. spec->value++;
  248. if (spec->value[0] == '\0') {
  249. spec->value = NULL;
  250. return NULL;
  251. }
  252. token = spec->value;
  253. /* find trailing space */
  254. while (spec->value[0] != '\0' && !isspace(spec->value[0]))
  255. spec->value++;
  256. /* chop this value out */
  257. if (spec->value[0] != '\0') {
  258. spec->value[0] = '\0';
  259. spec->value++;
  260. }
  261. return token;
  262. }
  263. /* traverse the path specified by spec starting at current */
  264. STATIC_INLINE_TREE\
  265. (device *)
  266. split_find_device(device *current,
  267. name_specifier *spec)
  268. {
  269. /* strip off (and process) any leading ., .., ./ and / */
  270. while (1) {
  271. if (strncmp(spec->path, "/", strlen("/")) == 0) {
  272. /* cd /... */
  273. while (current != NULL && device_parent(current) != NULL)
  274. current = device_parent(current);
  275. spec->path += strlen("/");
  276. }
  277. else if (strncmp(spec->path, "./", strlen("./")) == 0) {
  278. /* cd ./... */
  279. current = current;
  280. spec->path += strlen("./");
  281. }
  282. else if (strncmp(spec->path, "../", strlen("../")) == 0) {
  283. /* cd ../... */
  284. if (current != NULL && device_parent(current) != NULL)
  285. current = device_parent(current);
  286. spec->path += strlen("../");
  287. }
  288. else if (strcmp(spec->path, ".") == 0) {
  289. /* cd . */
  290. current = current;
  291. spec->path += strlen(".");
  292. }
  293. else if (strcmp(spec->path, "..") == 0) {
  294. /* cd . */
  295. if (current != NULL && device_parent(current) != NULL)
  296. current = device_parent(current);
  297. spec->path += strlen("..");
  298. }
  299. else
  300. break;
  301. }
  302. /* now go through the path proper */
  303. if (current == NULL) {
  304. split_device_name(spec);
  305. return NULL;
  306. }
  307. while (split_device_name(spec)) {
  308. device *child;
  309. for (child = device_child(current);
  310. child != NULL; child = device_sibling(child)) {
  311. if (strcmp(spec->name, device_name(child)) == 0) {
  312. if (spec->unit == NULL)
  313. break;
  314. else {
  315. device_unit phys;
  316. device_decode_unit(current, spec->unit, &phys);
  317. if (memcmp(&phys, device_unit_address(child),
  318. sizeof(device_unit)) == 0)
  319. break;
  320. }
  321. }
  322. }
  323. if (child == NULL)
  324. return current; /* search failed */
  325. current = child;
  326. }
  327. return current;
  328. }
  329. STATIC_INLINE_TREE\
  330. (device *)
  331. split_fill_path(device *current,
  332. const char *device_specifier,
  333. name_specifier *spec)
  334. {
  335. /* break it up */
  336. if (!split_device_specifier(current, device_specifier, spec))
  337. device_error(current, "error parsing %s\n", device_specifier);
  338. /* fill our tree with its contents */
  339. current = split_find_device(current, spec);
  340. /* add any additional devices as needed */
  341. if (spec->name != NULL) {
  342. do {
  343. current = device_create(current, spec->base, spec->name,
  344. spec->unit, spec->args);
  345. } while (split_device_name(spec));
  346. }
  347. return current;
  348. }
  349. INLINE_TREE\
  350. (void)
  351. tree_init(device *root,
  352. psim *system)
  353. {
  354. TRACE(trace_device_tree, ("tree_init(root=0x%lx, system=0x%lx)\n",
  355. (long)root,
  356. (long)system));
  357. /* remove the old, rebuild the new */
  358. tree_traverse(root, device_clean, NULL, system);
  359. tree_traverse(root, device_init_static_properties, NULL, system);
  360. tree_traverse(root, device_init_address, NULL, system);
  361. tree_traverse(root, device_init_runtime_properties, NULL, system);
  362. tree_traverse(root, device_init_data, NULL, system);
  363. }
  364. /* <non-white-space> */
  365. STATIC_INLINE_TREE\
  366. (const char *)
  367. skip_token(const char *chp)
  368. {
  369. while (!isspace(*chp) && *chp != '\0')
  370. chp++;
  371. while (isspace(*chp) && *chp != '\0')
  372. chp++;
  373. return chp;
  374. }
  375. /* count the number of entries */
  376. STATIC_INLINE_TREE\
  377. (int)
  378. count_entries(device *current,
  379. const char *property_name,
  380. const char *property_value,
  381. int modulo)
  382. {
  383. const char *chp = property_value;
  384. int nr_entries = 0;
  385. while (*chp != '\0') {
  386. nr_entries += 1;
  387. chp = skip_token(chp);
  388. }
  389. if ((nr_entries % modulo) != 0) {
  390. device_error(current, "incorrect number of entries for %s property %s, should be multiple of %d",
  391. property_name, property_value, modulo);
  392. }
  393. return nr_entries / modulo;
  394. }
  395. /* parse: <address> ::= <token> ; device dependant */
  396. STATIC_INLINE_TREE\
  397. (const char *)
  398. parse_address(device *current,
  399. device *bus,
  400. const char *chp,
  401. device_unit *address)
  402. {
  403. ASSERT(device_nr_address_cells(bus) > 0);
  404. if (device_decode_unit(bus, chp, address) < 0)
  405. device_error(current, "invalid unit address in %s", chp);
  406. return skip_token(chp);
  407. }
  408. /* parse: <size> ::= <number> { "," <number> } ; */
  409. STATIC_INLINE_TREE\
  410. (const char *)
  411. parse_size(device *current,
  412. device *bus,
  413. const char *chp,
  414. device_unit *size)
  415. {
  416. int i;
  417. int nr;
  418. const char *curr = chp;
  419. memset(size, 0, sizeof(*size));
  420. /* parse the numeric list */
  421. size->nr_cells = device_nr_size_cells(bus);
  422. nr = 0;
  423. ASSERT(size->nr_cells > 0);
  424. while (1) {
  425. char *next;
  426. size->cells[nr] = strtoul(curr, &next, 0);
  427. if (curr == next)
  428. device_error(current, "Problem parsing <size> %s", chp);
  429. nr += 1;
  430. if (next[0] != ',')
  431. break;
  432. if (nr == size->nr_cells)
  433. device_error(current, "Too many values in <size> %s", chp);
  434. curr = next + 1;
  435. }
  436. ASSERT(nr > 0 && nr <= size->nr_cells);
  437. /* right align the numbers */
  438. for (i = 1; i <= size->nr_cells; i++) {
  439. if (i <= nr)
  440. size->cells[size->nr_cells - i] = size->cells[nr - i];
  441. else
  442. size->cells[size->nr_cells - i] = 0;
  443. }
  444. return skip_token(chp);
  445. }
  446. /* parse: <reg> ::= { <address> <size> } ; */
  447. STATIC_INLINE_TREE\
  448. (void)
  449. parse_reg_property(device *current,
  450. const char *property_name,
  451. const char *property_value)
  452. {
  453. int nr_regs;
  454. int reg_nr;
  455. reg_property_spec *regs;
  456. const char *chp;
  457. device *bus = device_parent(current);
  458. /* determine the number of reg entries by counting tokens */
  459. nr_regs = count_entries(current, property_name, property_value,
  460. 1 + (device_nr_size_cells(bus) > 0));
  461. /* create working space */
  462. regs = zalloc(nr_regs * sizeof(*regs));
  463. /* fill it in */
  464. chp = property_value;
  465. for (reg_nr = 0; reg_nr < nr_regs; reg_nr++) {
  466. chp = parse_address(current, bus, chp, &regs[reg_nr].address);
  467. if (device_nr_size_cells(bus) > 0)
  468. chp = parse_size(current, bus, chp, &regs[reg_nr].size);
  469. else
  470. memset(&regs[reg_nr].size, 0, sizeof (&regs[reg_nr].size));
  471. }
  472. /* create it */
  473. device_add_reg_array_property(current, property_name,
  474. regs, nr_regs);
  475. free(regs);
  476. }
  477. /* { <child-address> <parent-address> <child-size> }* */
  478. STATIC_INLINE_TREE\
  479. (void)
  480. parse_ranges_property(device *current,
  481. const char *property_name,
  482. const char *property_value)
  483. {
  484. int nr_ranges;
  485. int range_nr;
  486. range_property_spec *ranges;
  487. const char *chp;
  488. /* determine the number of ranges specified */
  489. nr_ranges = count_entries(current, property_name, property_value, 3);
  490. /* create a property of that size */
  491. ranges = zalloc(nr_ranges * sizeof(*ranges));
  492. /* fill it in */
  493. chp = property_value;
  494. for (range_nr = 0; range_nr < nr_ranges; range_nr++) {
  495. chp = parse_address(current, current,
  496. chp, &ranges[range_nr].child_address);
  497. chp = parse_address(current, device_parent(current),
  498. chp, &ranges[range_nr].parent_address);
  499. chp = parse_size(current, current,
  500. chp, &ranges[range_nr].size);
  501. }
  502. /* create it */
  503. device_add_range_array_property(current, property_name, ranges, nr_ranges);
  504. free(ranges);
  505. }
  506. /* <integer> ... */
  507. STATIC_INLINE_TREE\
  508. (void)
  509. parse_integer_property(device *current,
  510. const char *property_name,
  511. const char *property_value)
  512. {
  513. int nr_entries;
  514. unsigned_cell words[1024];
  515. /* integer or integer array? */
  516. nr_entries = 0;
  517. while (1) {
  518. char *end;
  519. words[nr_entries] = strtoul(property_value, &end, 0);
  520. if (property_value == end)
  521. break;
  522. nr_entries += 1;
  523. if (nr_entries * sizeof(words[0]) >= sizeof(words))
  524. device_error(current, "buffer overflow");
  525. property_value = end;
  526. }
  527. if (nr_entries == 0)
  528. device_error(current, "error parsing integer property %s (%s)",
  529. property_name, property_value);
  530. else if (nr_entries == 1)
  531. device_add_integer_property(current, property_name, words[0]);
  532. else {
  533. int i;
  534. for (i = 0; i < nr_entries; i++) {
  535. H2BE(words[i]);
  536. }
  537. /* perhaps integer array property is better */
  538. device_add_array_property(current, property_name, words,
  539. sizeof(words[0]) * nr_entries);
  540. }
  541. }
  542. /* PROPERTY_VALUE is a raw property value. Quote it as required by
  543. parse_string_property. It is the caller's responsibility to free
  544. the memory returned. */
  545. EXTERN_TREE\
  546. (char *)
  547. tree_quote_property(const char *property_value)
  548. {
  549. char *p;
  550. char *ret;
  551. const char *chp;
  552. int quotees;
  553. /* Count characters needing quotes in PROPERTY_VALUE. */
  554. quotees = 0;
  555. for (chp = property_value; *chp; ++chp)
  556. if (*chp == '\\' || *chp == '"')
  557. ++quotees;
  558. ret = (char *) xmalloc (strlen (property_value)
  559. + 2 /* quotes */
  560. + quotees
  561. + 1 /* terminator */);
  562. p = ret;
  563. /* Add the opening quote. */
  564. *p++ = '"';
  565. /* Copy the value. */
  566. for (chp = property_value; *chp; ++chp)
  567. if (*chp == '\\' || *chp == '"')
  568. {
  569. /* Quote this character. */
  570. *p++ = '\\';
  571. *p++ = *chp;
  572. }
  573. else
  574. *p++ = *chp;
  575. /* Add the closing quote. */
  576. *p++ = '"';
  577. /* Terminate the string. */
  578. *p++ = '\0';
  579. return ret;
  580. }
  581. /* <string> ... */
  582. STATIC_INLINE_TREE\
  583. (void)
  584. parse_string_property(device *current,
  585. const char *property_name,
  586. const char *property_value)
  587. {
  588. char **strings;
  589. const char *chp;
  590. int nr_strings;
  591. int approx_nr_strings;
  592. /* get an estimate as to the number of strings by counting double
  593. quotes */
  594. approx_nr_strings = 2;
  595. for (chp = property_value; *chp; chp++) {
  596. if (*chp == '"')
  597. approx_nr_strings++;
  598. }
  599. approx_nr_strings = (approx_nr_strings) / 2;
  600. /* create a string buffer for that many (plus a null) */
  601. strings = (char**)zalloc((approx_nr_strings + 1) * sizeof(char*));
  602. /* now find all the strings */
  603. chp = property_value;
  604. nr_strings = 0;
  605. while (1) {
  606. /* skip leading space */
  607. while (*chp != '\0' && isspace(*chp))
  608. chp += 1;
  609. if (*chp == '\0')
  610. break;
  611. /* copy it in */
  612. if (*chp == '"') {
  613. /* a quoted string - watch for '\' et.al. */
  614. /* estimate the size and allocate space for it */
  615. int pos;
  616. chp++;
  617. pos = 0;
  618. while (chp[pos] != '\0' && chp[pos] != '"') {
  619. if (chp[pos] == '\\' && chp[pos+1] != '\0')
  620. pos += 2;
  621. else
  622. pos += 1;
  623. }
  624. strings[nr_strings] = zalloc(pos + 1);
  625. /* copy the string over */
  626. pos = 0;
  627. while (*chp != '\0' && *chp != '"') {
  628. if (*chp == '\\' && *(chp+1) != '\0') {
  629. strings[nr_strings][pos] = *(chp+1);
  630. chp += 2;
  631. pos++;
  632. }
  633. else {
  634. strings[nr_strings][pos] = *chp;
  635. chp += 1;
  636. pos++;
  637. }
  638. }
  639. if (*chp != '\0')
  640. chp++;
  641. strings[nr_strings][pos] = '\0';
  642. }
  643. else {
  644. /* copy over a single unquoted token */
  645. int len = 0;
  646. while (chp[len] != '\0' && !isspace(chp[len]))
  647. len++;
  648. strings[nr_strings] = zalloc(len + 1);
  649. strncpy(strings[nr_strings], chp, len);
  650. strings[nr_strings][len] = '\0';
  651. chp += len;
  652. }
  653. nr_strings++;
  654. if (nr_strings > approx_nr_strings)
  655. device_error(current, "String property %s badly formatted",
  656. property_name);
  657. }
  658. ASSERT(strings[nr_strings] == NULL); /* from zalloc */
  659. /* install it */
  660. if (nr_strings == 0)
  661. device_add_string_property(current, property_name, "");
  662. else if (nr_strings == 1)
  663. device_add_string_property(current, property_name, strings[0]);
  664. else {
  665. const char **specs = (const char**)strings; /* stop a bogus error */
  666. device_add_string_array_property(current, property_name,
  667. specs, nr_strings);
  668. }
  669. /* flush the created string */
  670. while (nr_strings > 0) {
  671. nr_strings--;
  672. free(strings[nr_strings]);
  673. }
  674. free(strings);
  675. }
  676. /* <path-to-ihandle-device> */
  677. STATIC_INLINE_TREE\
  678. (void)
  679. parse_ihandle_property(device *current,
  680. const char *property,
  681. const char *value)
  682. {
  683. ihandle_runtime_property_spec ihandle;
  684. /* pass the full path */
  685. ihandle.full_path = value;
  686. /* save this ready for the ihandle create */
  687. device_add_ihandle_runtime_property(current, property,
  688. &ihandle);
  689. }
  690. EXTERN_TREE\
  691. (device *)
  692. tree_parse(device *current,
  693. const char *fmt,
  694. ...)
  695. {
  696. char device_specifier[1024];
  697. name_specifier spec;
  698. /* format the path */
  699. {
  700. va_list ap;
  701. va_start(ap, fmt);
  702. vsprintf(device_specifier, fmt, ap);
  703. va_end(ap);
  704. if (strlen(device_specifier) >= sizeof(device_specifier))
  705. error("device_tree_add_deviced: buffer overflow\n");
  706. }
  707. /* construct the tree down to the final device */
  708. current = split_fill_path(current, device_specifier, &spec);
  709. /* is there an interrupt spec */
  710. if (spec.property == NULL
  711. && spec.value != NULL) {
  712. char *op = split_value(&spec);
  713. switch (op[0]) {
  714. case '>':
  715. {
  716. char *my_port_name = split_value(&spec);
  717. int my_port;
  718. char *dest_port_name = split_value(&spec);
  719. int dest_port;
  720. name_specifier dest_spec;
  721. char *dest_device_name = split_value(&spec);
  722. device *dest;
  723. /* find my name */
  724. my_port = device_interrupt_decode(current, my_port_name,
  725. output_port);
  726. /* find the dest device and port */
  727. dest = split_fill_path(current, dest_device_name, &dest_spec);
  728. dest_port = device_interrupt_decode(dest, dest_port_name,
  729. input_port);
  730. /* connect the two */
  731. device_interrupt_attach(current,
  732. my_port,
  733. dest,
  734. dest_port,
  735. permenant_object);
  736. }
  737. break;
  738. default:
  739. device_error(current, "unreconised interrupt spec %s\n", spec.value);
  740. break;
  741. }
  742. }
  743. /* is there a property */
  744. if (spec.property != NULL) {
  745. if (strcmp(spec.value, "true") == 0)
  746. device_add_boolean_property(current, spec.property, 1);
  747. else if (strcmp(spec.value, "false") == 0)
  748. device_add_boolean_property(current, spec.property, 0);
  749. else {
  750. const device_property *property;
  751. switch (spec.value[0]) {
  752. case '*':
  753. parse_ihandle_property(current, spec.property, spec.value + 1);
  754. break;
  755. case '[':
  756. {
  757. unsigned8 words[1024];
  758. char *curr = spec.value + 1;
  759. int nr_words = 0;
  760. while (1) {
  761. char *next;
  762. words[nr_words] = H2BE_1(strtoul(curr, &next, 0));
  763. if (curr == next)
  764. break;
  765. curr = next;
  766. nr_words += 1;
  767. }
  768. device_add_array_property(current, spec.property,
  769. words, sizeof(words[0]) * nr_words);
  770. }
  771. break;
  772. case '"':
  773. parse_string_property(current, spec.property, spec.value);
  774. break;
  775. case '!':
  776. spec.value++;
  777. property = tree_find_property(current, spec.value);
  778. if (property == NULL)
  779. device_error(current, "property %s not found\n", spec.value);
  780. device_add_duplicate_property(current,
  781. spec.property,
  782. property);
  783. break;
  784. default:
  785. if (strcmp(spec.property, "reg") == 0
  786. || strcmp(spec.property, "assigned-addresses") == 0
  787. || strcmp(spec.property, "alternate-reg") == 0){
  788. parse_reg_property(current, spec.property, spec.value);
  789. }
  790. else if (strcmp(spec.property, "ranges") == 0) {
  791. parse_ranges_property(current, spec.property, spec.value);
  792. }
  793. else if (isdigit(spec.value[0])
  794. || (spec.value[0] == '-' && isdigit(spec.value[1]))
  795. || (spec.value[0] == '+' && isdigit(spec.value[1]))) {
  796. parse_integer_property(current, spec.property, spec.value);
  797. }
  798. else
  799. parse_string_property(current, spec.property, spec.value);
  800. break;
  801. }
  802. }
  803. }
  804. return current;
  805. }
  806. INLINE_TREE\
  807. (void)
  808. tree_traverse(device *root,
  809. tree_traverse_function *prefix,
  810. tree_traverse_function *postfix,
  811. void *data)
  812. {
  813. device *child;
  814. if (prefix != NULL)
  815. prefix(root, data);
  816. for (child = device_child(root);
  817. child != NULL;
  818. child = device_sibling(child)) {
  819. tree_traverse(child, prefix, postfix, data);
  820. }
  821. if (postfix != NULL)
  822. postfix(root, data);
  823. }
  824. STATIC_INLINE_TREE\
  825. (void)
  826. print_address(device *bus,
  827. const device_unit *phys)
  828. {
  829. char unit[32];
  830. device_encode_unit(bus, phys, unit, sizeof(unit));
  831. printf_filtered(" %s", unit);
  832. }
  833. STATIC_INLINE_TREE\
  834. (void)
  835. print_size(device *bus,
  836. const device_unit *size)
  837. {
  838. int i;
  839. for (i = 0; i < size->nr_cells; i++)
  840. if (size->cells[i] != 0)
  841. break;
  842. if (i < size->nr_cells) {
  843. printf_filtered(" 0x%lx", (unsigned long)size->cells[i]);
  844. i++;
  845. for (; i < size->nr_cells; i++)
  846. printf_filtered(",0x%lx", (unsigned long)size->cells[i]);
  847. }
  848. else
  849. printf_filtered(" 0");
  850. }
  851. STATIC_INLINE_TREE\
  852. (void)
  853. print_reg_property(device *me,
  854. const device_property *property)
  855. {
  856. int reg_nr;
  857. reg_property_spec reg;
  858. for (reg_nr = 0;
  859. device_find_reg_array_property(me, property->name, reg_nr, &reg);
  860. reg_nr++) {
  861. print_address(device_parent(me), &reg.address);
  862. print_size(me, &reg.size);
  863. }
  864. }
  865. STATIC_INLINE_TREE\
  866. (void)
  867. print_ranges_property(device *me,
  868. const device_property *property)
  869. {
  870. int range_nr;
  871. range_property_spec range;
  872. for (range_nr = 0;
  873. device_find_range_array_property(me, property->name, range_nr, &range);
  874. range_nr++) {
  875. print_address(me, &range.child_address);
  876. print_address(device_parent(me), &range.parent_address);
  877. print_size(me, &range.size);
  878. }
  879. }
  880. STATIC_INLINE_TREE\
  881. (void)
  882. print_string(const char *string)
  883. {
  884. printf_filtered(" \"");
  885. while (*string != '\0') {
  886. switch (*string) {
  887. case '"':
  888. printf_filtered("\\\"");
  889. break;
  890. case '\\':
  891. printf_filtered("\\\\");
  892. break;
  893. default:
  894. printf_filtered("%c", *string);
  895. break;
  896. }
  897. string++;
  898. }
  899. printf_filtered("\"");
  900. }
  901. STATIC_INLINE_TREE\
  902. (void)
  903. print_string_array_property(device *me,
  904. const device_property *property)
  905. {
  906. int nr;
  907. string_property_spec string;
  908. for (nr = 0;
  909. device_find_string_array_property(me, property->name, nr, &string);
  910. nr++) {
  911. print_string(string);
  912. }
  913. }
  914. STATIC_INLINE_TREE\
  915. (void)
  916. print_properties(device *me)
  917. {
  918. const device_property *property;
  919. for (property = device_find_property(me, NULL);
  920. property != NULL;
  921. property = device_next_property(property)) {
  922. printf_filtered("%s/%s", device_path(me), property->name);
  923. if (property->original != NULL) {
  924. printf_filtered(" !");
  925. printf_filtered("%s/%s",
  926. device_path(property->original->owner),
  927. property->original->name);
  928. }
  929. else {
  930. switch (property->type) {
  931. case array_property:
  932. if ((property->sizeof_array % sizeof(signed_cell)) == 0) {
  933. unsigned_cell *w = (unsigned_cell*)property->array;
  934. int cell_nr;
  935. for (cell_nr = 0;
  936. cell_nr < (property->sizeof_array / sizeof(unsigned_cell));
  937. cell_nr++) {
  938. printf_filtered(" 0x%lx", (unsigned long)BE2H_cell(w[cell_nr]));
  939. }
  940. }
  941. else {
  942. unsigned8 *w = (unsigned8*)property->array;
  943. printf_filtered(" [");
  944. while ((char*)w - (char*)property->array < property->sizeof_array) {
  945. printf_filtered(" 0x%2x", BE2H_1(*w));
  946. w++;
  947. }
  948. }
  949. break;
  950. case boolean_property:
  951. {
  952. int b = device_find_boolean_property(me, property->name);
  953. printf_filtered(" %s", b ? "true" : "false");
  954. }
  955. break;
  956. case ihandle_property:
  957. {
  958. if (property->array != NULL) {
  959. device_instance *instance = device_find_ihandle_property(me, property->name);
  960. printf_filtered(" *%s", device_instance_path(instance));
  961. }
  962. else {
  963. /* not yet initialized, ask the device for the path */
  964. ihandle_runtime_property_spec spec;
  965. device_find_ihandle_runtime_property(me, property->name, &spec);
  966. printf_filtered(" *%s", spec.full_path);
  967. }
  968. }
  969. break;
  970. case integer_property:
  971. {
  972. unsigned_word w = device_find_integer_property(me, property->name);
  973. printf_filtered(" 0x%lx", (unsigned long)w);
  974. }
  975. break;
  976. case range_array_property:
  977. print_ranges_property(me, property);
  978. break;
  979. case reg_array_property:
  980. print_reg_property(me, property);
  981. break;
  982. case string_property:
  983. {
  984. const char *s = device_find_string_property(me, property->name);
  985. print_string(s);
  986. }
  987. break;
  988. case string_array_property:
  989. print_string_array_property(me, property);
  990. break;
  991. }
  992. }
  993. printf_filtered("\n");
  994. }
  995. }
  996. STATIC_INLINE_TREE\
  997. (void)
  998. print_interrupts(device *me,
  999. int my_port,
  1000. device *dest,
  1001. int dest_port,
  1002. void *ignore_or_null)
  1003. {
  1004. char src[32];
  1005. char dst[32];
  1006. device_interrupt_encode(me, my_port, src, sizeof(src), output_port);
  1007. device_interrupt_encode(dest, dest_port, dst, sizeof(dst), input_port);
  1008. printf_filtered("%s > %s %s %s\n",
  1009. device_path(me),
  1010. src, dst,
  1011. device_path(dest));
  1012. }
  1013. STATIC_INLINE_TREE\
  1014. (void)
  1015. print_device(device *me,
  1016. void *ignore_or_null)
  1017. {
  1018. printf_filtered("%s\n", device_path(me));
  1019. print_properties(me);
  1020. device_interrupt_traverse(me, print_interrupts, NULL);
  1021. }
  1022. INLINE_TREE\
  1023. (void)
  1024. tree_print(device *root)
  1025. {
  1026. tree_traverse(root,
  1027. print_device, NULL,
  1028. NULL);
  1029. }
  1030. INLINE_TREE\
  1031. (void)
  1032. tree_usage(int verbose)
  1033. {
  1034. if (verbose == 1) {
  1035. printf_filtered("\n");
  1036. printf_filtered("A device/property specifier has the form:\n");
  1037. printf_filtered("\n");
  1038. printf_filtered(" /path/to/a/device [ property-value ]\n");
  1039. printf_filtered("\n");
  1040. printf_filtered("and a possible device is\n");
  1041. printf_filtered("\n");
  1042. }
  1043. if (verbose > 1) {
  1044. printf_filtered("\n");
  1045. printf_filtered("A device/property specifier (<spec>) has the format:\n");
  1046. printf_filtered("\n");
  1047. printf_filtered(" <spec> ::= <path> [ <value> ] ;\n");
  1048. printf_filtered(" <path> ::= { <prefix> } { <node> \"/\" } <node> ;\n");
  1049. printf_filtered(" <prefix> ::= ( | \"/\" | \"../\" | \"./\" ) ;\n");
  1050. printf_filtered(" <node> ::= <name> [ \"@\" <unit> ] [ \":\" <args> ] ;\n");
  1051. printf_filtered(" <unit> ::= <number> { \",\" <number> } ;\n");
  1052. printf_filtered("\n");
  1053. printf_filtered("Where:\n");
  1054. printf_filtered("\n");
  1055. printf_filtered(" <name> is the name of a device (list below)\n");
  1056. printf_filtered(" <unit> is the unit-address relative to the parent bus\n");
  1057. printf_filtered(" <args> additional arguments used when creating the device\n");
  1058. printf_filtered(" <value> ::= ( <number> # integer property\n");
  1059. printf_filtered(" | \"[\" { <number> } # array property (byte)\n");
  1060. printf_filtered(" | \"{\" { <number> } # array property (cell)\n");
  1061. printf_filtered(" | [ \"true\" | \"false\" ] # boolean property\n");
  1062. printf_filtered(" | \"*\" <path> # ihandle property\n");
  1063. printf_filtered(" | \"!\" <path> # copy property\n");
  1064. printf_filtered(" | \">\" [ <number> ] <path> # attach interrupt\n");
  1065. printf_filtered(" | \"<\" <path> # attach child interrupt\n");
  1066. printf_filtered(" | \"\\\"\" <text> # string property\n");
  1067. printf_filtered(" | <text> # string property\n");
  1068. printf_filtered(" ) ;\n");
  1069. printf_filtered("\n");
  1070. printf_filtered("And the following are valid device names:\n");
  1071. printf_filtered("\n");
  1072. }
  1073. }
  1074. INLINE_TREE\
  1075. (device_instance *)
  1076. tree_instance(device *root,
  1077. const char *device_specifier)
  1078. {
  1079. /* find the device node */
  1080. device *me;
  1081. name_specifier spec;
  1082. if (!split_device_specifier(root, device_specifier, &spec))
  1083. return NULL;
  1084. me = split_find_device(root, &spec);
  1085. if (spec.name != NULL)
  1086. return NULL;
  1087. /* create the instance */
  1088. return device_create_instance(me, device_specifier, spec.last_args);
  1089. }
  1090. INLINE_TREE\
  1091. (device *)
  1092. tree_find_device(device *root,
  1093. const char *path_to_device)
  1094. {
  1095. device *node;
  1096. name_specifier spec;
  1097. /* parse the path */
  1098. split_device_specifier(root, path_to_device, &spec);
  1099. if (spec.value != NULL)
  1100. return NULL; /* something wierd */
  1101. /* now find it */
  1102. node = split_find_device(root, &spec);
  1103. if (spec.name != NULL)
  1104. return NULL; /* not a leaf */
  1105. return node;
  1106. }
  1107. INLINE_TREE\
  1108. (const device_property *)
  1109. tree_find_property(device *root,
  1110. const char *path_to_property)
  1111. {
  1112. name_specifier spec;
  1113. if (!split_property_specifier(root, path_to_property, &spec))
  1114. device_error(root, "Invalid property path %s", path_to_property);
  1115. root = split_find_device(root, &spec);
  1116. return device_find_property(root, spec.property);
  1117. }
  1118. INLINE_TREE\
  1119. (int)
  1120. tree_find_boolean_property(device *root,
  1121. const char *path_to_property)
  1122. {
  1123. name_specifier spec;
  1124. if (!split_property_specifier(root, path_to_property, &spec))
  1125. device_error(root, "Invalid property path %s", path_to_property);
  1126. root = split_find_device(root, &spec);
  1127. return device_find_boolean_property(root, spec.property);
  1128. }
  1129. INLINE_TREE\
  1130. (signed_cell)
  1131. tree_find_integer_property(device *root,
  1132. const char *path_to_property)
  1133. {
  1134. name_specifier spec;
  1135. if (!split_property_specifier(root, path_to_property, &spec))
  1136. device_error(root, "Invalid property path %s", path_to_property);
  1137. root = split_find_device(root, &spec);
  1138. return device_find_integer_property(root, spec.property);
  1139. }
  1140. INLINE_TREE\
  1141. (device_instance *)
  1142. tree_find_ihandle_property(device *root,
  1143. const char *path_to_property)
  1144. {
  1145. name_specifier spec;
  1146. if (!split_property_specifier(root, path_to_property, &spec))
  1147. device_error(root, "Invalid property path %s", path_to_property);
  1148. root = split_find_device(root, &spec);
  1149. return device_find_ihandle_property(root, spec.property);
  1150. }
  1151. INLINE_TREE\
  1152. (const char *)
  1153. tree_find_string_property(device *root,
  1154. const char *path_to_property)
  1155. {
  1156. name_specifier spec;
  1157. if (!split_property_specifier(root, path_to_property, &spec))
  1158. device_error(root, "Invalid property path %s", path_to_property);
  1159. root = split_find_device(root, &spec);
  1160. return device_find_string_property(root, spec.property);
  1161. }
  1162. #endif /* _PARSE_C_ */