1 /* This file is part of the program psim.
3 Copyright (C) 1994-1997, 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 3 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, see <http://www.gnu.org/licenses/>.
26 #include "device_table.h"
46 STATIC_INLINE_DEVICE (void) clean_device_properties(device
*);
48 /* property entries */
50 typedef struct _device_property_entry device_property_entry
;
51 struct _device_property_entry
{
52 device_property_entry
*next
;
53 device_property
*value
;
54 const void *init_array
;
55 unsigned sizeof_init_array
;
61 typedef struct _device_interrupt_edge device_interrupt_edge
;
62 struct _device_interrupt_edge
{
66 device_interrupt_edge
*next
;
67 object_disposition disposition
;
72 attach_device_interrupt_edge(device_interrupt_edge
**list
,
76 object_disposition disposition
)
78 device_interrupt_edge
*new_edge
= ZALLOC(device_interrupt_edge
);
79 new_edge
->my_port
= my_port
;
80 new_edge
->dest
= dest
;
81 new_edge
->dest_port
= dest_port
;
82 new_edge
->next
= *list
;
83 new_edge
->disposition
= disposition
;
89 detach_device_interrupt_edge(device
*me
,
90 device_interrupt_edge
**list
,
95 while (*list
!= NULL
) {
96 device_interrupt_edge
*old_edge
= *list
;
97 if (old_edge
->dest
== dest
98 && old_edge
->dest_port
== dest_port
99 && old_edge
->my_port
== my_port
) {
100 if (old_edge
->disposition
== permenant_object
)
101 device_error(me
, "attempt to delete permenant interrupt");
102 *list
= old_edge
->next
;
107 device_error(me
, "attempt to delete unattached interrupt");
110 STATIC_INLINE_DEVICE\
112 clean_device_interrupt_edges(device_interrupt_edge
**list
)
114 while (*list
!= NULL
) {
115 device_interrupt_edge
*old_edge
= *list
;
116 switch (old_edge
->disposition
) {
117 case permenant_object
:
118 list
= &old_edge
->next
;
120 case tempoary_object
:
121 *list
= old_edge
->next
;
135 device_unit unit_address
;
137 int nr_address_cells
;
145 /* its template methods */
146 void *data
; /* device specific data */
147 const device_callbacks
*callback
;
149 /* device properties */
150 device_property_entry
*properties
;
153 device_interrupt_edge
*interrupt_destinations
;
155 /* any open instances of this device */
156 device_instance
*instances
;
158 /* the internal/external mappings and other global requirements */
168 /* an instance of a device */
169 struct _device_instance
{
173 const device_instance_callbacks
*callback
;
174 /* the root instance */
176 device_instance
*next
;
177 /* interposed instance */
178 device_instance
*parent
;
179 device_instance
*child
;
186 STATIC_INLINE_DEVICE\
188 device_full_name(device
*leaf
,
193 char full_name
[1024];
194 if (buf
== (char*)0) {
196 sizeof_buf
= sizeof(full_name
);
199 /* construct a name */
200 if (leaf
->parent
== NULL
) {
202 error("device_full_name: buffer overflow");
207 device_full_name(leaf
->parent
, buf
, sizeof_buf
);
208 if (leaf
->parent
!= NULL
209 && device_encode_unit(leaf
->parent
,
216 if (strlen(buf
) + strlen("/") + strlen(leaf
->name
) + strlen(unit
)
218 error("device_full_name: buffer overflow");
220 strcat(buf
, leaf
->name
);
224 /* return it usefully */
225 if (buf
== full_name
)
226 buf
= (char *) strdup(full_name
);
230 STATIC_INLINE_DEVICE\
232 device_create_from(const char *name
,
233 const device_unit
*unit_address
,
235 const device_callbacks
*callbacks
,
238 device
*new_device
= ZALLOC(device
);
240 /* insert it into the device tree */
241 new_device
->parent
= parent
;
242 new_device
->children
= NULL
;
243 if (parent
!= NULL
) {
244 device
**sibling
= &parent
->children
;
245 while ((*sibling
) != NULL
)
246 sibling
= &(*sibling
)->sibling
;
247 *sibling
= new_device
;
251 new_device
->name
= (char *) strdup(name
);
252 new_device
->unit_address
= *unit_address
;
253 new_device
->path
= device_full_name(new_device
, NULL
, 0);
256 new_device
->data
= data
;
257 new_device
->callback
= callbacks
;
259 /* its properties - already null */
260 /* interrupts - already null */
262 /* mappings - if needed */
263 if (parent
== NULL
) {
264 new_device
->ihandles
= cap_create(name
);
265 new_device
->phandles
= cap_create(name
);
268 new_device
->ihandles
= device_root(parent
)->ihandles
;
269 new_device
->phandles
= device_root(parent
)->phandles
;
272 cap_add(new_device
->phandles
, new_device
);
280 device_create(device
*parent
,
283 const char *unit_address
,
286 const device_descriptor
*const *table
;
287 for (table
= device_table
; *table
!= NULL
; table
++) {
288 const device_descriptor
*descr
;
289 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
290 if (strcmp(base
, descr
->name
) == 0) {
291 device_unit address
= { 0 };
294 if (device_decode_unit(parent
, unit_address
, &address
) < 0)
295 device_error(parent
, "invalid address %s for device %s",
297 if (descr
->creator
!= NULL
)
298 data
= descr
->creator(name
, &address
, args
);
299 return device_create_from(name
, &address
, data
,
300 descr
->callbacks
, parent
);
304 device_error(parent
, "attempt to attach unknown device %s", name
);
312 device_usage(int verbose
)
314 const device_descriptor
*const *table
;
317 for (table
= device_table
; *table
!= NULL
; table
++) {
318 const device_descriptor
*descr
;
319 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
320 pos
+= strlen(descr
->name
) + 2;
322 pos
= strlen(descr
->name
) + 2;
323 printf_filtered("\n");
325 printf_filtered(" %s", descr
->name
);
327 printf_filtered("\n");
331 for (table
= device_table
; *table
!= NULL
; table
++) {
332 const device_descriptor
*descr
;
333 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
334 printf_filtered(" %s:\n", descr
->name
);
335 /* interrupt ports */
336 if (descr
->callbacks
->interrupt
.ports
!= NULL
) {
337 const device_interrupt_port_descriptor
*ports
=
338 descr
->callbacks
->interrupt
.ports
;
339 printf_filtered(" interrupt ports:");
340 while (ports
->name
!= NULL
) {
341 printf_filtered(" %s", ports
->name
);
344 printf_filtered("\n");
347 if (descr
->callbacks
->usage
!= NULL
)
348 descr
->callbacks
->usage(verbose
);
362 device_parent(device
*me
)
369 device_root(device
*me
)
372 while (me
->parent
!= NULL
)
379 device_sibling(device
*me
)
386 device_child(device
*me
)
393 device_name(device
*me
)
400 device_path(device
*me
)
407 device_data(device
*me
)
414 device_system(device
*me
)
420 (const device_unit
*)
421 device_unit_address(device
*me
)
423 return &me
->unit_address
;
429 device_address_to_attach_address(device
*me
,
430 const device_unit
*address
,
432 unsigned_word
*attach_address
,
435 if (me
->callback
->convert
.address_to_attach_address
== NULL
)
436 device_error(me
, "no convert.address_to_attach_address method");
437 return me
->callback
->convert
.address_to_attach_address(me
, address
, attach_space
, attach_address
, client
);
443 device_size_to_attach_size(device
*me
,
444 const device_unit
*size
,
448 if (me
->callback
->convert
.size_to_attach_size
== NULL
)
449 device_error(me
, "no convert.size_to_attach_size method");
450 return me
->callback
->convert
.size_to_attach_size(me
, size
, nr_bytes
, client
);
456 device_decode_unit(device
*bus
,
458 device_unit
*address
)
460 if (bus
->callback
->convert
.decode_unit
== NULL
)
461 device_error(bus
, "no convert.decode_unit method");
462 return bus
->callback
->convert
.decode_unit(bus
, unit
, address
);
468 device_encode_unit(device
*bus
,
469 const device_unit
*unit_address
,
473 if (bus
->callback
->convert
.encode_unit
== NULL
)
474 device_error(bus
, "no convert.encode_unit method");
475 return bus
->callback
->convert
.encode_unit(bus
, unit_address
, buf
, sizeof_buf
);
480 device_nr_address_cells(device
*me
)
482 if (me
->nr_address_cells
== 0) {
483 if (device_find_property(me
, "#address-cells") != NULL
)
484 me
->nr_address_cells
= device_find_integer_property(me
, "#address-cells");
486 me
->nr_address_cells
= 2;
488 return me
->nr_address_cells
;
493 device_nr_size_cells(device
*me
)
495 if (me
->nr_size_cells
== 0) {
496 if (device_find_property(me
, "#size-cells") != NULL
)
497 me
->nr_size_cells
= device_find_integer_property(me
, "#size-cells");
499 me
->nr_size_cells
= 1;
501 return me
->nr_size_cells
;
506 /* device-instance: */
510 device_create_instance_from(device
*me
,
511 device_instance
*parent
,
515 const device_instance_callbacks
*callbacks
)
517 device_instance
*instance
= ZALLOC(device_instance
);
518 if ((me
== NULL
) == (parent
== NULL
))
519 device_error(me
, "can't have both parent instance and parent device");
521 /* link this instance into the devices list */
523 ASSERT(parent
== NULL
);
524 instance
->owner
= me
;
525 instance
->parent
= NULL
;
526 /* link this instance into the front of the devices instance list */
527 instance
->next
= me
->instances
;
528 me
->instances
= instance
;
530 if (parent
!= NULL
) {
531 device_instance
**previous
;
532 ASSERT(parent
->child
== NULL
);
533 parent
->child
= instance
;
535 instance
->owner
= parent
->owner
;
536 instance
->parent
= parent
;
537 /* in the devices instance list replace the parent instance with
539 instance
->next
= parent
->next
;
540 /* replace parent with this new node */
541 previous
= &instance
->owner
->instances
;
542 while (*previous
!= parent
) {
543 ASSERT(*previous
!= NULL
);
544 previous
= &(*previous
)->next
;
546 *previous
= instance
;
548 instance
->data
= data
;
549 instance
->args
= (args
== NULL
? NULL
: (char *) strdup(args
));
550 instance
->path
= (path
== NULL
? NULL
: (char *) strdup(path
));
551 instance
->callback
= callbacks
;
552 cap_add(instance
->owner
->ihandles
, instance
);
559 device_create_instance(device
*me
,
563 /* create the instance */
564 if (me
->callback
->instance_create
== NULL
)
565 device_error(me
, "no instance_create method");
566 return me
->callback
->instance_create(me
, path
, args
);
570 STATIC_INLINE_DEVICE\
572 clean_device_instances(device
*me
)
574 device_instance
**instance
= &me
->instances
;
575 while (*instance
!= NULL
) {
576 device_instance
*old_instance
= *instance
;
577 device_instance_delete(old_instance
);
578 instance
= &me
->instances
;
585 device_instance_delete(device_instance
*instance
)
587 device
*me
= instance
->owner
;
588 if (instance
->callback
->delete == NULL
)
589 device_error(me
, "no delete method");
590 instance
->callback
->delete(instance
);
591 if (instance
->args
!= NULL
)
592 free(instance
->args
);
593 if (instance
->path
!= NULL
)
594 free(instance
->path
);
595 if (instance
->child
== NULL
) {
596 /* only remove leaf nodes */
597 device_instance
**curr
= &me
->instances
;
598 while (*curr
!= instance
) {
599 ASSERT(*curr
!= NULL
);
600 curr
= &(*curr
)->next
;
602 *curr
= instance
->next
;
605 /* check it isn't in the instance list */
606 device_instance
*curr
= me
->instances
;
607 while (curr
!= NULL
) {
608 ASSERT(curr
!= instance
);
611 /* unlink the child */
612 ASSERT(instance
->child
->parent
== instance
);
613 instance
->child
->parent
= NULL
;
615 cap_remove(me
->ihandles
, instance
);
621 device_instance_read(device_instance
*instance
,
625 device
*me
= instance
->owner
;
626 if (instance
->callback
->read
== NULL
)
627 device_error(me
, "no read method");
628 return instance
->callback
->read(instance
, addr
, len
);
633 device_instance_write(device_instance
*instance
,
637 device
*me
= instance
->owner
;
638 if (instance
->callback
->write
== NULL
)
639 device_error(me
, "no write method");
640 return instance
->callback
->write(instance
, addr
, len
);
645 device_instance_seek(device_instance
*instance
,
646 unsigned_word pos_hi
,
647 unsigned_word pos_lo
)
649 device
*me
= instance
->owner
;
650 if (instance
->callback
->seek
== NULL
)
651 device_error(me
, "no seek method");
652 return instance
->callback
->seek(instance
, pos_hi
, pos_lo
);
657 device_instance_call_method(device_instance
*instance
,
658 const char *method_name
,
660 unsigned_cell stack_args
[/*n_stack_args*/],
662 unsigned_cell stack_returns
[/*n_stack_args*/])
664 device
*me
= instance
->owner
;
665 const device_instance_methods
*method
= instance
->callback
->methods
;
666 if (method
== NULL
) {
667 device_error(me
, "no methods (want %s)", method_name
);
669 while (method
->name
!= NULL
) {
670 if (strcmp(method
->name
, method_name
) == 0) {
671 return method
->method(instance
,
672 n_stack_args
, stack_args
,
673 n_stack_returns
, stack_returns
);
677 device_error(me
, "no %s method", method_name
);
684 device_instance_device(device_instance
*instance
)
686 return instance
->owner
;
691 device_instance_path(device_instance
*instance
)
693 return instance
->path
;
698 device_instance_data(device_instance
*instance
)
700 return instance
->data
;
705 /* Device Properties: */
707 STATIC_INLINE_DEVICE\
708 (device_property_entry
*)
709 find_property_entry(device
*me
,
710 const char *property
)
712 device_property_entry
*entry
;
713 ASSERT(property
!= NULL
);
714 entry
= me
->properties
;
715 while (entry
!= NULL
) {
716 if (strcmp(entry
->value
->name
, property
) == 0)
723 STATIC_INLINE_DEVICE\
725 device_add_property(device
*me
,
726 const char *property
,
727 device_property_type type
,
728 const void *init_array
,
729 unsigned sizeof_init_array
,
731 unsigned sizeof_array
,
732 const device_property
*original
,
733 object_disposition disposition
)
735 device_property_entry
*new_entry
= NULL
;
736 device_property
*new_value
= NULL
;
738 /* find the list end */
739 device_property_entry
**insertion_point
= &me
->properties
;
740 while (*insertion_point
!= NULL
) {
741 if (strcmp((*insertion_point
)->value
->name
, property
) == 0)
743 insertion_point
= &(*insertion_point
)->next
;
746 /* create a new value */
747 new_value
= ZALLOC(device_property
);
748 new_value
->name
= (char *) strdup(property
);
749 new_value
->type
= type
;
750 if (sizeof_array
> 0) {
751 void *new_array
= zalloc(sizeof_array
);
752 memcpy(new_array
, array
, sizeof_array
);
753 new_value
->array
= new_array
;
754 new_value
->sizeof_array
= sizeof_array
;
756 new_value
->owner
= me
;
757 new_value
->original
= original
;
758 new_value
->disposition
= disposition
;
760 /* insert the value into the list */
761 new_entry
= ZALLOC(device_property_entry
);
762 *insertion_point
= new_entry
;
763 if (sizeof_init_array
> 0) {
764 void *new_init_array
= zalloc(sizeof_init_array
);
765 memcpy(new_init_array
, init_array
, sizeof_init_array
);
766 new_entry
->init_array
= new_init_array
;
767 new_entry
->sizeof_init_array
= sizeof_init_array
;
769 new_entry
->value
= new_value
;
773 /* local - not available externally */
774 STATIC_INLINE_DEVICE\
776 device_set_property(device
*me
,
777 const char *property
,
778 device_property_type type
,
782 /* find the property */
783 device_property_entry
*entry
= find_property_entry(me
, property
);
785 /* existing property - update it */
787 device_property
*value
= entry
->value
;
788 /* check the type matches */
789 if (value
->type
!= type
)
790 device_error(me
, "conflict between type of new and old value for property %s", property
);
791 /* replace its value */
792 if (value
->array
!= NULL
)
793 free((void*)value
->array
);
794 new_array
= (sizeof_array
> 0
795 ? zalloc(sizeof_array
)
797 value
->array
= new_array
;
798 value
->sizeof_array
= sizeof_array
;
799 if (sizeof_array
> 0)
800 memcpy(new_array
, array
, sizeof_array
);
804 /* new property - create it */
805 device_add_property(me
, property
, type
,
806 NULL
, 0, array
, sizeof_array
,
807 NULL
, tempoary_object
);
812 STATIC_INLINE_DEVICE\
814 clean_device_properties(device
*me
)
816 device_property_entry
**delete_point
= &me
->properties
;
817 while (*delete_point
!= NULL
) {
818 device_property_entry
*current
= *delete_point
;
819 switch (current
->value
->disposition
) {
820 case permenant_object
:
821 /* zap the current value, will be initialized later */
822 ASSERT(current
->init_array
!= NULL
);
823 if (current
->value
->array
!= NULL
) {
824 free((void*)current
->value
->array
);
825 current
->value
->array
= NULL
;
827 delete_point
= &(*delete_point
)->next
;
829 case tempoary_object
:
830 /* zap the actual property, was created during simulation run */
831 ASSERT(current
->init_array
== NULL
);
832 *delete_point
= current
->next
;
833 if (current
->value
->array
!= NULL
)
834 free((void*)current
->value
->array
);
835 free(current
->value
);
845 device_init_static_properties(device
*me
,
848 device_property_entry
*property
;
849 for (property
= me
->properties
;
851 property
= property
->next
) {
852 ASSERT(property
->init_array
!= NULL
);
853 ASSERT(property
->value
->array
== NULL
);
854 ASSERT(property
->value
->disposition
== permenant_object
);
855 switch (property
->value
->type
) {
857 case boolean_property
:
858 case range_array_property
:
859 case reg_array_property
:
860 case string_property
:
861 case string_array_property
:
862 case integer_property
:
863 /* delete the property, and replace it with the original */
864 device_set_property(me
, property
->value
->name
,
865 property
->value
->type
,
866 property
->init_array
,
867 property
->sizeof_init_array
);
869 case ihandle_property
:
878 device_init_runtime_properties(device
*me
,
881 device_property_entry
*property
;
882 for (property
= me
->properties
;
884 property
= property
->next
) {
885 switch (property
->value
->disposition
) {
886 case permenant_object
:
887 switch (property
->value
->type
) {
888 case ihandle_property
:
890 device_instance
*ihandle
;
891 ihandle_runtime_property_spec spec
;
892 ASSERT(property
->init_array
!= NULL
);
893 ASSERT(property
->value
->array
== NULL
);
894 device_find_ihandle_runtime_property(me
, property
->value
->name
, &spec
);
895 ihandle
= tree_instance(me
, spec
.full_path
);
896 device_set_ihandle_property(me
, property
->value
->name
, ihandle
);
900 case boolean_property
:
901 case range_array_property
:
902 case integer_property
:
903 case reg_array_property
:
904 case string_property
:
905 case string_array_property
:
906 ASSERT(property
->init_array
!= NULL
);
907 ASSERT(property
->value
->array
!= NULL
);
911 case tempoary_object
:
912 ASSERT(property
->init_array
== NULL
);
913 ASSERT(property
->value
->array
!= NULL
);
921 (const device_property
*)
922 device_next_property(const device_property
*property
)
924 /* find the property in the list */
925 device
*owner
= property
->owner
;
926 device_property_entry
*entry
= owner
->properties
;
927 while (entry
!= NULL
&& entry
->value
!= property
)
929 /* now return the following property */
930 ASSERT(entry
!= NULL
); /* must be a member! */
931 if (entry
->next
!= NULL
)
932 return entry
->next
->value
;
939 (const device_property
*)
940 device_find_property(device
*me
,
941 const char *property
)
946 else if (property
== NULL
|| strcmp(property
, "") == 0) {
947 if (me
->properties
== NULL
)
950 return me
->properties
->value
;
953 device_property_entry
*entry
= find_property_entry(me
, property
);
963 device_add_array_property(device
*me
,
964 const char *property
,
968 device_add_property(me
, property
, array_property
,
969 array
, sizeof_array
, array
, sizeof_array
,
970 NULL
, permenant_object
);
975 device_set_array_property(device
*me
,
976 const char *property
,
980 device_set_property(me
, property
, array_property
, array
, sizeof_array
);
984 (const device_property
*)
985 device_find_array_property(device
*me
,
986 const char *property
)
988 const device_property
*node
;
989 node
= device_find_property(me
, property
);
990 if (node
== (device_property
*)0
991 || node
->type
!= array_property
)
992 device_error(me
, "property %s not found or of wrong type", property
);
999 device_add_boolean_property(device
*me
,
1000 const char *property
,
1003 signed32 new_boolean
= (boolean
? -1 : 0);
1004 device_add_property(me
, property
, boolean_property
,
1005 &new_boolean
, sizeof(new_boolean
),
1006 &new_boolean
, sizeof(new_boolean
),
1007 NULL
, permenant_object
);
1012 device_find_boolean_property(device
*me
,
1013 const char *property
)
1015 const device_property
*node
;
1016 unsigned_cell boolean
;
1017 node
= device_find_property(me
, property
);
1018 if (node
== (device_property
*)0
1019 || node
->type
!= boolean_property
)
1020 device_error(me
, "property %s not found or of wrong type", property
);
1021 ASSERT(sizeof(boolean
) == node
->sizeof_array
);
1022 memcpy(&boolean
, node
->array
, sizeof(boolean
));
1029 device_add_ihandle_runtime_property(device
*me
,
1030 const char *property
,
1031 const ihandle_runtime_property_spec
*ihandle
)
1033 /* enter the full path as the init array */
1034 device_add_property(me
, property
, ihandle_property
,
1035 ihandle
->full_path
, strlen(ihandle
->full_path
) + 1,
1037 NULL
, permenant_object
);
1042 device_find_ihandle_runtime_property(device
*me
,
1043 const char *property
,
1044 ihandle_runtime_property_spec
*ihandle
)
1046 device_property_entry
*entry
= find_property_entry(me
, property
);
1047 TRACE(trace_devices
,
1048 ("device_find_ihandle_runtime_property(me=0x%lx, property=%s)\n",
1049 (long)me
, property
));
1051 || entry
->value
->type
!= ihandle_property
1052 || entry
->value
->disposition
!= permenant_object
)
1053 device_error(me
, "property %s not found or of wrong type", property
);
1054 ASSERT(entry
->init_array
!= NULL
);
1056 ihandle
->full_path
= entry
->init_array
;
1063 device_set_ihandle_property(device
*me
,
1064 const char *property
,
1065 device_instance
*ihandle
)
1067 unsigned_cell cells
;
1068 cells
= H2BE_cell(device_instance_to_external(ihandle
));
1069 device_set_property(me
, property
, ihandle_property
,
1070 &cells
, sizeof(cells
));
1076 device_find_ihandle_property(device
*me
,
1077 const char *property
)
1079 const device_property
*node
;
1080 unsigned_cell ihandle
;
1081 device_instance
*instance
;
1083 node
= device_find_property(me
, property
);
1084 if (node
== NULL
|| node
->type
!= ihandle_property
)
1085 device_error(me
, "property %s not found or of wrong type", property
);
1086 if (node
->array
== NULL
)
1087 device_error(me
, "runtime property %s not yet initialized", property
);
1089 ASSERT(sizeof(ihandle
) == node
->sizeof_array
);
1090 memcpy(&ihandle
, node
->array
, sizeof(ihandle
));
1091 instance
= external_to_device_instance(me
, BE2H_cell(ihandle
));
1092 ASSERT(instance
!= NULL
);
1099 device_add_integer_property(device
*me
,
1100 const char *property
,
1101 signed_cell integer
)
1104 device_add_property(me
, property
, integer_property
,
1105 &integer
, sizeof(integer
),
1106 &integer
, sizeof(integer
),
1107 NULL
, permenant_object
);
1112 device_find_integer_property(device
*me
,
1113 const char *property
)
1115 const device_property
*node
;
1116 signed_cell integer
;
1117 TRACE(trace_devices
,
1118 ("device_find_integer(me=0x%lx, property=%s)\n",
1119 (long)me
, property
));
1120 node
= device_find_property(me
, property
);
1121 if (node
== (device_property
*)0
1122 || node
->type
!= integer_property
)
1123 device_error(me
, "property %s not found or of wrong type", property
);
1124 ASSERT(sizeof(integer
) == node
->sizeof_array
);
1125 memcpy(&integer
, node
->array
, sizeof(integer
));
1126 return BE2H_cell(integer
);
1131 device_find_integer_array_property(device
*me
,
1132 const char *property
,
1134 signed_cell
*integer
)
1136 const device_property
*node
;
1137 int sizeof_integer
= sizeof(*integer
);
1139 TRACE(trace_devices
,
1140 ("device_find_integer(me=0x%lx, property=%s)\n",
1141 (long)me
, property
));
1143 /* check things sane */
1144 node
= device_find_property(me
, property
);
1145 if (node
== (device_property
*)0
1146 || (node
->type
!= integer_property
1147 && node
->type
!= array_property
))
1148 device_error(me
, "property %s not found or of wrong type", property
);
1149 if ((node
->sizeof_array
% sizeof_integer
) != 0)
1150 device_error(me
, "property %s contains an incomplete number of cells", property
);
1151 if (node
->sizeof_array
<= sizeof_integer
* index
)
1154 /* Find and convert the value */
1155 cell
= ((signed_cell
*)node
->array
) + index
;
1156 *integer
= BE2H_cell(*cell
);
1158 return node
->sizeof_array
/ sizeof_integer
;
1162 STATIC_INLINE_DEVICE\
1164 unit_address_to_cells(const device_unit
*unit
,
1165 unsigned_cell
*cell
,
1169 ASSERT(nr_cells
== unit
->nr_cells
);
1170 for (i
= 0; i
< unit
->nr_cells
; i
++) {
1171 *cell
= H2BE_cell(unit
->cells
[i
]);
1178 STATIC_INLINE_DEVICE\
1179 (const unsigned_cell
*)
1180 cells_to_unit_address(const unsigned_cell
*cell
,
1185 memset(unit
, 0, sizeof(*unit
));
1186 unit
->nr_cells
= nr_cells
;
1187 for (i
= 0; i
< unit
->nr_cells
; i
++) {
1188 unit
->cells
[i
] = BE2H_cell(*cell
);
1195 STATIC_INLINE_DEVICE\
1197 nr_range_property_cells(device
*me
,
1200 return ((device_nr_address_cells(me
)
1201 + device_nr_address_cells(device_parent(me
))
1202 + device_nr_size_cells(me
))
1208 device_add_range_array_property(device
*me
,
1209 const char *property
,
1210 const range_property_spec
*ranges
,
1213 unsigned sizeof_cells
= (nr_range_property_cells(me
, nr_ranges
)
1214 * sizeof(unsigned_cell
));
1215 unsigned_cell
*cells
= zalloc(sizeof_cells
);
1216 unsigned_cell
*cell
;
1219 /* copy the property elements over */
1221 for (i
= 0; i
< nr_ranges
; i
++) {
1222 const range_property_spec
*range
= &ranges
[i
];
1223 /* copy the child address */
1224 cell
= unit_address_to_cells(&range
->child_address
, cell
,
1225 device_nr_address_cells(me
));
1226 /* copy the parent address */
1227 cell
= unit_address_to_cells(&range
->parent_address
, cell
,
1228 device_nr_address_cells(device_parent(me
)));
1230 cell
= unit_address_to_cells(&range
->size
, cell
,
1231 device_nr_size_cells(me
));
1233 ASSERT(cell
== &cells
[nr_range_property_cells(me
, nr_ranges
)]);
1236 device_add_property(me
, property
, range_array_property
,
1237 cells
, sizeof_cells
,
1238 cells
, sizeof_cells
,
1239 NULL
, permenant_object
);
1246 device_find_range_array_property(device
*me
,
1247 const char *property
,
1249 range_property_spec
*range
)
1251 const device_property
*node
;
1252 unsigned sizeof_entry
= (nr_range_property_cells(me
, 1)
1253 * sizeof(unsigned_cell
));
1254 const unsigned_cell
*cells
;
1256 /* locate the property */
1257 node
= device_find_property(me
, property
);
1258 if (node
== (device_property
*)0
1259 || node
->type
!= range_array_property
)
1260 device_error(me
, "property %s not found or of wrong type", property
);
1263 if ((node
->sizeof_array
% sizeof_entry
) != 0)
1264 device_error(me
, "property %s contains an incomplete number of entries",
1267 /* within bounds? */
1268 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
1271 /* find the range of interest */
1272 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
1274 /* copy the child address out - converting as we go */
1275 cells
= cells_to_unit_address(cells
, &range
->child_address
,
1276 device_nr_address_cells(me
));
1278 /* copy the parent address out - converting as we go */
1279 cells
= cells_to_unit_address(cells
, &range
->parent_address
,
1280 device_nr_address_cells(device_parent(me
)));
1282 /* copy the size - converting as we go */
1283 cells
= cells_to_unit_address(cells
, &range
->size
,
1284 device_nr_size_cells(me
));
1286 return node
->sizeof_array
/ sizeof_entry
;
1290 STATIC_INLINE_DEVICE\
1292 nr_reg_property_cells(device
*me
,
1295 return (device_nr_address_cells(device_parent(me
))
1296 + device_nr_size_cells(device_parent(me
))
1302 device_add_reg_array_property(device
*me
,
1303 const char *property
,
1304 const reg_property_spec
*regs
,
1307 unsigned sizeof_cells
= (nr_reg_property_cells(me
, nr_regs
)
1308 * sizeof(unsigned_cell
));
1309 unsigned_cell
*cells
= zalloc(sizeof_cells
);
1310 unsigned_cell
*cell
;
1313 /* copy the property elements over */
1315 for (i
= 0; i
< nr_regs
; i
++) {
1316 const reg_property_spec
*reg
= ®s
[i
];
1317 /* copy the address */
1318 cell
= unit_address_to_cells(®
->address
, cell
,
1319 device_nr_address_cells(device_parent(me
)));
1321 cell
= unit_address_to_cells(®
->size
, cell
,
1322 device_nr_size_cells(device_parent(me
)));
1324 ASSERT(cell
== &cells
[nr_reg_property_cells(me
, nr_regs
)]);
1327 device_add_property(me
, property
, reg_array_property
,
1328 cells
, sizeof_cells
,
1329 cells
, sizeof_cells
,
1330 NULL
, permenant_object
);
1337 device_find_reg_array_property(device
*me
,
1338 const char *property
,
1340 reg_property_spec
*reg
)
1342 const device_property
*node
;
1343 unsigned sizeof_entry
= (nr_reg_property_cells(me
, 1)
1344 * sizeof(unsigned_cell
));
1345 const unsigned_cell
*cells
;
1347 /* locate the property */
1348 node
= device_find_property(me
, property
);
1349 if (node
== (device_property
*)0
1350 || node
->type
!= reg_array_property
)
1351 device_error(me
, "property %s not found or of wrong type", property
);
1354 if ((node
->sizeof_array
% sizeof_entry
) != 0)
1355 device_error(me
, "property %s contains an incomplete number of entries",
1358 /* within bounds? */
1359 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
1362 /* find the range of interest */
1363 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
1365 /* copy the address out - converting as we go */
1366 cells
= cells_to_unit_address(cells
, ®
->address
,
1367 device_nr_address_cells(device_parent(me
)));
1369 /* copy the size out - converting as we go */
1370 cells
= cells_to_unit_address(cells
, ®
->size
,
1371 device_nr_size_cells(device_parent(me
)));
1373 return node
->sizeof_array
/ sizeof_entry
;
1379 device_add_string_property(device
*me
,
1380 const char *property
,
1383 device_add_property(me
, property
, string_property
,
1384 string
, strlen(string
) + 1,
1385 string
, strlen(string
) + 1,
1386 NULL
, permenant_object
);
1391 device_find_string_property(device
*me
,
1392 const char *property
)
1394 const device_property
*node
;
1396 node
= device_find_property(me
, property
);
1397 if (node
== (device_property
*)0
1398 || node
->type
!= string_property
)
1399 device_error(me
, "property %s not found or of wrong type", property
);
1400 string
= node
->array
;
1401 ASSERT(strlen(string
) + 1 == node
->sizeof_array
);
1407 device_add_string_array_property(device
*me
,
1408 const char *property
,
1409 const string_property_spec
*strings
,
1410 unsigned nr_strings
)
1416 if (nr_strings
== 0)
1417 device_error(me
, "property %s must be non-null", property
);
1418 /* total up the size of the needed array */
1419 for (sizeof_array
= 0, string_nr
= 0;
1420 string_nr
< nr_strings
;
1422 sizeof_array
+= strlen(strings
[string_nr
]) + 1;
1424 /* create the array */
1425 array
= (char*)zalloc(sizeof_array
);
1428 string_nr
< nr_strings
;
1430 strcpy(chp
, strings
[string_nr
]);
1431 chp
+= strlen(chp
) + 1;
1433 ASSERT(chp
== array
+ sizeof_array
);
1435 device_add_property(me
, property
, string_array_property
,
1436 array
, sizeof_array
,
1437 array
, sizeof_array
,
1438 NULL
, permenant_object
);
1443 device_find_string_array_property(device
*me
,
1444 const char *property
,
1446 string_property_spec
*string
)
1448 const device_property
*node
;
1449 node
= device_find_property(me
, property
);
1450 if (node
== (device_property
*)0)
1451 device_error(me
, "property %s not found", property
);
1452 switch (node
->type
) {
1454 device_error(me
, "property %s of wrong type", property
);
1456 case string_property
:
1458 *string
= node
->array
;
1459 ASSERT(strlen(*string
) + 1 == node
->sizeof_array
);
1463 case array_property
:
1464 if (node
->sizeof_array
== 0
1465 || ((char*)node
->array
)[node
->sizeof_array
- 1] != '\0')
1466 device_error(me
, "property %s invalid for string array", property
);
1468 case string_array_property
:
1469 ASSERT(node
->sizeof_array
> 0);
1470 ASSERT(((char*)node
->array
)[node
->sizeof_array
- 1] == '\0');
1472 const char *chp
= node
->array
;
1474 /* count the number of strings, keeping an eye out for the one
1475 we're looking for */
1482 if (nr_entries
== index
)
1488 } while (chp
< (char*)node
->array
+ node
->sizeof_array
);
1489 if (index
< nr_entries
)
1503 device_add_duplicate_property(device
*me
,
1504 const char *property
,
1505 const device_property
*original
)
1507 device_property_entry
*master
;
1508 TRACE(trace_devices
,
1509 ("device_add_duplicate_property(me=0x%lx, property=%s, ...)\n",
1510 (long)me
, property
));
1511 if (original
->disposition
!= permenant_object
)
1512 device_error(me
, "Can only duplicate permenant objects");
1513 /* find the original's master */
1514 master
= original
->owner
->properties
;
1515 while (master
->value
!= original
) {
1516 master
= master
->next
;
1517 ASSERT(master
!= NULL
);
1519 /* now duplicate it */
1520 device_add_property(me
, property
,
1522 master
->init_array
, master
->sizeof_init_array
,
1523 original
->array
, original
->sizeof_array
,
1524 original
, permenant_object
);
1529 /* Device Hardware: */
1533 device_io_read_buffer(device
*me
,
1541 if (me
->callback
->io
.read_buffer
== NULL
)
1542 device_error(me
, "no io.read_buffer method");
1543 return me
->callback
->io
.read_buffer(me
, dest
, space
,
1550 device_io_write_buffer(device
*me
,
1558 if (me
->callback
->io
.write_buffer
== NULL
)
1559 device_error(me
, "no io.write_buffer method");
1560 return me
->callback
->io
.write_buffer(me
, source
, space
,
1567 device_dma_read_buffer(device
*me
,
1573 if (me
->callback
->dma
.read_buffer
== NULL
)
1574 device_error(me
, "no dma.read_buffer method");
1575 return me
->callback
->dma
.read_buffer(me
, dest
, space
,
1581 device_dma_write_buffer(device
*me
,
1586 int violate_read_only_section
)
1588 if (me
->callback
->dma
.write_buffer
== NULL
)
1589 device_error(me
, "no dma.write_buffer method");
1590 return me
->callback
->dma
.write_buffer(me
, source
, space
,
1592 violate_read_only_section
);
1597 device_attach_address(device
*me
,
1603 device
*client
) /*callback/default*/
1605 if (me
->callback
->address
.attach
== NULL
)
1606 device_error(me
, "no address.attach method");
1607 me
->callback
->address
.attach(me
, attach
, space
,
1608 addr
, nr_bytes
, access
, client
);
1613 device_detach_address(device
*me
,
1619 device
*client
) /*callback/default*/
1621 if (me
->callback
->address
.detach
== NULL
)
1622 device_error(me
, "no address.detach method");
1623 me
->callback
->address
.detach(me
, attach
, space
,
1624 addr
, nr_bytes
, access
, client
);
1632 device_interrupt_event(device
*me
,
1638 int found_an_edge
= 0;
1639 device_interrupt_edge
*edge
;
1640 /* device's interrupt lines directly connected */
1641 for (edge
= me
->interrupt_destinations
;
1643 edge
= edge
->next
) {
1644 if (edge
->my_port
== my_port
) {
1645 if (edge
->dest
->callback
->interrupt
.event
== NULL
)
1646 device_error(me
, "no interrupt method");
1647 edge
->dest
->callback
->interrupt
.event(edge
->dest
,
1656 if (!found_an_edge
) {
1657 device_error(me
, "No interrupt edge for port %d", my_port
);
1663 device_interrupt_attach(device
*me
,
1667 object_disposition disposition
)
1669 attach_device_interrupt_edge(&me
->interrupt_destinations
,
1678 device_interrupt_detach(device
*me
,
1683 detach_device_interrupt_edge(me
,
1684 &me
->interrupt_destinations
,
1692 device_interrupt_traverse(device
*me
,
1693 device_interrupt_traverse_function
*handler
,
1696 device_interrupt_edge
*interrupt_edge
;
1697 for (interrupt_edge
= me
->interrupt_destinations
;
1698 interrupt_edge
!= NULL
;
1699 interrupt_edge
= interrupt_edge
->next
) {
1700 handler(me
, interrupt_edge
->my_port
,
1701 interrupt_edge
->dest
, interrupt_edge
->dest_port
,
1708 device_interrupt_decode(device
*me
,
1709 const char *port_name
,
1710 port_direction direction
)
1712 if (port_name
== NULL
|| port_name
[0] == '\0')
1714 if (isdigit(port_name
[0])) {
1715 return strtoul(port_name
, NULL
, 0);
1718 const device_interrupt_port_descriptor
*ports
=
1719 me
->callback
->interrupt
.ports
;
1720 if (ports
!= NULL
) {
1721 while (ports
->name
!= NULL
) {
1722 if (ports
->direction
== bidirect_port
1723 || ports
->direction
== direction
) {
1724 if (ports
->nr_ports
> 0) {
1725 int len
= strlen(ports
->name
);
1726 if (strncmp(port_name
, ports
->name
, len
) == 0) {
1727 if (port_name
[len
] == '\0')
1728 return ports
->number
;
1729 else if(isdigit(port_name
[len
])) {
1730 int port
= ports
->number
+ strtoul(&port_name
[len
], NULL
, 0);
1731 if (port
>= ports
->number
+ ports
->nr_ports
)
1732 device_error(me
, "Interrupt port %s out of range",
1738 else if (strcmp(port_name
, ports
->name
) == 0)
1739 return ports
->number
;
1745 device_error(me
, "Unreconized interrupt port %s", port_name
);
1751 device_interrupt_encode(device
*me
,
1755 port_direction direction
)
1757 const device_interrupt_port_descriptor
*ports
= NULL
;
1758 ports
= me
->callback
->interrupt
.ports
;
1759 if (ports
!= NULL
) {
1760 while (ports
->name
!= NULL
) {
1761 if (ports
->direction
== bidirect_port
1762 || ports
->direction
== direction
) {
1763 if (ports
->nr_ports
> 0) {
1764 if (port_number
>= ports
->number
1765 && port_number
< ports
->number
+ ports
->nr_ports
) {
1766 strcpy(buf
, ports
->name
);
1767 sprintf(buf
+ strlen(buf
), "%d", port_number
- ports
->number
);
1768 if (strlen(buf
) >= sizeof_buf
)
1769 error("device_interrupt_encode: buffer overflow");
1774 if (ports
->number
== port_number
) {
1775 if (strlen(ports
->name
) >= sizeof_buf
)
1776 error("device_interrupt_encode: buffer overflow");
1777 strcpy(buf
, ports
->name
);
1785 sprintf(buf
, "%d", port_number
);
1786 if (strlen(buf
) >= sizeof_buf
)
1787 error("device_interrupt_encode: buffer overflow");
1797 device_ioctl(device
*me
,
1800 device_ioctl_request request
,
1805 va_start(ap
, request
);
1806 if (me
->callback
->ioctl
== NULL
)
1807 device_error(me
, "no ioctl method");
1808 status
= me
->callback
->ioctl(me
, processor
, cia
, request
, ap
);
1819 device_error(device
*me
,
1825 /* format the message */
1827 vsprintf(message
, fmt
, ap
);
1830 if (strlen(message
) >= sizeof(message
))
1831 error("device_error: buffer overflow");
1833 error("device: %s", message
);
1834 else if (me
->path
!= NULL
&& me
->path
[0] != '\0')
1835 error("%s: %s", me
->path
, message
);
1836 else if (me
->name
!= NULL
&& me
->name
[0] != '\0')
1837 error("%s: %s", me
->name
, message
);
1839 error("device: %s", message
);
1845 device_trace(device
*me
)
1851 /* External representation */
1855 external_to_device(device
*tree_member
,
1856 unsigned_cell phandle
)
1858 device
*me
= cap_internal(tree_member
->phandles
, phandle
);
1864 device_to_external(device
*me
)
1866 unsigned_cell phandle
= cap_external(me
->phandles
, me
);
1872 external_to_device_instance(device
*tree_member
,
1873 unsigned_cell ihandle
)
1875 device_instance
*instance
= cap_internal(tree_member
->ihandles
, ihandle
);
1881 device_instance_to_external(device_instance
*instance
)
1883 unsigned_cell ihandle
= cap_external(instance
->owner
->ihandles
, instance
);
1888 /* Map onto the event functions */
1892 device_event_queue_schedule(device
*me
,
1893 signed64 delta_time
,
1894 device_event_handler
*handler
,
1897 return event_queue_schedule(psim_event_queue(me
->system
),
1905 device_event_queue_deschedule(device
*me
,
1906 event_entry_tag event_to_remove
)
1908 event_queue_deschedule(psim_event_queue(me
->system
),
1914 device_event_queue_time(device
*me
)
1916 return event_queue_time(psim_event_queue(me
->system
));
1920 /* Initialization: */
1925 device_clean(device
*me
,
1929 system
= (psim
*)data
;
1930 TRACE(trace_device_init
, ("device_clean - initializing %s", me
->path
));
1931 clean_device_interrupt_edges(&me
->interrupt_destinations
);
1932 clean_device_instances(me
);
1933 clean_device_properties(me
);
1936 /* Device initialization: */
1940 device_init_address(device
*me
,
1943 psim
*system
= (psim
*)data
;
1944 int nr_address_cells
;
1946 TRACE(trace_device_init
, ("device_init_address - initializing %s", me
->path
));
1948 /* ensure the cap database is valid */
1949 if (me
->parent
== NULL
) {
1950 cap_init(me
->ihandles
);
1951 cap_init(me
->phandles
);
1955 me
->system
= system
; /* misc things not known until now */
1956 me
->trace
= (device_find_property(me
, "trace")
1957 ? device_find_integer_property(me
, "trace")
1960 /* Ensure that the first address found in the reg property matches
1961 anything that was specified as part of the devices name */
1962 if (device_find_property(me
, "reg") != NULL
) {
1963 reg_property_spec unit
;
1964 device_find_reg_array_property(me
, "reg", 0, &unit
);
1965 if (memcmp(device_unit_address(me
), &unit
.address
, sizeof(unit
.address
))
1967 device_error(me
, "Unit address as specified by the reg property in conflict with the value previously specified in the devices path");
1970 /* ensure that the devices #address/size-cells is consistent */
1971 nr_address_cells
= device_nr_address_cells(me
);
1972 if (device_find_property(me
, "#address-cells") != NULL
1973 && (nr_address_cells
1974 != device_find_integer_property(me
, "#address-cells")))
1975 device_error(me
, "#address-cells property used before defined");
1976 nr_size_cells
= device_nr_size_cells(me
);
1977 if (device_find_property(me
, "#size-cells") != NULL
1979 != device_find_integer_property(me
, "#size-cells")))
1980 device_error(me
, "#size-cells property used before defined");
1983 if (me
->callback
->init
.address
!= NULL
)
1984 me
->callback
->init
.address(me
);
1989 device_init_data(device
*me
,
1992 TRACE(trace_device_init
, ("device_init_data - initializing %s", me
->path
));
1993 if (me
->callback
->init
.data
!= NULL
)
1994 me
->callback
->init
.data(me
);
1997 #endif /* _DEVICE_C_ */