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
,
185 buf
= malloc(sizeof_buf
);
188 /* construct a name */
189 if (leaf
->parent
== NULL
) {
191 error("device_full_name: buffer overflow");
196 device_full_name(leaf
->parent
, buf
, sizeof_buf
);
197 if (leaf
->parent
!= NULL
198 && device_encode_unit(leaf
->parent
,
205 if (strlen(buf
) + strlen("/") + strlen(leaf
->name
) + strlen(unit
)
207 error("device_full_name: buffer overflow");
209 strcat(buf
, leaf
->name
);
216 STATIC_INLINE_DEVICE\
218 device_create_from(const char *name
,
219 const device_unit
*unit_address
,
221 const device_callbacks
*callbacks
,
224 device
*new_device
= ZALLOC(device
);
226 /* insert it into the device tree */
227 new_device
->parent
= parent
;
228 new_device
->children
= NULL
;
229 if (parent
!= NULL
) {
230 device
**sibling
= &parent
->children
;
231 while ((*sibling
) != NULL
)
232 sibling
= &(*sibling
)->sibling
;
233 *sibling
= new_device
;
237 new_device
->name
= (char *) strdup(name
);
238 new_device
->unit_address
= *unit_address
;
239 new_device
->path
= device_full_name(new_device
, NULL
, 0);
242 new_device
->data
= data
;
243 new_device
->callback
= callbacks
;
245 /* its properties - already null */
246 /* interrupts - already null */
248 /* mappings - if needed */
249 if (parent
== NULL
) {
250 new_device
->ihandles
= cap_create(name
);
251 new_device
->phandles
= cap_create(name
);
254 new_device
->ihandles
= device_root(parent
)->ihandles
;
255 new_device
->phandles
= device_root(parent
)->phandles
;
258 cap_add(new_device
->phandles
, new_device
);
266 device_create(device
*parent
,
269 const char *unit_address
,
272 const device_descriptor
*const *table
;
273 for (table
= device_table
; *table
!= NULL
; table
++) {
274 const device_descriptor
*descr
;
275 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
276 if (strcmp(base
, descr
->name
) == 0) {
277 device_unit address
= { 0 };
280 if (device_decode_unit(parent
, unit_address
, &address
) < 0)
281 device_error(parent
, "invalid address %s for device %s",
283 if (descr
->creator
!= NULL
)
284 data
= descr
->creator(name
, &address
, args
);
285 return device_create_from(name
, &address
, data
,
286 descr
->callbacks
, parent
);
290 device_error(parent
, "attempt to attach unknown device %s", name
);
298 device_usage(int verbose
)
300 const device_descriptor
*const *table
;
303 for (table
= device_table
; *table
!= NULL
; table
++) {
304 const device_descriptor
*descr
;
305 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
306 pos
+= strlen(descr
->name
) + 2;
308 pos
= strlen(descr
->name
) + 2;
309 printf_filtered("\n");
311 printf_filtered(" %s", descr
->name
);
313 printf_filtered("\n");
317 for (table
= device_table
; *table
!= NULL
; table
++) {
318 const device_descriptor
*descr
;
319 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
320 printf_filtered(" %s:\n", descr
->name
);
321 /* interrupt ports */
322 if (descr
->callbacks
->interrupt
.ports
!= NULL
) {
323 const device_interrupt_port_descriptor
*ports
=
324 descr
->callbacks
->interrupt
.ports
;
325 printf_filtered(" interrupt ports:");
326 while (ports
->name
!= NULL
) {
327 printf_filtered(" %s", ports
->name
);
330 printf_filtered("\n");
333 if (descr
->callbacks
->usage
!= NULL
)
334 descr
->callbacks
->usage(verbose
);
348 device_parent(device
*me
)
355 device_root(device
*me
)
358 while (me
->parent
!= NULL
)
365 device_sibling(device
*me
)
372 device_child(device
*me
)
379 device_name(device
*me
)
386 device_path(device
*me
)
393 device_data(device
*me
)
400 device_system(device
*me
)
406 (const device_unit
*)
407 device_unit_address(device
*me
)
409 return &me
->unit_address
;
415 device_address_to_attach_address(device
*me
,
416 const device_unit
*address
,
418 unsigned_word
*attach_address
,
421 if (me
->callback
->convert
.address_to_attach_address
== NULL
)
422 device_error(me
, "no convert.address_to_attach_address method");
423 return me
->callback
->convert
.address_to_attach_address(me
, address
, attach_space
, attach_address
, client
);
429 device_size_to_attach_size(device
*me
,
430 const device_unit
*size
,
434 if (me
->callback
->convert
.size_to_attach_size
== NULL
)
435 device_error(me
, "no convert.size_to_attach_size method");
436 return me
->callback
->convert
.size_to_attach_size(me
, size
, nr_bytes
, client
);
442 device_decode_unit(device
*bus
,
444 device_unit
*address
)
446 if (bus
->callback
->convert
.decode_unit
== NULL
)
447 device_error(bus
, "no convert.decode_unit method");
448 return bus
->callback
->convert
.decode_unit(bus
, unit
, address
);
454 device_encode_unit(device
*bus
,
455 const device_unit
*unit_address
,
459 if (bus
->callback
->convert
.encode_unit
== NULL
)
460 device_error(bus
, "no convert.encode_unit method");
461 return bus
->callback
->convert
.encode_unit(bus
, unit_address
, buf
, sizeof_buf
);
466 device_nr_address_cells(device
*me
)
468 if (me
->nr_address_cells
== 0) {
469 if (device_find_property(me
, "#address-cells") != NULL
)
470 me
->nr_address_cells
= device_find_integer_property(me
, "#address-cells");
472 me
->nr_address_cells
= 2;
474 return me
->nr_address_cells
;
479 device_nr_size_cells(device
*me
)
481 if (me
->nr_size_cells
== 0) {
482 if (device_find_property(me
, "#size-cells") != NULL
)
483 me
->nr_size_cells
= device_find_integer_property(me
, "#size-cells");
485 me
->nr_size_cells
= 1;
487 return me
->nr_size_cells
;
492 /* device-instance: */
496 device_create_instance_from(device
*me
,
497 device_instance
*parent
,
501 const device_instance_callbacks
*callbacks
)
503 device_instance
*instance
= ZALLOC(device_instance
);
504 if ((me
== NULL
) == (parent
== NULL
))
505 device_error(me
, "can't have both parent instance and parent device");
507 /* link this instance into the devices list */
509 ASSERT(parent
== NULL
);
510 instance
->owner
= me
;
511 instance
->parent
= NULL
;
512 /* link this instance into the front of the devices instance list */
513 instance
->next
= me
->instances
;
514 me
->instances
= instance
;
516 if (parent
!= NULL
) {
517 device_instance
**previous
;
518 ASSERT(parent
->child
== NULL
);
519 parent
->child
= instance
;
521 instance
->owner
= parent
->owner
;
522 instance
->parent
= parent
;
523 /* in the devices instance list replace the parent instance with
525 instance
->next
= parent
->next
;
526 /* replace parent with this new node */
527 previous
= &instance
->owner
->instances
;
528 while (*previous
!= parent
) {
529 ASSERT(*previous
!= NULL
);
530 previous
= &(*previous
)->next
;
532 *previous
= instance
;
534 instance
->data
= data
;
535 instance
->args
= (args
== NULL
? NULL
: (char *) strdup(args
));
536 instance
->path
= (path
== NULL
? NULL
: (char *) strdup(path
));
537 instance
->callback
= callbacks
;
538 cap_add(instance
->owner
->ihandles
, instance
);
545 device_create_instance(device
*me
,
549 /* create the instance */
550 if (me
->callback
->instance_create
== NULL
)
551 device_error(me
, "no instance_create method");
552 return me
->callback
->instance_create(me
, path
, args
);
556 STATIC_INLINE_DEVICE\
558 clean_device_instances(device
*me
)
560 device_instance
**instance
= &me
->instances
;
561 while (*instance
!= NULL
) {
562 device_instance
*old_instance
= *instance
;
563 device_instance_delete(old_instance
);
564 instance
= &me
->instances
;
571 device_instance_delete(device_instance
*instance
)
573 device
*me
= instance
->owner
;
574 if (instance
->callback
->delete == NULL
)
575 device_error(me
, "no delete method");
576 instance
->callback
->delete(instance
);
577 if (instance
->args
!= NULL
)
578 free(instance
->args
);
579 if (instance
->path
!= NULL
)
580 free(instance
->path
);
581 if (instance
->child
== NULL
) {
582 /* only remove leaf nodes */
583 device_instance
**curr
= &me
->instances
;
584 while (*curr
!= instance
) {
585 ASSERT(*curr
!= NULL
);
586 curr
= &(*curr
)->next
;
588 *curr
= instance
->next
;
591 /* check it isn't in the instance list */
592 device_instance
*curr
= me
->instances
;
593 while (curr
!= NULL
) {
594 ASSERT(curr
!= instance
);
597 /* unlink the child */
598 ASSERT(instance
->child
->parent
== instance
);
599 instance
->child
->parent
= NULL
;
601 cap_remove(me
->ihandles
, instance
);
607 device_instance_read(device_instance
*instance
,
611 device
*me
= instance
->owner
;
612 if (instance
->callback
->read
== NULL
)
613 device_error(me
, "no read method");
614 return instance
->callback
->read(instance
, addr
, len
);
619 device_instance_write(device_instance
*instance
,
623 device
*me
= instance
->owner
;
624 if (instance
->callback
->write
== NULL
)
625 device_error(me
, "no write method");
626 return instance
->callback
->write(instance
, addr
, len
);
631 device_instance_seek(device_instance
*instance
,
632 unsigned_word pos_hi
,
633 unsigned_word pos_lo
)
635 device
*me
= instance
->owner
;
636 if (instance
->callback
->seek
== NULL
)
637 device_error(me
, "no seek method");
638 return instance
->callback
->seek(instance
, pos_hi
, pos_lo
);
643 device_instance_call_method(device_instance
*instance
,
644 const char *method_name
,
646 unsigned_cell stack_args
[/*n_stack_args*/],
648 unsigned_cell stack_returns
[/*n_stack_args*/])
650 device
*me
= instance
->owner
;
651 const device_instance_methods
*method
= instance
->callback
->methods
;
652 if (method
== NULL
) {
653 device_error(me
, "no methods (want %s)", method_name
);
655 while (method
->name
!= NULL
) {
656 if (strcmp(method
->name
, method_name
) == 0) {
657 return method
->method(instance
,
658 n_stack_args
, stack_args
,
659 n_stack_returns
, stack_returns
);
663 device_error(me
, "no %s method", method_name
);
670 device_instance_device(device_instance
*instance
)
672 return instance
->owner
;
677 device_instance_path(device_instance
*instance
)
679 return instance
->path
;
684 device_instance_data(device_instance
*instance
)
686 return instance
->data
;
691 /* Device Properties: */
693 STATIC_INLINE_DEVICE\
694 (device_property_entry
*)
695 find_property_entry(device
*me
,
696 const char *property
)
698 device_property_entry
*entry
;
699 ASSERT(property
!= NULL
);
700 entry
= me
->properties
;
701 while (entry
!= NULL
) {
702 if (strcmp(entry
->value
->name
, property
) == 0)
709 STATIC_INLINE_DEVICE\
711 device_add_property(device
*me
,
712 const char *property
,
713 device_property_type type
,
714 const void *init_array
,
715 unsigned sizeof_init_array
,
717 unsigned sizeof_array
,
718 const device_property
*original
,
719 object_disposition disposition
)
721 device_property_entry
*new_entry
= NULL
;
722 device_property
*new_value
= NULL
;
724 /* find the list end */
725 device_property_entry
**insertion_point
= &me
->properties
;
726 while (*insertion_point
!= NULL
) {
727 if (strcmp((*insertion_point
)->value
->name
, property
) == 0)
729 insertion_point
= &(*insertion_point
)->next
;
732 /* create a new value */
733 new_value
= ZALLOC(device_property
);
734 new_value
->name
= (char *) strdup(property
);
735 new_value
->type
= type
;
736 if (sizeof_array
> 0) {
737 void *new_array
= zalloc(sizeof_array
);
738 memcpy(new_array
, array
, sizeof_array
);
739 new_value
->array
= new_array
;
740 new_value
->sizeof_array
= sizeof_array
;
742 new_value
->owner
= me
;
743 new_value
->original
= original
;
744 new_value
->disposition
= disposition
;
746 /* insert the value into the list */
747 new_entry
= ZALLOC(device_property_entry
);
748 *insertion_point
= new_entry
;
749 if (sizeof_init_array
> 0) {
750 void *new_init_array
= zalloc(sizeof_init_array
);
751 memcpy(new_init_array
, init_array
, sizeof_init_array
);
752 new_entry
->init_array
= new_init_array
;
753 new_entry
->sizeof_init_array
= sizeof_init_array
;
755 new_entry
->value
= new_value
;
759 /* local - not available externally */
760 STATIC_INLINE_DEVICE\
762 device_set_property(device
*me
,
763 const char *property
,
764 device_property_type type
,
768 /* find the property */
769 device_property_entry
*entry
= find_property_entry(me
, property
);
771 /* existing property - update it */
773 device_property
*value
= entry
->value
;
774 /* check the type matches */
775 if (value
->type
!= type
)
776 device_error(me
, "conflict between type of new and old value for property %s", property
);
777 /* replace its value */
778 if (value
->array
!= NULL
)
779 free((void*)value
->array
);
780 new_array
= (sizeof_array
> 0
781 ? zalloc(sizeof_array
)
783 value
->array
= new_array
;
784 value
->sizeof_array
= sizeof_array
;
785 if (sizeof_array
> 0)
786 memcpy(new_array
, array
, sizeof_array
);
790 /* new property - create it */
791 device_add_property(me
, property
, type
,
792 NULL
, 0, array
, sizeof_array
,
793 NULL
, tempoary_object
);
798 STATIC_INLINE_DEVICE\
800 clean_device_properties(device
*me
)
802 device_property_entry
**delete_point
= &me
->properties
;
803 while (*delete_point
!= NULL
) {
804 device_property_entry
*current
= *delete_point
;
805 switch (current
->value
->disposition
) {
806 case permenant_object
:
807 /* zap the current value, will be initialized later */
808 ASSERT(current
->init_array
!= NULL
);
809 if (current
->value
->array
!= NULL
) {
810 free((void*)current
->value
->array
);
811 current
->value
->array
= NULL
;
813 delete_point
= &(*delete_point
)->next
;
815 case tempoary_object
:
816 /* zap the actual property, was created during simulation run */
817 ASSERT(current
->init_array
== NULL
);
818 *delete_point
= current
->next
;
819 if (current
->value
->array
!= NULL
)
820 free((void*)current
->value
->array
);
821 free(current
->value
);
831 device_init_static_properties(device
*me
,
834 device_property_entry
*property
;
835 for (property
= me
->properties
;
837 property
= property
->next
) {
838 ASSERT(property
->init_array
!= NULL
);
839 ASSERT(property
->value
->array
== NULL
);
840 ASSERT(property
->value
->disposition
== permenant_object
);
841 switch (property
->value
->type
) {
843 case boolean_property
:
844 case range_array_property
:
845 case reg_array_property
:
846 case string_property
:
847 case string_array_property
:
848 case integer_property
:
849 /* delete the property, and replace it with the original */
850 device_set_property(me
, property
->value
->name
,
851 property
->value
->type
,
852 property
->init_array
,
853 property
->sizeof_init_array
);
855 case ihandle_property
:
864 device_init_runtime_properties(device
*me
,
867 device_property_entry
*property
;
868 for (property
= me
->properties
;
870 property
= property
->next
) {
871 switch (property
->value
->disposition
) {
872 case permenant_object
:
873 switch (property
->value
->type
) {
874 case ihandle_property
:
876 device_instance
*ihandle
;
877 ihandle_runtime_property_spec spec
;
878 ASSERT(property
->init_array
!= NULL
);
879 ASSERT(property
->value
->array
== NULL
);
880 device_find_ihandle_runtime_property(me
, property
->value
->name
, &spec
);
881 ihandle
= tree_instance(me
, spec
.full_path
);
882 device_set_ihandle_property(me
, property
->value
->name
, ihandle
);
886 case boolean_property
:
887 case range_array_property
:
888 case integer_property
:
889 case reg_array_property
:
890 case string_property
:
891 case string_array_property
:
892 ASSERT(property
->init_array
!= NULL
);
893 ASSERT(property
->value
->array
!= NULL
);
897 case tempoary_object
:
898 ASSERT(property
->init_array
== NULL
);
899 ASSERT(property
->value
->array
!= NULL
);
907 (const device_property
*)
908 device_next_property(const device_property
*property
)
910 /* find the property in the list */
911 device
*owner
= property
->owner
;
912 device_property_entry
*entry
= owner
->properties
;
913 while (entry
!= NULL
&& entry
->value
!= property
)
915 /* now return the following property */
916 ASSERT(entry
!= NULL
); /* must be a member! */
917 if (entry
->next
!= NULL
)
918 return entry
->next
->value
;
925 (const device_property
*)
926 device_find_property(device
*me
,
927 const char *property
)
932 else if (property
== NULL
|| strcmp(property
, "") == 0) {
933 if (me
->properties
== NULL
)
936 return me
->properties
->value
;
939 device_property_entry
*entry
= find_property_entry(me
, property
);
949 device_add_array_property(device
*me
,
950 const char *property
,
954 device_add_property(me
, property
, array_property
,
955 array
, sizeof_array
, array
, sizeof_array
,
956 NULL
, permenant_object
);
961 device_set_array_property(device
*me
,
962 const char *property
,
966 device_set_property(me
, property
, array_property
, array
, sizeof_array
);
970 (const device_property
*)
971 device_find_array_property(device
*me
,
972 const char *property
)
974 const device_property
*node
;
975 node
= device_find_property(me
, property
);
976 if (node
== (device_property
*)0
977 || node
->type
!= array_property
)
978 device_error(me
, "property %s not found or of wrong type", property
);
985 device_add_boolean_property(device
*me
,
986 const char *property
,
989 signed32 new_boolean
= (boolean
? -1 : 0);
990 device_add_property(me
, property
, boolean_property
,
991 &new_boolean
, sizeof(new_boolean
),
992 &new_boolean
, sizeof(new_boolean
),
993 NULL
, permenant_object
);
998 device_find_boolean_property(device
*me
,
999 const char *property
)
1001 const device_property
*node
;
1002 unsigned_cell boolean
;
1003 node
= device_find_property(me
, property
);
1004 if (node
== (device_property
*)0
1005 || node
->type
!= boolean_property
)
1006 device_error(me
, "property %s not found or of wrong type", property
);
1007 ASSERT(sizeof(boolean
) == node
->sizeof_array
);
1008 memcpy(&boolean
, node
->array
, sizeof(boolean
));
1015 device_add_ihandle_runtime_property(device
*me
,
1016 const char *property
,
1017 const ihandle_runtime_property_spec
*ihandle
)
1019 /* enter the full path as the init array */
1020 device_add_property(me
, property
, ihandle_property
,
1021 ihandle
->full_path
, strlen(ihandle
->full_path
) + 1,
1023 NULL
, permenant_object
);
1028 device_find_ihandle_runtime_property(device
*me
,
1029 const char *property
,
1030 ihandle_runtime_property_spec
*ihandle
)
1032 device_property_entry
*entry
= find_property_entry(me
, property
);
1033 TRACE(trace_devices
,
1034 ("device_find_ihandle_runtime_property(me=0x%lx, property=%s)\n",
1035 (long)me
, property
));
1037 || entry
->value
->type
!= ihandle_property
1038 || entry
->value
->disposition
!= permenant_object
)
1039 device_error(me
, "property %s not found or of wrong type", property
);
1040 ASSERT(entry
->init_array
!= NULL
);
1042 ihandle
->full_path
= entry
->init_array
;
1049 device_set_ihandle_property(device
*me
,
1050 const char *property
,
1051 device_instance
*ihandle
)
1053 unsigned_cell cells
;
1054 cells
= H2BE_cell(device_instance_to_external(ihandle
));
1055 device_set_property(me
, property
, ihandle_property
,
1056 &cells
, sizeof(cells
));
1062 device_find_ihandle_property(device
*me
,
1063 const char *property
)
1065 const device_property
*node
;
1066 unsigned_cell ihandle
;
1067 device_instance
*instance
;
1069 node
= device_find_property(me
, property
);
1070 if (node
== NULL
|| node
->type
!= ihandle_property
)
1071 device_error(me
, "property %s not found or of wrong type", property
);
1072 if (node
->array
== NULL
)
1073 device_error(me
, "runtime property %s not yet initialized", property
);
1075 ASSERT(sizeof(ihandle
) == node
->sizeof_array
);
1076 memcpy(&ihandle
, node
->array
, sizeof(ihandle
));
1077 instance
= external_to_device_instance(me
, BE2H_cell(ihandle
));
1078 ASSERT(instance
!= NULL
);
1085 device_add_integer_property(device
*me
,
1086 const char *property
,
1087 signed_cell integer
)
1090 device_add_property(me
, property
, integer_property
,
1091 &integer
, sizeof(integer
),
1092 &integer
, sizeof(integer
),
1093 NULL
, permenant_object
);
1098 device_find_integer_property(device
*me
,
1099 const char *property
)
1101 const device_property
*node
;
1102 signed_cell integer
;
1103 TRACE(trace_devices
,
1104 ("device_find_integer(me=0x%lx, property=%s)\n",
1105 (long)me
, property
));
1106 node
= device_find_property(me
, property
);
1107 if (node
== (device_property
*)0
1108 || node
->type
!= integer_property
)
1109 device_error(me
, "property %s not found or of wrong type", property
);
1110 ASSERT(sizeof(integer
) == node
->sizeof_array
);
1111 memcpy(&integer
, node
->array
, sizeof(integer
));
1112 return BE2H_cell(integer
);
1117 device_find_integer_array_property(device
*me
,
1118 const char *property
,
1120 signed_cell
*integer
)
1122 const device_property
*node
;
1123 int sizeof_integer
= sizeof(*integer
);
1125 TRACE(trace_devices
,
1126 ("device_find_integer(me=0x%lx, property=%s)\n",
1127 (long)me
, property
));
1129 /* check things sane */
1130 node
= device_find_property(me
, property
);
1131 if (node
== (device_property
*)0
1132 || (node
->type
!= integer_property
1133 && node
->type
!= array_property
))
1134 device_error(me
, "property %s not found or of wrong type", property
);
1135 if ((node
->sizeof_array
% sizeof_integer
) != 0)
1136 device_error(me
, "property %s contains an incomplete number of cells", property
);
1137 if (node
->sizeof_array
<= sizeof_integer
* index
)
1140 /* Find and convert the value */
1141 cell
= ((signed_cell
*)node
->array
) + index
;
1142 *integer
= BE2H_cell(*cell
);
1144 return node
->sizeof_array
/ sizeof_integer
;
1148 STATIC_INLINE_DEVICE\
1150 unit_address_to_cells(const device_unit
*unit
,
1151 unsigned_cell
*cell
,
1155 ASSERT(nr_cells
== unit
->nr_cells
);
1156 for (i
= 0; i
< unit
->nr_cells
; i
++) {
1157 *cell
= H2BE_cell(unit
->cells
[i
]);
1164 STATIC_INLINE_DEVICE\
1165 (const unsigned_cell
*)
1166 cells_to_unit_address(const unsigned_cell
*cell
,
1171 memset(unit
, 0, sizeof(*unit
));
1172 unit
->nr_cells
= nr_cells
;
1173 for (i
= 0; i
< unit
->nr_cells
; i
++) {
1174 unit
->cells
[i
] = BE2H_cell(*cell
);
1181 STATIC_INLINE_DEVICE\
1183 nr_range_property_cells(device
*me
,
1186 return ((device_nr_address_cells(me
)
1187 + device_nr_address_cells(device_parent(me
))
1188 + device_nr_size_cells(me
))
1194 device_add_range_array_property(device
*me
,
1195 const char *property
,
1196 const range_property_spec
*ranges
,
1199 unsigned sizeof_cells
= (nr_range_property_cells(me
, nr_ranges
)
1200 * sizeof(unsigned_cell
));
1201 unsigned_cell
*cells
= zalloc(sizeof_cells
);
1202 unsigned_cell
*cell
;
1205 /* copy the property elements over */
1207 for (i
= 0; i
< nr_ranges
; i
++) {
1208 const range_property_spec
*range
= &ranges
[i
];
1209 /* copy the child address */
1210 cell
= unit_address_to_cells(&range
->child_address
, cell
,
1211 device_nr_address_cells(me
));
1212 /* copy the parent address */
1213 cell
= unit_address_to_cells(&range
->parent_address
, cell
,
1214 device_nr_address_cells(device_parent(me
)));
1216 cell
= unit_address_to_cells(&range
->size
, cell
,
1217 device_nr_size_cells(me
));
1219 ASSERT(cell
== &cells
[nr_range_property_cells(me
, nr_ranges
)]);
1222 device_add_property(me
, property
, range_array_property
,
1223 cells
, sizeof_cells
,
1224 cells
, sizeof_cells
,
1225 NULL
, permenant_object
);
1232 device_find_range_array_property(device
*me
,
1233 const char *property
,
1235 range_property_spec
*range
)
1237 const device_property
*node
;
1238 unsigned sizeof_entry
= (nr_range_property_cells(me
, 1)
1239 * sizeof(unsigned_cell
));
1240 const unsigned_cell
*cells
;
1242 /* locate the property */
1243 node
= device_find_property(me
, property
);
1244 if (node
== (device_property
*)0
1245 || node
->type
!= range_array_property
)
1246 device_error(me
, "property %s not found or of wrong type", property
);
1249 if ((node
->sizeof_array
% sizeof_entry
) != 0)
1250 device_error(me
, "property %s contains an incomplete number of entries",
1253 /* within bounds? */
1254 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
1257 /* find the range of interest */
1258 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
1260 /* copy the child address out - converting as we go */
1261 cells
= cells_to_unit_address(cells
, &range
->child_address
,
1262 device_nr_address_cells(me
));
1264 /* copy the parent address out - converting as we go */
1265 cells
= cells_to_unit_address(cells
, &range
->parent_address
,
1266 device_nr_address_cells(device_parent(me
)));
1268 /* copy the size - converting as we go */
1269 cells
= cells_to_unit_address(cells
, &range
->size
,
1270 device_nr_size_cells(me
));
1272 return node
->sizeof_array
/ sizeof_entry
;
1276 STATIC_INLINE_DEVICE\
1278 nr_reg_property_cells(device
*me
,
1281 return (device_nr_address_cells(device_parent(me
))
1282 + device_nr_size_cells(device_parent(me
))
1288 device_add_reg_array_property(device
*me
,
1289 const char *property
,
1290 const reg_property_spec
*regs
,
1293 unsigned sizeof_cells
= (nr_reg_property_cells(me
, nr_regs
)
1294 * sizeof(unsigned_cell
));
1295 unsigned_cell
*cells
= zalloc(sizeof_cells
);
1296 unsigned_cell
*cell
;
1299 /* copy the property elements over */
1301 for (i
= 0; i
< nr_regs
; i
++) {
1302 const reg_property_spec
*reg
= ®s
[i
];
1303 /* copy the address */
1304 cell
= unit_address_to_cells(®
->address
, cell
,
1305 device_nr_address_cells(device_parent(me
)));
1307 cell
= unit_address_to_cells(®
->size
, cell
,
1308 device_nr_size_cells(device_parent(me
)));
1310 ASSERT(cell
== &cells
[nr_reg_property_cells(me
, nr_regs
)]);
1313 device_add_property(me
, property
, reg_array_property
,
1314 cells
, sizeof_cells
,
1315 cells
, sizeof_cells
,
1316 NULL
, permenant_object
);
1323 device_find_reg_array_property(device
*me
,
1324 const char *property
,
1326 reg_property_spec
*reg
)
1328 const device_property
*node
;
1329 unsigned sizeof_entry
= (nr_reg_property_cells(me
, 1)
1330 * sizeof(unsigned_cell
));
1331 const unsigned_cell
*cells
;
1333 /* locate the property */
1334 node
= device_find_property(me
, property
);
1335 if (node
== (device_property
*)0
1336 || node
->type
!= reg_array_property
)
1337 device_error(me
, "property %s not found or of wrong type", property
);
1340 if ((node
->sizeof_array
% sizeof_entry
) != 0)
1341 device_error(me
, "property %s contains an incomplete number of entries",
1344 /* within bounds? */
1345 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
1348 /* find the range of interest */
1349 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
1351 /* copy the address out - converting as we go */
1352 cells
= cells_to_unit_address(cells
, ®
->address
,
1353 device_nr_address_cells(device_parent(me
)));
1355 /* copy the size out - converting as we go */
1356 cells
= cells_to_unit_address(cells
, ®
->size
,
1357 device_nr_size_cells(device_parent(me
)));
1359 return node
->sizeof_array
/ sizeof_entry
;
1365 device_add_string_property(device
*me
,
1366 const char *property
,
1369 device_add_property(me
, property
, string_property
,
1370 string
, strlen(string
) + 1,
1371 string
, strlen(string
) + 1,
1372 NULL
, permenant_object
);
1377 device_find_string_property(device
*me
,
1378 const char *property
)
1380 const device_property
*node
;
1382 node
= device_find_property(me
, property
);
1383 if (node
== (device_property
*)0
1384 || node
->type
!= string_property
)
1385 device_error(me
, "property %s not found or of wrong type", property
);
1386 string
= node
->array
;
1387 ASSERT(strlen(string
) + 1 == node
->sizeof_array
);
1393 device_add_string_array_property(device
*me
,
1394 const char *property
,
1395 const string_property_spec
*strings
,
1396 unsigned nr_strings
)
1402 if (nr_strings
== 0)
1403 device_error(me
, "property %s must be non-null", property
);
1404 /* total up the size of the needed array */
1405 for (sizeof_array
= 0, string_nr
= 0;
1406 string_nr
< nr_strings
;
1408 sizeof_array
+= strlen(strings
[string_nr
]) + 1;
1410 /* create the array */
1411 array
= (char*)zalloc(sizeof_array
);
1414 string_nr
< nr_strings
;
1416 strcpy(chp
, strings
[string_nr
]);
1417 chp
+= strlen(chp
) + 1;
1419 ASSERT(chp
== array
+ sizeof_array
);
1421 device_add_property(me
, property
, string_array_property
,
1422 array
, sizeof_array
,
1423 array
, sizeof_array
,
1424 NULL
, permenant_object
);
1429 device_find_string_array_property(device
*me
,
1430 const char *property
,
1432 string_property_spec
*string
)
1434 const device_property
*node
;
1435 node
= device_find_property(me
, property
);
1436 if (node
== (device_property
*)0)
1437 device_error(me
, "property %s not found", property
);
1438 switch (node
->type
) {
1440 device_error(me
, "property %s of wrong type", property
);
1442 case string_property
:
1444 *string
= node
->array
;
1445 ASSERT(strlen(*string
) + 1 == node
->sizeof_array
);
1449 case array_property
:
1450 if (node
->sizeof_array
== 0
1451 || ((char*)node
->array
)[node
->sizeof_array
- 1] != '\0')
1452 device_error(me
, "property %s invalid for string array", property
);
1454 case string_array_property
:
1455 ASSERT(node
->sizeof_array
> 0);
1456 ASSERT(((char*)node
->array
)[node
->sizeof_array
- 1] == '\0');
1458 const char *chp
= node
->array
;
1460 /* count the number of strings, keeping an eye out for the one
1461 we're looking for */
1468 if (nr_entries
== index
)
1474 } while (chp
< (char*)node
->array
+ node
->sizeof_array
);
1475 if (index
< nr_entries
)
1489 device_add_duplicate_property(device
*me
,
1490 const char *property
,
1491 const device_property
*original
)
1493 device_property_entry
*master
;
1494 TRACE(trace_devices
,
1495 ("device_add_duplicate_property(me=0x%lx, property=%s, ...)\n",
1496 (long)me
, property
));
1497 if (original
->disposition
!= permenant_object
)
1498 device_error(me
, "Can only duplicate permenant objects");
1499 /* find the original's master */
1500 master
= original
->owner
->properties
;
1501 while (master
->value
!= original
) {
1502 master
= master
->next
;
1503 ASSERT(master
!= NULL
);
1505 /* now duplicate it */
1506 device_add_property(me
, property
,
1508 master
->init_array
, master
->sizeof_init_array
,
1509 original
->array
, original
->sizeof_array
,
1510 original
, permenant_object
);
1515 /* Device Hardware: */
1519 device_io_read_buffer(device
*me
,
1527 if (me
->callback
->io
.read_buffer
== NULL
)
1528 device_error(me
, "no io.read_buffer method");
1529 return me
->callback
->io
.read_buffer(me
, dest
, space
,
1536 device_io_write_buffer(device
*me
,
1544 if (me
->callback
->io
.write_buffer
== NULL
)
1545 device_error(me
, "no io.write_buffer method");
1546 return me
->callback
->io
.write_buffer(me
, source
, space
,
1553 device_dma_read_buffer(device
*me
,
1559 if (me
->callback
->dma
.read_buffer
== NULL
)
1560 device_error(me
, "no dma.read_buffer method");
1561 return me
->callback
->dma
.read_buffer(me
, dest
, space
,
1567 device_dma_write_buffer(device
*me
,
1572 int violate_read_only_section
)
1574 if (me
->callback
->dma
.write_buffer
== NULL
)
1575 device_error(me
, "no dma.write_buffer method");
1576 return me
->callback
->dma
.write_buffer(me
, source
, space
,
1578 violate_read_only_section
);
1583 device_attach_address(device
*me
,
1589 device
*client
) /*callback/default*/
1591 if (me
->callback
->address
.attach
== NULL
)
1592 device_error(me
, "no address.attach method");
1593 me
->callback
->address
.attach(me
, attach
, space
,
1594 addr
, nr_bytes
, access
, client
);
1599 device_detach_address(device
*me
,
1605 device
*client
) /*callback/default*/
1607 if (me
->callback
->address
.detach
== NULL
)
1608 device_error(me
, "no address.detach method");
1609 me
->callback
->address
.detach(me
, attach
, space
,
1610 addr
, nr_bytes
, access
, client
);
1618 device_interrupt_event(device
*me
,
1624 int found_an_edge
= 0;
1625 device_interrupt_edge
*edge
;
1626 /* device's interrupt lines directly connected */
1627 for (edge
= me
->interrupt_destinations
;
1629 edge
= edge
->next
) {
1630 if (edge
->my_port
== my_port
) {
1631 if (edge
->dest
->callback
->interrupt
.event
== NULL
)
1632 device_error(me
, "no interrupt method");
1633 edge
->dest
->callback
->interrupt
.event(edge
->dest
,
1642 if (!found_an_edge
) {
1643 device_error(me
, "No interrupt edge for port %d", my_port
);
1649 device_interrupt_attach(device
*me
,
1653 object_disposition disposition
)
1655 attach_device_interrupt_edge(&me
->interrupt_destinations
,
1664 device_interrupt_detach(device
*me
,
1669 detach_device_interrupt_edge(me
,
1670 &me
->interrupt_destinations
,
1678 device_interrupt_traverse(device
*me
,
1679 device_interrupt_traverse_function
*handler
,
1682 device_interrupt_edge
*interrupt_edge
;
1683 for (interrupt_edge
= me
->interrupt_destinations
;
1684 interrupt_edge
!= NULL
;
1685 interrupt_edge
= interrupt_edge
->next
) {
1686 handler(me
, interrupt_edge
->my_port
,
1687 interrupt_edge
->dest
, interrupt_edge
->dest_port
,
1694 device_interrupt_decode(device
*me
,
1695 const char *port_name
,
1696 port_direction direction
)
1698 if (port_name
== NULL
|| port_name
[0] == '\0')
1700 if (isdigit(port_name
[0])) {
1701 return strtoul(port_name
, NULL
, 0);
1704 const device_interrupt_port_descriptor
*ports
=
1705 me
->callback
->interrupt
.ports
;
1706 if (ports
!= NULL
) {
1707 while (ports
->name
!= NULL
) {
1708 if (ports
->direction
== bidirect_port
1709 || ports
->direction
== direction
) {
1710 if (ports
->nr_ports
> 0) {
1711 int len
= strlen(ports
->name
);
1712 if (strncmp(port_name
, ports
->name
, len
) == 0) {
1713 if (port_name
[len
] == '\0')
1714 return ports
->number
;
1715 else if(isdigit(port_name
[len
])) {
1716 int port
= ports
->number
+ strtoul(&port_name
[len
], NULL
, 0);
1717 if (port
>= ports
->number
+ ports
->nr_ports
)
1718 device_error(me
, "Interrupt port %s out of range",
1724 else if (strcmp(port_name
, ports
->name
) == 0)
1725 return ports
->number
;
1731 device_error(me
, "Unreconized interrupt port %s", port_name
);
1737 device_interrupt_encode(device
*me
,
1741 port_direction direction
)
1743 const device_interrupt_port_descriptor
*ports
= NULL
;
1744 ports
= me
->callback
->interrupt
.ports
;
1745 if (ports
!= NULL
) {
1746 while (ports
->name
!= NULL
) {
1747 if (ports
->direction
== bidirect_port
1748 || ports
->direction
== direction
) {
1749 if (ports
->nr_ports
> 0) {
1750 if (port_number
>= ports
->number
1751 && port_number
< ports
->number
+ ports
->nr_ports
) {
1752 strcpy(buf
, ports
->name
);
1753 sprintf(buf
+ strlen(buf
), "%d", port_number
- ports
->number
);
1754 if (strlen(buf
) >= sizeof_buf
)
1755 error("device_interrupt_encode: buffer overflow");
1760 if (ports
->number
== port_number
) {
1761 if (strlen(ports
->name
) >= sizeof_buf
)
1762 error("device_interrupt_encode: buffer overflow");
1763 strcpy(buf
, ports
->name
);
1771 sprintf(buf
, "%d", port_number
);
1772 if (strlen(buf
) >= sizeof_buf
)
1773 error("device_interrupt_encode: buffer overflow");
1783 device_ioctl(device
*me
,
1786 device_ioctl_request request
,
1791 va_start(ap
, request
);
1792 if (me
->callback
->ioctl
== NULL
)
1793 device_error(me
, "no ioctl method");
1794 status
= me
->callback
->ioctl(me
, processor
, cia
, request
, ap
);
1805 device_error(device
*me
,
1811 /* format the message */
1813 vsprintf(message
, fmt
, ap
);
1816 if (strlen(message
) >= sizeof(message
))
1817 error("device_error: buffer overflow");
1819 error("device: %s", message
);
1820 else if (me
->path
!= NULL
&& me
->path
[0] != '\0')
1821 error("%s: %s", me
->path
, message
);
1822 else if (me
->name
!= NULL
&& me
->name
[0] != '\0')
1823 error("%s: %s", me
->name
, message
);
1825 error("device: %s", message
);
1831 device_trace(device
*me
)
1837 /* External representation */
1841 external_to_device(device
*tree_member
,
1842 unsigned_cell phandle
)
1844 device
*me
= cap_internal(tree_member
->phandles
, phandle
);
1850 device_to_external(device
*me
)
1852 unsigned_cell phandle
= cap_external(me
->phandles
, me
);
1858 external_to_device_instance(device
*tree_member
,
1859 unsigned_cell ihandle
)
1861 device_instance
*instance
= cap_internal(tree_member
->ihandles
, ihandle
);
1867 device_instance_to_external(device_instance
*instance
)
1869 unsigned_cell ihandle
= cap_external(instance
->owner
->ihandles
, instance
);
1874 /* Map onto the event functions */
1878 device_event_queue_schedule(device
*me
,
1879 signed64 delta_time
,
1880 device_event_handler
*handler
,
1883 return event_queue_schedule(psim_event_queue(me
->system
),
1891 device_event_queue_deschedule(device
*me
,
1892 event_entry_tag event_to_remove
)
1894 event_queue_deschedule(psim_event_queue(me
->system
),
1900 device_event_queue_time(device
*me
)
1902 return event_queue_time(psim_event_queue(me
->system
));
1906 /* Initialization: */
1911 device_clean(device
*me
,
1914 TRACE(trace_device_init
, ("device_clean - initializing %s", me
->path
));
1915 clean_device_interrupt_edges(&me
->interrupt_destinations
);
1916 clean_device_instances(me
);
1917 clean_device_properties(me
);
1920 /* Device initialization: */
1924 device_init_address(device
*me
,
1927 psim
*system
= (psim
*)data
;
1928 int nr_address_cells
;
1930 TRACE(trace_device_init
, ("device_init_address - initializing %s", me
->path
));
1932 /* ensure the cap database is valid */
1933 if (me
->parent
== NULL
) {
1934 cap_init(me
->ihandles
);
1935 cap_init(me
->phandles
);
1939 me
->system
= system
; /* misc things not known until now */
1940 me
->trace
= (device_find_property(me
, "trace")
1941 ? device_find_integer_property(me
, "trace")
1944 /* Ensure that the first address found in the reg property matches
1945 anything that was specified as part of the devices name */
1946 if (device_find_property(me
, "reg") != NULL
) {
1947 reg_property_spec unit
;
1948 device_find_reg_array_property(me
, "reg", 0, &unit
);
1949 if (memcmp(device_unit_address(me
), &unit
.address
, sizeof(unit
.address
))
1951 device_error(me
, "Unit address as specified by the reg property in conflict with the value previously specified in the devices path");
1954 /* ensure that the devices #address/size-cells is consistent */
1955 nr_address_cells
= device_nr_address_cells(me
);
1956 if (device_find_property(me
, "#address-cells") != NULL
1957 && (nr_address_cells
1958 != device_find_integer_property(me
, "#address-cells")))
1959 device_error(me
, "#address-cells property used before defined");
1960 nr_size_cells
= device_nr_size_cells(me
);
1961 if (device_find_property(me
, "#size-cells") != NULL
1963 != device_find_integer_property(me
, "#size-cells")))
1964 device_error(me
, "#size-cells property used before defined");
1967 if (me
->callback
->init
.address
!= NULL
)
1968 me
->callback
->init
.address(me
);
1973 device_init_data(device
*me
,
1976 TRACE(trace_device_init
, ("device_init_data - initializing %s", me
->path
));
1977 if (me
->callback
->init
.data
!= NULL
)
1978 me
->callback
->init
.data(me
);
1981 #endif /* _DEVICE_C_ */