1 /* This file is part of the program psim.
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
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.
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.
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.
27 #include "device_table.h"
44 STATIC_INLINE_DEVICE (void) clean_device_properties(device
*);
45 STATIC_INLINE_DEVICE (void) init_device_properties(device
*, void*);
47 /* property entries */
49 typedef struct _device_property_entry device_property_entry
;
50 struct _device_property_entry
{
51 device_property_entry
*next
;
52 device_property
*value
;
53 const void *init_array
;
54 unsigned sizeof_init_array
;
60 typedef struct _device_interrupt_edge device_interrupt_edge
;
61 struct _device_interrupt_edge
{
65 device_interrupt_edge
*next
;
66 object_disposition disposition
;
71 attach_device_interrupt_edge(device_interrupt_edge
**list
,
75 object_disposition disposition
)
77 device_interrupt_edge
*new_edge
= ZALLOC(device_interrupt_edge
);
78 new_edge
->my_port
= my_port
;
79 new_edge
->dest
= dest
;
80 new_edge
->dest_port
= dest_port
;
81 new_edge
->next
= *list
;
82 new_edge
->disposition
= disposition
;
88 detach_device_interrupt_edge(device
*me
,
89 device_interrupt_edge
**list
,
94 while (*list
!= NULL
) {
95 device_interrupt_edge
*old_edge
= *list
;
96 if (old_edge
->dest
== dest
97 && old_edge
->dest_port
== dest_port
98 && old_edge
->my_port
== my_port
) {
99 if (old_edge
->disposition
== permenant_object
)
100 device_error(me
, "attempt to delete permenant interrupt\n");
101 *list
= old_edge
->next
;
106 device_error(me
, "attempt to delete unattached interrupt\n");
109 STATIC_INLINE_DEVICE\
111 clean_device_interrupt_edges(device_interrupt_edge
**list
)
113 while (*list
!= NULL
) {
114 device_interrupt_edge
*old_edge
= *list
;
115 switch (old_edge
->disposition
) {
116 case permenant_object
:
117 list
= &old_edge
->next
;
119 case tempoary_object
:
120 *list
= old_edge
->next
;
134 device_unit unit_address
;
142 /* its template methods */
143 void *data
; /* device specific data */
144 const device_callbacks
*callback
;
146 /* device properties */
147 device_property_entry
*properties
;
150 device_interrupt_edge
*interrupt_destinations
;
152 /* any open instances of this device */
153 device_instance
*instances
;
155 /* the internal/external mappings and other global requirements */
162 /* an instance of a device */
163 struct _device_instance
{
167 const device_instance_callbacks
*callback
;
168 /* the root instance */
170 device_instance
*next
;
171 /* interposed instance */
172 device_instance
*parent
;
173 device_instance
*child
;
182 device_parent(device
*me
)
189 device_sibling(device
*me
)
196 device_child(device
*me
)
203 device_name(device
*me
)
210 device_path(device
*me
)
217 device_data(device
*me
)
224 device_system(device
*me
)
230 (const device_unit
*)
231 device_unit_address(device
*me
)
233 return &me
->unit_address
;
238 /* device template: */
240 /* determine the full name of the device. If buf is specified it is
241 stored in there. Failing that, a safe area of memory is allocated */
243 STATIC_INLINE_DEVICE\
245 device_full_name(device
*leaf
,
250 char full_name
[1024];
251 if (buf
== (char*)0) {
253 sizeof_buf
= sizeof(full_name
);
256 /* construct a name */
257 if (leaf
->parent
== NULL
) {
259 error("device_full_name: buffer overflow\n");
264 device_full_name(leaf
->parent
, buf
, sizeof_buf
);
265 if (leaf
->parent
!= NULL
266 && leaf
->parent
->callback
->convert
.encode_unit(leaf
->parent
,
273 if (strlen(buf
) + strlen("/") + strlen(leaf
->name
) + strlen(unit
)
275 error("device_full_name: buffer overflow\n");
277 strcat(buf
, leaf
->name
);
281 /* return it usefully */
282 if (buf
== full_name
)
283 buf
= strdup(full_name
);
287 /* manipulate/lookup device names */
289 typedef struct _name_specifier
{
290 /* components in the full length name */
298 /* previous device */
306 /* Given a device specifier, break it up into its main components:
307 path (and if present) property name and property value. */
308 STATIC_INLINE_DEVICE\
310 split_device_specifier(const char *device_specifier
,
311 name_specifier
*spec
)
314 if (strlen(device_specifier
) >= sizeof(spec
->buf
))
315 error("split_device_specifier: buffer overflow\n");
317 /* expand aliases (later) */
318 strcpy(spec
->buf
, device_specifier
);
320 /* strip the leading spaces and check that remainder isn't a comment */
322 while (*chp
!= '\0' && isspace(*chp
))
324 if (*chp
== '\0' || *chp
== '#')
327 /* find the path and terminate it with null */
329 while (*chp
!= '\0' && !isspace(*chp
))
337 while (*chp
!= '\0' && isspace(*chp
))
341 /* now go back and chop the property off of the path */
342 if (spec
->value
[0] == '\0') {
343 spec
->property
= NULL
; /*not a property*/
346 else if (spec
->value
[0] == '>'
347 || spec
->value
[0] == '<') {
348 /* an interrupt spec */
349 spec
->property
= NULL
;
352 chp
= strrchr(spec
->path
, '/');
354 spec
->property
= spec
->path
;
355 spec
->path
= strchr(spec
->property
, '\0');
359 spec
->property
= chp
+1;
363 /* and mark the rest as invalid */
367 spec
->last_name
= NULL
;
368 spec
->last_unit
= NULL
;
369 spec
->last_args
= NULL
;
374 /* given a device specifier break it up into its main components -
375 path and property name - assuming that the last `device' is a
377 STATIC_INLINE_DEVICE\
379 split_property_specifier(const char *property_specifier
,
380 name_specifier
*spec
)
382 if (split_device_specifier(property_specifier
, spec
)) {
383 if (spec
->property
== NULL
) {
384 /* force the last name to be a property name */
385 char *chp
= strrchr(spec
->path
, '/');
387 spec
->property
= spec
->path
;
388 spec
->path
= strrchr(spec
->property
, '\0');;
392 spec
->property
= chp
+1;
401 /* parse the next device name and split it up, return 0 when no more
403 STATIC_INLINE_DEVICE\
405 split_device_name(name_specifier
*spec
)
408 /* remember what came before */
409 spec
->last_name
= spec
->name
;
410 spec
->last_unit
= spec
->unit
;
411 spec
->last_args
= spec
->args
;
413 if (spec
->path
[0] == '\0') {
419 /* break the device name from the path */
420 spec
->name
= spec
->path
;
421 chp
= strchr(spec
->name
, '/');
423 spec
->path
= strchr(spec
->name
, '\0');
428 /* now break out the unit */
429 chp
= strchr(spec
->name
, '@');
439 /* finally any args */
440 chp
= strchr(chp
, ':');
450 /* parse the value, returning the next non-space token */
452 STATIC_INLINE_DEVICE\
454 split_value(name_specifier
*spec
)
457 if (spec
->value
== NULL
)
459 /* skip leading white space */
460 while (isspace(spec
->value
[0]))
462 if (spec
->value
[0] == '\0') {
467 /* find trailing space */
468 while (spec
->value
[0] != '\0' && !isspace(spec
->value
[0]))
470 /* chop this value out */
471 if (spec
->value
[0] != '\0') {
472 spec
->value
[0] = '\0';
480 /* traverse the path specified by spec starting at current */
482 STATIC_INLINE_DEVICE\
484 split_find_device(device
*current
,
485 name_specifier
*spec
)
487 /* strip off (and process) any leading ., .., ./ and / */
489 if (strncmp(spec
->path
, "/", strlen("/")) == 0) {
491 while (current
!= NULL
&& current
->parent
!= NULL
)
492 current
= current
->parent
;
493 spec
->path
+= strlen("/");
495 else if (strncmp(spec
->path
, "./", strlen("./")) == 0) {
498 spec
->path
+= strlen("./");
500 else if (strncmp(spec
->path
, "../", strlen("../")) == 0) {
502 if (current
!= NULL
&& current
->parent
!= NULL
)
503 current
= current
->parent
;
504 spec
->path
+= strlen("../");
506 else if (strcmp(spec
->path
, ".") == 0) {
509 spec
->path
+= strlen(".");
511 else if (strcmp(spec
->path
, "..") == 0) {
513 if (current
!= NULL
&& current
->parent
!= NULL
)
514 current
= current
->parent
;
515 spec
->path
+= strlen("..");
521 /* now go through the path proper */
523 if (current
== NULL
) {
524 split_device_name(spec
);
528 while (split_device_name(spec
)) {
531 current
->callback
->convert
.decode_unit(current
, spec
->unit
, &phys
);
532 for (child
= current
->children
; child
!= NULL
; child
= child
->sibling
) {
533 if (strcmp(spec
->name
, child
->name
) == 0) {
534 if (phys
.nr_cells
== 0
535 || memcmp(&phys
, &child
->unit_address
, sizeof(device_unit
)) == 0)
540 return current
; /* search failed */
548 STATIC_INLINE_DEVICE\
550 device_create_from(const char *name
,
551 const device_unit
*unit_address
,
553 const device_callbacks
*callbacks
,
556 device
*new_device
= ZALLOC(device
);
558 /* insert it into the device tree */
559 new_device
->parent
= parent
;
560 new_device
->children
= NULL
;
561 if (parent
!= NULL
) {
562 device
**sibling
= &parent
->children
;
563 while ((*sibling
) != NULL
)
564 sibling
= &(*sibling
)->sibling
;
565 *sibling
= new_device
;
569 new_device
->name
= strdup(name
);
570 new_device
->unit_address
= *unit_address
;
571 new_device
->path
= device_full_name(new_device
, NULL
, 0);
574 new_device
->data
= data
;
575 new_device
->callback
= callbacks
;
577 /* its properties - already null */
578 /* interrupts - already null */
580 /* mappings - if needed */
581 if (parent
== NULL
) {
582 new_device
->ihandles
= cap_create(name
);
583 new_device
->phandles
= cap_create(name
);
590 STATIC_INLINE_DEVICE\
592 device_template_create_device(device
*parent
,
594 const char *unit_address
,
597 const device_descriptor
*const *table
;
600 chp
= strchr(name
, '@');
601 name_len
= (chp
== NULL
? strlen(name
) : chp
- name
);
602 for (table
= device_table
; *table
!= NULL
; table
++) {
603 const device_descriptor
*descr
;
604 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
605 if (strncmp(name
, descr
->name
, name_len
) == 0
606 && (descr
->name
[name_len
] == '\0'
607 || descr
->name
[name_len
] == '@')) {
608 device_unit address
= { 0 };
610 if (parent
!= NULL
&& parent
->callback
->convert
.decode_unit
!= NULL
)
611 parent
->callback
->convert
.decode_unit(parent
,
614 if (descr
->creator
!= NULL
)
615 data
= descr
->creator(name
, &address
, args
);
616 return device_create_from(name
, &address
, data
,
617 descr
->callbacks
, parent
);
621 device_error(parent
, "attempt to attach unknown device %s\n", name
);
626 /* device-instance: */
630 device_create_instance_from(device
*me
,
631 device_instance
*parent
,
635 const device_instance_callbacks
*callbacks
)
637 device_instance
*instance
= ZALLOC(device_instance
);
638 if ((me
== NULL
) == (parent
== NULL
))
639 device_error(me
, "can't have both parent instance and parent device\n");
640 instance
->owner
= me
;
641 instance
->parent
= parent
;
642 instance
->data
= data
;
643 instance
->args
= (args
== NULL
? NULL
: strdup(args
));
644 instance
->path
= (path
== NULL
? NULL
: strdup(path
));
645 instance
->callback
= callbacks
;
648 instance
->next
= me
->instances
;
649 me
->instances
= instance
;
651 if (parent
!= NULL
) {
652 device_instance
**previous
;
653 parent
->child
= instance
;
654 instance
->owner
= parent
->owner
;
655 instance
->next
= parent
->next
;
656 /* replace parent with this new node */
657 previous
= &instance
->owner
->instances
;
658 while (*previous
!= parent
)
659 previous
= &(*previous
)->next
;
660 *previous
= instance
;
668 device_create_instance(device
*me
,
669 const char *device_specifier
)
671 /* find the device node */
673 if (!split_device_specifier(device_specifier
, &spec
))
675 me
= split_find_device(me
, &spec
);
676 if (spec
.name
!= NULL
)
678 /* create the instance */
679 if (me
->callback
->instance_create
== NULL
)
680 device_error(me
, "no instance_create method\n");
681 return me
->callback
->instance_create(me
,
682 device_specifier
, spec
.last_args
);
685 STATIC_INLINE_DEVICE\
687 clean_device_instances(device
*me
)
689 device_instance
**instance
= &me
->instances
;
690 while (*instance
!= NULL
) {
691 device_instance
*old_instance
= *instance
;
692 device_instance_delete(old_instance
);
693 instance
= &me
->instances
;
699 device_instance_delete(device_instance
*instance
)
701 device
*me
= instance
->owner
;
702 device_instance
**curr
;
703 if (instance
->callback
->delete == NULL
)
704 device_error(me
, "no delete method\n");
705 instance
->callback
->delete(instance
);
706 if (instance
->args
!= NULL
)
707 zfree(instance
->args
);
708 if (instance
->path
!= NULL
)
709 zfree(instance
->path
);
710 curr
= &me
->instances
;
711 while (*curr
!= NULL
&& *curr
!= instance
)
712 curr
= &(*curr
)->next
;
713 ASSERT(*curr
!= NULL
);
714 *curr
= instance
->next
;
720 device_instance_read(device_instance
*instance
,
724 device
*me
= instance
->owner
;
725 if (instance
->callback
->read
== NULL
)
726 device_error(me
, "no read method\n");
727 return instance
->callback
->read(instance
, addr
, len
);
732 device_instance_write(device_instance
*instance
,
736 device
*me
= instance
->owner
;
737 if (instance
->callback
->write
== NULL
)
738 device_error(me
, "no write method\n");
739 return instance
->callback
->write(instance
, addr
, len
);
744 device_instance_seek(device_instance
*instance
,
745 unsigned_word pos_hi
,
746 unsigned_word pos_lo
)
748 device
*me
= instance
->owner
;
749 if (instance
->callback
->seek
== NULL
)
750 device_error(me
, "no seek method\n");
751 return instance
->callback
->seek(instance
, pos_hi
, pos_lo
);
756 device_instance_claim(device_instance
*instance
,
757 unsigned_word address
,
758 unsigned_word length
,
759 unsigned_word alignment
)
761 device
*me
= instance
->owner
;
762 if (instance
->callback
->claim
== NULL
)
763 device_error(me
, "no claim method\n");
764 return instance
->callback
->claim(instance
, address
, length
, alignment
);
769 device_instance_release(device_instance
*instance
,
770 unsigned_word address
,
771 unsigned_word length
)
773 device
*me
= instance
->owner
;
774 if (instance
->callback
->release
== NULL
)
775 device_error(me
, "no release method\n");
776 instance
->callback
->release(instance
, address
, length
);
781 device_instance_device(device_instance
*instance
)
783 return instance
->owner
;
788 device_instance_path(device_instance
*instance
)
790 return instance
->path
;
795 device_instance_data(device_instance
*instance
)
797 return instance
->data
;
802 /* Device initialization: */
804 STATIC_INLINE_DEVICE\
806 clean_device(device
*root
,
810 system
= (psim
*)data
;
811 clean_device_interrupt_edges(&root
->interrupt_destinations
);
812 clean_device_instances(root
);
813 clean_device_properties(root
);
816 STATIC_INLINE_DEVICE\
818 init_device_address(device
*me
,
821 psim
*system
= (psim
*)data
;
822 TRACE(trace_device_init
, ("init_device_address() initializing %s\n", me
->path
));
823 me
->system
= system
; /* misc things not known until now */
824 if (me
->callback
->init
.address
!= NULL
)
825 me
->callback
->init
.address(me
);
828 STATIC_INLINE_DEVICE\
830 init_device_data(device
*me
,
833 TRACE(trace_device_init
, ("device_init_data() initializing %s\n", me
->path
));
834 if (me
->callback
->init
.data
!= NULL
)
835 me
->callback
->init
.data(me
);
840 device_tree_init(device
*root
,
843 TRACE(trace_device_tree
, ("device_tree_init(root=0x%lx, system=0x%lx)\n",
846 /* remove the old, rebuild the new */
847 device_tree_traverse(root
, clean_device
, NULL
, system
);
848 TRACE(trace_tbd
, ("Need to dump the device tree here\n"));
849 device_tree_traverse(root
, init_device_address
, NULL
, system
);
850 device_tree_traverse(root
, init_device_properties
, NULL
, system
);
851 device_tree_traverse(root
, init_device_data
, NULL
, system
);
852 TRACE(trace_device_tree
, ("device_tree_init() = void\n"));
857 /* Device Properties: */
859 /* local - not available externally */
860 STATIC_INLINE_DEVICE\
862 device_add_property(device
*me
,
863 const char *property
,
864 device_property_type type
,
865 const void *init_array
,
866 unsigned sizeof_init_array
,
868 unsigned sizeof_array
,
869 const device_property
*original
,
870 object_disposition disposition
)
872 device_property_entry
*new_entry
= NULL
;
873 device_property
*new_value
= NULL
;
874 void *new_array
= NULL
;
875 void *new_init_array
= NULL
;
877 /* find the list end */
878 device_property_entry
**insertion_point
= &me
->properties
;
879 while (*insertion_point
!= NULL
) {
880 if (strcmp((*insertion_point
)->value
->name
, property
) == 0)
882 insertion_point
= &(*insertion_point
)->next
;
885 /* create a new value */
886 new_value
= ZALLOC(device_property
);
887 new_value
->name
= strdup(property
);
888 new_value
->type
= type
;
889 new_value
->sizeof_array
= sizeof_array
;
890 new_array
= (sizeof_array
> 0 ? zalloc(sizeof_array
) : NULL
);
891 new_value
->array
= new_array
;
892 new_value
->owner
= me
;
893 new_value
->original
= original
;
894 new_value
->disposition
= disposition
;
895 if (sizeof_array
> 0)
896 memcpy(new_array
, array
, sizeof_array
);
898 /* insert the value into the list */
899 new_entry
= ZALLOC(device_property_entry
);
900 *insertion_point
= new_entry
;
901 new_entry
->sizeof_init_array
= sizeof_init_array
;
902 new_init_array
= (sizeof_init_array
> 0 ? zalloc(sizeof_init_array
) : NULL
);
903 new_entry
->init_array
= new_init_array
;
904 new_entry
->value
= new_value
;
905 if (sizeof_init_array
> 0)
906 memcpy(new_init_array
, init_array
, sizeof_init_array
);
911 /* local - not available externally */
912 STATIC_INLINE_DEVICE\
914 device_set_property(device
*me
,
915 const char *property
,
916 device_property_type type
,
919 const device_property
*original
)
921 /* find the property */
922 device_property_entry
*entry
= me
->properties
;
923 while (entry
!= NULL
) {
924 if (strcmp(entry
->value
->name
, property
) == 0) {
926 device_property
*value
= entry
->value
;
927 /* check the type matches */
928 if (value
->type
!= type
)
929 device_error(me
, "conflict between type of new and old value for property %s\n", property
);
930 /* replace its value */
931 if (value
->array
!= NULL
)
932 zfree((void*)value
->array
);
933 new_array
= (sizeof_array
> 0
934 ? zalloc(sizeof_array
)
936 value
->array
= new_array
;
937 value
->sizeof_array
= sizeof_array
;
938 if (sizeof_array
> 0)
939 memcpy(new_array
, array
, sizeof_array
);
944 device_add_property(me
, property
, type
,
945 NULL
, 0, array
, sizeof_array
,
946 original
, tempoary_object
);
950 STATIC_INLINE_DEVICE\
952 clean_device_properties(device
*me
)
954 device_property_entry
**delete_point
= &me
->properties
;
955 while (*delete_point
!= NULL
) {
956 device_property_entry
*current
= *delete_point
;
957 device_property
*property
= current
->value
;
958 switch (current
->value
->disposition
) {
959 case permenant_object
:
961 /* delete the property, and replace it with the original */
962 ASSERT(((property
->array
== NULL
) == (current
->init_array
== NULL
))
963 || property
->type
== ihandle_property
);
964 if (current
->init_array
!= NULL
) {
965 zfree((void*)current
->value
->array
);
966 current
->value
->array
= NULL
;
967 if (property
->type
!= ihandle_property
) {
968 device_set_property(me
, property
->name
,
970 current
->init_array
, current
->sizeof_init_array
,
974 delete_point
= &(*delete_point
)->next
;
977 case tempoary_object
:
979 /* zap the actual property, was created during simulation run */
980 *delete_point
= current
->next
;
981 if (current
->value
->array
!= NULL
)
982 zfree((void*)current
->value
->array
);
983 zfree(current
->value
);
992 STATIC_INLINE_DEVICE\
994 init_device_properties(device
*me
,
997 device_property_entry
*property
= me
->properties
;
998 while (property
!= NULL
) {
999 /* now do the phandles */
1000 if (property
->value
->type
== ihandle_property
) {
1001 if (property
->value
->original
!= NULL
) {
1002 const device_property
*original
= property
->value
->original
;
1003 if (original
->array
== NULL
) {
1004 init_device_properties(original
->owner
, data
);
1006 ASSERT(original
->array
!= NULL
);
1007 device_set_property(me
, property
->value
->name
,
1009 original
->array
, original
->sizeof_array
, NULL
);
1012 device_instance
*instance
=
1013 device_create_instance(me
, (char*)property
->init_array
);
1014 unsigned32 ihandle
= H2BE_4(device_instance_to_external(instance
));
1015 device_set_property(me
, property
->value
->name
,
1017 &ihandle
, sizeof(ihandle
), NULL
);
1020 property
= property
->next
;
1026 (const device_property
*)
1027 device_next_property(const device_property
*property
)
1029 /* find the property in the list */
1030 device
*owner
= property
->owner
;
1031 device_property_entry
*entry
= owner
->properties
;
1032 while (entry
!= NULL
&& entry
->value
!= property
)
1033 entry
= entry
->next
;
1034 /* now return the following property */
1035 ASSERT(entry
!= NULL
); /* must be a member! */
1036 if (entry
->next
!= NULL
)
1037 return entry
->next
->value
;
1043 (const device_property
*)
1044 device_find_property(device
*me
,
1045 const char *property
)
1047 name_specifier spec
;
1051 else if (property
== NULL
|| strcmp(property
, "") == 0) {
1052 if (me
->properties
== NULL
)
1055 return me
->properties
->value
;
1057 else if (split_property_specifier(property
, &spec
)) {
1058 me
= split_find_device(me
, &spec
);
1059 if (spec
.name
== NULL
) { /*got to root*/
1060 device_property_entry
*entry
= me
->properties
;
1061 while (entry
!= NULL
) {
1062 if (strcmp(entry
->value
->name
, spec
.property
) == 0)
1063 return entry
->value
;
1064 entry
= entry
->next
;
1071 STATIC_INLINE_DEVICE\
1073 device_add_array_property(device
*me
,
1074 const char *property
,
1078 TRACE(trace_devices
,
1079 ("device_add_array_property(me=0x%lx, property=%s, ...)\n",
1080 (long)me
, property
));
1081 device_add_property(me
, property
, array_property
,
1082 array
, sizeof_array
, array
, sizeof_array
,
1083 NULL
, permenant_object
);
1088 device_set_array_property(device
*me
,
1089 const char *property
,
1093 TRACE(trace_devices
,
1094 ("device_set_array_property(me=0x%lx, property=%s, ...)\n",
1095 (long)me
, property
));
1096 device_set_property(me
, property
, array_property
, array
, sizeof_array
, NULL
);
1100 (const device_property
*)
1101 device_find_array_property(device
*me
,
1102 const char *property
)
1104 const device_property
*node
;
1105 TRACE(trace_devices
,
1106 ("device_find_integer(me=0x%lx, property=%s)\n",
1107 (long)me
, property
));
1108 node
= device_find_property(me
, property
);
1109 if (node
== (device_property
*)0
1110 || node
->type
!= array_property
)
1111 device_error(me
, "property %s not found or of wrong type\n", property
);
1116 STATIC_INLINE_DEVICE\
1118 device_add_boolean_property(device
*me
,
1119 const char *property
,
1122 signed32 new_boolean
= (boolean
? -1 : 0);
1123 TRACE(trace_devices
,
1124 ("device_add_boolean(me=0x%lx, property=%s, boolean=%d)\n",
1125 (long)me
, property
, boolean
));
1126 device_add_property(me
, property
, boolean_property
,
1127 &new_boolean
, sizeof(new_boolean
),
1128 &new_boolean
, sizeof(new_boolean
),
1129 NULL
, permenant_object
);
1134 device_find_boolean_property(device
*me
,
1135 const char *property
)
1137 const device_property
*node
;
1139 TRACE(trace_devices
,
1140 ("device_find_boolean(me=0x%lx, property=%s)\n",
1141 (long)me
, property
));
1142 node
= device_find_property(me
, property
);
1143 if (node
== (device_property
*)0
1144 || node
->type
!= boolean_property
)
1145 device_error(me
, "property %s not found or of wrong type\n", property
);
1146 ASSERT(sizeof(boolean
) == node
->sizeof_array
);
1147 memcpy(&boolean
, node
->array
, sizeof(boolean
));
1151 STATIC_INLINE_DEVICE\
1153 device_add_ihandle_property(device
*me
,
1154 const char *property
,
1157 TRACE(trace_devices
,
1158 ("device_add_ihandle_property(me=0x%lx, property=%s, path=%s)\n",
1159 (long)me
, property
, path
));
1160 device_add_property(me
, property
, ihandle_property
,
1161 path
, strlen(path
) + 1,
1163 NULL
, permenant_object
);
1168 device_find_ihandle_property(device
*me
,
1169 const char *property
)
1171 const device_property
*node
;
1173 device_instance
*instance
;
1174 TRACE(trace_devices
,
1175 ("device_find_ihandle_property(me=0x%lx, property=%s)\n",
1176 (long)me
, property
));
1177 node
= device_find_property(me
, property
);
1178 if (node
== NULL
|| node
->type
!= ihandle_property
)
1179 device_error(me
, "property %s not found or of wrong type\n", property
);
1180 if (node
->array
== NULL
)
1181 device_error(me
, "property %s not yet initialized\n", property
);
1182 ASSERT(sizeof(ihandle
) == node
->sizeof_array
);
1183 memcpy(&ihandle
, node
->array
, sizeof(ihandle
));
1185 instance
= external_to_device_instance(me
, ihandle
);
1186 ASSERT(instance
!= NULL
);
1190 STATIC_INLINE_DEVICE\
1192 device_add_integer_property(device
*me
,
1193 const char *property
,
1196 TRACE(trace_devices
,
1197 ("device_add_integer_property(me=0x%lx, property=%s, integer=%ld)\n",
1198 (long)me
, property
, (long)integer
));
1200 device_add_property(me
, property
, integer_property
,
1201 &integer
, sizeof(integer
),
1202 &integer
, sizeof(integer
),
1203 NULL
, permenant_object
);
1208 device_find_integer_property(device
*me
,
1209 const char *property
)
1211 const device_property
*node
;
1213 TRACE(trace_devices
,
1214 ("device_find_integer(me=0x%lx, property=%s)\n",
1215 (long)me
, property
));
1216 node
= device_find_property(me
, property
);
1217 if (node
== (device_property
*)0
1218 || node
->type
!= integer_property
)
1219 device_error(me
, "property %s not found or of wrong type\n", property
);
1220 ASSERT(sizeof(integer
) == node
->sizeof_array
);
1221 memcpy(&integer
, node
->array
, sizeof(integer
));
1226 STATIC_INLINE_DEVICE\
1228 device_add_string_property(device
*me
,
1229 const char *property
,
1233 TRACE(trace_devices
,
1234 ("device_add_property(me=0x%lx, property=%s, string=%s)\n",
1235 (long)me
, property
, string
));
1236 device_add_property(me
, property
, string_property
,
1237 string
, strlen(string
) + 1,
1238 string
, strlen(string
) + 1,
1239 NULL
, permenant_object
);
1244 device_find_string_property(device
*me
,
1245 const char *property
)
1247 const device_property
*node
;
1249 TRACE(trace_devices
,
1250 ("device_find_string(me=0x%lx, property=%s)\n",
1251 (long)me
, property
));
1252 node
= device_find_property(me
, property
);
1253 if (node
== (device_property
*)0
1254 || node
->type
!= string_property
)
1255 device_error(me
, "property %s not found or of wrong type\n", property
);
1256 string
= node
->array
;
1257 ASSERT(strlen(string
) + 1 == node
->sizeof_array
);
1261 STATIC_INLINE_DEVICE\
1263 device_add_duplicate_property(device
*me
,
1264 const char *property
,
1265 const device_property
*original
)
1267 TRACE(trace_devices
,
1268 ("device_add_duplicate_property(me=0x%lx, property=%s, ...)\n",
1269 (long)me
, property
));
1270 if (original
->disposition
!= permenant_object
)
1271 device_error(me
, "Can only duplicate permenant objects\n");
1272 device_add_property(me
, property
,
1274 original
->array
, original
->sizeof_array
,
1275 original
->array
, original
->sizeof_array
,
1276 original
, permenant_object
);
1281 /* Device Hardware: */
1285 device_io_read_buffer(device
*me
,
1293 if (me
->callback
->io
.read_buffer
== NULL
)
1294 device_error(me
, "no io_read_buffer method\n");
1295 return me
->callback
->io
.read_buffer(me
, dest
, space
,
1302 device_io_write_buffer(device
*me
,
1310 if (me
->callback
->io
.write_buffer
== NULL
)
1311 device_error(me
, "no io_write_buffer method\n");
1312 return me
->callback
->io
.write_buffer(me
, source
, space
,
1319 device_dma_read_buffer(device
*me
,
1325 if (me
->callback
->dma
.read_buffer
== NULL
)
1326 device_error(me
, "no dma_read_buffer method\n");
1327 return me
->callback
->dma
.read_buffer(me
, dest
, space
,
1333 device_dma_write_buffer(device
*me
,
1338 int violate_read_only_section
)
1340 if (me
->callback
->dma
.write_buffer
== NULL
)
1341 device_error(me
, "no dma_write_buffer method\n");
1342 return me
->callback
->dma
.write_buffer(me
, source
, space
,
1344 violate_read_only_section
);
1349 device_attach_address(device
*me
,
1356 device
*who
) /*callback/default*/
1358 if (me
->callback
->address
.attach
== NULL
)
1359 device_error(me
, "no address_attach method\n");
1360 me
->callback
->address
.attach(me
, name
, attach
, space
,
1361 addr
, nr_bytes
, access
, who
);
1366 device_detach_address(device
*me
,
1373 device
*who
) /*callback/default*/
1375 if (me
->callback
->address
.detach
== NULL
)
1376 device_error(me
, "no address_detach method\n");
1377 me
->callback
->address
.detach(me
, name
, attach
, space
,
1378 addr
, nr_bytes
, access
, who
);
1386 device_interrupt_event(device
*me
,
1392 int found_an_edge
= 0;
1393 device_interrupt_edge
*edge
;
1394 /* device's interrupt lines directly connected */
1395 for (edge
= me
->interrupt_destinations
;
1397 edge
= edge
->next
) {
1398 if (edge
->my_port
== my_port
) {
1399 if (edge
->dest
->callback
->interrupt
.event
== NULL
)
1400 device_error(me
, "no interrupt method\n");
1401 edge
->dest
->callback
->interrupt
.event(edge
->dest
,
1410 if (!found_an_edge
) {
1411 device_error(me
, "No interrupt edge for port %d\n", my_port
);
1417 device_interrupt_attach(device
*me
,
1421 object_disposition disposition
)
1423 attach_device_interrupt_edge(&me
->interrupt_destinations
,
1432 device_interrupt_detach(device
*me
,
1437 detach_device_interrupt_edge(me
,
1438 &me
->interrupt_destinations
,
1446 device_interrupt_decode(device
*me
,
1447 const char *port_name
)
1449 if (port_name
== NULL
|| port_name
[0] == '\0')
1451 if (isdigit(port_name
[0])) {
1452 return strtoul(port_name
, NULL
, 0);
1455 const device_interrupt_port_descriptor
*ports
=
1456 me
->callback
->interrupt
.ports
;
1457 if (ports
!= NULL
) {
1458 while (ports
->name
!= NULL
) {
1459 if (ports
->bound
> ports
->number
) {
1460 int len
= strlen(ports
->name
);
1461 if (strncmp(port_name
, ports
->name
, len
) == 0) {
1462 if (port_name
[len
] == '\0')
1463 return ports
->number
;
1464 else if(isdigit(port_name
[len
])) {
1465 int port
= ports
->number
+ strtoul(&port_name
[len
], NULL
, 0);
1466 if (port
>= ports
->bound
)
1467 device_error(me
, "Interrupt port %s out of range\n",
1473 else if (strcmp(port_name
, ports
->name
) == 0)
1474 return ports
->number
;
1479 device_error(me
, "Unreconized interrupt port %s\n", port_name
);
1485 device_interrupt_encode(device
*me
,
1490 const device_interrupt_port_descriptor
*ports
= NULL
;
1491 ports
= me
->callback
->interrupt
.ports
;
1492 if (ports
!= NULL
) {
1493 while (ports
->name
!= NULL
) {
1494 if (ports
->bound
> ports
->number
) {
1495 if (port_number
>= ports
->number
1496 && port_number
< ports
->bound
) {
1497 strcpy(buf
, ports
->name
);
1498 sprintf(buf
+ strlen(buf
), "%d", port_number
- ports
->number
);
1499 if (strlen(buf
) >= sizeof_buf
)
1500 error("device_interrupt_encode:buffer overflow\n");
1505 if (ports
->number
== port_number
) {
1506 if (strlen(ports
->name
) >= sizeof_buf
)
1507 error("device_interrupt_encode: buffer overflow\n");
1508 strcpy(buf
, ports
->name
);
1515 sprintf(buf
, "%d", port_number
);
1516 if (strlen(buf
) >= sizeof_buf
)
1517 error("device_interrupt_encode: buffer overflow\n");
1527 device_ioctl(device
*me
,
1535 if (me
->callback
->ioctl
== NULL
)
1536 device_error(me
, "no ioctl method\n");
1537 status
= me
->callback
->ioctl(me
, processor
, cia
, ap
);
1548 device_error(device
*me
,
1554 /* format the message */
1556 vsprintf(message
, fmt
, ap
);
1559 if (strlen(message
) >= sizeof(message
))
1560 error("device_error: buffer overflow\n");
1562 error("device: %s\n", message
);
1564 error("%s: %s\n", me
->path
, message
);
1569 /* Tree utilities: */
1573 device_tree_add_parsed(device
*current
,
1577 char device_specifier
[1024];
1578 name_specifier spec
;
1580 /* format the path */
1584 vsprintf(device_specifier
, fmt
, ap
);
1586 if (strlen(device_specifier
) >= sizeof(device_specifier
))
1587 error("device_tree_add_parsed: buffer overflow\n");
1591 if (!split_device_specifier(device_specifier
, &spec
))
1592 device_error(current
, "error parsing %s\n", device_specifier
);
1594 /* fill our tree with its contents */
1595 current
= split_find_device(current
, &spec
);
1597 /* add any additional devices as needed */
1598 if (spec
.name
!= NULL
) {
1601 device_template_create_device(current
, spec
.name
, spec
.unit
, spec
.args
);
1602 } while (split_device_name(&spec
));
1605 /* is there an interrupt spec */
1606 if (spec
.property
== NULL
1607 && spec
.value
!= NULL
) {
1608 char *op
= split_value(&spec
);
1612 char *my_port_name
= split_value(&spec
);
1613 char *dest_port_name
= split_value(&spec
);
1614 device
*dest
= device_tree_find_device(current
, split_value(&spec
));
1615 int my_port
= device_interrupt_decode(current
, my_port_name
);
1616 int dest_port
= device_interrupt_decode(dest
, dest_port_name
);
1617 device_interrupt_attach(current
,
1625 device_error(current
, "unreconised interrupt spec %s\n", spec
.value
);
1630 /* is there a property */
1631 if (spec
.property
!= NULL
) {
1632 if (strcmp(spec
.value
, "true") == 0)
1633 device_add_boolean_property(current
, spec
.property
, 1);
1634 else if (strcmp(spec
.value
, "false") == 0)
1635 device_add_boolean_property(current
, spec
.property
, 0);
1637 const device_property
*property
;
1638 switch (spec
.value
[0]) {
1642 device_add_ihandle_property(current
, spec
.property
, spec
.value
);
1646 case '0': case '1': case '2': case '3': case '4':
1647 case '5': case '6': case '7': case '8': case '9':
1649 unsigned long ul
= strtoul(spec
.value
, &spec
.value
, 0);
1650 device_add_integer_property(current
, spec
.property
, ul
);
1655 unsigned8 words
[1024];
1656 char *curr
= spec
.value
+ 1;
1660 words
[nr_words
] = H2BE_1(strtoul(curr
, &next
, 0));
1666 device_add_array_property(current
, spec
.property
,
1667 words
, sizeof(words
[0]) * nr_words
);
1672 unsigned32 words
[1024];
1673 char *curr
= spec
.value
+ 1;
1677 words
[nr_words
] = H2BE_4(strtoul(curr
, &next
, 0));
1683 device_add_array_property(current
, spec
.property
,
1684 words
, sizeof(words
[0]) * nr_words
);
1690 device_add_string_property(current
, spec
.property
, spec
.value
);
1694 property
= device_find_property(current
, spec
.value
);
1695 if (property
== NULL
)
1696 device_error(current
, "property %s not found\n", spec
.value
);
1697 device_add_duplicate_property(current
,
1709 device_tree_traverse(device
*root
,
1710 device_tree_traverse_function
*prefix
,
1711 device_tree_traverse_function
*postfix
,
1717 for (child
= root
->children
; child
!= NULL
; child
= child
->sibling
) {
1718 device_tree_traverse(child
, prefix
, postfix
, data
);
1720 if (postfix
!= NULL
)
1721 postfix(root
, data
);
1726 device_tree_print_device(device
*me
,
1727 void *ignore_or_null
)
1729 const device_property
*property
;
1730 device_interrupt_edge
*interrupt_edge
;
1731 /* output my name */
1732 printf_filtered("%s\n", me
->path
);
1734 for (property
= device_find_property(me
, NULL
);
1736 property
= device_next_property(property
)) {
1737 printf_filtered("%s/%s", me
->path
, property
->name
);
1738 if (property
->original
!= NULL
) {
1739 printf_filtered(" !");
1740 printf_filtered("%s/%s\n", property
->original
->owner
->path
,
1741 property
->original
->name
);
1744 switch (property
->type
) {
1745 case array_property
:
1747 if ((property
->sizeof_array
% sizeof(unsigned32
)) == 0) {
1748 unsigned32
*w
= (unsigned32
*)property
->array
;
1749 printf_filtered(" {");
1750 while ((char*)w
- (char*)property
->array
< property
->sizeof_array
) {
1751 printf_filtered(" 0x%lx", BE2H_4(*w
));
1756 unsigned8
*w
= (unsigned8
*)property
->array
;
1757 printf_filtered(" [");
1758 while ((char*)w
- (char*)property
->array
< property
->sizeof_array
) {
1759 printf_filtered(" 0x%2x", BE2H_1(*w
));
1763 printf_filtered("\n");
1766 case boolean_property
:
1768 int b
= device_find_boolean_property(me
, property
->name
);
1769 printf_filtered(" %s\n", b
? "true" : "false");
1772 case ihandle_property
:
1774 if (property
->array
!= NULL
) {
1775 device_instance
*i
= device_find_ihandle_property(me
, property
->name
);
1776 printf_filtered(" *%s\n", i
->path
);
1779 /* drats, the instance hasn't yet been created. Grub
1780 around and find the path that will be used to create
1782 device_property_entry
*entry
= me
->properties
;
1783 while (entry
->value
!= property
) {
1784 entry
= entry
->next
;
1785 ASSERT(entry
!= NULL
);
1787 ASSERT(entry
->init_array
!= NULL
);
1788 printf_filtered(" *%s\n", (char*)entry
->init_array
);
1792 case integer_property
:
1794 unsigned_word w
= device_find_integer_property(me
, property
->name
);
1795 printf_filtered(" 0x%lx\n", (unsigned long)w
);
1798 case string_property
:
1800 const char *s
= device_find_string_property(me
, property
->name
);
1801 printf_filtered(" \"%s\n", s
);
1808 for (interrupt_edge
= me
->interrupt_destinations
;
1809 interrupt_edge
!= NULL
;
1810 interrupt_edge
= interrupt_edge
->next
) {
1813 device_interrupt_encode(me
, interrupt_edge
->my_port
, src
, sizeof(src
));
1814 device_interrupt_encode(interrupt_edge
->dest
,
1815 interrupt_edge
->dest_port
, dst
, sizeof(dst
));
1816 printf_filtered("%s > %s %s %s\n",
1819 interrupt_edge
->dest
->path
);
1825 device_tree_find_device(device
*root
,
1829 name_specifier spec
;
1830 TRACE(trace_device_tree
,
1831 ("device_tree_find_device_tree(root=0x%lx, path=%s)\n",
1833 /* parse the path */
1834 split_device_specifier(path
, &spec
);
1835 if (spec
.value
!= NULL
)
1836 return NULL
; /* something wierd */
1839 node
= split_find_device(root
, &spec
);
1840 if (spec
.name
!= NULL
)
1841 return NULL
; /* not a leaf */
1848 device_usage(int verbose
)
1851 const device_descriptor
*const *table
;
1853 printf_filtered("\n");
1854 printf_filtered("A device/property specifier has the form:\n");
1855 printf_filtered("\n");
1856 printf_filtered(" /path/to/a/device [ property-value ]\n");
1857 printf_filtered("\n");
1858 printf_filtered("and a possible device is\n");
1859 printf_filtered("\n");
1861 for (table
= device_table
; *table
!= NULL
; table
++) {
1862 const device_descriptor
*descr
;
1863 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
1864 pos
+= strlen(descr
->name
) + 2;
1866 pos
= strlen(descr
->name
) + 2;
1867 printf_filtered("\n");
1869 printf_filtered(" %s", descr
->name
);
1871 printf_filtered("\n");
1875 const device_descriptor
*const *table
;
1876 printf_filtered("\n");
1877 printf_filtered("A device/property specifier (<spec>) has the format:\n");
1878 printf_filtered("\n");
1879 printf_filtered(" <spec> ::= <path> [ <value> ] ;\n");
1880 printf_filtered(" <path> ::= { <prefix> } { <node> \"/\" } <node> ;\n");
1881 printf_filtered(" <prefix> ::= ( | \"/\" | \"../\" | \"./\" ) ;\n");
1882 printf_filtered(" <node> ::= <name> [ \"@\" <unit> ] [ \":\" <args> ] ;\n");
1883 printf_filtered(" <unit> ::= <number> { \",\" <number> } ;\n");
1884 printf_filtered("\n");
1885 printf_filtered("Where:\n");
1886 printf_filtered("\n");
1887 printf_filtered(" <name> is the name of a device (list below)\n");
1888 printf_filtered(" <unit> is the unit-address relative to the parent bus\n");
1889 printf_filtered(" <args> additional arguments used when creating the device\n");
1890 printf_filtered(" <value> ::= ( <number> # integer property\n");
1891 printf_filtered(" | \"[\" { <number> } # array property (byte)\n");
1892 printf_filtered(" | \"{\" { <number> } # array property (cell)\n");
1893 printf_filtered(" | [ \"true\" | \"false\" ] # boolean property\n");
1894 printf_filtered(" | \"*\" <path> # ihandle property\n");
1895 printf_filtered(" | \"!\" <path> # copy property\n");
1896 printf_filtered(" | \">\" [ <number> ] <path> # attach interrupt\n");
1897 printf_filtered(" | \"<\" <path> # attach child interrupt\n");
1898 printf_filtered(" | \"\\\"\" <text> # string property\n");
1899 printf_filtered(" | <text> # string property\n");
1900 printf_filtered(" ) ;\n");
1901 printf_filtered("\n");
1902 printf_filtered("And the following are valid device names:\n");
1903 printf_filtered("\n");
1904 for (table
= device_table
; *table
!= NULL
; table
++) {
1905 const device_descriptor
*descr
;
1906 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
1907 printf_filtered(" %s:\n", descr
->name
);
1908 /* interrupt ports */
1909 if (descr
->callbacks
->interrupt
.ports
!= NULL
) {
1910 const device_interrupt_port_descriptor
*ports
=
1911 descr
->callbacks
->interrupt
.ports
;
1912 printf_filtered(" interrupt ports:");
1913 while (ports
->name
!= NULL
) {
1914 printf_filtered(" %s", ports
->name
);
1917 printf_filtered("\n");
1920 if (descr
->callbacks
->usage
!= NULL
)
1921 descr
->callbacks
->usage(verbose
);
1929 /* External representation */
1933 external_to_device(device
*tree_member
,
1936 device
*root
= device_tree_find_device(tree_member
, "/");
1937 device
*me
= cap_internal(root
->phandles
, phandle
);
1943 device_to_external(device
*me
)
1945 device
*root
= device_tree_find_device(me
, "/");
1946 unsigned32 phandle
= cap_external(root
->phandles
, me
);
1952 external_to_device_instance(device
*tree_member
,
1955 device
*root
= device_tree_find_device(tree_member
, "/");
1956 device_instance
*instance
= cap_internal(root
->ihandles
, ihandle
);
1962 device_instance_to_external(device_instance
*instance
)
1964 device
*root
= device_tree_find_device(instance
->owner
, "/");
1965 unsigned32 ihandle
= cap_external(root
->ihandles
, instance
);
1969 #endif /* _DEVICE_C_ */