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/>.
24 /* This must come before any other includes. */
29 #include "device_table.h"
39 STATIC_INLINE_DEVICE (void) clean_device_properties(device
*);
41 /* property entries */
43 typedef struct _device_property_entry device_property_entry
;
44 struct _device_property_entry
{
45 device_property_entry
*next
;
46 device_property
*value
;
47 const void *init_array
;
48 unsigned sizeof_init_array
;
54 typedef struct _device_interrupt_edge device_interrupt_edge
;
55 struct _device_interrupt_edge
{
59 device_interrupt_edge
*next
;
60 object_disposition disposition
;
65 attach_device_interrupt_edge(device_interrupt_edge
**list
,
69 object_disposition disposition
)
71 device_interrupt_edge
*new_edge
= ZALLOC(device_interrupt_edge
);
72 new_edge
->my_port
= my_port
;
73 new_edge
->dest
= dest
;
74 new_edge
->dest_port
= dest_port
;
75 new_edge
->next
= *list
;
76 new_edge
->disposition
= disposition
;
82 detach_device_interrupt_edge(device
*me
,
83 device_interrupt_edge
**list
,
88 while (*list
!= NULL
) {
89 device_interrupt_edge
*old_edge
= *list
;
90 if (old_edge
->dest
== dest
91 && old_edge
->dest_port
== dest_port
92 && old_edge
->my_port
== my_port
) {
93 if (old_edge
->disposition
== permenant_object
)
94 device_error(me
, "attempt to delete permenant interrupt");
95 *list
= old_edge
->next
;
100 device_error(me
, "attempt to delete unattached interrupt");
103 STATIC_INLINE_DEVICE\
105 clean_device_interrupt_edges(device_interrupt_edge
**list
)
107 while (*list
!= NULL
) {
108 device_interrupt_edge
*old_edge
= *list
;
109 switch (old_edge
->disposition
) {
110 case permenant_object
:
111 list
= &old_edge
->next
;
113 case tempoary_object
:
114 *list
= old_edge
->next
;
128 device_unit unit_address
;
130 int nr_address_cells
;
138 /* its template methods */
139 void *data
; /* device specific data */
140 const device_callbacks
*callback
;
142 /* device properties */
143 device_property_entry
*properties
;
146 device_interrupt_edge
*interrupt_destinations
;
148 /* any open instances of this device */
149 device_instance
*instances
;
151 /* the internal/external mappings and other global requirements */
161 /* an instance of a device */
162 struct _device_instance
{
166 const device_instance_callbacks
*callback
;
167 /* the root instance */
169 device_instance
*next
;
170 /* interposed instance */
171 device_instance
*parent
;
172 device_instance
*child
;
179 STATIC_INLINE_DEVICE\
181 device_full_name(device
*leaf
,
188 buf
= malloc(sizeof_buf
);
191 /* construct a name */
192 if (leaf
->parent
== NULL
) {
194 error("device_full_name: buffer overflow");
199 device_full_name(leaf
->parent
, buf
, sizeof_buf
);
200 if (leaf
->parent
!= NULL
201 && device_encode_unit(leaf
->parent
,
208 if (strlen(buf
) + strlen("/") + strlen(leaf
->name
) + strlen(unit
)
210 error("device_full_name: buffer overflow");
212 strcat(buf
, leaf
->name
);
219 STATIC_INLINE_DEVICE\
221 device_create_from(const char *name
,
222 const device_unit
*unit_address
,
224 const device_callbacks
*callbacks
,
227 device
*new_device
= ZALLOC(device
);
229 /* insert it into the device tree */
230 new_device
->parent
= parent
;
231 new_device
->children
= NULL
;
232 if (parent
!= NULL
) {
233 device
**sibling
= &parent
->children
;
234 while ((*sibling
) != NULL
)
235 sibling
= &(*sibling
)->sibling
;
236 *sibling
= new_device
;
240 new_device
->name
= (char *) strdup(name
);
241 new_device
->unit_address
= *unit_address
;
242 new_device
->path
= device_full_name(new_device
, NULL
, 0);
245 new_device
->data
= data
;
246 new_device
->callback
= callbacks
;
248 /* its properties - already null */
249 /* interrupts - already null */
251 /* mappings - if needed */
252 if (parent
== NULL
) {
253 new_device
->ihandles
= cap_create(name
);
254 new_device
->phandles
= cap_create(name
);
257 new_device
->ihandles
= device_root(parent
)->ihandles
;
258 new_device
->phandles
= device_root(parent
)->phandles
;
261 cap_add(new_device
->phandles
, new_device
);
269 device_create(device
*parent
,
272 const char *unit_address
,
275 const device_descriptor
*const *table
;
276 for (table
= device_table
; *table
!= NULL
; table
++) {
277 const device_descriptor
*descr
;
278 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
279 if (strcmp(base
, descr
->name
) == 0) {
280 device_unit address
= { 0 };
283 if (device_decode_unit(parent
, unit_address
, &address
) < 0)
284 device_error(parent
, "invalid address %s for device %s",
286 if (descr
->creator
!= NULL
)
287 data
= descr
->creator(name
, &address
, args
);
288 return device_create_from(name
, &address
, data
,
289 descr
->callbacks
, parent
);
293 device_error(parent
, "attempt to attach unknown device %s", name
);
301 device_usage(int verbose
)
303 const device_descriptor
*const *table
;
306 for (table
= device_table
; *table
!= NULL
; table
++) {
307 const device_descriptor
*descr
;
308 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
309 pos
+= strlen(descr
->name
) + 2;
311 pos
= strlen(descr
->name
) + 2;
312 printf_filtered("\n");
314 printf_filtered(" %s", descr
->name
);
316 printf_filtered("\n");
320 for (table
= device_table
; *table
!= NULL
; table
++) {
321 const device_descriptor
*descr
;
322 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
323 printf_filtered(" %s:\n", descr
->name
);
324 /* interrupt ports */
325 if (descr
->callbacks
->interrupt
.ports
!= NULL
) {
326 const device_interrupt_port_descriptor
*ports
=
327 descr
->callbacks
->interrupt
.ports
;
328 printf_filtered(" interrupt ports:");
329 while (ports
->name
!= NULL
) {
330 printf_filtered(" %s", ports
->name
);
333 printf_filtered("\n");
336 if (descr
->callbacks
->usage
!= NULL
)
337 descr
->callbacks
->usage(verbose
);
351 device_parent(device
*me
)
358 device_root(device
*me
)
361 while (me
->parent
!= NULL
)
368 device_sibling(device
*me
)
375 device_child(device
*me
)
382 device_name(device
*me
)
389 device_path(device
*me
)
396 device_data(device
*me
)
403 device_system(device
*me
)
409 (const device_unit
*)
410 device_unit_address(device
*me
)
412 return &me
->unit_address
;
418 device_address_to_attach_address(device
*me
,
419 const device_unit
*address
,
421 unsigned_word
*attach_address
,
424 if (me
->callback
->convert
.address_to_attach_address
== NULL
)
425 device_error(me
, "no convert.address_to_attach_address method");
426 return me
->callback
->convert
.address_to_attach_address(me
, address
, attach_space
, attach_address
, client
);
432 device_size_to_attach_size(device
*me
,
433 const device_unit
*size
,
437 if (me
->callback
->convert
.size_to_attach_size
== NULL
)
438 device_error(me
, "no convert.size_to_attach_size method");
439 return me
->callback
->convert
.size_to_attach_size(me
, size
, nr_bytes
, client
);
445 device_decode_unit(device
*bus
,
447 device_unit
*address
)
449 if (bus
->callback
->convert
.decode_unit
== NULL
)
450 device_error(bus
, "no convert.decode_unit method");
451 return bus
->callback
->convert
.decode_unit(bus
, unit
, address
);
457 device_encode_unit(device
*bus
,
458 const device_unit
*unit_address
,
462 if (bus
->callback
->convert
.encode_unit
== NULL
)
463 device_error(bus
, "no convert.encode_unit method");
464 return bus
->callback
->convert
.encode_unit(bus
, unit_address
, buf
, sizeof_buf
);
469 device_nr_address_cells(device
*me
)
471 if (me
->nr_address_cells
== 0) {
472 if (device_find_property(me
, "#address-cells") != NULL
)
473 me
->nr_address_cells
= device_find_integer_property(me
, "#address-cells");
475 me
->nr_address_cells
= 2;
477 return me
->nr_address_cells
;
482 device_nr_size_cells(device
*me
)
484 if (me
->nr_size_cells
== 0) {
485 if (device_find_property(me
, "#size-cells") != NULL
)
486 me
->nr_size_cells
= device_find_integer_property(me
, "#size-cells");
488 me
->nr_size_cells
= 1;
490 return me
->nr_size_cells
;
495 /* device-instance: */
499 device_create_instance_from(device
*me
,
500 device_instance
*parent
,
504 const device_instance_callbacks
*callbacks
)
506 device_instance
*instance
= ZALLOC(device_instance
);
507 if ((me
== NULL
) == (parent
== NULL
))
508 device_error(me
, "can't have both parent instance and parent device");
510 /* link this instance into the devices list */
512 ASSERT(parent
== NULL
);
513 instance
->owner
= me
;
514 instance
->parent
= NULL
;
515 /* link this instance into the front of the devices instance list */
516 instance
->next
= me
->instances
;
517 me
->instances
= instance
;
519 if (parent
!= NULL
) {
520 device_instance
**previous
;
521 ASSERT(parent
->child
== NULL
);
522 parent
->child
= instance
;
524 instance
->owner
= parent
->owner
;
525 instance
->parent
= parent
;
526 /* in the devices instance list replace the parent instance with
528 instance
->next
= parent
->next
;
529 /* replace parent with this new node */
530 previous
= &instance
->owner
->instances
;
531 while (*previous
!= parent
) {
532 ASSERT(*previous
!= NULL
);
533 previous
= &(*previous
)->next
;
535 *previous
= instance
;
537 instance
->data
= data
;
538 instance
->args
= (args
== NULL
? NULL
: (char *) strdup(args
));
539 instance
->path
= (path
== NULL
? NULL
: (char *) strdup(path
));
540 instance
->callback
= callbacks
;
541 cap_add(instance
->owner
->ihandles
, instance
);
548 device_create_instance(device
*me
,
552 /* create the instance */
553 if (me
->callback
->instance_create
== NULL
)
554 device_error(me
, "no instance_create method");
555 return me
->callback
->instance_create(me
, path
, args
);
559 STATIC_INLINE_DEVICE\
561 clean_device_instances(device
*me
)
563 device_instance
**instance
= &me
->instances
;
564 while (*instance
!= NULL
) {
565 device_instance
*old_instance
= *instance
;
566 device_instance_delete(old_instance
);
567 instance
= &me
->instances
;
574 device_instance_delete(device_instance
*instance
)
576 device
*me
= instance
->owner
;
577 if (instance
->callback
->delete == NULL
)
578 device_error(me
, "no delete method");
579 instance
->callback
->delete(instance
);
580 if (instance
->args
!= NULL
)
581 free(instance
->args
);
582 if (instance
->path
!= NULL
)
583 free(instance
->path
);
584 if (instance
->child
== NULL
) {
585 /* only remove leaf nodes */
586 device_instance
**curr
= &me
->instances
;
587 while (*curr
!= instance
) {
588 ASSERT(*curr
!= NULL
);
589 curr
= &(*curr
)->next
;
591 *curr
= instance
->next
;
594 /* check it isn't in the instance list */
595 device_instance
*curr
= me
->instances
;
596 while (curr
!= NULL
) {
597 ASSERT(curr
!= instance
);
600 /* unlink the child */
601 ASSERT(instance
->child
->parent
== instance
);
602 instance
->child
->parent
= NULL
;
604 cap_remove(me
->ihandles
, instance
);
610 device_instance_read(device_instance
*instance
,
614 device
*me
= instance
->owner
;
615 if (instance
->callback
->read
== NULL
)
616 device_error(me
, "no read method");
617 return instance
->callback
->read(instance
, addr
, len
);
622 device_instance_write(device_instance
*instance
,
626 device
*me
= instance
->owner
;
627 if (instance
->callback
->write
== NULL
)
628 device_error(me
, "no write method");
629 return instance
->callback
->write(instance
, addr
, len
);
634 device_instance_seek(device_instance
*instance
,
635 unsigned_word pos_hi
,
636 unsigned_word pos_lo
)
638 device
*me
= instance
->owner
;
639 if (instance
->callback
->seek
== NULL
)
640 device_error(me
, "no seek method");
641 return instance
->callback
->seek(instance
, pos_hi
, pos_lo
);
646 device_instance_call_method(device_instance
*instance
,
647 const char *method_name
,
649 unsigned_cell stack_args
[/*n_stack_args*/],
651 unsigned_cell stack_returns
[/*n_stack_args*/])
653 device
*me
= instance
->owner
;
654 const device_instance_methods
*method
= instance
->callback
->methods
;
655 if (method
== NULL
) {
656 device_error(me
, "no methods (want %s)", method_name
);
658 while (method
->name
!= NULL
) {
659 if (strcmp(method
->name
, method_name
) == 0) {
660 return method
->method(instance
,
661 n_stack_args
, stack_args
,
662 n_stack_returns
, stack_returns
);
666 device_error(me
, "no %s method", method_name
);
673 device_instance_device(device_instance
*instance
)
675 return instance
->owner
;
680 device_instance_path(device_instance
*instance
)
682 return instance
->path
;
687 device_instance_data(device_instance
*instance
)
689 return instance
->data
;
694 /* Device Properties: */
696 STATIC_INLINE_DEVICE\
697 (device_property_entry
*)
698 find_property_entry(device
*me
,
699 const char *property
)
701 device_property_entry
*entry
;
702 ASSERT(property
!= NULL
);
703 entry
= me
->properties
;
704 while (entry
!= NULL
) {
705 if (strcmp(entry
->value
->name
, property
) == 0)
712 STATIC_INLINE_DEVICE\
714 device_add_property(device
*me
,
715 const char *property
,
716 device_property_type type
,
717 const void *init_array
,
718 unsigned sizeof_init_array
,
720 unsigned sizeof_array
,
721 const device_property
*original
,
722 object_disposition disposition
)
724 device_property_entry
*new_entry
= NULL
;
725 device_property
*new_value
= NULL
;
727 /* find the list end */
728 device_property_entry
**insertion_point
= &me
->properties
;
729 while (*insertion_point
!= NULL
) {
730 if (strcmp((*insertion_point
)->value
->name
, property
) == 0)
732 insertion_point
= &(*insertion_point
)->next
;
735 /* create a new value */
736 new_value
= ZALLOC(device_property
);
737 new_value
->name
= (char *) strdup(property
);
738 new_value
->type
= type
;
739 if (sizeof_array
> 0) {
740 void *new_array
= zalloc(sizeof_array
);
741 memcpy(new_array
, array
, sizeof_array
);
742 new_value
->array
= new_array
;
743 new_value
->sizeof_array
= sizeof_array
;
745 new_value
->owner
= me
;
746 new_value
->original
= original
;
747 new_value
->disposition
= disposition
;
749 /* insert the value into the list */
750 new_entry
= ZALLOC(device_property_entry
);
751 *insertion_point
= new_entry
;
752 if (sizeof_init_array
> 0) {
753 void *new_init_array
= zalloc(sizeof_init_array
);
754 memcpy(new_init_array
, init_array
, sizeof_init_array
);
755 new_entry
->init_array
= new_init_array
;
756 new_entry
->sizeof_init_array
= sizeof_init_array
;
758 new_entry
->value
= new_value
;
762 /* local - not available externally */
763 STATIC_INLINE_DEVICE\
765 device_set_property(device
*me
,
766 const char *property
,
767 device_property_type type
,
771 /* find the property */
772 device_property_entry
*entry
= find_property_entry(me
, property
);
774 /* existing property - update it */
776 device_property
*value
= entry
->value
;
777 /* check the type matches */
778 if (value
->type
!= type
)
779 device_error(me
, "conflict between type of new and old value for property %s", property
);
780 /* replace its value */
781 if (value
->array
!= NULL
)
782 free((void*)value
->array
);
783 new_array
= (sizeof_array
> 0
784 ? zalloc(sizeof_array
)
786 value
->array
= new_array
;
787 value
->sizeof_array
= sizeof_array
;
788 if (sizeof_array
> 0)
789 memcpy(new_array
, array
, sizeof_array
);
793 /* new property - create it */
794 device_add_property(me
, property
, type
,
795 NULL
, 0, array
, sizeof_array
,
796 NULL
, tempoary_object
);
801 STATIC_INLINE_DEVICE\
803 clean_device_properties(device
*me
)
805 device_property_entry
**delete_point
= &me
->properties
;
806 while (*delete_point
!= NULL
) {
807 device_property_entry
*current
= *delete_point
;
808 switch (current
->value
->disposition
) {
809 case permenant_object
:
810 /* zap the current value, will be initialized later */
811 ASSERT(current
->init_array
!= NULL
);
812 if (current
->value
->array
!= NULL
) {
813 free((void*)current
->value
->array
);
814 current
->value
->array
= NULL
;
816 delete_point
= &(*delete_point
)->next
;
818 case tempoary_object
:
819 /* zap the actual property, was created during simulation run */
820 ASSERT(current
->init_array
== NULL
);
821 *delete_point
= current
->next
;
822 if (current
->value
->array
!= NULL
)
823 free((void*)current
->value
->array
);
824 free(current
->value
);
834 device_init_static_properties(device
*me
,
837 device_property_entry
*property
;
838 for (property
= me
->properties
;
840 property
= property
->next
) {
841 ASSERT(property
->init_array
!= NULL
);
842 ASSERT(property
->value
->array
== NULL
);
843 ASSERT(property
->value
->disposition
== permenant_object
);
844 switch (property
->value
->type
) {
846 case boolean_property
:
847 case range_array_property
:
848 case reg_array_property
:
849 case string_property
:
850 case string_array_property
:
851 case integer_property
:
852 /* delete the property, and replace it with the original */
853 device_set_property(me
, property
->value
->name
,
854 property
->value
->type
,
855 property
->init_array
,
856 property
->sizeof_init_array
);
858 case ihandle_property
:
867 device_init_runtime_properties(device
*me
,
870 device_property_entry
*property
;
871 for (property
= me
->properties
;
873 property
= property
->next
) {
874 switch (property
->value
->disposition
) {
875 case permenant_object
:
876 switch (property
->value
->type
) {
877 case ihandle_property
:
879 device_instance
*ihandle
;
880 ihandle_runtime_property_spec spec
;
881 ASSERT(property
->init_array
!= NULL
);
882 ASSERT(property
->value
->array
== NULL
);
883 device_find_ihandle_runtime_property(me
, property
->value
->name
, &spec
);
884 ihandle
= tree_instance(me
, spec
.full_path
);
885 device_set_ihandle_property(me
, property
->value
->name
, ihandle
);
889 case boolean_property
:
890 case range_array_property
:
891 case integer_property
:
892 case reg_array_property
:
893 case string_property
:
894 case string_array_property
:
895 ASSERT(property
->init_array
!= NULL
);
896 ASSERT(property
->value
->array
!= NULL
);
900 case tempoary_object
:
901 ASSERT(property
->init_array
== NULL
);
902 ASSERT(property
->value
->array
!= NULL
);
910 (const device_property
*)
911 device_next_property(const device_property
*property
)
913 /* find the property in the list */
914 device
*owner
= property
->owner
;
915 device_property_entry
*entry
= owner
->properties
;
916 while (entry
!= NULL
&& entry
->value
!= property
)
918 /* now return the following property */
919 ASSERT(entry
!= NULL
); /* must be a member! */
920 if (entry
->next
!= NULL
)
921 return entry
->next
->value
;
928 (const device_property
*)
929 device_find_property(device
*me
,
930 const char *property
)
935 else if (property
== NULL
|| strcmp(property
, "") == 0) {
936 if (me
->properties
== NULL
)
939 return me
->properties
->value
;
942 device_property_entry
*entry
= find_property_entry(me
, property
);
952 device_add_array_property(device
*me
,
953 const char *property
,
957 device_add_property(me
, property
, array_property
,
958 array
, sizeof_array
, array
, sizeof_array
,
959 NULL
, permenant_object
);
964 device_set_array_property(device
*me
,
965 const char *property
,
969 device_set_property(me
, property
, array_property
, array
, sizeof_array
);
973 (const device_property
*)
974 device_find_array_property(device
*me
,
975 const char *property
)
977 const device_property
*node
;
978 node
= device_find_property(me
, property
);
979 if (node
== (device_property
*)0
980 || node
->type
!= array_property
)
981 device_error(me
, "property %s not found or of wrong type", property
);
988 device_add_boolean_property(device
*me
,
989 const char *property
,
992 int32_t new_boolean
= (boolean
? -1 : 0);
993 device_add_property(me
, property
, boolean_property
,
994 &new_boolean
, sizeof(new_boolean
),
995 &new_boolean
, sizeof(new_boolean
),
996 NULL
, permenant_object
);
1001 device_find_boolean_property(device
*me
,
1002 const char *property
)
1004 const device_property
*node
;
1005 unsigned_cell boolean
;
1006 node
= device_find_property(me
, property
);
1007 if (node
== (device_property
*)0
1008 || node
->type
!= boolean_property
)
1009 device_error(me
, "property %s not found or of wrong type", property
);
1010 ASSERT(sizeof(boolean
) == node
->sizeof_array
);
1011 memcpy(&boolean
, node
->array
, sizeof(boolean
));
1018 device_add_ihandle_runtime_property(device
*me
,
1019 const char *property
,
1020 const ihandle_runtime_property_spec
*ihandle
)
1022 /* enter the full path as the init array */
1023 device_add_property(me
, property
, ihandle_property
,
1024 ihandle
->full_path
, strlen(ihandle
->full_path
) + 1,
1026 NULL
, permenant_object
);
1031 device_find_ihandle_runtime_property(device
*me
,
1032 const char *property
,
1033 ihandle_runtime_property_spec
*ihandle
)
1035 device_property_entry
*entry
= find_property_entry(me
, property
);
1036 TRACE(trace_devices
,
1037 ("device_find_ihandle_runtime_property(me=%p, property=%s)\n",
1040 || entry
->value
->type
!= ihandle_property
1041 || entry
->value
->disposition
!= permenant_object
)
1042 device_error(me
, "property %s not found or of wrong type", property
);
1043 ASSERT(entry
->init_array
!= NULL
);
1045 ihandle
->full_path
= entry
->init_array
;
1052 device_set_ihandle_property(device
*me
,
1053 const char *property
,
1054 device_instance
*ihandle
)
1056 unsigned_cell cells
;
1057 cells
= H2BE_cell(device_instance_to_external(ihandle
));
1058 device_set_property(me
, property
, ihandle_property
,
1059 &cells
, sizeof(cells
));
1065 device_find_ihandle_property(device
*me
,
1066 const char *property
)
1068 const device_property
*node
;
1069 unsigned_cell ihandle
;
1070 device_instance
*instance
;
1072 node
= device_find_property(me
, property
);
1073 if (node
== NULL
|| node
->type
!= ihandle_property
)
1074 device_error(me
, "property %s not found or of wrong type", property
);
1075 if (node
->array
== NULL
)
1076 device_error(me
, "runtime property %s not yet initialized", property
);
1078 ASSERT(sizeof(ihandle
) == node
->sizeof_array
);
1079 memcpy(&ihandle
, node
->array
, sizeof(ihandle
));
1080 instance
= external_to_device_instance(me
, BE2H_cell(ihandle
));
1081 ASSERT(instance
!= NULL
);
1088 device_add_integer_property(device
*me
,
1089 const char *property
,
1090 signed_cell integer
)
1093 device_add_property(me
, property
, integer_property
,
1094 &integer
, sizeof(integer
),
1095 &integer
, sizeof(integer
),
1096 NULL
, permenant_object
);
1101 device_find_integer_property(device
*me
,
1102 const char *property
)
1104 const device_property
*node
;
1105 signed_cell integer
;
1106 TRACE(trace_devices
,
1107 ("device_find_integer(me=%p, property=%s)\n",
1109 node
= device_find_property(me
, property
);
1110 if (node
== (device_property
*)0
1111 || node
->type
!= integer_property
)
1112 device_error(me
, "property %s not found or of wrong type", property
);
1113 ASSERT(sizeof(integer
) == node
->sizeof_array
);
1114 memcpy(&integer
, node
->array
, sizeof(integer
));
1115 return BE2H_cell(integer
);
1120 device_find_integer_array_property(device
*me
,
1121 const char *property
,
1123 signed_cell
*integer
)
1125 const device_property
*node
;
1126 int sizeof_integer
= sizeof(*integer
);
1128 TRACE(trace_devices
,
1129 ("device_find_integer(me=%p, property=%s)\n",
1132 /* check things sane */
1133 node
= device_find_property(me
, property
);
1134 if (node
== (device_property
*)0
1135 || (node
->type
!= integer_property
1136 && node
->type
!= array_property
))
1137 device_error(me
, "property %s not found or of wrong type", property
);
1138 if ((node
->sizeof_array
% sizeof_integer
) != 0)
1139 device_error(me
, "property %s contains an incomplete number of cells", property
);
1140 if (node
->sizeof_array
<= sizeof_integer
* index
)
1143 /* Find and convert the value */
1144 cell
= ((signed_cell
*)node
->array
) + index
;
1145 *integer
= BE2H_cell(*cell
);
1147 return node
->sizeof_array
/ sizeof_integer
;
1151 STATIC_INLINE_DEVICE\
1153 unit_address_to_cells(const device_unit
*unit
,
1154 unsigned_cell
*cell
,
1158 ASSERT(nr_cells
== unit
->nr_cells
);
1159 for (i
= 0; i
< unit
->nr_cells
; i
++) {
1160 *cell
= H2BE_cell(unit
->cells
[i
]);
1167 STATIC_INLINE_DEVICE\
1168 (const unsigned_cell
*)
1169 cells_to_unit_address(const unsigned_cell
*cell
,
1174 memset(unit
, 0, sizeof(*unit
));
1175 unit
->nr_cells
= nr_cells
;
1176 for (i
= 0; i
< unit
->nr_cells
; i
++) {
1177 unit
->cells
[i
] = BE2H_cell(*cell
);
1184 STATIC_INLINE_DEVICE\
1186 nr_range_property_cells(device
*me
,
1189 return ((device_nr_address_cells(me
)
1190 + device_nr_address_cells(device_parent(me
))
1191 + device_nr_size_cells(me
))
1197 device_add_range_array_property(device
*me
,
1198 const char *property
,
1199 const range_property_spec
*ranges
,
1202 unsigned sizeof_cells
= (nr_range_property_cells(me
, nr_ranges
)
1203 * sizeof(unsigned_cell
));
1204 unsigned_cell
*cells
= zalloc(sizeof_cells
);
1205 unsigned_cell
*cell
;
1208 /* copy the property elements over */
1210 for (i
= 0; i
< nr_ranges
; i
++) {
1211 const range_property_spec
*range
= &ranges
[i
];
1212 /* copy the child address */
1213 cell
= unit_address_to_cells(&range
->child_address
, cell
,
1214 device_nr_address_cells(me
));
1215 /* copy the parent address */
1216 cell
= unit_address_to_cells(&range
->parent_address
, cell
,
1217 device_nr_address_cells(device_parent(me
)));
1219 cell
= unit_address_to_cells(&range
->size
, cell
,
1220 device_nr_size_cells(me
));
1222 ASSERT(cell
== &cells
[nr_range_property_cells(me
, nr_ranges
)]);
1225 device_add_property(me
, property
, range_array_property
,
1226 cells
, sizeof_cells
,
1227 cells
, sizeof_cells
,
1228 NULL
, permenant_object
);
1235 device_find_range_array_property(device
*me
,
1236 const char *property
,
1238 range_property_spec
*range
)
1240 const device_property
*node
;
1241 unsigned sizeof_entry
= (nr_range_property_cells(me
, 1)
1242 * sizeof(unsigned_cell
));
1243 const unsigned_cell
*cells
;
1245 /* locate the property */
1246 node
= device_find_property(me
, property
);
1247 if (node
== (device_property
*)0
1248 || node
->type
!= range_array_property
)
1249 device_error(me
, "property %s not found or of wrong type", property
);
1252 if ((node
->sizeof_array
% sizeof_entry
) != 0)
1253 device_error(me
, "property %s contains an incomplete number of entries",
1256 /* within bounds? */
1257 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
1260 /* find the range of interest */
1261 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
1263 /* copy the child address out - converting as we go */
1264 cells
= cells_to_unit_address(cells
, &range
->child_address
,
1265 device_nr_address_cells(me
));
1267 /* copy the parent address out - converting as we go */
1268 cells
= cells_to_unit_address(cells
, &range
->parent_address
,
1269 device_nr_address_cells(device_parent(me
)));
1271 /* copy the size - converting as we go */
1272 cells
= cells_to_unit_address(cells
, &range
->size
,
1273 device_nr_size_cells(me
));
1275 return node
->sizeof_array
/ sizeof_entry
;
1279 STATIC_INLINE_DEVICE\
1281 nr_reg_property_cells(device
*me
,
1284 return (device_nr_address_cells(device_parent(me
))
1285 + device_nr_size_cells(device_parent(me
))
1291 device_add_reg_array_property(device
*me
,
1292 const char *property
,
1293 const reg_property_spec
*regs
,
1296 unsigned sizeof_cells
= (nr_reg_property_cells(me
, nr_regs
)
1297 * sizeof(unsigned_cell
));
1298 unsigned_cell
*cells
= zalloc(sizeof_cells
);
1299 unsigned_cell
*cell
;
1302 /* copy the property elements over */
1304 for (i
= 0; i
< nr_regs
; i
++) {
1305 const reg_property_spec
*reg
= ®s
[i
];
1306 /* copy the address */
1307 cell
= unit_address_to_cells(®
->address
, cell
,
1308 device_nr_address_cells(device_parent(me
)));
1310 cell
= unit_address_to_cells(®
->size
, cell
,
1311 device_nr_size_cells(device_parent(me
)));
1313 ASSERT(cell
== &cells
[nr_reg_property_cells(me
, nr_regs
)]);
1316 device_add_property(me
, property
, reg_array_property
,
1317 cells
, sizeof_cells
,
1318 cells
, sizeof_cells
,
1319 NULL
, permenant_object
);
1326 device_find_reg_array_property(device
*me
,
1327 const char *property
,
1329 reg_property_spec
*reg
)
1331 const device_property
*node
;
1332 unsigned sizeof_entry
= (nr_reg_property_cells(me
, 1)
1333 * sizeof(unsigned_cell
));
1334 const unsigned_cell
*cells
;
1336 /* locate the property */
1337 node
= device_find_property(me
, property
);
1338 if (node
== (device_property
*)0
1339 || node
->type
!= reg_array_property
)
1340 device_error(me
, "property %s not found or of wrong type", property
);
1343 if ((node
->sizeof_array
% sizeof_entry
) != 0)
1344 device_error(me
, "property %s contains an incomplete number of entries",
1347 /* within bounds? */
1348 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
1351 /* find the range of interest */
1352 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
1354 /* copy the address out - converting as we go */
1355 cells
= cells_to_unit_address(cells
, ®
->address
,
1356 device_nr_address_cells(device_parent(me
)));
1358 /* copy the size out - converting as we go */
1359 cells
= cells_to_unit_address(cells
, ®
->size
,
1360 device_nr_size_cells(device_parent(me
)));
1362 return node
->sizeof_array
/ sizeof_entry
;
1368 device_add_string_property(device
*me
,
1369 const char *property
,
1372 device_add_property(me
, property
, string_property
,
1373 string
, strlen(string
) + 1,
1374 string
, strlen(string
) + 1,
1375 NULL
, permenant_object
);
1380 device_find_string_property(device
*me
,
1381 const char *property
)
1383 const device_property
*node
;
1385 node
= device_find_property(me
, property
);
1386 if (node
== (device_property
*)0
1387 || node
->type
!= string_property
)
1388 device_error(me
, "property %s not found or of wrong type", property
);
1389 string
= node
->array
;
1390 ASSERT(strlen(string
) + 1 == node
->sizeof_array
);
1396 device_add_string_array_property(device
*me
,
1397 const char *property
,
1398 const string_property_spec
*strings
,
1399 unsigned nr_strings
)
1405 if (nr_strings
== 0)
1406 device_error(me
, "property %s must be non-null", property
);
1407 /* total up the size of the needed array */
1408 for (sizeof_array
= 0, string_nr
= 0;
1409 string_nr
< nr_strings
;
1411 sizeof_array
+= strlen(strings
[string_nr
]) + 1;
1413 /* create the array */
1414 array
= (char*)zalloc(sizeof_array
);
1417 string_nr
< nr_strings
;
1419 strcpy(chp
, strings
[string_nr
]);
1420 chp
+= strlen(chp
) + 1;
1422 ASSERT(chp
== array
+ sizeof_array
);
1424 device_add_property(me
, property
, string_array_property
,
1425 array
, sizeof_array
,
1426 array
, sizeof_array
,
1427 NULL
, permenant_object
);
1432 device_find_string_array_property(device
*me
,
1433 const char *property
,
1435 string_property_spec
*string
)
1437 const device_property
*node
;
1438 node
= device_find_property(me
, property
);
1439 if (node
== (device_property
*)0)
1440 device_error(me
, "property %s not found", property
);
1441 switch (node
->type
) {
1443 device_error(me
, "property %s of wrong type", property
);
1445 case string_property
:
1447 *string
= node
->array
;
1448 ASSERT(strlen(*string
) + 1 == node
->sizeof_array
);
1452 case array_property
:
1453 if (node
->sizeof_array
== 0
1454 || ((char*)node
->array
)[node
->sizeof_array
- 1] != '\0')
1455 device_error(me
, "property %s invalid for string array", property
);
1457 case string_array_property
:
1458 ASSERT(node
->sizeof_array
> 0);
1459 ASSERT(((char*)node
->array
)[node
->sizeof_array
- 1] == '\0');
1461 const char *chp
= node
->array
;
1463 /* count the number of strings, keeping an eye out for the one
1464 we're looking for */
1471 if (nr_entries
== index
)
1477 } while (chp
< (char*)node
->array
+ node
->sizeof_array
);
1478 if (index
< nr_entries
)
1492 device_add_duplicate_property(device
*me
,
1493 const char *property
,
1494 const device_property
*original
)
1496 device_property_entry
*master
;
1497 TRACE(trace_devices
,
1498 ("device_add_duplicate_property(me=%p, property=%s, ...)\n",
1500 if (original
->disposition
!= permenant_object
)
1501 device_error(me
, "Can only duplicate permenant objects");
1502 /* find the original's master */
1503 master
= original
->owner
->properties
;
1504 while (master
->value
!= original
) {
1505 master
= master
->next
;
1506 ASSERT(master
!= NULL
);
1508 /* now duplicate it */
1509 device_add_property(me
, property
,
1511 master
->init_array
, master
->sizeof_init_array
,
1512 original
->array
, original
->sizeof_array
,
1513 original
, permenant_object
);
1518 /* Device Hardware: */
1522 device_io_read_buffer(device
*me
,
1530 if (me
->callback
->io
.read_buffer
== NULL
)
1531 device_error(me
, "no io.read_buffer method");
1532 return me
->callback
->io
.read_buffer(me
, dest
, space
,
1539 device_io_write_buffer(device
*me
,
1547 if (me
->callback
->io
.write_buffer
== NULL
)
1548 device_error(me
, "no io.write_buffer method");
1549 return me
->callback
->io
.write_buffer(me
, source
, space
,
1556 device_dma_read_buffer(device
*me
,
1562 if (me
->callback
->dma
.read_buffer
== NULL
)
1563 device_error(me
, "no dma.read_buffer method");
1564 return me
->callback
->dma
.read_buffer(me
, dest
, space
,
1570 device_dma_write_buffer(device
*me
,
1575 int violate_read_only_section
)
1577 if (me
->callback
->dma
.write_buffer
== NULL
)
1578 device_error(me
, "no dma.write_buffer method");
1579 return me
->callback
->dma
.write_buffer(me
, source
, space
,
1581 violate_read_only_section
);
1586 device_attach_address(device
*me
,
1592 device
*client
) /*callback/default*/
1594 if (me
->callback
->address
.attach
== NULL
)
1595 device_error(me
, "no address.attach method");
1596 me
->callback
->address
.attach(me
, attach
, space
,
1597 addr
, nr_bytes
, access
, client
);
1602 device_detach_address(device
*me
,
1608 device
*client
) /*callback/default*/
1610 if (me
->callback
->address
.detach
== NULL
)
1611 device_error(me
, "no address.detach method");
1612 me
->callback
->address
.detach(me
, attach
, space
,
1613 addr
, nr_bytes
, access
, client
);
1621 device_interrupt_event(device
*me
,
1627 int found_an_edge
= 0;
1628 device_interrupt_edge
*edge
;
1629 /* device's interrupt lines directly connected */
1630 for (edge
= me
->interrupt_destinations
;
1632 edge
= edge
->next
) {
1633 if (edge
->my_port
== my_port
) {
1634 if (edge
->dest
->callback
->interrupt
.event
== NULL
)
1635 device_error(me
, "no interrupt method");
1636 edge
->dest
->callback
->interrupt
.event(edge
->dest
,
1645 if (!found_an_edge
) {
1646 device_error(me
, "No interrupt edge for port %d", my_port
);
1652 device_interrupt_attach(device
*me
,
1656 object_disposition disposition
)
1658 attach_device_interrupt_edge(&me
->interrupt_destinations
,
1667 device_interrupt_detach(device
*me
,
1672 detach_device_interrupt_edge(me
,
1673 &me
->interrupt_destinations
,
1681 device_interrupt_traverse(device
*me
,
1682 device_interrupt_traverse_function
*handler
,
1685 device_interrupt_edge
*interrupt_edge
;
1686 for (interrupt_edge
= me
->interrupt_destinations
;
1687 interrupt_edge
!= NULL
;
1688 interrupt_edge
= interrupt_edge
->next
) {
1689 handler(me
, interrupt_edge
->my_port
,
1690 interrupt_edge
->dest
, interrupt_edge
->dest_port
,
1697 device_interrupt_decode(device
*me
,
1698 const char *port_name
,
1699 port_direction direction
)
1701 if (port_name
== NULL
|| port_name
[0] == '\0')
1703 if (isdigit(port_name
[0])) {
1704 return strtoul(port_name
, NULL
, 0);
1707 const device_interrupt_port_descriptor
*ports
=
1708 me
->callback
->interrupt
.ports
;
1709 if (ports
!= NULL
) {
1710 while (ports
->name
!= NULL
) {
1711 if (ports
->direction
== bidirect_port
1712 || ports
->direction
== direction
) {
1713 if (ports
->nr_ports
> 0) {
1714 int len
= strlen(ports
->name
);
1715 if (strncmp(port_name
, ports
->name
, len
) == 0) {
1716 if (port_name
[len
] == '\0')
1717 return ports
->number
;
1718 else if(isdigit(port_name
[len
])) {
1719 int port
= ports
->number
+ strtoul(&port_name
[len
], NULL
, 0);
1720 if (port
>= ports
->number
+ ports
->nr_ports
)
1721 device_error(me
, "Interrupt port %s out of range",
1727 else if (strcmp(port_name
, ports
->name
) == 0)
1728 return ports
->number
;
1734 device_error(me
, "Unreconized interrupt port %s", port_name
);
1740 device_interrupt_encode(device
*me
,
1744 port_direction direction
)
1746 const device_interrupt_port_descriptor
*ports
= NULL
;
1747 ports
= me
->callback
->interrupt
.ports
;
1748 if (ports
!= NULL
) {
1749 while (ports
->name
!= NULL
) {
1750 if (ports
->direction
== bidirect_port
1751 || ports
->direction
== direction
) {
1752 if (ports
->nr_ports
> 0) {
1753 if (port_number
>= ports
->number
1754 && port_number
< ports
->number
+ ports
->nr_ports
) {
1755 strcpy(buf
, ports
->name
);
1756 sprintf(buf
+ strlen(buf
), "%d", port_number
- ports
->number
);
1757 if (strlen(buf
) >= sizeof_buf
)
1758 error("device_interrupt_encode: buffer overflow");
1763 if (ports
->number
== port_number
) {
1764 if (strlen(ports
->name
) >= sizeof_buf
)
1765 error("device_interrupt_encode: buffer overflow");
1766 strcpy(buf
, ports
->name
);
1774 sprintf(buf
, "%d", port_number
);
1775 if (strlen(buf
) >= sizeof_buf
)
1776 error("device_interrupt_encode: buffer overflow");
1786 device_ioctl(device
*me
,
1789 device_ioctl_request request
,
1794 va_start(ap
, request
);
1795 if (me
->callback
->ioctl
== NULL
)
1796 device_error(me
, "no ioctl method");
1797 status
= me
->callback
->ioctl(me
, processor
, cia
, request
, ap
);
1808 device_error(device
*me
,
1814 /* format the message */
1816 vsprintf(message
, fmt
, ap
);
1819 if (strlen(message
) >= sizeof(message
))
1820 error("device_error: buffer overflow");
1822 error("device: %s", message
);
1823 else if (me
->path
!= NULL
&& me
->path
[0] != '\0')
1824 error("%s: %s", me
->path
, message
);
1825 else if (me
->name
!= NULL
&& me
->name
[0] != '\0')
1826 error("%s: %s", me
->name
, message
);
1828 error("device: %s", message
);
1834 device_trace(device
*me
)
1840 /* External representation */
1844 external_to_device(device
*tree_member
,
1845 unsigned_cell phandle
)
1847 device
*me
= cap_internal(tree_member
->phandles
, phandle
);
1853 device_to_external(device
*me
)
1855 unsigned_cell phandle
= cap_external(me
->phandles
, me
);
1861 external_to_device_instance(device
*tree_member
,
1862 unsigned_cell ihandle
)
1864 device_instance
*instance
= cap_internal(tree_member
->ihandles
, ihandle
);
1870 device_instance_to_external(device_instance
*instance
)
1872 unsigned_cell ihandle
= cap_external(instance
->owner
->ihandles
, instance
);
1877 /* Map onto the event functions */
1881 device_event_queue_schedule(device
*me
,
1883 device_event_handler
*handler
,
1886 return event_queue_schedule(psim_event_queue(me
->system
),
1894 device_event_queue_deschedule(device
*me
,
1895 event_entry_tag event_to_remove
)
1897 event_queue_deschedule(psim_event_queue(me
->system
),
1903 device_event_queue_time(device
*me
)
1905 return event_queue_time(psim_event_queue(me
->system
));
1909 /* Initialization: */
1914 device_clean(device
*me
,
1917 TRACE(trace_device_init
, ("device_clean - initializing %s", me
->path
));
1918 clean_device_interrupt_edges(&me
->interrupt_destinations
);
1919 clean_device_instances(me
);
1920 clean_device_properties(me
);
1923 /* Device initialization: */
1927 device_init_address(device
*me
,
1930 psim
*system
= (psim
*)data
;
1931 int nr_address_cells
;
1933 TRACE(trace_device_init
, ("device_init_address - initializing %s", me
->path
));
1935 /* ensure the cap database is valid */
1936 if (me
->parent
== NULL
) {
1937 cap_init(me
->ihandles
);
1938 cap_init(me
->phandles
);
1942 me
->system
= system
; /* misc things not known until now */
1943 me
->trace
= (device_find_property(me
, "trace")
1944 ? device_find_integer_property(me
, "trace")
1947 /* Ensure that the first address found in the reg property matches
1948 anything that was specified as part of the devices name */
1949 if (device_find_property(me
, "reg") != NULL
) {
1950 reg_property_spec unit
;
1951 device_find_reg_array_property(me
, "reg", 0, &unit
);
1952 if (memcmp(device_unit_address(me
), &unit
.address
, sizeof(unit
.address
))
1954 device_error(me
, "Unit address as specified by the reg property in conflict with the value previously specified in the devices path");
1957 /* ensure that the devices #address/size-cells is consistent */
1958 nr_address_cells
= device_nr_address_cells(me
);
1959 if (device_find_property(me
, "#address-cells") != NULL
1960 && (nr_address_cells
1961 != device_find_integer_property(me
, "#address-cells")))
1962 device_error(me
, "#address-cells property used before defined");
1963 nr_size_cells
= device_nr_size_cells(me
);
1964 if (device_find_property(me
, "#size-cells") != NULL
1966 != device_find_integer_property(me
, "#size-cells")))
1967 device_error(me
, "#size-cells property used before defined");
1970 if (me
->callback
->init
.address
!= NULL
)
1971 me
->callback
->init
.address(me
);
1976 device_init_data(device
*me
,
1979 TRACE(trace_device_init
, ("device_init_data - initializing %s", me
->path
));
1980 if (me
->callback
->init
.data
!= NULL
)
1981 me
->callback
->init
.data(me
);
1984 #endif /* _DEVICE_C_ */