1 /* This file is part of the program psim.
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #include "device_table.h"
47 STATIC_INLINE_DEVICE (void) clean_device_properties(device
*);
49 /* property entries */
51 typedef struct _device_property_entry device_property_entry
;
52 struct _device_property_entry
{
53 device_property_entry
*next
;
54 device_property
*value
;
55 const void *init_array
;
56 unsigned sizeof_init_array
;
62 typedef struct _device_interrupt_edge device_interrupt_edge
;
63 struct _device_interrupt_edge
{
67 device_interrupt_edge
*next
;
68 object_disposition disposition
;
73 attach_device_interrupt_edge(device_interrupt_edge
**list
,
77 object_disposition disposition
)
79 device_interrupt_edge
*new_edge
= ZALLOC(device_interrupt_edge
);
80 new_edge
->my_port
= my_port
;
81 new_edge
->dest
= dest
;
82 new_edge
->dest_port
= dest_port
;
83 new_edge
->next
= *list
;
84 new_edge
->disposition
= disposition
;
90 detach_device_interrupt_edge(device
*me
,
91 device_interrupt_edge
**list
,
96 while (*list
!= NULL
) {
97 device_interrupt_edge
*old_edge
= *list
;
98 if (old_edge
->dest
== dest
99 && old_edge
->dest_port
== dest_port
100 && old_edge
->my_port
== my_port
) {
101 if (old_edge
->disposition
== permenant_object
)
102 device_error(me
, "attempt to delete permenant interrupt");
103 *list
= old_edge
->next
;
108 device_error(me
, "attempt to delete unattached interrupt");
111 STATIC_INLINE_DEVICE\
113 clean_device_interrupt_edges(device_interrupt_edge
**list
)
115 while (*list
!= NULL
) {
116 device_interrupt_edge
*old_edge
= *list
;
117 switch (old_edge
->disposition
) {
118 case permenant_object
:
119 list
= &old_edge
->next
;
121 case tempoary_object
:
122 *list
= old_edge
->next
;
136 device_unit unit_address
;
138 int nr_address_cells
;
146 /* its template methods */
147 void *data
; /* device specific data */
148 const device_callbacks
*callback
;
150 /* device properties */
151 device_property_entry
*properties
;
154 device_interrupt_edge
*interrupt_destinations
;
156 /* any open instances of this device */
157 device_instance
*instances
;
159 /* the internal/external mappings and other global requirements */
169 /* an instance of a device */
170 struct _device_instance
{
174 const device_instance_callbacks
*callback
;
175 /* the root instance */
177 device_instance
*next
;
178 /* interposed instance */
179 device_instance
*parent
;
180 device_instance
*child
;
187 STATIC_INLINE_DEVICE\
189 device_full_name(device
*leaf
,
194 char full_name
[1024];
195 if (buf
== (char*)0) {
197 sizeof_buf
= sizeof(full_name
);
200 /* construct a name */
201 if (leaf
->parent
== NULL
) {
203 error("device_full_name: buffer overflow");
208 device_full_name(leaf
->parent
, buf
, sizeof_buf
);
209 if (leaf
->parent
!= NULL
210 && device_encode_unit(leaf
->parent
,
217 if (strlen(buf
) + strlen("/") + strlen(leaf
->name
) + strlen(unit
)
219 error("device_full_name: buffer overflow");
221 strcat(buf
, leaf
->name
);
225 /* return it usefully */
226 if (buf
== full_name
)
227 buf
= (char *) strdup(full_name
);
231 STATIC_INLINE_DEVICE\
233 device_create_from(const char *name
,
234 const device_unit
*unit_address
,
236 const device_callbacks
*callbacks
,
239 device
*new_device
= ZALLOC(device
);
241 /* insert it into the device tree */
242 new_device
->parent
= parent
;
243 new_device
->children
= NULL
;
244 if (parent
!= NULL
) {
245 device
**sibling
= &parent
->children
;
246 while ((*sibling
) != NULL
)
247 sibling
= &(*sibling
)->sibling
;
248 *sibling
= new_device
;
252 new_device
->name
= (char *) strdup(name
);
253 new_device
->unit_address
= *unit_address
;
254 new_device
->path
= device_full_name(new_device
, NULL
, 0);
257 new_device
->data
= data
;
258 new_device
->callback
= callbacks
;
260 /* its properties - already null */
261 /* interrupts - already null */
263 /* mappings - if needed */
264 if (parent
== NULL
) {
265 new_device
->ihandles
= cap_create(name
);
266 new_device
->phandles
= cap_create(name
);
269 new_device
->ihandles
= device_root(parent
)->ihandles
;
270 new_device
->phandles
= device_root(parent
)->phandles
;
273 cap_add(new_device
->phandles
, new_device
);
281 device_create(device
*parent
,
284 const char *unit_address
,
287 const device_descriptor
*const *table
;
288 for (table
= device_table
; *table
!= NULL
; table
++) {
289 const device_descriptor
*descr
;
290 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
291 if (strcmp(base
, descr
->name
) == 0) {
292 device_unit address
= { 0 };
295 if (device_decode_unit(parent
, unit_address
, &address
) < 0)
296 device_error(parent
, "invalid address %s for device %s",
298 if (descr
->creator
!= NULL
)
299 data
= descr
->creator(name
, &address
, args
);
300 return device_create_from(name
, &address
, data
,
301 descr
->callbacks
, parent
);
305 device_error(parent
, "attempt to attach unknown device %s", name
);
313 device_usage(int verbose
)
315 const device_descriptor
*const *table
;
318 for (table
= device_table
; *table
!= NULL
; table
++) {
319 const device_descriptor
*descr
;
320 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
321 pos
+= strlen(descr
->name
) + 2;
323 pos
= strlen(descr
->name
) + 2;
324 printf_filtered("\n");
326 printf_filtered(" %s", descr
->name
);
328 printf_filtered("\n");
332 for (table
= device_table
; *table
!= NULL
; table
++) {
333 const device_descriptor
*descr
;
334 for (descr
= *table
; descr
->name
!= NULL
; descr
++) {
335 printf_filtered(" %s:\n", descr
->name
);
336 /* interrupt ports */
337 if (descr
->callbacks
->interrupt
.ports
!= NULL
) {
338 const device_interrupt_port_descriptor
*ports
=
339 descr
->callbacks
->interrupt
.ports
;
340 printf_filtered(" interrupt ports:");
341 while (ports
->name
!= NULL
) {
342 printf_filtered(" %s", ports
->name
);
345 printf_filtered("\n");
348 if (descr
->callbacks
->usage
!= NULL
)
349 descr
->callbacks
->usage(verbose
);
363 device_parent(device
*me
)
370 device_root(device
*me
)
373 while (me
->parent
!= NULL
)
380 device_sibling(device
*me
)
387 device_child(device
*me
)
394 device_name(device
*me
)
401 device_path(device
*me
)
408 device_data(device
*me
)
415 device_system(device
*me
)
421 (const device_unit
*)
422 device_unit_address(device
*me
)
424 return &me
->unit_address
;
430 device_address_to_attach_address(device
*me
,
431 const device_unit
*address
,
433 unsigned_word
*attach_address
,
436 if (me
->callback
->convert
.address_to_attach_address
== NULL
)
437 device_error(me
, "no convert.address_to_attach_address method");
438 return me
->callback
->convert
.address_to_attach_address(me
, address
, attach_space
, attach_address
, client
);
444 device_size_to_attach_size(device
*me
,
445 const device_unit
*size
,
449 if (me
->callback
->convert
.size_to_attach_size
== NULL
)
450 device_error(me
, "no convert.size_to_attach_size method");
451 return me
->callback
->convert
.size_to_attach_size(me
, size
, nr_bytes
, client
);
457 device_decode_unit(device
*bus
,
459 device_unit
*address
)
461 if (bus
->callback
->convert
.decode_unit
== NULL
)
462 device_error(bus
, "no convert.decode_unit method");
463 return bus
->callback
->convert
.decode_unit(bus
, unit
, address
);
469 device_encode_unit(device
*bus
,
470 const device_unit
*unit_address
,
474 if (bus
->callback
->convert
.encode_unit
== NULL
)
475 device_error(bus
, "no convert.encode_unit method");
476 return bus
->callback
->convert
.encode_unit(bus
, unit_address
, buf
, sizeof_buf
);
481 device_nr_address_cells(device
*me
)
483 if (me
->nr_address_cells
== 0) {
484 if (device_find_property(me
, "#address-cells") != NULL
)
485 me
->nr_address_cells
= device_find_integer_property(me
, "#address-cells");
487 me
->nr_address_cells
= 2;
489 return me
->nr_address_cells
;
494 device_nr_size_cells(device
*me
)
496 if (me
->nr_size_cells
== 0) {
497 if (device_find_property(me
, "#size-cells") != NULL
)
498 me
->nr_size_cells
= device_find_integer_property(me
, "#size-cells");
500 me
->nr_size_cells
= 1;
502 return me
->nr_size_cells
;
507 /* device-instance: */
511 device_create_instance_from(device
*me
,
512 device_instance
*parent
,
516 const device_instance_callbacks
*callbacks
)
518 device_instance
*instance
= ZALLOC(device_instance
);
519 if ((me
== NULL
) == (parent
== NULL
))
520 device_error(me
, "can't have both parent instance and parent device");
522 /* link this instance into the devices list */
524 ASSERT(parent
== NULL
);
525 instance
->owner
= me
;
526 instance
->parent
= NULL
;
527 /* link this instance into the front of the devices instance list */
528 instance
->next
= me
->instances
;
529 me
->instances
= instance
;
531 if (parent
!= NULL
) {
532 device_instance
**previous
;
533 ASSERT(parent
->child
== NULL
);
534 parent
->child
= instance
;
536 instance
->owner
= parent
->owner
;
537 instance
->parent
= parent
;
538 /* in the devices instance list replace the parent instance with
540 instance
->next
= parent
->next
;
541 /* replace parent with this new node */
542 previous
= &instance
->owner
->instances
;
543 while (*previous
!= parent
) {
544 ASSERT(*previous
!= NULL
);
545 previous
= &(*previous
)->next
;
547 *previous
= instance
;
549 instance
->data
= data
;
550 instance
->args
= (args
== NULL
? NULL
: (char *) strdup(args
));
551 instance
->path
= (path
== NULL
? NULL
: (char *) strdup(path
));
552 instance
->callback
= callbacks
;
553 cap_add(instance
->owner
->ihandles
, instance
);
560 device_create_instance(device
*me
,
564 /* create the instance */
565 if (me
->callback
->instance_create
== NULL
)
566 device_error(me
, "no instance_create method");
567 return me
->callback
->instance_create(me
, path
, args
);
571 STATIC_INLINE_DEVICE\
573 clean_device_instances(device
*me
)
575 device_instance
**instance
= &me
->instances
;
576 while (*instance
!= NULL
) {
577 device_instance
*old_instance
= *instance
;
578 device_instance_delete(old_instance
);
579 instance
= &me
->instances
;
586 device_instance_delete(device_instance
*instance
)
588 device
*me
= instance
->owner
;
589 if (instance
->callback
->delete == NULL
)
590 device_error(me
, "no delete method");
591 instance
->callback
->delete(instance
);
592 if (instance
->args
!= NULL
)
593 zfree(instance
->args
);
594 if (instance
->path
!= NULL
)
595 zfree(instance
->path
);
596 if (instance
->child
== NULL
) {
597 /* only remove leaf nodes */
598 device_instance
**curr
= &me
->instances
;
599 while (*curr
!= instance
) {
600 ASSERT(*curr
!= NULL
);
601 curr
= &(*curr
)->next
;
603 *curr
= instance
->next
;
606 /* check it isn't in the instance list */
607 device_instance
*curr
= me
->instances
;
608 while (curr
!= NULL
) {
609 ASSERT(curr
!= instance
);
612 /* unlink the child */
613 ASSERT(instance
->child
->parent
== instance
);
614 instance
->child
->parent
= NULL
;
616 cap_remove(me
->ihandles
, instance
);
622 device_instance_read(device_instance
*instance
,
626 device
*me
= instance
->owner
;
627 if (instance
->callback
->read
== NULL
)
628 device_error(me
, "no read method");
629 return instance
->callback
->read(instance
, addr
, len
);
634 device_instance_write(device_instance
*instance
,
638 device
*me
= instance
->owner
;
639 if (instance
->callback
->write
== NULL
)
640 device_error(me
, "no write method");
641 return instance
->callback
->write(instance
, addr
, len
);
646 device_instance_seek(device_instance
*instance
,
647 unsigned_word pos_hi
,
648 unsigned_word pos_lo
)
650 device
*me
= instance
->owner
;
651 if (instance
->callback
->seek
== NULL
)
652 device_error(me
, "no seek method");
653 return instance
->callback
->seek(instance
, pos_hi
, pos_lo
);
658 device_instance_call_method(device_instance
*instance
,
659 const char *method_name
,
661 unsigned_cell stack_args
[/*n_stack_args*/],
663 unsigned_cell stack_returns
[/*n_stack_args*/])
665 device
*me
= instance
->owner
;
666 const device_instance_methods
*method
= instance
->callback
->methods
;
667 if (method
== NULL
) {
668 device_error(me
, "no methods (want %s)", method_name
);
670 while (method
->name
!= NULL
) {
671 if (strcmp(method
->name
, method_name
) == 0) {
672 return method
->method(instance
,
673 n_stack_args
, stack_args
,
674 n_stack_returns
, stack_returns
);
678 device_error(me
, "no %s method", method_name
);
685 device_instance_device(device_instance
*instance
)
687 return instance
->owner
;
692 device_instance_path(device_instance
*instance
)
694 return instance
->path
;
699 device_instance_data(device_instance
*instance
)
701 return instance
->data
;
706 /* Device Properties: */
708 STATIC_INLINE_DEVICE\
709 (device_property_entry
*)
710 find_property_entry(device
*me
,
711 const char *property
)
713 device_property_entry
*entry
;
714 ASSERT(property
!= NULL
);
715 entry
= me
->properties
;
716 while (entry
!= NULL
) {
717 if (strcmp(entry
->value
->name
, property
) == 0)
724 STATIC_INLINE_DEVICE\
726 device_add_property(device
*me
,
727 const char *property
,
728 device_property_type type
,
729 const void *init_array
,
730 unsigned sizeof_init_array
,
732 unsigned sizeof_array
,
733 const device_property
*original
,
734 object_disposition disposition
)
736 device_property_entry
*new_entry
= NULL
;
737 device_property
*new_value
= NULL
;
739 /* find the list end */
740 device_property_entry
**insertion_point
= &me
->properties
;
741 while (*insertion_point
!= NULL
) {
742 if (strcmp((*insertion_point
)->value
->name
, property
) == 0)
744 insertion_point
= &(*insertion_point
)->next
;
747 /* create a new value */
748 new_value
= ZALLOC(device_property
);
749 new_value
->name
= (char *) strdup(property
);
750 new_value
->type
= type
;
751 if (sizeof_array
> 0) {
752 void *new_array
= zalloc(sizeof_array
);
753 memcpy(new_array
, array
, sizeof_array
);
754 new_value
->array
= new_array
;
755 new_value
->sizeof_array
= sizeof_array
;
757 new_value
->owner
= me
;
758 new_value
->original
= original
;
759 new_value
->disposition
= disposition
;
761 /* insert the value into the list */
762 new_entry
= ZALLOC(device_property_entry
);
763 *insertion_point
= new_entry
;
764 if (sizeof_init_array
> 0) {
765 void *new_init_array
= zalloc(sizeof_init_array
);
766 memcpy(new_init_array
, init_array
, sizeof_init_array
);
767 new_entry
->init_array
= new_init_array
;
768 new_entry
->sizeof_init_array
= sizeof_init_array
;
770 new_entry
->value
= new_value
;
775 /* local - not available externally */
776 STATIC_INLINE_DEVICE\
778 device_set_property(device
*me
,
779 const char *property
,
780 device_property_type type
,
784 /* find the property */
785 device_property_entry
*entry
= find_property_entry(me
, property
);
787 /* existing property - update it */
789 device_property
*value
= entry
->value
;
790 /* check the type matches */
791 if (value
->type
!= type
)
792 device_error(me
, "conflict between type of new and old value for property %s", property
);
793 /* replace its value */
794 if (value
->array
!= NULL
)
795 zfree((void*)value
->array
);
796 new_array
= (sizeof_array
> 0
797 ? zalloc(sizeof_array
)
799 value
->array
= new_array
;
800 value
->sizeof_array
= sizeof_array
;
801 if (sizeof_array
> 0)
802 memcpy(new_array
, array
, sizeof_array
);
806 /* new property - create it */
807 device_add_property(me
, property
, type
,
808 NULL
, 0, array
, sizeof_array
,
809 NULL
, tempoary_object
);
814 STATIC_INLINE_DEVICE\
816 clean_device_properties(device
*me
)
818 device_property_entry
**delete_point
= &me
->properties
;
819 while (*delete_point
!= NULL
) {
820 device_property_entry
*current
= *delete_point
;
821 switch (current
->value
->disposition
) {
822 case permenant_object
:
823 /* zap the current value, will be initialized later */
824 ASSERT(current
->init_array
!= NULL
);
825 if (current
->value
->array
!= NULL
) {
826 zfree((void*)current
->value
->array
);
827 current
->value
->array
= NULL
;
829 delete_point
= &(*delete_point
)->next
;
831 case tempoary_object
:
832 /* zap the actual property, was created during simulation run */
833 ASSERT(current
->init_array
== NULL
);
834 *delete_point
= current
->next
;
835 if (current
->value
->array
!= NULL
)
836 zfree((void*)current
->value
->array
);
837 zfree(current
->value
);
847 device_init_static_properties(device
*me
,
850 device_property_entry
*property
;
851 for (property
= me
->properties
;
853 property
= property
->next
) {
854 ASSERT(property
->init_array
!= NULL
);
855 ASSERT(property
->value
->array
== NULL
);
856 ASSERT(property
->value
->disposition
== permenant_object
);
857 switch (property
->value
->type
) {
859 case boolean_property
:
860 case range_array_property
:
861 case reg_array_property
:
862 case string_property
:
863 case string_array_property
:
864 case integer_property
:
865 /* delete the property, and replace it with the original */
866 device_set_property(me
, property
->value
->name
,
867 property
->value
->type
,
868 property
->init_array
,
869 property
->sizeof_init_array
);
871 case ihandle_property
:
880 device_init_runtime_properties(device
*me
,
883 device_property_entry
*property
;
884 for (property
= me
->properties
;
886 property
= property
->next
) {
887 switch (property
->value
->disposition
) {
888 case permenant_object
:
889 switch (property
->value
->type
) {
890 case ihandle_property
:
892 device_instance
*ihandle
;
893 ihandle_runtime_property_spec spec
;
894 ASSERT(property
->init_array
!= NULL
);
895 ASSERT(property
->value
->array
== NULL
);
896 device_find_ihandle_runtime_property(me
, property
->value
->name
, &spec
);
897 ihandle
= device_create_instance(spec
.phandle
,
900 device_set_ihandle_property(me
, property
->value
->name
, ihandle
);
904 case boolean_property
:
905 case range_array_property
:
906 case integer_property
:
907 case reg_array_property
:
908 case string_property
:
909 case string_array_property
:
910 ASSERT(property
->init_array
!= NULL
);
911 ASSERT(property
->value
->array
!= NULL
);
915 case tempoary_object
:
916 ASSERT(property
->init_array
== NULL
);
917 ASSERT(property
->value
->array
!= NULL
);
925 (const device_property
*)
926 device_next_property(const device_property
*property
)
928 /* find the property in the list */
929 device
*owner
= property
->owner
;
930 device_property_entry
*entry
= owner
->properties
;
931 while (entry
!= NULL
&& entry
->value
!= property
)
933 /* now return the following property */
934 ASSERT(entry
!= NULL
); /* must be a member! */
935 if (entry
->next
!= NULL
)
936 return entry
->next
->value
;
943 (const device_property
*)
944 device_find_property(device
*me
,
945 const char *property
)
950 else if (property
== NULL
|| strcmp(property
, "") == 0) {
951 if (me
->properties
== NULL
)
954 return me
->properties
->value
;
957 device_property_entry
*entry
= find_property_entry(me
, property
);
967 device_add_array_property(device
*me
,
968 const char *property
,
972 device_add_property(me
, property
, array_property
,
973 array
, sizeof_array
, array
, sizeof_array
,
974 NULL
, permenant_object
);
979 device_set_array_property(device
*me
,
980 const char *property
,
984 device_set_property(me
, property
, array_property
, array
, sizeof_array
);
988 (const device_property
*)
989 device_find_array_property(device
*me
,
990 const char *property
)
992 const device_property
*node
;
993 node
= device_find_property(me
, property
);
994 if (node
== (device_property
*)0
995 || node
->type
!= array_property
)
996 device_error(me
, "property %s not found or of wrong type", property
);
1003 device_add_boolean_property(device
*me
,
1004 const char *property
,
1007 signed32 new_boolean
= (boolean
? -1 : 0);
1008 device_add_property(me
, property
, boolean_property
,
1009 &new_boolean
, sizeof(new_boolean
),
1010 &new_boolean
, sizeof(new_boolean
),
1011 NULL
, permenant_object
);
1016 device_find_boolean_property(device
*me
,
1017 const char *property
)
1019 const device_property
*node
;
1020 unsigned_cell boolean
;
1021 node
= device_find_property(me
, property
);
1022 if (node
== (device_property
*)0
1023 || node
->type
!= boolean_property
)
1024 device_error(me
, "property %s not found or of wrong type", property
);
1025 ASSERT(sizeof(boolean
) == node
->sizeof_array
);
1026 memcpy(&boolean
, node
->array
, sizeof(boolean
));
1033 device_add_ihandle_runtime_property(device
*me
,
1034 const char *property
,
1035 const ihandle_runtime_property_spec
*ihandle
)
1037 unsigned_cell
*cells
;
1039 unsigned sizeof_cells
= (sizeof(unsigned_cell
) * 3
1040 + (strlen(ihandle
->full_path
) + 1)
1041 + (ihandle
->args
!= NULL
1042 ? (strlen(ihandle
->args
) + 1)
1046 cells
= zalloc(sizeof_cells
);
1047 cells
[0] = H2BE_cell(device_to_external(ihandle
->phandle
));
1048 cells
[1] = (ihandle
->full_path
== NULL
? 0 : -1);
1049 cells
[2] = (ihandle
->args
== NULL
? 0 : -1);
1050 chp
= (char*)&cells
[3];
1052 /* the full path (if present) */
1053 if (ihandle
->full_path
!= NULL
) {
1054 strcpy(chp
, ihandle
->full_path
);
1055 chp
+= strlen(ihandle
->full_path
) + 1;
1058 /* the args (if present) */
1059 if (ihandle
->args
!= NULL
) {
1060 strcpy(chp
, ihandle
->args
);
1061 chp
+= strlen(ihandle
->args
) + 1;
1065 ASSERT(sizeof_cells
== (chp
- (char*)cells
));
1066 device_add_property(me
, property
, ihandle_property
,
1067 cells
, sizeof_cells
,
1069 NULL
, permenant_object
);
1074 device_find_ihandle_runtime_property(device
*me
,
1075 const char *property
,
1076 ihandle_runtime_property_spec
*ihandle
)
1078 const unsigned_cell
*cells
;
1080 device_property_entry
*entry
= find_property_entry(me
, property
);
1081 TRACE(trace_devices
,
1082 ("device_find_ihandle_runtime_property(me=0x%lx, property=%s)\n",
1083 (long)me
, property
));
1085 || entry
->value
->type
!= ihandle_property
1086 || entry
->value
->disposition
!= permenant_object
)
1087 device_error(me
, "property %s not found or of wrong type", property
);
1088 cells
= entry
->init_array
;
1089 chp
= (char*)&cells
[3];
1090 ASSERT(entry
->init_array
!= NULL
);
1091 /* the device to be opened */
1092 ihandle
->phandle
= external_to_device(me
, BE2H_cell(cells
[0]));
1094 if (cells
[1] != 0) {
1095 ihandle
->full_path
= chp
;
1096 chp
+= strlen(ihandle
->full_path
) + 1;
1099 ihandle
->full_path
= NULL
;
1101 if (cells
[2] != 0) {
1102 ihandle
->args
= chp
;
1103 chp
+= strlen(ihandle
->args
) + 1;
1106 ihandle
->args
= NULL
;
1107 /* reached the end? */
1108 ASSERT(entry
->sizeof_init_array
1109 == (chp
- (char*)cells
));
1117 device_set_ihandle_property(device
*me
,
1118 const char *property
,
1119 device_instance
*ihandle
)
1121 unsigned_cell cells
;
1122 cells
= H2BE_cell(device_instance_to_external(ihandle
));
1123 device_set_property(me
, property
, ihandle_property
,
1124 &cells
, sizeof(cells
));
1130 device_find_ihandle_property(device
*me
,
1131 const char *property
)
1133 const device_property
*node
;
1134 unsigned_cell ihandle
;
1135 device_instance
*instance
;
1137 node
= device_find_property(me
, property
);
1138 if (node
== NULL
|| node
->type
!= ihandle_property
)
1139 device_error(me
, "property %s not found or of wrong type", property
);
1140 if (node
->array
== NULL
)
1141 device_error(me
, "runtime property %s not yet initialized", property
);
1143 ASSERT(sizeof(ihandle
) == node
->sizeof_array
);
1144 memcpy(&ihandle
, node
->array
, sizeof(ihandle
));
1145 instance
= external_to_device_instance(me
, BE2H_cell(ihandle
));
1146 ASSERT(instance
!= NULL
);
1153 device_add_integer_property(device
*me
,
1154 const char *property
,
1155 signed_cell integer
)
1158 device_add_property(me
, property
, integer_property
,
1159 &integer
, sizeof(integer
),
1160 &integer
, sizeof(integer
),
1161 NULL
, permenant_object
);
1166 device_find_integer_property(device
*me
,
1167 const char *property
)
1169 const device_property
*node
;
1170 signed_cell integer
;
1171 TRACE(trace_devices
,
1172 ("device_find_integer(me=0x%lx, property=%s)\n",
1173 (long)me
, property
));
1174 node
= device_find_property(me
, property
);
1175 if (node
== (device_property
*)0
1176 || node
->type
!= integer_property
)
1177 device_error(me
, "property %s not found or of wrong type", property
);
1178 ASSERT(sizeof(integer
) == node
->sizeof_array
);
1179 memcpy(&integer
, node
->array
, sizeof(integer
));
1180 return BE2H_cell(integer
);
1185 device_find_integer_array_property(device
*me
,
1186 const char *property
,
1188 signed_cell
*integer
)
1190 const device_property
*node
;
1191 int sizeof_integer
= sizeof(*integer
);
1193 TRACE(trace_devices
,
1194 ("device_find_integer(me=0x%lx, property=%s)\n",
1195 (long)me
, property
));
1197 /* check things sane */
1198 node
= device_find_property(me
, property
);
1199 if (node
== (device_property
*)0
1200 || (node
->type
!= integer_property
1201 && node
->type
!= array_property
))
1202 device_error(me
, "property %s not found or of wrong type", property
);
1203 if ((node
->sizeof_array
% sizeof_integer
) != 0)
1204 device_error(me
, "property %s contains an incomplete number of cells", property
);
1205 if (node
->sizeof_array
<= sizeof_integer
* index
)
1208 /* Find and convert the value */
1209 cell
= ((signed_cell
*)node
->array
) + index
;
1210 *integer
= BE2H_cell(*cell
);
1212 return node
->sizeof_array
/ sizeof_integer
;
1216 STATIC_INLINE_DEVICE\
1218 unit_address_to_cells(const device_unit
*unit
,
1219 unsigned_cell
*cell
,
1223 ASSERT(nr_cells
== unit
->nr_cells
);
1224 for (i
= 0; i
< unit
->nr_cells
; i
++) {
1225 *cell
= H2BE_cell(unit
->cells
[i
]);
1232 STATIC_INLINE_DEVICE\
1233 (const unsigned_cell
*)
1234 cells_to_unit_address(const unsigned_cell
*cell
,
1239 memset(unit
, 0, sizeof(*unit
));
1240 unit
->nr_cells
= nr_cells
;
1241 for (i
= 0; i
< unit
->nr_cells
; i
++) {
1242 unit
->cells
[i
] = BE2H_cell(*cell
);
1249 STATIC_INLINE_DEVICE\
1251 nr_range_property_cells(device
*me
,
1254 return ((device_nr_address_cells(me
)
1255 + device_nr_address_cells(device_parent(me
))
1256 + device_nr_size_cells(me
))
1262 device_add_range_array_property(device
*me
,
1263 const char *property
,
1264 const range_property_spec
*ranges
,
1267 unsigned sizeof_cells
= (nr_range_property_cells(me
, nr_ranges
)
1268 * sizeof(unsigned_cell
));
1269 unsigned_cell
*cells
= zalloc(sizeof_cells
);
1270 unsigned_cell
*cell
;
1273 /* copy the property elements over */
1275 for (i
= 0; i
< nr_ranges
; i
++) {
1276 const range_property_spec
*range
= &ranges
[i
];
1277 /* copy the child address */
1278 cell
= unit_address_to_cells(&range
->child_address
, cell
,
1279 device_nr_address_cells(me
));
1280 /* copy the parent address */
1281 cell
= unit_address_to_cells(&range
->parent_address
, cell
,
1282 device_nr_address_cells(device_parent(me
)));
1284 cell
= unit_address_to_cells(&range
->size
, cell
,
1285 device_nr_size_cells(me
));
1287 ASSERT(cell
== &cells
[nr_range_property_cells(me
, nr_ranges
)]);
1290 device_add_property(me
, property
, range_array_property
,
1291 cells
, sizeof_cells
,
1292 cells
, sizeof_cells
,
1293 NULL
, permenant_object
);
1300 device_find_range_array_property(device
*me
,
1301 const char *property
,
1303 range_property_spec
*range
)
1305 const device_property
*node
;
1306 unsigned sizeof_entry
= (nr_range_property_cells(me
, 1)
1307 * sizeof(unsigned_cell
));
1308 const unsigned_cell
*cells
;
1310 /* locate the property */
1311 node
= device_find_property(me
, property
);
1312 if (node
== (device_property
*)0
1313 || node
->type
!= range_array_property
)
1314 device_error(me
, "property %s not found or of wrong type", property
);
1317 if ((node
->sizeof_array
% sizeof_entry
) != 0)
1318 device_error(me
, "property %s contains an incomplete number of entries",
1321 /* within bounds? */
1322 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
1325 /* find the range of interest */
1326 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
1328 /* copy the child address out - converting as we go */
1329 cells
= cells_to_unit_address(cells
, &range
->child_address
,
1330 device_nr_address_cells(me
));
1332 /* copy the parent address out - converting as we go */
1333 cells
= cells_to_unit_address(cells
, &range
->parent_address
,
1334 device_nr_address_cells(device_parent(me
)));
1336 /* copy the size - converting as we go */
1337 cells
= cells_to_unit_address(cells
, &range
->size
,
1338 device_nr_size_cells(me
));
1340 return node
->sizeof_array
/ sizeof_entry
;
1344 STATIC_INLINE_DEVICE\
1346 nr_reg_property_cells(device
*me
,
1349 return (device_nr_address_cells(device_parent(me
))
1350 + device_nr_size_cells(device_parent(me
))
1356 device_add_reg_array_property(device
*me
,
1357 const char *property
,
1358 const reg_property_spec
*regs
,
1361 unsigned sizeof_cells
= (nr_reg_property_cells(me
, nr_regs
)
1362 * sizeof(unsigned_cell
));
1363 unsigned_cell
*cells
= zalloc(sizeof_cells
);
1364 unsigned_cell
*cell
;
1367 /* copy the property elements over */
1369 for (i
= 0; i
< nr_regs
; i
++) {
1370 const reg_property_spec
*reg
= ®s
[i
];
1371 /* copy the address */
1372 cell
= unit_address_to_cells(®
->address
, cell
,
1373 device_nr_address_cells(device_parent(me
)));
1375 cell
= unit_address_to_cells(®
->size
, cell
,
1376 device_nr_size_cells(device_parent(me
)));
1378 ASSERT(cell
== &cells
[nr_reg_property_cells(me
, nr_regs
)]);
1381 device_add_property(me
, property
, reg_array_property
,
1382 cells
, sizeof_cells
,
1383 cells
, sizeof_cells
,
1384 NULL
, permenant_object
);
1391 device_find_reg_array_property(device
*me
,
1392 const char *property
,
1394 reg_property_spec
*reg
)
1396 const device_property
*node
;
1397 unsigned sizeof_entry
= (nr_reg_property_cells(me
, 1)
1398 * sizeof(unsigned_cell
));
1399 const unsigned_cell
*cells
;
1401 /* locate the property */
1402 node
= device_find_property(me
, property
);
1403 if (node
== (device_property
*)0
1404 || node
->type
!= reg_array_property
)
1405 device_error(me
, "property %s not found or of wrong type", property
);
1408 if ((node
->sizeof_array
% sizeof_entry
) != 0)
1409 device_error(me
, "property %s contains an incomplete number of entries",
1412 /* within bounds? */
1413 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
1416 /* find the range of interest */
1417 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
1419 /* copy the address out - converting as we go */
1420 cells
= cells_to_unit_address(cells
, ®
->address
,
1421 device_nr_address_cells(device_parent(me
)));
1423 /* copy the size out - converting as we go */
1424 cells
= cells_to_unit_address(cells
, ®
->size
,
1425 device_nr_size_cells(device_parent(me
)));
1427 return node
->sizeof_array
/ sizeof_entry
;
1433 device_add_string_property(device
*me
,
1434 const char *property
,
1437 device_add_property(me
, property
, string_property
,
1438 string
, strlen(string
) + 1,
1439 string
, strlen(string
) + 1,
1440 NULL
, permenant_object
);
1445 device_find_string_property(device
*me
,
1446 const char *property
)
1448 const device_property
*node
;
1450 node
= device_find_property(me
, property
);
1451 if (node
== (device_property
*)0
1452 || node
->type
!= string_property
)
1453 device_error(me
, "property %s not found or of wrong type", property
);
1454 string
= node
->array
;
1455 ASSERT(strlen(string
) + 1 == node
->sizeof_array
);
1461 device_add_string_array_property(device
*me
,
1462 const char *property
,
1463 const string_property_spec
*strings
,
1464 unsigned nr_strings
)
1470 if (nr_strings
== 0)
1471 device_error(me
, "property %s must be non-null", property
);
1472 /* total up the size of the needed array */
1473 for (sizeof_array
= 0, string_nr
= 0;
1474 string_nr
< nr_strings
;
1476 sizeof_array
+= strlen(strings
[string_nr
]) + 1;
1478 /* create the array */
1479 array
= (char*)zalloc(sizeof_array
);
1482 string_nr
< nr_strings
;
1484 strcpy(chp
, strings
[string_nr
]);
1485 chp
+= strlen(chp
) + 1;
1487 ASSERT(chp
== array
+ sizeof_array
);
1489 device_add_property(me
, property
, string_array_property
,
1490 array
, sizeof_array
,
1491 array
, sizeof_array
,
1492 NULL
, permenant_object
);
1497 device_find_string_array_property(device
*me
,
1498 const char *property
,
1500 string_property_spec
*string
)
1502 const device_property
*node
;
1503 node
= device_find_property(me
, property
);
1504 if (node
== (device_property
*)0)
1505 device_error(me
, "property %s not found", property
);
1506 switch (node
->type
) {
1508 device_error(me
, "property %s of wrong type", property
);
1510 case string_property
:
1512 *string
= node
->array
;
1513 ASSERT(strlen(*string
) + 1 == node
->sizeof_array
);
1517 case array_property
:
1518 if (node
->sizeof_array
== 0
1519 || ((char*)node
->array
)[node
->sizeof_array
- 1] != '\0')
1520 device_error(me
, "property %s invalid for string array", property
);
1522 case string_array_property
:
1523 ASSERT(node
->sizeof_array
> 0);
1524 ASSERT(((char*)node
->array
)[node
->sizeof_array
- 1] == '\0');
1526 const char *chp
= node
->array
;
1528 /* count the number of strings, keeping an eye out for the one
1529 we're looking for */
1536 if (nr_entries
== index
)
1542 } while (chp
< (char*)node
->array
+ node
->sizeof_array
);
1543 if (index
< nr_entries
)
1557 device_add_duplicate_property(device
*me
,
1558 const char *property
,
1559 const device_property
*original
)
1561 device_property_entry
*master
;
1562 TRACE(trace_devices
,
1563 ("device_add_duplicate_property(me=0x%lx, property=%s, ...)\n",
1564 (long)me
, property
));
1565 if (original
->disposition
!= permenant_object
)
1566 device_error(me
, "Can only duplicate permenant objects");
1567 /* find the original's master */
1568 master
= original
->owner
->properties
;
1569 while (master
->value
!= original
) {
1570 master
= master
->next
;
1571 ASSERT(master
!= NULL
);
1573 /* now duplicate it */
1574 device_add_property(me
, property
,
1576 master
->init_array
, master
->sizeof_init_array
,
1577 original
->array
, original
->sizeof_array
,
1578 original
, permenant_object
);
1583 /* Device Hardware: */
1587 device_io_read_buffer(device
*me
,
1595 if (me
->callback
->io
.read_buffer
== NULL
)
1596 device_error(me
, "no io.read_buffer method");
1597 return me
->callback
->io
.read_buffer(me
, dest
, space
,
1604 device_io_write_buffer(device
*me
,
1612 if (me
->callback
->io
.write_buffer
== NULL
)
1613 device_error(me
, "no io.write_buffer method");
1614 return me
->callback
->io
.write_buffer(me
, source
, space
,
1621 device_dma_read_buffer(device
*me
,
1627 if (me
->callback
->dma
.read_buffer
== NULL
)
1628 device_error(me
, "no dma.read_buffer method");
1629 return me
->callback
->dma
.read_buffer(me
, dest
, space
,
1635 device_dma_write_buffer(device
*me
,
1640 int violate_read_only_section
)
1642 if (me
->callback
->dma
.write_buffer
== NULL
)
1643 device_error(me
, "no dma.write_buffer method");
1644 return me
->callback
->dma
.write_buffer(me
, source
, space
,
1646 violate_read_only_section
);
1651 device_attach_address(device
*me
,
1657 device
*client
) /*callback/default*/
1659 if (me
->callback
->address
.attach
== NULL
)
1660 device_error(me
, "no address.attach method");
1661 me
->callback
->address
.attach(me
, attach
, space
,
1662 addr
, nr_bytes
, access
, client
);
1667 device_detach_address(device
*me
,
1673 device
*client
) /*callback/default*/
1675 if (me
->callback
->address
.detach
== NULL
)
1676 device_error(me
, "no address.detach method");
1677 me
->callback
->address
.detach(me
, attach
, space
,
1678 addr
, nr_bytes
, access
, client
);
1686 device_interrupt_event(device
*me
,
1692 int found_an_edge
= 0;
1693 device_interrupt_edge
*edge
;
1694 /* device's interrupt lines directly connected */
1695 for (edge
= me
->interrupt_destinations
;
1697 edge
= edge
->next
) {
1698 if (edge
->my_port
== my_port
) {
1699 if (edge
->dest
->callback
->interrupt
.event
== NULL
)
1700 device_error(me
, "no interrupt method");
1701 edge
->dest
->callback
->interrupt
.event(edge
->dest
,
1710 if (!found_an_edge
) {
1711 device_error(me
, "No interrupt edge for port %d", my_port
);
1717 device_interrupt_attach(device
*me
,
1721 object_disposition disposition
)
1723 attach_device_interrupt_edge(&me
->interrupt_destinations
,
1732 device_interrupt_detach(device
*me
,
1737 detach_device_interrupt_edge(me
,
1738 &me
->interrupt_destinations
,
1746 device_interrupt_traverse(device
*me
,
1747 device_interrupt_traverse_function
*handler
,
1750 device_interrupt_edge
*interrupt_edge
;
1751 for (interrupt_edge
= me
->interrupt_destinations
;
1752 interrupt_edge
!= NULL
;
1753 interrupt_edge
= interrupt_edge
->next
) {
1754 handler(me
, interrupt_edge
->my_port
,
1755 interrupt_edge
->dest
, interrupt_edge
->dest_port
,
1762 device_interrupt_decode(device
*me
,
1763 const char *port_name
,
1764 port_direction direction
)
1766 if (port_name
== NULL
|| port_name
[0] == '\0')
1768 if (isdigit(port_name
[0])) {
1769 return strtoul(port_name
, NULL
, 0);
1772 const device_interrupt_port_descriptor
*ports
=
1773 me
->callback
->interrupt
.ports
;
1774 if (ports
!= NULL
) {
1775 while (ports
->name
!= NULL
) {
1776 if (ports
->direction
== bidirect_port
1777 || ports
->direction
== direction
) {
1778 if (ports
->nr_ports
> 0) {
1779 int len
= strlen(ports
->name
);
1780 if (strncmp(port_name
, ports
->name
, len
) == 0) {
1781 if (port_name
[len
] == '\0')
1782 return ports
->number
;
1783 else if(isdigit(port_name
[len
])) {
1784 int port
= ports
->number
+ strtoul(&port_name
[len
], NULL
, 0);
1785 if (port
>= ports
->number
+ ports
->nr_ports
)
1786 device_error(me
, "Interrupt port %s out of range",
1792 else if (strcmp(port_name
, ports
->name
) == 0)
1793 return ports
->number
;
1799 device_error(me
, "Unreconized interrupt port %s", port_name
);
1805 device_interrupt_encode(device
*me
,
1809 port_direction direction
)
1811 const device_interrupt_port_descriptor
*ports
= NULL
;
1812 ports
= me
->callback
->interrupt
.ports
;
1813 if (ports
!= NULL
) {
1814 while (ports
->name
!= NULL
) {
1815 if (ports
->direction
== bidirect_port
1816 || ports
->direction
== direction
) {
1817 if (ports
->nr_ports
> 0) {
1818 if (port_number
>= ports
->number
1819 && port_number
< ports
->number
+ ports
->nr_ports
) {
1820 strcpy(buf
, ports
->name
);
1821 sprintf(buf
+ strlen(buf
), "%d", port_number
- ports
->number
);
1822 if (strlen(buf
) >= sizeof_buf
)
1823 error("device_interrupt_encode: buffer overflow");
1828 if (ports
->number
== port_number
) {
1829 if (strlen(ports
->name
) >= sizeof_buf
)
1830 error("device_interrupt_encode: buffer overflow");
1831 strcpy(buf
, ports
->name
);
1839 sprintf(buf
, "%d", port_number
);
1840 if (strlen(buf
) >= sizeof_buf
)
1841 error("device_interrupt_encode: buffer overflow");
1851 device_ioctl(device
*me
,
1854 device_ioctl_request request
,
1859 va_start(ap
, request
);
1860 if (me
->callback
->ioctl
== NULL
)
1861 device_error(me
, "no ioctl method");
1862 status
= me
->callback
->ioctl(me
, processor
, cia
, request
, ap
);
1873 device_error(device
*me
,
1879 /* format the message */
1881 vsprintf(message
, fmt
, ap
);
1884 if (strlen(message
) >= sizeof(message
))
1885 error("device_error: buffer overflow");
1887 error("device: %s", message
);
1888 else if (me
->path
!= NULL
&& me
->path
[0] != '\0')
1889 error("%s: %s", me
->path
, message
);
1890 else if (me
->name
!= NULL
&& me
->name
[0] != '\0')
1891 error("%s: %s", me
->name
, message
);
1893 error("device: %s", message
);
1899 device_trace(device
*me
)
1905 /* External representation */
1909 external_to_device(device
*tree_member
,
1910 unsigned_cell phandle
)
1912 device
*me
= cap_internal(tree_member
->phandles
, phandle
);
1918 device_to_external(device
*me
)
1920 unsigned_cell phandle
= cap_external(me
->phandles
, me
);
1926 external_to_device_instance(device
*tree_member
,
1927 unsigned_cell ihandle
)
1929 device_instance
*instance
= cap_internal(tree_member
->ihandles
, ihandle
);
1935 device_instance_to_external(device_instance
*instance
)
1937 unsigned_cell ihandle
= cap_external(instance
->owner
->ihandles
, instance
);
1942 /* Map onto the event functions */
1946 device_event_queue_schedule(device
*me
,
1947 signed64 delta_time
,
1948 device_event_handler
*handler
,
1951 return event_queue_schedule(psim_event_queue(me
->system
),
1959 device_event_queue_deschedule(device
*me
,
1960 event_entry_tag event_to_remove
)
1962 event_queue_deschedule(psim_event_queue(me
->system
),
1968 device_event_queue_time(device
*me
)
1970 return event_queue_time(psim_event_queue(me
->system
));
1974 /* Initialization: */
1979 device_clean(device
*me
,
1983 system
= (psim
*)data
;
1984 TRACE(trace_device_init
, ("device_clean - initializing %s", me
->path
));
1985 clean_device_interrupt_edges(&me
->interrupt_destinations
);
1986 clean_device_instances(me
);
1987 clean_device_properties(me
);
1990 /* Device initialization: */
1994 device_init_address(device
*me
,
1997 psim
*system
= (psim
*)data
;
1998 int nr_address_cells
;
2000 TRACE(trace_device_init
, ("device_init_address - initializing %s", me
->path
));
2002 /* ensure the cap database is valid */
2003 if (me
->parent
== NULL
) {
2004 cap_init(me
->ihandles
);
2005 cap_init(me
->phandles
);
2009 me
->system
= system
; /* misc things not known until now */
2010 me
->trace
= (device_find_property(me
, "trace")
2011 ? device_find_integer_property(me
, "trace")
2014 /* Ensure that the first address found in the reg property matches
2015 anything that was specified as part of the devices name */
2016 if (device_find_property(me
, "reg") != NULL
) {
2017 reg_property_spec unit
;
2018 device_find_reg_array_property(me
, "reg", 0, &unit
);
2019 if (memcmp(device_unit_address(me
), &unit
.address
, sizeof(unit
.address
))
2021 device_error(me
, "Unit address as specified by the reg property in conflict with the value previously specified in the devices path");
2024 /* ensure that the devices #address/size-cells is consistent */
2025 nr_address_cells
= device_nr_address_cells(me
);
2026 if (device_find_property(me
, "#address-cells") != NULL
2027 && (nr_address_cells
2028 != device_find_integer_property(me
, "#address-cells")))
2029 device_error(me
, "#address-cells property used before defined");
2030 nr_size_cells
= device_nr_size_cells(me
);
2031 if (device_find_property(me
, "#size-cells") != NULL
2033 != device_find_integer_property(me
, "#size-cells")))
2034 device_error(me
, "#size-cells property used before defined");
2037 if (me
->callback
->init
.address
!= NULL
)
2038 me
->callback
->init
.address(me
);
2043 device_init_data(device
*me
,
2046 TRACE(trace_device_init
, ("device_init_data - initializing %s", me
->path
));
2047 if (me
->callback
->init
.data
!= NULL
)
2048 me
->callback
->init
.data(me
);
2051 #endif /* _DEVICE_C_ */