Make simulator build again on SunOS and HP/US systems
[deliverable/binutils-gdb.git] / sim / ppc / device.c
CommitLineData
93fac324
MM
1/* This file is part of the program psim.
2
3 Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21
22#ifndef _DEVICE_C_
23#define _DEVICE_C_
24
25#include <stdio.h>
26
27#include "device_table.h"
28
29#ifdef HAVE_STDLIB_H
30#include <stdlib.h>
31#endif
32
33#ifdef HAVE_STRING_H
34#include <string.h>
35#else
36#ifdef HAVE_STRINGS_H
37#include <strings.h>
38#endif
39#endif
40
41#include <ctype.h>
42
43
44
45typedef struct _device_property_entry device_property_entry;
46struct _device_property_entry {
47 const char *name;
48 device_property_entry *next;
49 device_property *value;
50};
51
52
53/* A device */
54struct _device {
55 /* my name is ... */
56 const char *name;
57 const char *full_name;
58 /* device tree */
59 device *parent;
60 device *children;
61 device *sibling;
62 /* hw/sw callbacks */
63 void *data; /* device specific data */
64 const device_callbacks *callback;
65 /* device properties */
66 device_property_entry *properties;
67};
68
69
979c3c25
MM
70INLINE_DEVICE\
71(device *)
93fac324
MM
72device_create(const char *name,
73 device *parent)
74{
75 device_descriptor *descr;
76 int name_len;
77 char *chp;
78 chp = strchr(name, '@');
79 name_len = (chp == NULL ? strlen(name) : chp - name);
80 for (descr = device_table; descr->name != NULL; descr++) {
81 if (strncmp(name, descr->name, name_len) == 0
82 && (descr->name[name_len] == '\0'
83 || descr->name[name_len] == '@')) {
84 void *data = (descr->creator != NULL
85 ? descr->creator(name, parent)
86 : NULL);
87 return device_create_from(name, data, descr->callbacks, parent);
88 }
89 }
90 error("device_create() unknown device %s\n", name);
91 return NULL;
92}
93
979c3c25
MM
94INLINE_DEVICE\
95(device *)
93fac324
MM
96device_create_from(const char *name,
97 void *data,
98 const device_callbacks *callbacks,
99 device *parent)
100{
101 device *new_device = ZALLOC(device);
102 new_device->data = data;
103 new_device->name = strdup(name);
104 new_device->callback = callbacks;
105 new_device->parent = parent;
106 return new_device;
107}
108
109
979c3c25
MM
110INLINE_DEVICE\
111(device *)
93fac324
MM
112device_parent(device *me)
113{
114 return me->parent;
115}
116
979c3c25
MM
117INLINE_DEVICE\
118(device *)
119device_sibling(device *me)
120{
121 return me->sibling;
122}
123
124INLINE_DEVICE\
125(device *)
126device_child(device *me)
127{
128 return me->children;
129}
130
131INLINE_DEVICE\
132(const char *)
93fac324
MM
133device_name(device *me)
134{
135 return me->name;
136}
137
979c3c25
MM
138INLINE_DEVICE\
139(void *)
93fac324
MM
140device_data(device *me)
141{
142 return me->data;
143}
144
979c3c25
MM
145INLINE_DEVICE\
146(void)
93fac324
MM
147device_traverse_properties(device *me,
148 device_traverse_property_function *traverse,
149 void *data)
150{
151 device_property_entry *entry = me->properties;
152 while (entry != NULL) {
153 traverse(me, entry->name, data);
154 entry = entry->next;
155 }
156}
157
979c3c25
MM
158INLINE_DEVICE\
159(void)
93fac324
MM
160device_init(device *me,
161 psim *system)
162{
163 me->callback->init(me, system);
164}
165
979c3c25
MM
166INLINE_DEVICE\
167(void)
93fac324
MM
168device_attach_address(device *me,
169 const char *name,
170 attach_type attach,
171 int space,
172 unsigned_word addr,
173 unsigned nr_bytes,
174 access_type access,
175 device *who) /*callback/default*/
176{
177 me->callback->attach_address(me, name, attach, space,
178 addr, nr_bytes, access, who);
179}
180
979c3c25
MM
181INLINE_DEVICE\
182(void)
93fac324
MM
183device_detach_address(device *me,
184 const char *name,
185 attach_type attach,
186 int space,
187 unsigned_word addr,
188 unsigned nr_bytes,
189 access_type access,
190 device *who) /*callback/default*/
191{
192 me->callback->detach_address(me, name, attach, space,
193 addr, nr_bytes, access, who);
194}
195
979c3c25
MM
196INLINE_DEVICE\
197(unsigned)
93fac324
MM
198device_io_read_buffer(device *me,
199 void *dest,
200 int space,
201 unsigned_word addr,
202 unsigned nr_bytes,
203 cpu *processor,
204 unsigned_word cia)
205{
206 return me->callback->io_read_buffer(me, dest, space,
207 addr, nr_bytes,
208 processor, cia);
209}
210
979c3c25
MM
211INLINE_DEVICE\
212(unsigned)
93fac324
MM
213device_io_write_buffer(device *me,
214 const void *source,
215 int space,
216 unsigned_word addr,
217 unsigned nr_bytes,
218 cpu *processor,
219 unsigned_word cia)
220{
221 return me->callback->io_write_buffer(me, source, space,
222 addr, nr_bytes,
223 processor, cia);
224}
225
979c3c25
MM
226INLINE_DEVICE\
227(unsigned)
93fac324
MM
228device_dma_read_buffer(device *me,
229 void *dest,
230 int space,
231 unsigned_word addr,
232 unsigned nr_bytes)
233{
234 return me->callback->dma_read_buffer(me, dest, space,
235 addr, nr_bytes);
236}
237
979c3c25
MM
238INLINE_DEVICE\
239(unsigned)
93fac324
MM
240device_dma_write_buffer(device *me,
241 const void *source,
242 int space,
243 unsigned_word addr,
244 unsigned nr_bytes,
245 int violate_read_only_section)
246{
247 return me->callback->dma_write_buffer(me, source, space,
248 addr, nr_bytes,
249 violate_read_only_section);
250}
251
979c3c25
MM
252INLINE_DEVICE\
253(void)
93fac324
MM
254device_attach_interrupt(device *me,
255 device *who,
256 int interrupt_line,
257 const char *name)
258{
259 me->callback->attach_interrupt(me, who, interrupt_line, name);
260}
261
979c3c25
MM
262INLINE_DEVICE\
263(void)
93fac324
MM
264device_detach_interrupt(device *me,
265 device *who,
266 int interrupt_line,
267 const char *name)
268{
269 me->callback->detach_interrupt(me, who, interrupt_line, name);
270}
271
979c3c25
MM
272INLINE_DEVICE\
273(void)
93fac324
MM
274device_interrupt(device *me,
275 device *who,
276 int interrupt_line,
277 int interrupt_status,
278 cpu *processor,
279 unsigned_word cia)
280{
281 me->callback->interrupt(me, who, interrupt_line, interrupt_status,
282 processor, cia);
283}
284
979c3c25
MM
285INLINE_DEVICE\
286(void)
93fac324
MM
287device_interrupt_ack(device *me,
288 int interrupt_line,
289 int interrupt_status)
290{
291 me->callback->interrupt_ack(me, interrupt_line, interrupt_status);
292}
293
979c3c25
MM
294EXTERN_DEVICE\
295(void)
93fac324
MM
296device_ioctl(device *me,
297 psim *system,
298 cpu *processor,
299 unsigned_word cia,
300 ...)
301{
302 va_list ap;
303 va_start(ap, cia);
304 me->callback->ioctl(me, system, processor, cia, ap);
305 va_end(ap);
306}
307
308
309/* Manipulate properties attached to devices */
310
979c3c25
MM
311STATIC_INLINE_DEVICE\
312(device_property *)
93fac324
MM
313device_add_property(device *me,
314 const char *property,
315 device_property_type type,
316 const void *array,
317 int sizeof_array)
318{
319 device_property_entry *new_entry = 0;
320 device_property *new_value = 0;
321 void *new_array = 0;
322 /* find the list end */
323 device_property_entry **insertion_point = &me->properties;
324 while (*insertion_point != NULL) {
325 if (strcmp((**insertion_point).name, property) == 0)
326 return (**insertion_point).value;
327 insertion_point = &(**insertion_point).next;
328 }
329 /* alloc data for the new property */
330 new_entry = ZALLOC(device_property_entry);
331 new_value = ZALLOC(device_property);
332 new_array = (sizeof_array > 0
333 ? zalloc(sizeof_array)
334 : (void*)0);
335 /* insert the new property into the list */
336 *insertion_point = new_entry;
337 new_entry->name = strdup(property);
338 new_entry->value = new_value;
339 new_value->type = type;
340 new_value->sizeof_array = sizeof_array;
341 new_value->array = new_array;
342 if (sizeof_array > 0)
343 memcpy(new_array, array, sizeof_array);
344 return new_value;
345}
346
979c3c25
MM
347INLINE_DEVICE\
348(void)
93fac324
MM
349device_add_array_property(device *me,
350 const char *property,
351 const void *array,
352 int sizeof_array)
353{
354 TRACE(trace_devices,
355 ("device_add_array_property(me=0x%lx, property=%s, ...)\n",
356 (long)me, property));
357 device_add_property(me, property,
358 array_property, array, sizeof_array);
359}
360
979c3c25
MM
361INLINE_DEVICE\
362(void)
93fac324
MM
363device_add_integer_property(device *me,
364 const char *property,
365 signed32 integer)
366{
367 TRACE(trace_devices,
368 ("device_add_integer_property(me=0x%lx, property=%s, integer=%ld)\n",
369 (long)me, property, (long)integer));
370 H2BE(integer);
371 device_add_property(me, property, integer_property,
372 &integer, sizeof(integer));
373}
374
979c3c25
MM
375INLINE_DEVICE\
376(void)
93fac324
MM
377device_add_boolean_property(device *me,
378 const char *property,
379 int boolean)
380{
381 signed32 new_boolean = (boolean ? -1 : 0);
382 TRACE(trace_devices,
383 ("device_add_boolean(me=0x%lx, property=%s, boolean=%d)\n",
384 (long)me, property, boolean));
385 device_add_property(me, property, boolean_property,
386 &new_boolean, sizeof(new_boolean));
387}
388
979c3c25
MM
389INLINE_DEVICE\
390(void)
93fac324
MM
391device_add_null_property(device *me,
392 const char *property)
393{
394 TRACE(trace_devices,
395 ("device_add_null(me=0x%lx, property=%s)\n",
396 (long)me, property));
397 device_add_property(me, property, null_property,
398 NULL, 0);
399}
400
979c3c25
MM
401INLINE_DEVICE\
402(void)
93fac324
MM
403device_add_string_property(device *me,
404 const char *property,
405 const char *string)
406{
407
408 TRACE(trace_devices,
409 ("device_add_property(me=0x%lx, property=%s, string=%s)\n",
410 (long)me, property, string));
411 device_add_property(me, property, string_property,
412 string, strlen(string) + 1);
413}
414
979c3c25
MM
415INLINE_DEVICE\
416(const device_property *)
93fac324
MM
417device_find_property(device *me,
418 const char *property)
419{
420 if (me != (device*)0) {
421 device_property_entry *entry = me->properties;
422 while (entry != (device_property_entry*)0) {
423 if (strcmp(entry->name, property) == 0)
424 return entry->value;
425 entry = entry->next;
426 }
427 }
428 return (device_property*)0;
429}
430
979c3c25
MM
431INLINE_DEVICE\
432(const char *)
93fac324
MM
433device_find_next_property(device *me,
434 const char *property)
435{
436 if (me != NULL) {
437 if (property == NULL || strcmp(property, "") == 0) {
438 return (me->properties != NULL
439 ? me->properties->name
440 : NULL);
441 }
442 else {
443 device_property_entry *entry = me->properties;
444 while (entry != NULL) {
445 if (strcmp(entry->name, property) == 0)
446 return (entry->next != NULL
447 ? entry->next->name
448 : NULL);
449 entry = entry->next;
450 }
451 }
452 }
453 return NULL;
454}
455
979c3c25
MM
456INLINE_DEVICE\
457(const device_property *)
93fac324
MM
458device_find_array_property(device *me,
459 const char *property)
460{
461 const device_property *node;
462 TRACE(trace_devices,
463 ("device_find_integer(me=0x%lx, property=%s)\n",
464 (long)me, property));
465 node = device_find_property(me, property);
466 if (node == (device_property*)0
467 || node->type != array_property)
468 error("%s property %s not found or of wrong type\n",
469 me->name, property);
470 return node;
471}
472
979c3c25
MM
473INLINE_DEVICE\
474(signed_word)
93fac324
MM
475device_find_integer_property(device *me,
476 const char *property)
477{
478 const device_property *node;
479 signed32 integer;
480 TRACE(trace_devices,
481 ("device_find_integer(me=0x%lx, property=%s)\n",
482 (long)me, property));
483 node = device_find_property(me, property);
484 if (node == (device_property*)0
485 || node->type != integer_property)
486 error("%s property %s not found or of wrong type\n",
487 me->name, property);
488 ASSERT(sizeof(integer) == node->sizeof_array);
489 memcpy(&integer, node->array, sizeof(integer));
490 BE2H(integer);
491 return integer;
492}
493
979c3c25
MM
494INLINE_DEVICE\
495(int)
93fac324
MM
496device_find_boolean_property(device *me,
497 const char *property)
498{
499 const device_property *node;
500 unsigned32 boolean;
501 TRACE(trace_devices,
502 ("device_find_boolean(me=0x%lx, property=%s)\n",
503 (long)me, property));
504 node = device_find_property(me, property);
505 if (node == (device_property*)0
506 || node->type != boolean_property)
507 error("%s property %s not found or of wrong type\n",
508 me->name, property);
509 ASSERT(sizeof(boolean) == node->sizeof_array);
510 memcpy(&boolean, node->array, sizeof(boolean));
511 return boolean;
512}
513
979c3c25
MM
514INLINE_DEVICE\
515(const char *)
93fac324
MM
516device_find_string_property(device *me,
517 const char *property)
518{
519 const device_property *node;
520 const char *string;
521 TRACE(trace_devices,
522 ("device_find_string(me=0x%lx, property=%s)\n",
523 (long)me, property));
524 node = device_find_property(me, property);
525 if (node == (device_property*)0
526 || node->type != string_property)
527 error("%s property %s not found or of wrong type\n",
528 me->name, property);
529 string = node->array;
530 ASSERT(strlen(string) + 1 == node->sizeof_array);
531 return string;
532}
533
534
535/* determine the full name of the device. If buf is specified it is
536 stored in there. Failing that, a safe area of memory is allocated */
979c3c25
MM
537STATIC_INLINE_DEVICE\
538(const char *)
93fac324
MM
539device_tree_full_name(device *leaf,
540 char *buf,
541 unsigned sizeof_buf)
542{
543 /* get a buffer */
544 char full_name[1024];
545 if (buf == (char*)0) {
546 buf = full_name;
547 sizeof_buf = sizeof(full_name);
548 }
549
550 /* construct a name */
551 if (leaf->parent == NULL) {
552 if (sizeof_buf < 1)
553 error("device_full_name() buffer overflow\n");
554 *buf = '\0';
555 }
556 else {
557 device_tree_full_name(leaf->parent, buf, sizeof_buf);
558 if (strlen(buf) + strlen("/") + strlen(leaf->name) + 1 > sizeof_buf)
559 error("device_full_name() buffer overflow\n");
560 strcat(buf, "/");
561 strcat(buf, leaf->name);
562 }
563
564 /* return it usefully */
565 if (buf == full_name)
566 buf = strdup(full_name);
567 return buf;
568}
569
570
571/* find/create a node in the device tree */
572
573typedef enum {
574 device_tree_return_null = 2,
575 device_tree_abort = 3,
576} device_tree_action;
577
979c3c25
MM
578STATIC_INLINE_DEVICE\
579(device *)
93fac324
MM
580device_tree_find_node(device *root,
581 const char *path,
582 const char *full_path,
583 device_tree_action action)
584{
585 const char *name;
586 int strlen_name;
587 device *child;
588
589 /* strip off any leading `/', `../' or `./' */
590 while (1) {
591 if (strncmp(path, "/", strlen("/")) == 0) {
592 while (root != NULL && root->parent != NULL)
593 root = root->parent;
594 path += strlen("/");
595 }
596 else if (strncmp(path, "./", strlen("./")) == 0) {
597 root = root;
598 path += strlen("./");
599 }
600 else if (strncmp(path, "../", strlen("../")) == 0) {
601 if (root != NULL && root->parent != NULL)
602 root = root->parent;
603 path += strlen("../");
604 }
605 else {
606 break;
607 }
608 }
609
610 /* parse the driver_name/unit-address */
611 ASSERT(*path != '/');
612 name = path;
613 while (isalnum(*path)
614 || *path == ',' || *path == ',' || *path == '_'
615 || *path == '+' || *path == '-')
616 path++;
617 if ((*path != '/' && *path != '@' && *path != ':' && *path != '\0')
618 || (name == path && *name != '\0'))
619 error("device_tree: path %s invalid at %s\n", full_path, path);
620
621 /* parse the unit-address */
622 if (*path == '@') {
623 path++;
624 while ((*path != '\0' && *path != ':' && *path != '/')
625 || (*path == ':' && path[-1] == '\\')
626 || (*path == '/' && path[-1] == '\\'))
627 path++;
628 }
629 strlen_name = path - name;
630
631 /* skip the device-arguments */
632 if (*path == ':') {
633 path++;
634 while ((*path != '\0' && *path != '/' && *path != ':' && *path != '@')
635 || (*path == '/' && path[-1] == '\\')
636 || (*path == ':' && path[-1] == '\\')
637 || (*path == '@' && path[-1] == '\\'))
638 path++;
639 }
640
641 /* sanity checks */
642 if (*path != '\0' && *path != '/')
643 error("device_tree: path %s invalid at %s\n", full_path, path);
644
645 /* leaf? and growing? */
646 if (name[0] == '\0') {
647 return root;
648 }
649 else if (root != NULL) {
650 for (child = root->children;
651 child != NULL;
652 child = child->sibling) {
653 if (strncmp(name, child->name, strlen_name) == 0
979c3c25
MM
654 && strlen(child->name) >= strlen_name
655 && (child->name[strlen_name] == '\0'
656 || child->name[strlen_name] == '@')) {
93fac324
MM
657 if (*path == '\0')
658 return child;
659 else
660 return device_tree_find_node(child,
661 path + 1/* / */,
662 full_path,
663 action);
664 }
665 }
666 }
667
668 /* search failed, take default action */
669 switch (action) {
670 case device_tree_return_null:
671 return NULL;
672 case device_tree_abort:
673 error("device_tree_find_node() could not find %s in tree\n",
674 full_path);
675 return NULL;
676 default:
677 error("device_tree_find_node() invalid default action %d\n", action);
678 return NULL;
679 }
680}
681
682
683/* grow the device tree */
684
979c3c25
MM
685INLINE_DEVICE\
686(device *)
93fac324
MM
687device_tree_add_device(device *root,
688 const char *prefix,
689 device *new_sub_tree)
690{
691 device *parent;
692 TRACE(trace_device_tree,
693 ("device_tree_add_device(root=0x%lx, prefix=%s, dev=0x%lx)\n",
694 (long)root, prefix, (long)new_sub_tree));
695
696 /* find our parent */
697 parent = device_tree_find_node(root,
698 prefix,
699 prefix, /* full-path */
700 device_tree_abort);
701
702 /* create/insert a new child */
703 new_sub_tree->parent = parent;
704 if (parent != NULL) {
705 device **sibling = &parent->children;
706 while ((*sibling) != NULL)
707 sibling = &(*sibling)->sibling;
708 *sibling = new_sub_tree;
709 }
710
711 return new_sub_tree;
712}
713
979c3c25
MM
714INLINE_DEVICE\
715(device *)
93fac324
MM
716device_tree_find_device(device *root,
717 const char *path)
718{
719 device *node;
720 TRACE(trace_device_tree,
721 ("device_tree_find_device_tree(root=0x%lx, path=%s)\n",
722 (long)root, path));
723 node = device_tree_find_node(root,
724 path,
725 path, /* full-name */
726 device_tree_return_null);
727 return node;
728}
729
730
731/* init all the devices */
732
979c3c25
MM
733STATIC_INLINE_DEVICE\
734(void)
93fac324
MM
735device_tree_init_device(device *root,
736 void *data)
737{
738 psim *system;
739 system = (psim*)data;
740 TRACE(trace_device_tree,
741 ("device_tree_init() initializing device=0x%lx:%s\n",
742 (long)root, root->full_name));
743 device_init(root, system);
744}
745
746
979c3c25
MM
747INLINE_DEVICE\
748(void)
93fac324
MM
749device_tree_init(device *root,
750 psim *system)
751{
752 TRACE(trace_device_tree,
753 ("device_tree_init(root=0x%lx, system=0x%lx)\n", (long)root, (long)system));
754 device_tree_traverse(root, device_tree_init_device, NULL, system);
755 TRACE(trace_device_tree,
756 ("device_tree_init() = void\n"));
757}
758
759
760/* traverse a device tree applying prefix/postfix functions to it */
761
979c3c25
MM
762INLINE_DEVICE\
763(void)
93fac324
MM
764device_tree_traverse(device *root,
765 device_tree_traverse_function *prefix,
766 device_tree_traverse_function *postfix,
767 void *data)
768{
769 device *child;
770 if (prefix != NULL)
771 prefix(root, data);
772 for (child = root->children; child != NULL; child = child->sibling) {
773 device_tree_traverse(child, prefix, postfix, data);
774 }
775 if (postfix != NULL)
776 postfix(root, data);
777}
778
779
780/* dump out a device node and addresses */
781
979c3c25
MM
782INLINE_DEVICE\
783(void)
93fac324
MM
784device_tree_dump(device *device,
785 void *ignore_data_argument)
786{
787 printf_filtered("(device_tree@0x%lx\n", (long)device);
788 printf_filtered(" (parent 0x%lx)\n", (long)device->parent);
789 printf_filtered(" (children 0x%lx)\n", (long)device->children);
790 printf_filtered(" (sibling 0x%lx)\n", (long)device->sibling);
791 printf_filtered(" (name %s)\n", device->name);
792 error("FIXME - need to print out properties\n");
793 printf_filtered(")\n");
794}
795
796
797/* lookup/create a device various formats */
798
979c3c25
MM
799STATIC_INLINE_DEVICE\
800(void)
93fac324
MM
801u_strcat(char *buf,
802 unsigned_word uw)
803{
804 if (MASKED64(uw, 32, 63) == uw
805 || WITH_HOST_WORD_BITSIZE == 64) {
806 char *end = strchr(buf, '\0');
807 sprintf(end, "0x%x", (unsigned)uw);
808 }
809 else {
810 char *end = strchr(buf, '\0');
811 sprintf(end, "0x%x%08x",
812 (unsigned)EXTRACTED64(uw, 0, 31),
813 (unsigned)EXTRACTED64(uw, 32, 63));
814 }
815}
816
979c3c25
MM
817STATIC_INLINE_DEVICE\
818(void)
93fac324
MM
819c_strcat(char *buf,
820 const char *c)
821{
822 char *end = strchr(buf, '\0');
823 while (*c) {
824 if (*c == '/' || *c == ',')
825 *end++ = '\\';
826 *end++ = *c++;
827 }
828 *end = '\0';
829}
830
979c3c25
MM
831INLINE_DEVICE\
832(device *)
93fac324
MM
833device_tree_add_found(device *root,
834 const char *prefix,
835 const char *name)
836{
837 device *parent;
838 device *new_device;
839 device *new_node;
840 TRACE(trace_device_tree,
979c3c25
MM
841 ("device_tree_add_found(root=0x%lx, prefix=%s, name=%lx)\n",
842 (unsigned long)root, prefix, (unsigned long)name));
93fac324
MM
843 parent = device_tree_find_node(root, prefix, prefix,
844 device_tree_abort);
845 new_device = device_tree_find_device(parent, name);
846 if (new_device != NULL)
847 return new_device;
848 else {
849 new_device = device_create(name, parent);
850 new_node = device_tree_add_device(parent, "", new_device);
851 ASSERT(new_device == new_node);
852 return new_node;
853 }
854}
855
979c3c25
MM
856INLINE_DEVICE\
857(device *)
93fac324
MM
858device_tree_add_found_c(device *root,
859 const char *prefix,
860 const char *name,
861 const char *c1)
862{
863 char buf[1024];
864 strcpy(buf, name);
865 strcat(buf, "@");
866 c_strcat(buf, c1);
867 if (strlen(buf) + 1 >= sizeof(buf))
868 error("device_tree_add_found_c - buffer overflow\n");
869 return device_tree_add_found(root, prefix, buf);
870}
871
979c3c25
MM
872INLINE_DEVICE\
873(device *)
93fac324
MM
874device_tree_add_found_c_uw(device *root,
875 const char *prefix,
876 const char *name,
877 const char *c1,
878 unsigned_word uw2)
879{
880 char buf[1024];
881 strcpy(buf, name);
882 strcat(buf, "@");
883 c_strcat(buf, c1);
884 strcat(buf, ",");
885 u_strcat(buf, uw2);
886 if (strlen(buf) + 1 >= sizeof(buf))
887 error("device_tree_add_found_* - buffer overflow\n");
888 return device_tree_add_found(root, prefix, buf);
889}
890
979c3c25
MM
891INLINE_DEVICE\
892(device *)
93fac324
MM
893device_tree_add_found_uw_u(device *root,
894 const char *prefix,
895 const char *name,
896 unsigned_word uw1,
897 unsigned u2)
898{
899 char buf[1024];
900 strcpy(buf, name);
901 strcat(buf, "@");
902 u_strcat(buf, uw1);
903 strcat(buf, ",");
904 u_strcat(buf, u2);
905 if (strlen(buf) + 1 >= sizeof(buf))
906 error("device_tree_add_found_* - buffer overflow\n");
907 return device_tree_add_found(root, prefix, buf);
908}
909
979c3c25
MM
910INLINE_DEVICE\
911(device *)
93fac324
MM
912device_tree_add_found_uw_u_u(device *root,
913 const char *prefix,
914 const char *name,
915 unsigned_word uw1,
916 unsigned u2,
917 unsigned u3)
918{
919 char buf[1024];
920 strcpy(buf, name);
921 strcat(buf, "@");
922 u_strcat(buf, uw1);
923 strcat(buf, ",");
924 u_strcat(buf, u2);
925 strcat(buf, ",");
926 u_strcat(buf, u3);
927 if (strlen(buf) + 1 >= sizeof(buf))
928 error("device_tree_add_found_* - buffer overflow\n");
929 return device_tree_add_found(root, prefix, buf);
930}
931
979c3c25
MM
932INLINE_DEVICE\
933(device *)
93fac324
MM
934device_tree_add_found_uw_u_u_c(device *root,
935 const char *prefix,
936 const char *name,
937 unsigned_word uw1,
938 unsigned u2,
939 unsigned u3,
940 const char *c4)
941{
942 char buf[1024];
943 strcpy(buf, name);
944 strcat(buf, "@");
945 u_strcat(buf, uw1);
946 strcat(buf, ",");
947 u_strcat(buf, u2);
948 strcat(buf, ",");
949 u_strcat(buf, u3);
950 strcat(buf, ",");
951 c_strcat(buf, c4);
952 if (strlen(buf) + 1 >= sizeof(buf))
953 error("device_tree_add_found_* - buffer overflow\n");
954 return device_tree_add_found(root, prefix, buf);
955}
956
979c3c25
MM
957INLINE_DEVICE\
958(device *)
93fac324
MM
959device_tree_add_found_uw_uw_u_u_c(device *root,
960 const char *prefix,
961 const char *name,
962 unsigned_word uw1,
963 unsigned_word uw2,
964 unsigned u3,
965 unsigned u4,
966 const char *c5)
967{
968 char buf[1024];
969 strcpy(buf, name);
970 strcat(buf, "@");
971 u_strcat(buf, uw1);
972 strcat(buf, ",");
973 u_strcat(buf, uw2);
974 strcat(buf, ",");
975 u_strcat(buf, u3);
976 strcat(buf, ",");
977 u_strcat(buf, u4);
978 strcat(buf, ",");
979 c_strcat(buf, c5);
980 if (strlen(buf) + 1 >= sizeof(buf))
981 error("device_tree_add_found_* - buffer overflow\n");
982 return device_tree_add_found(root, prefix, buf);
983}
984
979c3c25
MM
985INLINE_DEVICE\
986(device *)
93fac324
MM
987device_tree_add_found_uw_uw_u_u_u(device *root,
988 const char *prefix,
989 const char *name,
990 unsigned_word uw1,
991 unsigned_word uw2,
992 unsigned u3,
993 unsigned u4,
994 unsigned u5)
995{
996 char buf[1024];
997 strcpy(buf, name);
998 strcat(buf, "@");
999 u_strcat(buf, uw1);
1000 strcat(buf, ",");
1001 u_strcat(buf, uw2);
1002 strcat(buf, ",");
1003 u_strcat(buf, u3);
1004 strcat(buf, ",");
1005 u_strcat(buf, u4);
1006 strcat(buf, ",");
1007 u_strcat(buf, u5);
1008 if (strlen(buf) + 1 >= sizeof(buf))
1009 error("device_tree_add_found_* - buffer overflow\n");
1010 return device_tree_add_found(root, prefix, buf);
1011}
1012
1013
1014/* Parse a device name, various formats */
1015
1016#define SCAN_INIT(NAME) \
1017 char *START = (char*)0; \
1018 char *END = (char*)0; \
1019 int COUNT = -1; \
1020 /* find the first element */ \
1021 END = strchr(NAME, '@'); \
1022 if (END == (char*)0) \
1023 return COUNT; \
1024 COUNT += 1; \
1025 START = END + 1
1026
1027#define SCAN_END \
1028 return COUNT
1029
1030#define SCAN_U(U) \
1031do { \
1032 *U = strtoul(START, &END, 0); \
1033 if (START == END) \
1034 return COUNT; \
1035 COUNT += 1; \
1036 if (*END != ',') \
1037 return COUNT; \
1038 START = END + 1; \
1039} while (0)
1040
1041#define SCAN_P(P) \
1042do { \
1043 *P = (void*)(unsigned)strtouq(START, END, 0); \
1044 if (START == END) \
1045 return COUNT; \
1046 COUNT += 1; \
1047 if (*END != ',') \
1048 return COUNT; \
1049 START = END + 1; \
1050} while (0)
1051
1052#define SCAN_C(C, SIZE) \
1053do { \
1054 char *chp = C; \
1055 END = START; \
1056 while (*END != '\0' && *END != ',') { \
1057 if (*END == '\\') \
1058 END += 1; \
1059 *chp = *END; \
1060 chp += 1; \
1061 END += 1; \
1062 if ((SIZE) <= ((END) - (START))) \
1063 return COUNT; /* overflow */ \
1064 } \
1065 *chp = '\0'; \
1066 if (START == END) \
1067 return COUNT; \
1068 COUNT += 1; \
1069 if (*END != ',') \
1070 return COUNT; \
1071 START = END + 1; \
1072} while (0)
1073
979c3c25
MM
1074INLINE_DEVICE\
1075(int)
93fac324
MM
1076scand_c(const char *name,
1077 char *c1,
1078 unsigned c1size)
1079{
1080 SCAN_INIT(name);
1081 SCAN_C(c1, c1size);
1082 SCAN_END;
1083}
1084
979c3c25
MM
1085INLINE_DEVICE\
1086(int)
93fac324
MM
1087scand_c_uw_u(const char *name,
1088 char *c1,
1089 unsigned c1size,
1090 unsigned_word *uw2,
1091 unsigned *u3)
1092{
1093 SCAN_INIT(name);
1094 SCAN_C(c1, c1size);
1095 SCAN_U(uw2);
1096 SCAN_U(u3);
1097 SCAN_END;
1098}
1099
979c3c25
MM
1100INLINE_DEVICE\
1101(int)
93fac324
MM
1102scand_uw(const char *name,
1103 unsigned_word *uw1)
1104{
1105 SCAN_INIT(name);
1106 SCAN_U(uw1);
1107 SCAN_END;
1108}
1109
979c3c25
MM
1110INLINE_DEVICE\
1111(int)
93fac324
MM
1112scand_uw_c(const char *name,
1113 unsigned_word *uw1,
1114 char *c2,
1115 unsigned c2size)
1116{
1117 SCAN_INIT(name);
1118 SCAN_U(uw1);
1119 SCAN_C(c2, c2size);
1120 SCAN_END;
1121}
1122
979c3c25
MM
1123INLINE_DEVICE\
1124(int)
93fac324
MM
1125scand_uw_u(const char *name,
1126 unsigned_word *uw1,
1127 unsigned *u2)
1128{
1129 SCAN_INIT(name);
1130 SCAN_U(uw1);
1131 SCAN_U(u2);
1132 SCAN_END;
1133}
1134
979c3c25
MM
1135INLINE_DEVICE\
1136(int)
93fac324
MM
1137scand_uw_u_u(const char *name,
1138 unsigned_word *uw1,
1139 unsigned *u2,
1140 unsigned *u3)
1141{
1142 SCAN_INIT(name);
1143 SCAN_U(uw1);
1144 SCAN_U(u2);
1145 SCAN_U(u3);
1146 SCAN_END;
1147}
1148
979c3c25
MM
1149INLINE_DEVICE\
1150(int)
93fac324
MM
1151scand_uw_u_u_c(const char *name,
1152 unsigned_word *uw1,
1153 unsigned *u2,
1154 unsigned *u3,
1155 char *c4,
1156 unsigned c4size)
1157{
1158 SCAN_INIT(name);
1159 SCAN_U(uw1);
1160 SCAN_U(u2);
1161 SCAN_U(u3);
1162 SCAN_C(c4, c4size);
1163 SCAN_END;
1164}
1165
979c3c25
MM
1166INLINE_DEVICE\
1167(int)
93fac324
MM
1168scand_uw_uw(const char *name,
1169 unsigned_word *uw1,
1170 unsigned_word *uw2)
1171{
1172 SCAN_INIT(name);
1173 SCAN_U(uw1);
1174 SCAN_U(uw2);
1175 SCAN_END;
1176}
1177
979c3c25
MM
1178INLINE_DEVICE\
1179(int)
93fac324
MM
1180scand_uw_uw_u(const char *name,
1181 unsigned_word *uw1,
1182 unsigned_word *uw2,
1183 unsigned *u3)
1184{
1185 SCAN_INIT(name);
1186 SCAN_U(uw1);
1187 SCAN_U(uw2);
1188 SCAN_U(u3);
1189 SCAN_END;
1190}
1191
979c3c25
MM
1192INLINE_DEVICE\
1193(int)
93fac324
MM
1194scand_uw_uw_u_u_c(const char *name,
1195 unsigned_word *uw1,
1196 unsigned_word *uw2,
1197 unsigned *u3,
1198 unsigned *u4,
1199 char *c5,
1200 unsigned c5size)
1201{
1202 SCAN_INIT(name);
1203 SCAN_U(uw1);
1204 SCAN_U(uw2);
1205 SCAN_U(u3);
1206 SCAN_U(u4);
1207 SCAN_C(c5, c5size);
1208 SCAN_END;
1209}
1210
979c3c25
MM
1211INLINE_DEVICE\
1212(int)
93fac324
MM
1213scand_uw_uw_u_u_u(const char *name,
1214 unsigned_word *uw1,
1215 unsigned_word *uw2,
1216 unsigned *u3,
1217 unsigned *u4,
1218 unsigned *u5)
1219{
1220 SCAN_INIT(name);
1221 SCAN_U(uw1);
1222 SCAN_U(uw2);
1223 SCAN_U(u3);
1224 SCAN_U(u4);
1225 SCAN_U(u5);
1226 SCAN_END;
1227}
1228
1229
1230#endif /* _DEVICE_C_ */
This page took 0.084461 seconds and 4 git commands to generate.