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