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"
36 STATIC_INLINE_DEVICE (void) clean_device_properties(device
*);
38 /* property entries */
40 typedef struct _device_property_entry device_property_entry
;
41 struct _device_property_entry
{
42 device_property_entry
*next
;
43 device_property
*value
;
44 const void *init_array
;
45 unsigned sizeof_init_array
;
51 typedef struct _device_interrupt_edge device_interrupt_edge
;
52 struct _device_interrupt_edge
{
56 device_interrupt_edge
*next
;
57 object_disposition disposition
;
62 attach_device_interrupt_edge(device_interrupt_edge
**list
,
66 object_disposition disposition
)
68 device_interrupt_edge
*new_edge
= ZALLOC(device_interrupt_edge
);
69 new_edge
->my_port
= my_port
;
70 new_edge
->dest
= dest
;
71 new_edge
->dest_port
= dest_port
;
72 new_edge
->next
= *list
;
73 new_edge
->disposition
= disposition
;
79 detach_device_interrupt_edge(device
*me
,
80 device_interrupt_edge
**list
,
85 while (*list
!= NULL
) {
86 device_interrupt_edge
*old_edge
= *list
;
87 if (old_edge
->dest
== dest
88 && old_edge
->dest_port
== dest_port
89 && old_edge
->my_port
== my_port
) {
90 if (old_edge
->disposition
== permenant_object
)
91 device_error(me
, "attempt to delete permenant interrupt");
92 *list
= old_edge
->next
;
97 device_error(me
, "attempt to delete unattached interrupt");
100 STATIC_INLINE_DEVICE\
102 clean_device_interrupt_edges(device_interrupt_edge
**list
)
104 while (*list
!= NULL
) {
105 device_interrupt_edge
*old_edge
= *list
;
106 switch (old_edge
->disposition
) {
107 case permenant_object
:
108 list
= &old_edge
->next
;
110 case tempoary_object
:
111 *list
= old_edge
->next
;
125 device_unit unit_address
;
127 int nr_address_cells
;
135 /* its template methods */
136 void *data
; /* device specific data */
137 const device_callbacks
*callback
;
139 /* device properties */
140 device_property_entry
*properties
;
143 device_interrupt_edge
*interrupt_destinations
;
145 /* any open instances of this device */
146 device_instance
*instances
;
148 /* the internal/external mappings and other global requirements */
158 /* an instance of a device */
159 struct _device_instance
{
163 const device_instance_callbacks
*callback
;
164 /* the root instance */
166 device_instance
*next
;
167 /* interposed instance */
168 device_instance
*parent
;
169 device_instance
*child
;
176 STATIC_INLINE_DEVICE\
178 device_full_name(device
*leaf
,
183 char full_name
[1024];
184 if (buf
== (char*)0) {
186 sizeof_buf
= sizeof(full_name
);
189 /* construct a name */
190 if (leaf
->parent
== NULL
) {
192 error("device_full_name: buffer overflow");
197 device_full_name(leaf
->parent
, buf
, sizeof_buf
);
198 if (leaf
->parent
!= NULL
199 && device_encode_unit(leaf
->parent
,
206 if (strlen(buf
) + strlen("/") + strlen(leaf
->name
) + strlen(unit
)
208 error("device_full_name: buffer overflow");
210 strcat(buf
, leaf
->name
);
214 /* return it usefully */
215 if (buf
== full_name
)
216 buf
= (char *) strdup(full_name
);
220 STATIC_INLINE_DEVICE\
222 device_create_from(const char *name
,
223 const device_unit
*unit_address
,
225 const device_callbacks
*callbacks
,
228 device
*new_device
= ZALLOC(device
);
230 /* insert it into the device tree */
231 new_device
->parent
= parent
;
232 new_device
->children
= NULL
;
233 if (parent
!= NULL
) {
234 device
**sibling
= &parent
->children
;
235 while ((*sibling
) != NULL
)
236 sibling
= &(*sibling
)->sibling
;
237 *sibling
= new_device
;
241 new_device
->name
= (char *) strdup(name
);
242 new_device
->unit_address
= *unit_address
;
243 new_device
->path
= device_full_name(new_device
, NULL
, 0);
246 new_device
->data
= data
;
247 new_device
->callback
= callbacks
;
249 /* its properties - already null */
250 /* interrupts - already null */
252 /* mappings - if needed */
253 if (parent
== NULL
) {
254 new_device
->ihandles
= cap_create(name
);
255 new_device
->phandles
= cap_create(name
);
258 new_device
->ihandles
= device_root(parent
)->ihandles
;
259 new_device
->phandles
= device_root(parent
)->phandles
;
262 cap_add(new_device
->phandles
, new_device
);
270 device_create(device
*parent
,
273 const char *unit_address
,
276 const device_descriptor
*const *table
;
277 for (table
= device_table
; *table
!= NULL
; table
++) {
278 const device_descriptor
*descr
;
279 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
280 if (strcmp(base
, descr
->name
) == 0) {
281 device_unit address
= { 0 };
284 if (device_decode_unit(parent
, unit_address
, &address
) < 0)
285 device_error(parent
, "invalid address %s for device %s",
287 if (descr
->creator
!= NULL
)
288 data
= descr
->creator(name
, &address
, args
);
289 return device_create_from(name
, &address
, data
,
290 descr
->callbacks
, parent
);
294 device_error(parent
, "attempt to attach unknown device %s", name
);
302 device_usage(int verbose
)
304 const device_descriptor
*const *table
;
307 for (table
= device_table
; *table
!= NULL
; table
++) {
308 const device_descriptor
*descr
;
309 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
310 pos
+= strlen(descr
->name
) + 2;
312 pos
= strlen(descr
->name
) + 2;
313 printf_filtered("\n");
315 printf_filtered(" %s", descr
->name
);
317 printf_filtered("\n");
321 for (table
= device_table
; *table
!= NULL
; table
++) {
322 const device_descriptor
*descr
;
323 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
324 printf_filtered(" %s:\n", descr
->name
);
325 /* interrupt ports */
326 if (descr
->callbacks
->interrupt
.ports
!= NULL
) {
327 const device_interrupt_port_descriptor
*ports
=
328 descr
->callbacks
->interrupt
.ports
;
329 printf_filtered(" interrupt ports:");
330 while (ports
->name
!= NULL
) {
331 printf_filtered(" %s", ports
->name
);
334 printf_filtered("\n");
337 if (descr
->callbacks
->usage
!= NULL
)
338 descr
->callbacks
->usage(verbose
);
352 device_parent(device
*me
)
359 device_root(device
*me
)
362 while (me
->parent
!= NULL
)
369 device_sibling(device
*me
)
376 device_child(device
*me
)
383 device_name(device
*me
)
390 device_path(device
*me
)
397 device_data(device
*me
)
404 device_system(device
*me
)
410 (const device_unit
*)
411 device_unit_address(device
*me
)
413 return &me
->unit_address
;
419 device_address_to_attach_address(device
*me
,
420 const device_unit
*address
,
422 unsigned_word
*attach_address
,
425 if (me
->callback
->convert
.address_to_attach_address
== NULL
)
426 device_error(me
, "no convert.address_to_attach_address method");
427 return me
->callback
->convert
.address_to_attach_address(me
, address
, attach_space
, attach_address
, client
);
433 device_size_to_attach_size(device
*me
,
434 const device_unit
*size
,
438 if (me
->callback
->convert
.size_to_attach_size
== NULL
)
439 device_error(me
, "no convert.size_to_attach_size method");
440 return me
->callback
->convert
.size_to_attach_size(me
, size
, nr_bytes
, client
);
446 device_decode_unit(device
*bus
,
448 device_unit
*address
)
450 if (bus
->callback
->convert
.decode_unit
== NULL
)
451 device_error(bus
, "no convert.decode_unit method");
452 return bus
->callback
->convert
.decode_unit(bus
, unit
, address
);
458 device_encode_unit(device
*bus
,
459 const device_unit
*unit_address
,
463 if (bus
->callback
->convert
.encode_unit
== NULL
)
464 device_error(bus
, "no convert.encode_unit method");
465 return bus
->callback
->convert
.encode_unit(bus
, unit_address
, buf
, sizeof_buf
);
470 device_nr_address_cells(device
*me
)
472 if (me
->nr_address_cells
== 0) {
473 if (device_find_property(me
, "#address-cells") != NULL
)
474 me
->nr_address_cells
= device_find_integer_property(me
, "#address-cells");
476 me
->nr_address_cells
= 2;
478 return me
->nr_address_cells
;
483 device_nr_size_cells(device
*me
)
485 if (me
->nr_size_cells
== 0) {
486 if (device_find_property(me
, "#size-cells") != NULL
)
487 me
->nr_size_cells
= device_find_integer_property(me
, "#size-cells");
489 me
->nr_size_cells
= 1;
491 return me
->nr_size_cells
;
496 /* device-instance: */
500 device_create_instance_from(device
*me
,
501 device_instance
*parent
,
505 const device_instance_callbacks
*callbacks
)
507 device_instance
*instance
= ZALLOC(device_instance
);
508 if ((me
== NULL
) == (parent
== NULL
))
509 device_error(me
, "can't have both parent instance and parent device");
511 /* link this instance into the devices list */
513 ASSERT(parent
== NULL
);
514 instance
->owner
= me
;
515 instance
->parent
= NULL
;
516 /* link this instance into the front of the devices instance list */
517 instance
->next
= me
->instances
;
518 me
->instances
= instance
;
520 if (parent
!= NULL
) {
521 device_instance
**previous
;
522 ASSERT(parent
->child
== NULL
);
523 parent
->child
= instance
;
525 instance
->owner
= parent
->owner
;
526 instance
->parent
= parent
;
527 /* in the devices instance list replace the parent instance with
529 instance
->next
= parent
->next
;
530 /* replace parent with this new node */
531 previous
= &instance
->owner
->instances
;
532 while (*previous
!= parent
) {
533 ASSERT(*previous
!= NULL
);
534 previous
= &(*previous
)->next
;
536 *previous
= instance
;
538 instance
->data
= data
;
539 instance
->args
= (args
== NULL
? NULL
: (char *) strdup(args
));
540 instance
->path
= (path
== NULL
? NULL
: (char *) strdup(path
));
541 instance
->callback
= callbacks
;
542 cap_add(instance
->owner
->ihandles
, instance
);
549 device_create_instance(device
*me
,
553 /* create the instance */
554 if (me
->callback
->instance_create
== NULL
)
555 device_error(me
, "no instance_create method");
556 return me
->callback
->instance_create(me
, path
, args
);
560 STATIC_INLINE_DEVICE\
562 clean_device_instances(device
*me
)
564 device_instance
**instance
= &me
->instances
;
565 while (*instance
!= NULL
) {
566 device_instance
*old_instance
= *instance
;
567 device_instance_delete(old_instance
);
568 instance
= &me
->instances
;
575 device_instance_delete(device_instance
*instance
)
577 device
*me
= instance
->owner
;
578 if (instance
->callback
->delete == NULL
)
579 device_error(me
, "no delete method");
580 instance
->callback
->delete(instance
);
581 if (instance
->args
!= NULL
)
582 free(instance
->args
);
583 if (instance
->path
!= NULL
)
584 free(instance
->path
);
585 if (instance
->child
== NULL
) {
586 /* only remove leaf nodes */
587 device_instance
**curr
= &me
->instances
;
588 while (*curr
!= instance
) {
589 ASSERT(*curr
!= NULL
);
590 curr
= &(*curr
)->next
;
592 *curr
= instance
->next
;
595 /* check it isn't in the instance list */
596 device_instance
*curr
= me
->instances
;
597 while (curr
!= NULL
) {
598 ASSERT(curr
!= instance
);
601 /* unlink the child */
602 ASSERT(instance
->child
->parent
== instance
);
603 instance
->child
->parent
= NULL
;
605 cap_remove(me
->ihandles
, instance
);
611 device_instance_read(device_instance
*instance
,
615 device
*me
= instance
->owner
;
616 if (instance
->callback
->read
== NULL
)
617 device_error(me
, "no read method");
618 return instance
->callback
->read(instance
, addr
, len
);
623 device_instance_write(device_instance
*instance
,
627 device
*me
= instance
->owner
;
628 if (instance
->callback
->write
== NULL
)
629 device_error(me
, "no write method");
630 return instance
->callback
->write(instance
, addr
, len
);
635 device_instance_seek(device_instance
*instance
,
636 unsigned_word pos_hi
,
637 unsigned_word pos_lo
)
639 device
*me
= instance
->owner
;
640 if (instance
->callback
->seek
== NULL
)
641 device_error(me
, "no seek method");
642 return instance
->callback
->seek(instance
, pos_hi
, pos_lo
);
647 device_instance_call_method(device_instance
*instance
,
648 const char *method_name
,
650 unsigned_cell stack_args
[/*n_stack_args*/],
652 unsigned_cell stack_returns
[/*n_stack_args*/])
654 device
*me
= instance
->owner
;
655 const device_instance_methods
*method
= instance
->callback
->methods
;
656 if (method
== NULL
) {
657 device_error(me
, "no methods (want %s)", method_name
);
659 while (method
->name
!= NULL
) {
660 if (strcmp(method
->name
, method_name
) == 0) {
661 return method
->method(instance
,
662 n_stack_args
, stack_args
,
663 n_stack_returns
, stack_returns
);
667 device_error(me
, "no %s method", method_name
);
674 device_instance_device(device_instance
*instance
)
676 return instance
->owner
;
681 device_instance_path(device_instance
*instance
)
683 return instance
->path
;
688 device_instance_data(device_instance
*instance
)
690 return instance
->data
;
695 /* Device Properties: */
697 STATIC_INLINE_DEVICE\
698 (device_property_entry
*)
699 find_property_entry(device
*me
,
700 const char *property
)
702 device_property_entry
*entry
;
703 ASSERT(property
!= NULL
);
704 entry
= me
->properties
;
705 while (entry
!= NULL
) {
706 if (strcmp(entry
->value
->name
, property
) == 0)
713 STATIC_INLINE_DEVICE\
715 device_add_property(device
*me
,
716 const char *property
,
717 device_property_type type
,
718 const void *init_array
,
719 unsigned sizeof_init_array
,
721 unsigned sizeof_array
,
722 const device_property
*original
,
723 object_disposition disposition
)
725 device_property_entry
*new_entry
= NULL
;
726 device_property
*new_value
= NULL
;
728 /* find the list end */
729 device_property_entry
**insertion_point
= &me
->properties
;
730 while (*insertion_point
!= NULL
) {
731 if (strcmp((*insertion_point
)->value
->name
, property
) == 0)
733 insertion_point
= &(*insertion_point
)->next
;
736 /* create a new value */
737 new_value
= ZALLOC(device_property
);
738 new_value
->name
= (char *) strdup(property
);
739 new_value
->type
= type
;
740 if (sizeof_array
> 0) {
741 void *new_array
= zalloc(sizeof_array
);
742 memcpy(new_array
, array
, sizeof_array
);
743 new_value
->array
= new_array
;
744 new_value
->sizeof_array
= sizeof_array
;
746 new_value
->owner
= me
;
747 new_value
->original
= original
;
748 new_value
->disposition
= disposition
;
750 /* insert the value into the list */
751 new_entry
= ZALLOC(device_property_entry
);
752 *insertion_point
= new_entry
;
753 if (sizeof_init_array
> 0) {
754 void *new_init_array
= zalloc(sizeof_init_array
);
755 memcpy(new_init_array
, init_array
, sizeof_init_array
);
756 new_entry
->init_array
= new_init_array
;
757 new_entry
->sizeof_init_array
= sizeof_init_array
;
759 new_entry
->value
= new_value
;
763 /* local - not available externally */
764 STATIC_INLINE_DEVICE\
766 device_set_property(device
*me
,
767 const char *property
,
768 device_property_type type
,
772 /* find the property */
773 device_property_entry
*entry
= find_property_entry(me
, property
);
775 /* existing property - update it */
777 device_property
*value
= entry
->value
;
778 /* check the type matches */
779 if (value
->type
!= type
)
780 device_error(me
, "conflict between type of new and old value for property %s", property
);
781 /* replace its value */
782 if (value
->array
!= NULL
)
783 free((void*)value
->array
);
784 new_array
= (sizeof_array
> 0
785 ? zalloc(sizeof_array
)
787 value
->array
= new_array
;
788 value
->sizeof_array
= sizeof_array
;
789 if (sizeof_array
> 0)
790 memcpy(new_array
, array
, sizeof_array
);
794 /* new property - create it */
795 device_add_property(me
, property
, type
,
796 NULL
, 0, array
, sizeof_array
,
797 NULL
, tempoary_object
);
802 STATIC_INLINE_DEVICE\
804 clean_device_properties(device
*me
)
806 device_property_entry
**delete_point
= &me
->properties
;
807 while (*delete_point
!= NULL
) {
808 device_property_entry
*current
= *delete_point
;
809 switch (current
->value
->disposition
) {
810 case permenant_object
:
811 /* zap the current value, will be initialized later */
812 ASSERT(current
->init_array
!= NULL
);
813 if (current
->value
->array
!= NULL
) {
814 free((void*)current
->value
->array
);
815 current
->value
->array
= NULL
;
817 delete_point
= &(*delete_point
)->next
;
819 case tempoary_object
:
820 /* zap the actual property, was created during simulation run */
821 ASSERT(current
->init_array
== NULL
);
822 *delete_point
= current
->next
;
823 if (current
->value
->array
!= NULL
)
824 free((void*)current
->value
->array
);
825 free(current
->value
);
835 device_init_static_properties(device
*me
,
838 device_property_entry
*property
;
839 for (property
= me
->properties
;
841 property
= property
->next
) {
842 ASSERT(property
->init_array
!= NULL
);
843 ASSERT(property
->value
->array
== NULL
);
844 ASSERT(property
->value
->disposition
== permenant_object
);
845 switch (property
->value
->type
) {
847 case boolean_property
:
848 case range_array_property
:
849 case reg_array_property
:
850 case string_property
:
851 case string_array_property
:
852 case integer_property
:
853 /* delete the property, and replace it with the original */
854 device_set_property(me
, property
->value
->name
,
855 property
->value
->type
,
856 property
->init_array
,
857 property
->sizeof_init_array
);
859 case ihandle_property
:
868 device_init_runtime_properties(device
*me
,
871 device_property_entry
*property
;
872 for (property
= me
->properties
;
874 property
= property
->next
) {
875 switch (property
->value
->disposition
) {
876 case permenant_object
:
877 switch (property
->value
->type
) {
878 case ihandle_property
:
880 device_instance
*ihandle
;
881 ihandle_runtime_property_spec spec
;
882 ASSERT(property
->init_array
!= NULL
);
883 ASSERT(property
->value
->array
== NULL
);
884 device_find_ihandle_runtime_property(me
, property
->value
->name
, &spec
);
885 ihandle
= tree_instance(me
, spec
.full_path
);
886 device_set_ihandle_property(me
, property
->value
->name
, ihandle
);
890 case boolean_property
:
891 case range_array_property
:
892 case integer_property
:
893 case reg_array_property
:
894 case string_property
:
895 case string_array_property
:
896 ASSERT(property
->init_array
!= NULL
);
897 ASSERT(property
->value
->array
!= NULL
);
901 case tempoary_object
:
902 ASSERT(property
->init_array
== NULL
);
903 ASSERT(property
->value
->array
!= NULL
);
911 (const device_property
*)
912 device_next_property(const device_property
*property
)
914 /* find the property in the list */
915 device
*owner
= property
->owner
;
916 device_property_entry
*entry
= owner
->properties
;
917 while (entry
!= NULL
&& entry
->value
!= property
)
919 /* now return the following property */
920 ASSERT(entry
!= NULL
); /* must be a member! */
921 if (entry
->next
!= NULL
)
922 return entry
->next
->value
;
929 (const device_property
*)
930 device_find_property(device
*me
,
931 const char *property
)
936 else if (property
== NULL
|| strcmp(property
, "") == 0) {
937 if (me
->properties
== NULL
)
940 return me
->properties
->value
;
943 device_property_entry
*entry
= find_property_entry(me
, property
);
953 device_add_array_property(device
*me
,
954 const char *property
,
958 device_add_property(me
, property
, array_property
,
959 array
, sizeof_array
, array
, sizeof_array
,
960 NULL
, permenant_object
);
965 device_set_array_property(device
*me
,
966 const char *property
,
970 device_set_property(me
, property
, array_property
, array
, sizeof_array
);
974 (const device_property
*)
975 device_find_array_property(device
*me
,
976 const char *property
)
978 const device_property
*node
;
979 node
= device_find_property(me
, property
);
980 if (node
== (device_property
*)0
981 || node
->type
!= array_property
)
982 device_error(me
, "property %s not found or of wrong type", property
);
989 device_add_boolean_property(device
*me
,
990 const char *property
,
993 signed32 new_boolean
= (boolean
? -1 : 0);
994 device_add_property(me
, property
, boolean_property
,
995 &new_boolean
, sizeof(new_boolean
),
996 &new_boolean
, sizeof(new_boolean
),
997 NULL
, permenant_object
);
1002 device_find_boolean_property(device
*me
,
1003 const char *property
)
1005 const device_property
*node
;
1006 unsigned_cell boolean
;
1007 node
= device_find_property(me
, property
);
1008 if (node
== (device_property
*)0
1009 || node
->type
!= boolean_property
)
1010 device_error(me
, "property %s not found or of wrong type", property
);
1011 ASSERT(sizeof(boolean
) == node
->sizeof_array
);
1012 memcpy(&boolean
, node
->array
, sizeof(boolean
));
1019 device_add_ihandle_runtime_property(device
*me
,
1020 const char *property
,
1021 const ihandle_runtime_property_spec
*ihandle
)
1023 /* enter the full path as the init array */
1024 device_add_property(me
, property
, ihandle_property
,
1025 ihandle
->full_path
, strlen(ihandle
->full_path
) + 1,
1027 NULL
, permenant_object
);
1032 device_find_ihandle_runtime_property(device
*me
,
1033 const char *property
,
1034 ihandle_runtime_property_spec
*ihandle
)
1036 device_property_entry
*entry
= find_property_entry(me
, property
);
1037 TRACE(trace_devices
,
1038 ("device_find_ihandle_runtime_property(me=0x%lx, property=%s)\n",
1039 (long)me
, property
));
1041 || entry
->value
->type
!= ihandle_property
1042 || entry
->value
->disposition
!= permenant_object
)
1043 device_error(me
, "property %s not found or of wrong type", property
);
1044 ASSERT(entry
->init_array
!= NULL
);
1046 ihandle
->full_path
= entry
->init_array
;
1053 device_set_ihandle_property(device
*me
,
1054 const char *property
,
1055 device_instance
*ihandle
)
1057 unsigned_cell cells
;
1058 cells
= H2BE_cell(device_instance_to_external(ihandle
));
1059 device_set_property(me
, property
, ihandle_property
,
1060 &cells
, sizeof(cells
));
1066 device_find_ihandle_property(device
*me
,
1067 const char *property
)
1069 const device_property
*node
;
1070 unsigned_cell ihandle
;
1071 device_instance
*instance
;
1073 node
= device_find_property(me
, property
);
1074 if (node
== NULL
|| node
->type
!= ihandle_property
)
1075 device_error(me
, "property %s not found or of wrong type", property
);
1076 if (node
->array
== NULL
)
1077 device_error(me
, "runtime property %s not yet initialized", property
);
1079 ASSERT(sizeof(ihandle
) == node
->sizeof_array
);
1080 memcpy(&ihandle
, node
->array
, sizeof(ihandle
));
1081 instance
= external_to_device_instance(me
, BE2H_cell(ihandle
));
1082 ASSERT(instance
!= NULL
);
1089 device_add_integer_property(device
*me
,
1090 const char *property
,
1091 signed_cell integer
)
1094 device_add_property(me
, property
, integer_property
,
1095 &integer
, sizeof(integer
),
1096 &integer
, sizeof(integer
),
1097 NULL
, permenant_object
);
1102 device_find_integer_property(device
*me
,
1103 const char *property
)
1105 const device_property
*node
;
1106 signed_cell integer
;
1107 TRACE(trace_devices
,
1108 ("device_find_integer(me=0x%lx, property=%s)\n",
1109 (long)me
, property
));
1110 node
= device_find_property(me
, property
);
1111 if (node
== (device_property
*)0
1112 || node
->type
!= integer_property
)
1113 device_error(me
, "property %s not found or of wrong type", property
);
1114 ASSERT(sizeof(integer
) == node
->sizeof_array
);
1115 memcpy(&integer
, node
->array
, sizeof(integer
));
1116 return BE2H_cell(integer
);
1121 device_find_integer_array_property(device
*me
,
1122 const char *property
,
1124 signed_cell
*integer
)
1126 const device_property
*node
;
1127 int sizeof_integer
= sizeof(*integer
);
1129 TRACE(trace_devices
,
1130 ("device_find_integer(me=0x%lx, property=%s)\n",
1131 (long)me
, property
));
1133 /* check things sane */
1134 node
= device_find_property(me
, property
);
1135 if (node
== (device_property
*)0
1136 || (node
->type
!= integer_property
1137 && node
->type
!= array_property
))
1138 device_error(me
, "property %s not found or of wrong type", property
);
1139 if ((node
->sizeof_array
% sizeof_integer
) != 0)
1140 device_error(me
, "property %s contains an incomplete number of cells", property
);
1141 if (node
->sizeof_array
<= sizeof_integer
* index
)
1144 /* Find and convert the value */
1145 cell
= ((signed_cell
*)node
->array
) + index
;
1146 *integer
= BE2H_cell(*cell
);
1148 return node
->sizeof_array
/ sizeof_integer
;
1152 STATIC_INLINE_DEVICE\
1154 unit_address_to_cells(const device_unit
*unit
,
1155 unsigned_cell
*cell
,
1159 ASSERT(nr_cells
== unit
->nr_cells
);
1160 for (i
= 0; i
< unit
->nr_cells
; i
++) {
1161 *cell
= H2BE_cell(unit
->cells
[i
]);
1168 STATIC_INLINE_DEVICE\
1169 (const unsigned_cell
*)
1170 cells_to_unit_address(const unsigned_cell
*cell
,
1175 memset(unit
, 0, sizeof(*unit
));
1176 unit
->nr_cells
= nr_cells
;
1177 for (i
= 0; i
< unit
->nr_cells
; i
++) {
1178 unit
->cells
[i
] = BE2H_cell(*cell
);
1185 STATIC_INLINE_DEVICE\
1187 nr_range_property_cells(device
*me
,
1190 return ((device_nr_address_cells(me
)
1191 + device_nr_address_cells(device_parent(me
))
1192 + device_nr_size_cells(me
))
1198 device_add_range_array_property(device
*me
,
1199 const char *property
,
1200 const range_property_spec
*ranges
,
1203 unsigned sizeof_cells
= (nr_range_property_cells(me
, nr_ranges
)
1204 * sizeof(unsigned_cell
));
1205 unsigned_cell
*cells
= zalloc(sizeof_cells
);
1206 unsigned_cell
*cell
;
1209 /* copy the property elements over */
1211 for (i
= 0; i
< nr_ranges
; i
++) {
1212 const range_property_spec
*range
= &ranges
[i
];
1213 /* copy the child address */
1214 cell
= unit_address_to_cells(&range
->child_address
, cell
,
1215 device_nr_address_cells(me
));
1216 /* copy the parent address */
1217 cell
= unit_address_to_cells(&range
->parent_address
, cell
,
1218 device_nr_address_cells(device_parent(me
)));
1220 cell
= unit_address_to_cells(&range
->size
, cell
,
1221 device_nr_size_cells(me
));
1223 ASSERT(cell
== &cells
[nr_range_property_cells(me
, nr_ranges
)]);
1226 device_add_property(me
, property
, range_array_property
,
1227 cells
, sizeof_cells
,
1228 cells
, sizeof_cells
,
1229 NULL
, permenant_object
);
1236 device_find_range_array_property(device
*me
,
1237 const char *property
,
1239 range_property_spec
*range
)
1241 const device_property
*node
;
1242 unsigned sizeof_entry
= (nr_range_property_cells(me
, 1)
1243 * sizeof(unsigned_cell
));
1244 const unsigned_cell
*cells
;
1246 /* locate the property */
1247 node
= device_find_property(me
, property
);
1248 if (node
== (device_property
*)0
1249 || node
->type
!= range_array_property
)
1250 device_error(me
, "property %s not found or of wrong type", property
);
1253 if ((node
->sizeof_array
% sizeof_entry
) != 0)
1254 device_error(me
, "property %s contains an incomplete number of entries",
1257 /* within bounds? */
1258 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
1261 /* find the range of interest */
1262 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
1264 /* copy the child address out - converting as we go */
1265 cells
= cells_to_unit_address(cells
, &range
->child_address
,
1266 device_nr_address_cells(me
));
1268 /* copy the parent address out - converting as we go */
1269 cells
= cells_to_unit_address(cells
, &range
->parent_address
,
1270 device_nr_address_cells(device_parent(me
)));
1272 /* copy the size - converting as we go */
1273 cells
= cells_to_unit_address(cells
, &range
->size
,
1274 device_nr_size_cells(me
));
1276 return node
->sizeof_array
/ sizeof_entry
;
1280 STATIC_INLINE_DEVICE\
1282 nr_reg_property_cells(device
*me
,
1285 return (device_nr_address_cells(device_parent(me
))
1286 + device_nr_size_cells(device_parent(me
))
1292 device_add_reg_array_property(device
*me
,
1293 const char *property
,
1294 const reg_property_spec
*regs
,
1297 unsigned sizeof_cells
= (nr_reg_property_cells(me
, nr_regs
)
1298 * sizeof(unsigned_cell
));
1299 unsigned_cell
*cells
= zalloc(sizeof_cells
);
1300 unsigned_cell
*cell
;
1303 /* copy the property elements over */
1305 for (i
= 0; i
< nr_regs
; i
++) {
1306 const reg_property_spec
*reg
= ®s
[i
];
1307 /* copy the address */
1308 cell
= unit_address_to_cells(®
->address
, cell
,
1309 device_nr_address_cells(device_parent(me
)));
1311 cell
= unit_address_to_cells(®
->size
, cell
,
1312 device_nr_size_cells(device_parent(me
)));
1314 ASSERT(cell
== &cells
[nr_reg_property_cells(me
, nr_regs
)]);
1317 device_add_property(me
, property
, reg_array_property
,
1318 cells
, sizeof_cells
,
1319 cells
, sizeof_cells
,
1320 NULL
, permenant_object
);
1327 device_find_reg_array_property(device
*me
,
1328 const char *property
,
1330 reg_property_spec
*reg
)
1332 const device_property
*node
;
1333 unsigned sizeof_entry
= (nr_reg_property_cells(me
, 1)
1334 * sizeof(unsigned_cell
));
1335 const unsigned_cell
*cells
;
1337 /* locate the property */
1338 node
= device_find_property(me
, property
);
1339 if (node
== (device_property
*)0
1340 || node
->type
!= reg_array_property
)
1341 device_error(me
, "property %s not found or of wrong type", property
);
1344 if ((node
->sizeof_array
% sizeof_entry
) != 0)
1345 device_error(me
, "property %s contains an incomplete number of entries",
1348 /* within bounds? */
1349 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
1352 /* find the range of interest */
1353 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
1355 /* copy the address out - converting as we go */
1356 cells
= cells_to_unit_address(cells
, ®
->address
,
1357 device_nr_address_cells(device_parent(me
)));
1359 /* copy the size out - converting as we go */
1360 cells
= cells_to_unit_address(cells
, ®
->size
,
1361 device_nr_size_cells(device_parent(me
)));
1363 return node
->sizeof_array
/ sizeof_entry
;
1369 device_add_string_property(device
*me
,
1370 const char *property
,
1373 device_add_property(me
, property
, string_property
,
1374 string
, strlen(string
) + 1,
1375 string
, strlen(string
) + 1,
1376 NULL
, permenant_object
);
1381 device_find_string_property(device
*me
,
1382 const char *property
)
1384 const device_property
*node
;
1386 node
= device_find_property(me
, property
);
1387 if (node
== (device_property
*)0
1388 || node
->type
!= string_property
)
1389 device_error(me
, "property %s not found or of wrong type", property
);
1390 string
= node
->array
;
1391 ASSERT(strlen(string
) + 1 == node
->sizeof_array
);
1397 device_add_string_array_property(device
*me
,
1398 const char *property
,
1399 const string_property_spec
*strings
,
1400 unsigned nr_strings
)
1406 if (nr_strings
== 0)
1407 device_error(me
, "property %s must be non-null", property
);
1408 /* total up the size of the needed array */
1409 for (sizeof_array
= 0, string_nr
= 0;
1410 string_nr
< nr_strings
;
1412 sizeof_array
+= strlen(strings
[string_nr
]) + 1;
1414 /* create the array */
1415 array
= (char*)zalloc(sizeof_array
);
1418 string_nr
< nr_strings
;
1420 strcpy(chp
, strings
[string_nr
]);
1421 chp
+= strlen(chp
) + 1;
1423 ASSERT(chp
== array
+ sizeof_array
);
1425 device_add_property(me
, property
, string_array_property
,
1426 array
, sizeof_array
,
1427 array
, sizeof_array
,
1428 NULL
, permenant_object
);
1433 device_find_string_array_property(device
*me
,
1434 const char *property
,
1436 string_property_spec
*string
)
1438 const device_property
*node
;
1439 node
= device_find_property(me
, property
);
1440 if (node
== (device_property
*)0)
1441 device_error(me
, "property %s not found", property
);
1442 switch (node
->type
) {
1444 device_error(me
, "property %s of wrong type", property
);
1446 case string_property
:
1448 *string
= node
->array
;
1449 ASSERT(strlen(*string
) + 1 == node
->sizeof_array
);
1453 case array_property
:
1454 if (node
->sizeof_array
== 0
1455 || ((char*)node
->array
)[node
->sizeof_array
- 1] != '\0')
1456 device_error(me
, "property %s invalid for string array", property
);
1458 case string_array_property
:
1459 ASSERT(node
->sizeof_array
> 0);
1460 ASSERT(((char*)node
->array
)[node
->sizeof_array
- 1] == '\0');
1462 const char *chp
= node
->array
;
1464 /* count the number of strings, keeping an eye out for the one
1465 we're looking for */
1472 if (nr_entries
== index
)
1478 } while (chp
< (char*)node
->array
+ node
->sizeof_array
);
1479 if (index
< nr_entries
)
1493 device_add_duplicate_property(device
*me
,
1494 const char *property
,
1495 const device_property
*original
)
1497 device_property_entry
*master
;
1498 TRACE(trace_devices
,
1499 ("device_add_duplicate_property(me=0x%lx, property=%s, ...)\n",
1500 (long)me
, property
));
1501 if (original
->disposition
!= permenant_object
)
1502 device_error(me
, "Can only duplicate permenant objects");
1503 /* find the original's master */
1504 master
= original
->owner
->properties
;
1505 while (master
->value
!= original
) {
1506 master
= master
->next
;
1507 ASSERT(master
!= NULL
);
1509 /* now duplicate it */
1510 device_add_property(me
, property
,
1512 master
->init_array
, master
->sizeof_init_array
,
1513 original
->array
, original
->sizeof_array
,
1514 original
, permenant_object
);
1519 /* Device Hardware: */
1523 device_io_read_buffer(device
*me
,
1531 if (me
->callback
->io
.read_buffer
== NULL
)
1532 device_error(me
, "no io.read_buffer method");
1533 return me
->callback
->io
.read_buffer(me
, dest
, space
,
1540 device_io_write_buffer(device
*me
,
1548 if (me
->callback
->io
.write_buffer
== NULL
)
1549 device_error(me
, "no io.write_buffer method");
1550 return me
->callback
->io
.write_buffer(me
, source
, space
,
1557 device_dma_read_buffer(device
*me
,
1563 if (me
->callback
->dma
.read_buffer
== NULL
)
1564 device_error(me
, "no dma.read_buffer method");
1565 return me
->callback
->dma
.read_buffer(me
, dest
, space
,
1571 device_dma_write_buffer(device
*me
,
1576 int violate_read_only_section
)
1578 if (me
->callback
->dma
.write_buffer
== NULL
)
1579 device_error(me
, "no dma.write_buffer method");
1580 return me
->callback
->dma
.write_buffer(me
, source
, space
,
1582 violate_read_only_section
);
1587 device_attach_address(device
*me
,
1593 device
*client
) /*callback/default*/
1595 if (me
->callback
->address
.attach
== NULL
)
1596 device_error(me
, "no address.attach method");
1597 me
->callback
->address
.attach(me
, attach
, space
,
1598 addr
, nr_bytes
, access
, client
);
1603 device_detach_address(device
*me
,
1609 device
*client
) /*callback/default*/
1611 if (me
->callback
->address
.detach
== NULL
)
1612 device_error(me
, "no address.detach method");
1613 me
->callback
->address
.detach(me
, attach
, space
,
1614 addr
, nr_bytes
, access
, client
);
1622 device_interrupt_event(device
*me
,
1628 int found_an_edge
= 0;
1629 device_interrupt_edge
*edge
;
1630 /* device's interrupt lines directly connected */
1631 for (edge
= me
->interrupt_destinations
;
1633 edge
= edge
->next
) {
1634 if (edge
->my_port
== my_port
) {
1635 if (edge
->dest
->callback
->interrupt
.event
== NULL
)
1636 device_error(me
, "no interrupt method");
1637 edge
->dest
->callback
->interrupt
.event(edge
->dest
,
1646 if (!found_an_edge
) {
1647 device_error(me
, "No interrupt edge for port %d", my_port
);
1653 device_interrupt_attach(device
*me
,
1657 object_disposition disposition
)
1659 attach_device_interrupt_edge(&me
->interrupt_destinations
,
1668 device_interrupt_detach(device
*me
,
1673 detach_device_interrupt_edge(me
,
1674 &me
->interrupt_destinations
,
1682 device_interrupt_traverse(device
*me
,
1683 device_interrupt_traverse_function
*handler
,
1686 device_interrupt_edge
*interrupt_edge
;
1687 for (interrupt_edge
= me
->interrupt_destinations
;
1688 interrupt_edge
!= NULL
;
1689 interrupt_edge
= interrupt_edge
->next
) {
1690 handler(me
, interrupt_edge
->my_port
,
1691 interrupt_edge
->dest
, interrupt_edge
->dest_port
,
1698 device_interrupt_decode(device
*me
,
1699 const char *port_name
,
1700 port_direction direction
)
1702 if (port_name
== NULL
|| port_name
[0] == '\0')
1704 if (isdigit(port_name
[0])) {
1705 return strtoul(port_name
, NULL
, 0);
1708 const device_interrupt_port_descriptor
*ports
=
1709 me
->callback
->interrupt
.ports
;
1710 if (ports
!= NULL
) {
1711 while (ports
->name
!= NULL
) {
1712 if (ports
->direction
== bidirect_port
1713 || ports
->direction
== direction
) {
1714 if (ports
->nr_ports
> 0) {
1715 int len
= strlen(ports
->name
);
1716 if (strncmp(port_name
, ports
->name
, len
) == 0) {
1717 if (port_name
[len
] == '\0')
1718 return ports
->number
;
1719 else if(isdigit(port_name
[len
])) {
1720 int port
= ports
->number
+ strtoul(&port_name
[len
], NULL
, 0);
1721 if (port
>= ports
->number
+ ports
->nr_ports
)
1722 device_error(me
, "Interrupt port %s out of range",
1728 else if (strcmp(port_name
, ports
->name
) == 0)
1729 return ports
->number
;
1735 device_error(me
, "Unreconized interrupt port %s", port_name
);
1741 device_interrupt_encode(device
*me
,
1745 port_direction direction
)
1747 const device_interrupt_port_descriptor
*ports
= NULL
;
1748 ports
= me
->callback
->interrupt
.ports
;
1749 if (ports
!= NULL
) {
1750 while (ports
->name
!= NULL
) {
1751 if (ports
->direction
== bidirect_port
1752 || ports
->direction
== direction
) {
1753 if (ports
->nr_ports
> 0) {
1754 if (port_number
>= ports
->number
1755 && port_number
< ports
->number
+ ports
->nr_ports
) {
1756 strcpy(buf
, ports
->name
);
1757 sprintf(buf
+ strlen(buf
), "%d", port_number
- ports
->number
);
1758 if (strlen(buf
) >= sizeof_buf
)
1759 error("device_interrupt_encode: buffer overflow");
1764 if (ports
->number
== port_number
) {
1765 if (strlen(ports
->name
) >= sizeof_buf
)
1766 error("device_interrupt_encode: buffer overflow");
1767 strcpy(buf
, ports
->name
);
1775 sprintf(buf
, "%d", port_number
);
1776 if (strlen(buf
) >= sizeof_buf
)
1777 error("device_interrupt_encode: buffer overflow");
1787 device_ioctl(device
*me
,
1790 device_ioctl_request request
,
1795 va_start(ap
, request
);
1796 if (me
->callback
->ioctl
== NULL
)
1797 device_error(me
, "no ioctl method");
1798 status
= me
->callback
->ioctl(me
, processor
, cia
, request
, ap
);
1809 device_error(device
*me
,
1815 /* format the message */
1817 vsprintf(message
, fmt
, ap
);
1820 if (strlen(message
) >= sizeof(message
))
1821 error("device_error: buffer overflow");
1823 error("device: %s", message
);
1824 else if (me
->path
!= NULL
&& me
->path
[0] != '\0')
1825 error("%s: %s", me
->path
, message
);
1826 else if (me
->name
!= NULL
&& me
->name
[0] != '\0')
1827 error("%s: %s", me
->name
, message
);
1829 error("device: %s", message
);
1835 device_trace(device
*me
)
1841 /* External representation */
1845 external_to_device(device
*tree_member
,
1846 unsigned_cell phandle
)
1848 device
*me
= cap_internal(tree_member
->phandles
, phandle
);
1854 device_to_external(device
*me
)
1856 unsigned_cell phandle
= cap_external(me
->phandles
, me
);
1862 external_to_device_instance(device
*tree_member
,
1863 unsigned_cell ihandle
)
1865 device_instance
*instance
= cap_internal(tree_member
->ihandles
, ihandle
);
1871 device_instance_to_external(device_instance
*instance
)
1873 unsigned_cell ihandle
= cap_external(instance
->owner
->ihandles
, instance
);
1878 /* Map onto the event functions */
1882 device_event_queue_schedule(device
*me
,
1883 signed64 delta_time
,
1884 device_event_handler
*handler
,
1887 return event_queue_schedule(psim_event_queue(me
->system
),
1895 device_event_queue_deschedule(device
*me
,
1896 event_entry_tag event_to_remove
)
1898 event_queue_deschedule(psim_event_queue(me
->system
),
1904 device_event_queue_time(device
*me
)
1906 return event_queue_time(psim_event_queue(me
->system
));
1910 /* Initialization: */
1915 device_clean(device
*me
,
1919 system
= (psim
*)data
;
1920 TRACE(trace_device_init
, ("device_clean - initializing %s", me
->path
));
1921 clean_device_interrupt_edges(&me
->interrupt_destinations
);
1922 clean_device_instances(me
);
1923 clean_device_properties(me
);
1926 /* Device initialization: */
1930 device_init_address(device
*me
,
1933 psim
*system
= (psim
*)data
;
1934 int nr_address_cells
;
1936 TRACE(trace_device_init
, ("device_init_address - initializing %s", me
->path
));
1938 /* ensure the cap database is valid */
1939 if (me
->parent
== NULL
) {
1940 cap_init(me
->ihandles
);
1941 cap_init(me
->phandles
);
1945 me
->system
= system
; /* misc things not known until now */
1946 me
->trace
= (device_find_property(me
, "trace")
1947 ? device_find_integer_property(me
, "trace")
1950 /* Ensure that the first address found in the reg property matches
1951 anything that was specified as part of the devices name */
1952 if (device_find_property(me
, "reg") != NULL
) {
1953 reg_property_spec unit
;
1954 device_find_reg_array_property(me
, "reg", 0, &unit
);
1955 if (memcmp(device_unit_address(me
), &unit
.address
, sizeof(unit
.address
))
1957 device_error(me
, "Unit address as specified by the reg property in conflict with the value previously specified in the devices path");
1960 /* ensure that the devices #address/size-cells is consistent */
1961 nr_address_cells
= device_nr_address_cells(me
);
1962 if (device_find_property(me
, "#address-cells") != NULL
1963 && (nr_address_cells
1964 != device_find_integer_property(me
, "#address-cells")))
1965 device_error(me
, "#address-cells property used before defined");
1966 nr_size_cells
= device_nr_size_cells(me
);
1967 if (device_find_property(me
, "#size-cells") != NULL
1969 != device_find_integer_property(me
, "#size-cells")))
1970 device_error(me
, "#size-cells property used before defined");
1973 if (me
->callback
->init
.address
!= NULL
)
1974 me
->callback
->init
.address(me
);
1979 device_init_data(device
*me
,
1982 TRACE(trace_device_init
, ("device_init_data - initializing %s", me
->path
));
1983 if (me
->callback
->init
.data
!= NULL
)
1984 me
->callback
->init
.data(me
);
1987 #endif /* _DEVICE_C_ */