aboutsummaryrefslogtreecommitdiff
path: root/sim/ppc/device.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/ppc/device.c')
-rw-r--r--sim/ppc/device.c2182
1 files changed, 1132 insertions, 1050 deletions
diff --git a/sim/ppc/device.c b/sim/ppc/device.c
index 83d9e3f..7d69c3f 100644
--- a/sim/ppc/device.c
+++ b/sim/ppc/device.c
@@ -27,6 +27,9 @@
#include "device_table.h"
#include "cap.h"
+#include "events.h"
+#include "psim.h"
+
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
@@ -42,7 +45,6 @@
#include <ctype.h>
STATIC_INLINE_DEVICE (void) clean_device_properties(device *);
-STATIC_INLINE_DEVICE (void) init_device_properties(device *, void*);
/* property entries */
@@ -97,13 +99,13 @@ detach_device_interrupt_edge(device *me,
&& old_edge->dest_port == dest_port
&& old_edge->my_port == my_port) {
if (old_edge->disposition == permenant_object)
- device_error(me, "attempt to delete permenant interrupt\n");
+ device_error(me, "attempt to delete permenant interrupt");
*list = old_edge->next;
zfree(old_edge);
return;
}
}
- device_error(me, "attempt to delete unattached interrupt\n");
+ device_error(me, "attempt to delete unattached interrupt");
}
STATIC_INLINE_DEVICE\
@@ -133,6 +135,8 @@ struct _device {
const char *name;
device_unit unit_address;
const char *path;
+ int nr_address_cells;
+ int nr_size_cells;
/* device tree */
device *parent;
@@ -156,6 +160,9 @@ struct _device {
cap *ihandles;
cap *phandles;
psim *system;
+
+ /* debugging */
+ int trace;
};
@@ -175,76 +182,13 @@ struct _device_instance {
-/* Device node: */
-
-INLINE_DEVICE\
-(device *)
-device_parent(device *me)
-{
- return me->parent;
-}
-
-INLINE_DEVICE\
-(device *)
-device_sibling(device *me)
-{
- return me->sibling;
-}
-
-INLINE_DEVICE\
-(device *)
-device_child(device *me)
-{
- return me->children;
-}
-
-INLINE_DEVICE\
-(const char *)
-device_name(device *me)
-{
- return me->name;
-}
-
-INLINE_DEVICE\
-(const char *)
-device_path(device *me)
-{
- return me->path;
-}
-
-INLINE_DEVICE\
-(void *)
-device_data(device *me)
-{
- return me->data;
-}
-
-INLINE_DEVICE\
-(psim *)
-device_system(device *me)
-{
- return me->system;
-}
-
-INLINE_DEVICE\
-(const device_unit *)
-device_unit_address(device *me)
-{
- return &me->unit_address;
-}
-
-
-
-/* device template: */
-
-/* determine the full name of the device. If buf is specified it is
- stored in there. Failing that, a safe area of memory is allocated */
+/* creation */
STATIC_INLINE_DEVICE\
(const char *)
device_full_name(device *leaf,
- char *buf,
- unsigned sizeof_buf)
+ char *buf,
+ unsigned sizeof_buf)
{
/* get a buffer */
char full_name[1024];
@@ -256,23 +200,23 @@ device_full_name(device *leaf,
/* construct a name */
if (leaf->parent == NULL) {
if (sizeof_buf < 1)
- error("device_full_name: buffer overflow\n");
+ error("device_full_name: buffer overflow");
*buf = '\0';
}
else {
char unit[1024];
device_full_name(leaf->parent, buf, sizeof_buf);
if (leaf->parent != NULL
- && leaf->parent->callback->convert.encode_unit(leaf->parent,
- &leaf->unit_address,
- unit+1,
- sizeof(unit)-1) > 0)
+ && device_encode_unit(leaf->parent,
+ &leaf->unit_address,
+ unit+1,
+ sizeof(unit)-1) > 0)
unit[0] = '@';
else
unit[0] = '\0';
if (strlen(buf) + strlen("/") + strlen(leaf->name) + strlen(unit)
- >= sizeof_buf)
- error("device_full_name: buffer overflow\n");
+ >= sizeof_buf)
+ error("device_full_name: buffer overflow");
strcat(buf, "/");
strcat(buf, leaf->name);
strcat (buf, unit);
@@ -280,271 +224,10 @@ device_full_name(device *leaf,
/* return it usefully */
if (buf == full_name)
- buf = strdup(full_name);
+ buf = (char *) strdup(full_name);
return buf;
}
-/* manipulate/lookup device names */
-
-typedef struct _name_specifier {
- /* components in the full length name */
- char *path;
- char *property;
- char *value;
- /* current device */
- char *name;
- char *unit;
- char *args;
- /* previous device */
- char *last_name;
- char *last_unit;
- char *last_args;
- /* work area */
- char buf[1024];
-} name_specifier;
-
-/* Given a device specifier, break it up into its main components:
- path (and if present) property name and property value. */
-STATIC_INLINE_DEVICE\
-(int)
-split_device_specifier(const char *device_specifier,
- name_specifier *spec)
-{
- char *chp;
- if (strlen(device_specifier) >= sizeof(spec->buf))
- error("split_device_specifier: buffer overflow\n");
-
- /* expand aliases (later) */
- strcpy(spec->buf, device_specifier);
-
- /* strip the leading spaces and check that remainder isn't a comment */
- chp = spec->buf;
- while (*chp != '\0' && isspace(*chp))
- chp++;
- if (*chp == '\0' || *chp == '#')
- return 0;
-
- /* find the path and terminate it with null */
- spec->path = chp;
- while (*chp != '\0' && !isspace(*chp))
- chp++;
- if (*chp != '\0') {
- *chp = '\0';
- chp++;
- }
-
- /* and any value */
- while (*chp != '\0' && isspace(*chp))
- chp++;
- spec->value = chp;
-
- /* now go back and chop the property off of the path */
- if (spec->value[0] == '\0') {
- spec->property = NULL; /*not a property*/
- spec->value = NULL;
- }
- else if (spec->value[0] == '>'
- || spec->value[0] == '<') {
- /* an interrupt spec */
- spec->property = NULL;
- }
- else {
- chp = strrchr(spec->path, '/');
- if (chp == NULL) {
- spec->property = spec->path;
- spec->path = strchr(spec->property, '\0');
- }
- else {
- *chp = '\0';
- spec->property = chp+1;
- }
- }
-
- /* and mark the rest as invalid */
- spec->name = NULL;
- spec->unit = NULL;
- spec->args = NULL;
- spec->last_name = NULL;
- spec->last_unit = NULL;
- spec->last_args = NULL;
-
- return 1;
-}
-
-/* given a device specifier break it up into its main components -
- path and property name - assuming that the last `device' is a
- property name. */
-STATIC_INLINE_DEVICE\
-(int)
-split_property_specifier(const char *property_specifier,
- name_specifier *spec)
-{
- if (split_device_specifier(property_specifier, spec)) {
- if (spec->property == NULL) {
- /* force the last name to be a property name */
- char *chp = strrchr(spec->path, '/');
- if (chp == NULL) {
- spec->property = spec->path;
- spec->path = strrchr(spec->property, '\0');;
- }
- else {
- *chp = '\0';
- spec->property = chp+1;
- }
- }
- return 1;
- }
- else
- return 0;
-}
-
-/* parse the next device name and split it up, return 0 when no more
- names to parse */
-STATIC_INLINE_DEVICE\
-(int)
-split_device_name(name_specifier *spec)
-{
- char *chp;
- /* remember what came before */
- spec->last_name = spec->name;
- spec->last_unit = spec->unit;
- spec->last_args = spec->args;
- /* finished? */
- if (spec->path[0] == '\0') {
- spec->name = NULL;
- spec->unit = NULL;
- spec->args = NULL;
- return 0;
- }
- /* break the device name from the path */
- spec->name = spec->path;
- chp = strchr(spec->name, '/');
- if (chp == NULL)
- spec->path = strchr(spec->name, '\0');
- else {
- spec->path = chp+1;
- *chp = '\0';
- }
- /* now break out the unit */
- chp = strchr(spec->name, '@');
- if (chp == NULL) {
- spec->unit = NULL;
- chp = spec->name;
- }
- else {
- *chp = '\0';
- chp += 1;
- spec->unit = chp;
- }
- /* finally any args */
- chp = strchr(chp, ':');
- if (chp == NULL)
- spec->args = NULL;
- else {
- *chp = '\0';
- spec->args = chp+1;
- }
- return 1;
-}
-
-/* parse the value, returning the next non-space token */
-
-STATIC_INLINE_DEVICE\
-(char *)
-split_value(name_specifier *spec)
-{
- char *token;
- if (spec->value == NULL)
- return NULL;
- /* skip leading white space */
- while (isspace(spec->value[0]))
- spec->value++;
- if (spec->value[0] == '\0') {
- spec->value = NULL;
- return NULL;
- }
- token = spec->value;
- /* find trailing space */
- while (spec->value[0] != '\0' && !isspace(spec->value[0]))
- spec->value++;
- /* chop this value out */
- if (spec->value[0] != '\0') {
- spec->value[0] = '\0';
- spec->value++;
- }
- return token;
-}
-
-
-
-/* traverse the path specified by spec starting at current */
-
-STATIC_INLINE_DEVICE\
-(device *)
-split_find_device(device *current,
- name_specifier *spec)
-{
- /* strip off (and process) any leading ., .., ./ and / */
- while (1) {
- if (strncmp(spec->path, "/", strlen("/")) == 0) {
- /* cd /... */
- while (current != NULL && current->parent != NULL)
- current = current->parent;
- spec->path += strlen("/");
- }
- else if (strncmp(spec->path, "./", strlen("./")) == 0) {
- /* cd ./... */
- current = current;
- spec->path += strlen("./");
- }
- else if (strncmp(spec->path, "../", strlen("../")) == 0) {
- /* cd ../... */
- if (current != NULL && current->parent != NULL)
- current = current->parent;
- spec->path += strlen("../");
- }
- else if (strcmp(spec->path, ".") == 0) {
- /* cd . */
- current = current;
- spec->path += strlen(".");
- }
- else if (strcmp(spec->path, "..") == 0) {
- /* cd . */
- if (current != NULL && current->parent != NULL)
- current = current->parent;
- spec->path += strlen("..");
- }
- else
- break;
- }
-
- /* now go through the path proper */
-
- if (current == NULL) {
- split_device_name(spec);
- return current;
- }
-
- while (split_device_name(spec)) {
- device_unit phys;
- device *child;
- current->callback->convert.decode_unit(current, spec->unit, &phys);
- for (child = current->children; child != NULL; child = child->sibling) {
- if (strcmp(spec->name, child->name) == 0) {
- if (phys.nr_cells == 0
- || memcmp(&phys, &child->unit_address, sizeof(device_unit)) == 0)
- break;
- }
- }
- if (child == NULL)
- return current; /* search failed */
- current = child;
- }
-
- return current;
-}
-
-
STATIC_INLINE_DEVICE\
(device *)
device_create_from(const char *name,
@@ -566,7 +249,7 @@ device_create_from(const char *name,
}
/* give it a name */
- new_device->name = strdup(name);
+ new_device->name = (char *) strdup(name);
new_device->unit_address = *unit_address;
new_device->path = device_full_name(new_device, NULL, 0);
@@ -582,35 +265,36 @@ device_create_from(const char *name,
new_device->ihandles = cap_create(name);
new_device->phandles = cap_create(name);
}
+ else {
+ new_device->ihandles = device_root(parent)->ihandles;
+ new_device->phandles = device_root(parent)->phandles;
+ }
+ cap_add(new_device->phandles, new_device);
return new_device;
}
-STATIC_INLINE_DEVICE\
+
+INLINE_DEVICE\
(device *)
-device_template_create_device(device *parent,
- const char *name,
- const char *unit_address,
- const char *args)
+device_create(device *parent,
+ const char *base,
+ const char *name,
+ const char *unit_address,
+ const char *args)
{
const device_descriptor *const *table;
- int name_len;
- char *chp;
- chp = strchr(name, '@');
- name_len = (chp == NULL ? strlen(name) : chp - name);
for (table = device_table; *table != NULL; table++) {
const device_descriptor *descr;
for (descr = *table; descr->name != NULL; descr++) {
- if (strncmp(name, descr->name, name_len) == 0
- && (descr->name[name_len] == '\0'
- || descr->name[name_len] == '@')) {
+ if (strcmp(base, descr->name) == 0) {
device_unit address = { 0 };
void *data = NULL;
- if (parent != NULL && parent->callback->convert.decode_unit != NULL)
- parent->callback->convert.decode_unit(parent,
- unit_address,
- &address);
+ if (parent != NULL)
+ if (device_decode_unit(parent, unit_address, &address) < 0)
+ device_error(parent, "invalid address %s for device %s",
+ unit_address, name);
if (descr->creator != NULL)
data = descr->creator(name, &address, args);
return device_create_from(name, &address, data,
@@ -618,10 +302,207 @@ device_template_create_device(device *parent,
}
}
}
- device_error(parent, "attempt to attach unknown device %s\n", name);
+ device_error(parent, "attempt to attach unknown device %s", name);
return NULL;
}
+
+
+INLINE_DEVICE\
+(void)
+device_usage(int verbose)
+{
+ const device_descriptor *const *table;
+ if (verbose == 1) {
+ int pos = 0;
+ for (table = device_table; *table != NULL; table++) {
+ const device_descriptor *descr;
+ for (descr = *table; descr->name != NULL; descr++) {
+ pos += strlen(descr->name) + 2;
+ if (pos > 75) {
+ pos = strlen(descr->name) + 2;
+ printf_filtered("\n");
+ }
+ printf_filtered(" %s", descr->name);
+ }
+ printf_filtered("\n");
+ }
+ }
+ if (verbose > 1) {
+ for (table = device_table; *table != NULL; table++) {
+ const device_descriptor *descr;
+ for (descr = *table; descr->name != NULL; descr++) {
+ printf_filtered(" %s:\n", descr->name);
+ /* interrupt ports */
+ if (descr->callbacks->interrupt.ports != NULL) {
+ const device_interrupt_port_descriptor *ports =
+ descr->callbacks->interrupt.ports;
+ printf_filtered(" interrupt ports:");
+ while (ports->name != NULL) {
+ printf_filtered(" %s", ports->name);
+ ports++;
+ }
+ printf_filtered("\n");
+ }
+ /* general info */
+ if (descr->callbacks->usage != NULL)
+ descr->callbacks->usage(verbose);
+ }
+ }
+ }
+}
+
+
+
+
+
+/* Device node: */
+
+INLINE_DEVICE\
+(device *)
+device_parent(device *me)
+{
+ return me->parent;
+}
+
+INLINE_DEVICE\
+(device *)
+device_root(device *me)
+{
+ ASSERT(me != NULL);
+ while (me->parent != NULL)
+ me = me->parent;
+ return me;
+}
+
+INLINE_DEVICE\
+(device *)
+device_sibling(device *me)
+{
+ return me->sibling;
+}
+
+INLINE_DEVICE\
+(device *)
+device_child(device *me)
+{
+ return me->children;
+}
+
+INLINE_DEVICE\
+(const char *)
+device_name(device *me)
+{
+ return me->name;
+}
+
+INLINE_DEVICE\
+(const char *)
+device_path(device *me)
+{
+ return me->path;
+}
+
+INLINE_DEVICE\
+(void *)
+device_data(device *me)
+{
+ return me->data;
+}
+
+INLINE_DEVICE\
+(psim *)
+device_system(device *me)
+{
+ return me->system;
+}
+
+INLINE_DEVICE\
+(const device_unit *)
+device_unit_address(device *me)
+{
+ return &me->unit_address;
+}
+
+
+INLINE_DEVICE\
+(int)
+device_address_to_attach_address(device *me,
+ const device_unit *address,
+ int *attach_space,
+ unsigned_word *attach_address,
+ device *client)
+{
+ if (me->callback->convert.address_to_attach_address == NULL)
+ device_error(me, "no convert.address_to_attach_address method");
+ return me->callback->convert.address_to_attach_address(me, address, attach_space, attach_address, client);
+}
+
+
+INLINE_DEVICE\
+(int)
+device_size_to_attach_size(device *me,
+ const device_unit *size,
+ unsigned *nr_bytes,
+ device *client)
+{
+ if (me->callback->convert.size_to_attach_size == NULL)
+ device_error(me, "no convert.size_to_attach_size method");
+ return me->callback->convert.size_to_attach_size(me, size, nr_bytes, client);
+}
+
+
+INLINE_DEVICE\
+(int)
+device_decode_unit(device *bus,
+ const char *unit,
+ device_unit *address)
+{
+ if (bus->callback->convert.decode_unit == NULL)
+ device_error(bus, "no convert.decode_unit method");
+ return bus->callback->convert.decode_unit(bus, unit, address);
+}
+
+
+INLINE_DEVICE\
+(int)
+device_encode_unit(device *bus,
+ const device_unit *unit_address,
+ char *buf,
+ int sizeof_buf)
+{
+ if (bus->callback->convert.encode_unit == NULL)
+ device_error(bus, "no convert.encode_unit method");
+ return bus->callback->convert.encode_unit(bus, unit_address, buf, sizeof_buf);
+}
+
+INLINE_DEVICE\
+(unsigned)
+device_nr_address_cells(device *me)
+{
+ if (me->nr_address_cells == 0) {
+ if (device_find_property(me, "#address-cells") != NULL)
+ me->nr_address_cells = device_find_integer_property(me, "#address-cells");
+ else
+ me->nr_address_cells = 2;
+ }
+ return me->nr_address_cells;
+}
+
+INLINE_DEVICE\
+(unsigned)
+device_nr_size_cells(device *me)
+{
+ if (me->nr_size_cells == 0) {
+ if (device_find_property(me, "#size-cells") != NULL)
+ me->nr_size_cells = device_find_integer_property(me, "#size-cells");
+ else
+ me->nr_size_cells = 1;
+ }
+ return me->nr_size_cells;
+}
+
+
/* device-instance: */
@@ -636,29 +517,40 @@ device_create_instance_from(device *me,
{
device_instance *instance = ZALLOC(device_instance);
if ((me == NULL) == (parent == NULL))
- device_error(me, "can't have both parent instance and parent device\n");
- instance->owner = me;
- instance->parent = parent;
- instance->data = data;
- instance->args = (args == NULL ? NULL : strdup(args));
- instance->path = (path == NULL ? NULL : strdup(path));
- instance->callback = callbacks;
+ device_error(me, "can't have both parent instance and parent device");
/*instance->unit*/
+ /* link this instance into the devices list */
if (me != NULL) {
+ ASSERT(parent == NULL);
+ instance->owner = me;
+ instance->parent = NULL;
+ /* link this instance into the front of the devices instance list */
instance->next = me->instances;
me->instances = instance;
}
if (parent != NULL) {
device_instance **previous;
+ ASSERT(parent->child == NULL);
parent->child = instance;
+ ASSERT(me == NULL);
instance->owner = parent->owner;
+ instance->parent = parent;
+ /* in the devices instance list replace the parent instance with
+ this one */
instance->next = parent->next;
/* replace parent with this new node */
previous = &instance->owner->instances;
- while (*previous != parent)
+ while (*previous != parent) {
+ ASSERT(*previous != NULL);
previous = &(*previous)->next;
+ }
*previous = instance;
}
+ instance->data = data;
+ instance->args = (args == NULL ? NULL : (char *) strdup(args));
+ instance->path = (path == NULL ? NULL : (char *) strdup(path));
+ instance->callback = callbacks;
+ cap_add(instance->owner->ihandles, instance);
return instance;
}
@@ -666,22 +558,16 @@ device_create_instance_from(device *me,
INLINE_DEVICE\
(device_instance *)
device_create_instance(device *me,
- const char *device_specifier)
+ const char *path,
+ const char *args)
{
- /* find the device node */
- name_specifier spec;
- if (!split_device_specifier(device_specifier, &spec))
- return NULL;
- me = split_find_device(me, &spec);
- if (spec.name != NULL)
- return NULL;
/* create the instance */
if (me->callback->instance_create == NULL)
- device_error(me, "no instance_create method\n");
- return me->callback->instance_create(me,
- device_specifier, spec.last_args);
+ device_error(me, "no instance_create method");
+ return me->callback->instance_create(me, path, args);
}
+
STATIC_INLINE_DEVICE\
(void)
clean_device_instances(device *me)
@@ -694,24 +580,40 @@ clean_device_instances(device *me)
}
}
+
INLINE_DEVICE\
(void)
device_instance_delete(device_instance *instance)
{
device *me = instance->owner;
- device_instance **curr;
if (instance->callback->delete == NULL)
- device_error(me, "no delete method\n");
+ device_error(me, "no delete method");
instance->callback->delete(instance);
if (instance->args != NULL)
zfree(instance->args);
if (instance->path != NULL)
zfree(instance->path);
- curr = &me->instances;
- while (*curr != NULL && *curr != instance)
- curr = &(*curr)->next;
- ASSERT(*curr != NULL);
- *curr = instance->next;
+ if (instance->child == NULL) {
+ /* only remove leaf nodes */
+ device_instance **curr = &me->instances;
+ while (*curr != instance) {
+ ASSERT(*curr != NULL);
+ curr = &(*curr)->next;
+ }
+ *curr = instance->next;
+ }
+ else {
+ /* check it isn't in the instance list */
+ device_instance *curr = me->instances;
+ while (curr != NULL) {
+ ASSERT(curr != instance);
+ curr = curr->next;
+ }
+ /* unlink the child */
+ ASSERT(instance->child->parent == instance);
+ instance->child->parent = NULL;
+ }
+ cap_remove(me->ihandles, instance);
zfree(instance);
}
@@ -723,7 +625,7 @@ device_instance_read(device_instance *instance,
{
device *me = instance->owner;
if (instance->callback->read == NULL)
- device_error(me, "no read method\n");
+ device_error(me, "no read method");
return instance->callback->read(instance, addr, len);
}
@@ -735,7 +637,7 @@ device_instance_write(device_instance *instance,
{
device *me = instance->owner;
if (instance->callback->write == NULL)
- device_error(me, "no write method\n");
+ device_error(me, "no write method");
return instance->callback->write(instance, addr, len);
}
@@ -747,34 +649,36 @@ device_instance_seek(device_instance *instance,
{
device *me = instance->owner;
if (instance->callback->seek == NULL)
- device_error(me, "no seek method\n");
+ device_error(me, "no seek method");
return instance->callback->seek(instance, pos_hi, pos_lo);
}
INLINE_DEVICE\
-(unsigned_word)
-device_instance_claim(device_instance *instance,
- unsigned_word address,
- unsigned_word length,
- unsigned_word alignment)
+(int)
+device_instance_call_method(device_instance *instance,
+ const char *method_name,
+ int n_stack_args,
+ unsigned_cell stack_args[/*n_stack_args*/],
+ int n_stack_returns,
+ unsigned_cell stack_returns[/*n_stack_args*/])
{
device *me = instance->owner;
- if (instance->callback->claim == NULL)
- device_error(me, "no claim method\n");
- return instance->callback->claim(instance, address, length, alignment);
+ const device_instance_methods *method = instance->callback->methods;
+ if (method == NULL) {
+ device_error(me, "no methods (want %s)", method_name);
+ }
+ while (method->name != NULL) {
+ if (strcmp(method->name, method_name) == 0) {
+ return method->method(instance,
+ n_stack_args, stack_args,
+ n_stack_returns, stack_returns);
+ }
+ method++;
+ }
+ device_error(me, "no %s method", method_name);
+ return 0;
}
-INLINE_DEVICE\
-(void)
-device_instance_release(device_instance *instance,
- unsigned_word address,
- unsigned_word length)
-{
- device *me = instance->owner;
- if (instance->callback->release == NULL)
- device_error(me, "no release method\n");
- instance->callback->release(instance, address, length);
-}
INLINE_DEVICE\
(device *)
@@ -799,64 +703,24 @@ device_instance_data(device_instance *instance)
-/* Device initialization: */
-
-STATIC_INLINE_DEVICE\
-(void)
-clean_device(device *root,
- void *data)
-{
- psim *system;
- system = (psim*)data;
- clean_device_interrupt_edges(&root->interrupt_destinations);
- clean_device_instances(root);
- clean_device_properties(root);
-}
-
-STATIC_INLINE_DEVICE\
-(void)
-init_device_address(device *me,
- void *data)
-{
- psim *system = (psim*)data;
- TRACE(trace_device_init, ("init_device_address() initializing %s\n", me->path));
- me->system = system; /* misc things not known until now */
- if (me->callback->init.address != NULL)
- me->callback->init.address(me);
-}
+/* Device Properties: */
STATIC_INLINE_DEVICE\
-(void)
-init_device_data(device *me,
- void *data)
-{
- TRACE(trace_device_init, ("device_init_data() initializing %s\n", me->path));
- if (me->callback->init.data != NULL)
- me->callback->init.data(me);
-}
-
-INLINE_DEVICE\
-(void)
-device_tree_init(device *root,
- psim *system)
+(device_property_entry *)
+find_property_entry(device *me,
+ const char *property)
{
- TRACE(trace_device_tree, ("device_tree_init(root=0x%lx, system=0x%lx)\n",
- (long)root,
- (long)system));
- /* remove the old, rebuild the new */
- device_tree_traverse(root, clean_device, NULL, system);
- TRACE(trace_tbd, ("Need to dump the device tree here\n"));
- device_tree_traverse(root, init_device_address, NULL, system);
- device_tree_traverse(root, init_device_properties, NULL, system);
- device_tree_traverse(root, init_device_data, NULL, system);
- TRACE(trace_device_tree, ("device_tree_init() = void\n"));
+ device_property_entry *entry;
+ ASSERT(property != NULL);
+ entry = me->properties;
+ while (entry != NULL) {
+ if (strcmp(entry->value->name, property) == 0)
+ return entry;
+ entry = entry->next;
+ }
+ return NULL;
}
-
-
-/* Device Properties: */
-
-/* local - not available externally */
STATIC_INLINE_DEVICE\
(void)
device_add_property(device *me,
@@ -871,8 +735,6 @@ device_add_property(device *me,
{
device_property_entry *new_entry = NULL;
device_property *new_value = NULL;
- void *new_array = NULL;
- void *new_init_array = NULL;
/* find the list end */
device_property_entry **insertion_point = &me->properties;
@@ -884,26 +746,28 @@ device_add_property(device *me,
/* create a new value */
new_value = ZALLOC(device_property);
- new_value->name = strdup(property);
+ new_value->name = (char *) strdup(property);
new_value->type = type;
- new_value->sizeof_array = sizeof_array;
- new_array = (sizeof_array > 0 ? zalloc(sizeof_array) : NULL);
- new_value->array = new_array;
+ if (sizeof_array > 0) {
+ void *new_array = zalloc(sizeof_array);
+ memcpy(new_array, array, sizeof_array);
+ new_value->array = new_array;
+ new_value->sizeof_array = sizeof_array;
+ }
new_value->owner = me;
new_value->original = original;
new_value->disposition = disposition;
- if (sizeof_array > 0)
- memcpy(new_array, array, sizeof_array);
/* insert the value into the list */
new_entry = ZALLOC(device_property_entry);
*insertion_point = new_entry;
- new_entry->sizeof_init_array = sizeof_init_array;
- new_init_array = (sizeof_init_array > 0 ? zalloc(sizeof_init_array) : NULL);
- new_entry->init_array = new_init_array;
- new_entry->value = new_value;
- if (sizeof_init_array > 0)
+ if (sizeof_init_array > 0) {
+ void *new_init_array = zalloc(sizeof_init_array);
memcpy(new_init_array, init_array, sizeof_init_array);
+ new_entry->init_array = new_init_array;
+ new_entry->sizeof_init_array = sizeof_init_array;
+ }
+ new_entry->value = new_value;
}
@@ -915,35 +779,35 @@ device_set_property(device *me,
const char *property,
device_property_type type,
const void *array,
- int sizeof_array,
- const device_property *original)
+ int sizeof_array)
{
/* find the property */
- device_property_entry *entry = me->properties;
- while (entry != NULL) {
- if (strcmp(entry->value->name, property) == 0) {
- void *new_array = 0;
- device_property *value = entry->value;
- /* check the type matches */
- if (value->type != type)
- device_error(me, "conflict between type of new and old value for property %s\n", property);
- /* replace its value */
- if (value->array != NULL)
- zfree((void*)value->array);
- new_array = (sizeof_array > 0
- ? zalloc(sizeof_array)
- : (void*)0);
- value->array = new_array;
- value->sizeof_array = sizeof_array;
- if (sizeof_array > 0)
- memcpy(new_array, array, sizeof_array);
- return;
- }
- entry = entry->next;
+ device_property_entry *entry = find_property_entry(me, property);
+ if (entry != NULL) {
+ /* existing property - update it */
+ void *new_array = 0;
+ device_property *value = entry->value;
+ /* check the type matches */
+ if (value->type != type)
+ device_error(me, "conflict between type of new and old value for property %s", property);
+ /* replace its value */
+ if (value->array != NULL)
+ zfree((void*)value->array);
+ new_array = (sizeof_array > 0
+ ? zalloc(sizeof_array)
+ : (void*)0);
+ value->array = new_array;
+ value->sizeof_array = sizeof_array;
+ if (sizeof_array > 0)
+ memcpy(new_array, array, sizeof_array);
+ return;
+ }
+ else {
+ /* new property - create it */
+ device_add_property(me, property, type,
+ NULL, 0, array, sizeof_array,
+ NULL, tempoary_object);
}
- device_add_property(me, property, type,
- NULL, 0, array, sizeof_array,
- original, tempoary_object);
}
@@ -954,70 +818,105 @@ clean_device_properties(device *me)
device_property_entry **delete_point = &me->properties;
while (*delete_point != NULL) {
device_property_entry *current = *delete_point;
- device_property *property = current->value;
switch (current->value->disposition) {
case permenant_object:
- {
- /* delete the property, and replace it with the original */
- ASSERT(((property->array == NULL) == (current->init_array == NULL))
- || property->type == ihandle_property);
- if (current->init_array != NULL) {
- zfree((void*)current->value->array);
- current->value->array = NULL;
- if (property->type != ihandle_property) {
- device_set_property(me, property->name,
- property->type,
- current->init_array, current->sizeof_init_array,
- NULL);
- }
- }
- delete_point = &(*delete_point)->next;
+ /* zap the current value, will be initialized later */
+ ASSERT(current->init_array != NULL);
+ if (current->value->array != NULL) {
+ zfree((void*)current->value->array);
+ current->value->array = NULL;
}
+ delete_point = &(*delete_point)->next;
break;
case tempoary_object:
- {
- /* zap the actual property, was created during simulation run */
- *delete_point = current->next;
- if (current->value->array != NULL)
- zfree((void*)current->value->array);
- zfree(current->value);
- zfree(current);
- }
+ /* zap the actual property, was created during simulation run */
+ ASSERT(current->init_array == NULL);
+ *delete_point = current->next;
+ if (current->value->array != NULL)
+ zfree((void*)current->value->array);
+ zfree(current->value);
+ zfree(current);
break;
}
}
}
-STATIC_INLINE_DEVICE\
+INLINE_DEVICE\
(void)
-init_device_properties(device *me,
- void *data)
-{
- device_property_entry *property = me->properties;
- while (property != NULL) {
- /* now do the phandles */
- if (property->value->type == ihandle_property) {
- if (property->value->original != NULL) {
- const device_property *original = property->value->original;
- if (original->array == NULL) {
- init_device_properties(original->owner, data);
+device_init_static_properties(device *me,
+ void *data)
+{
+ device_property_entry *property;
+ for (property = me->properties;
+ property != NULL;
+ property = property->next) {
+ ASSERT(property->init_array != NULL);
+ ASSERT(property->value->array == NULL);
+ ASSERT(property->value->disposition == permenant_object);
+ switch (property->value->type) {
+ case array_property:
+ case boolean_property:
+ case range_array_property:
+ case reg_array_property:
+ case string_property:
+ case string_array_property:
+ case integer_property:
+ /* delete the property, and replace it with the original */
+ device_set_property(me, property->value->name,
+ property->value->type,
+ property->init_array,
+ property->sizeof_init_array);
+ break;
+ case ihandle_property:
+ break;
+ }
+ }
+}
+
+
+INLINE_DEVICE\
+(void)
+device_init_runtime_properties(device *me,
+ void *data)
+{
+ device_property_entry *property;
+ for (property = me->properties;
+ property != NULL;
+ property = property->next) {
+ switch (property->value->disposition) {
+ case permenant_object:
+ switch (property->value->type) {
+ case ihandle_property:
+ {
+ device_instance *ihandle;
+ ihandle_runtime_property_spec spec;
+ ASSERT(property->init_array != NULL);
+ ASSERT(property->value->array == NULL);
+ device_find_ihandle_runtime_property(me, property->value->name, &spec);
+ ihandle = device_create_instance(spec.phandle,
+ spec.full_path,
+ spec.args);
+ device_set_ihandle_property(me, property->value->name, ihandle);
+ break;
}
- ASSERT(original->array != NULL);
- device_set_property(me, property->value->name,
- ihandle_property,
- original->array, original->sizeof_array, NULL);
- }
- else {
- device_instance *instance =
- device_create_instance(me, (char*)property->init_array);
- unsigned32 ihandle = H2BE_4(device_instance_to_external(instance));
- device_set_property(me, property->value->name,
- ihandle_property,
- &ihandle, sizeof(ihandle), NULL);
+ case array_property:
+ case boolean_property:
+ case range_array_property:
+ case integer_property:
+ case reg_array_property:
+ case string_property:
+ case string_array_property:
+ ASSERT(property->init_array != NULL);
+ ASSERT(property->value->array != NULL);
+ break;
}
+ break;
+ case tempoary_object:
+ ASSERT(property->init_array == NULL);
+ ASSERT(property->value->array != NULL);
+ break;
}
- property = property->next;
}
}
@@ -1039,12 +938,12 @@ device_next_property(const device_property *property)
return NULL;
}
+
INLINE_DEVICE\
(const device_property *)
device_find_property(device *me,
const char *property)
{
- name_specifier spec;
if (me == NULL) {
return NULL;
}
@@ -1054,33 +953,25 @@ device_find_property(device *me,
else
return me->properties->value;
}
- else if (split_property_specifier(property, &spec)) {
- me = split_find_device(me, &spec);
- if (spec.name == NULL) { /*got to root*/
- device_property_entry *entry = me->properties;
- while (entry != NULL) {
- if (strcmp(entry->value->name, spec.property) == 0)
- return entry->value;
- entry = entry->next;
- }
- }
+ else {
+ device_property_entry *entry = find_property_entry(me, property);
+ if (entry != NULL)
+ return entry->value;
}
return NULL;
}
-STATIC_INLINE_DEVICE\
+
+INLINE_DEVICE\
(void)
device_add_array_property(device *me,
- const char *property,
- const void *array,
- int sizeof_array)
+ const char *property,
+ const void *array,
+ int sizeof_array)
{
- TRACE(trace_devices,
- ("device_add_array_property(me=0x%lx, property=%s, ...)\n",
- (long)me, property));
device_add_property(me, property, array_property,
- array, sizeof_array, array, sizeof_array,
- NULL, permenant_object);
+ array, sizeof_array, array, sizeof_array,
+ NULL, permenant_object);
}
INLINE_DEVICE\
@@ -1090,10 +981,7 @@ device_set_array_property(device *me,
const void *array,
int sizeof_array)
{
- TRACE(trace_devices,
- ("device_set_array_property(me=0x%lx, property=%s, ...)\n",
- (long)me, property));
- device_set_property(me, property, array_property, array, sizeof_array, NULL);
+ device_set_property(me, property, array_property, array, sizeof_array);
}
INLINE_DEVICE\
@@ -1102,31 +990,25 @@ device_find_array_property(device *me,
const char *property)
{
const device_property *node;
- TRACE(trace_devices,
- ("device_find_integer(me=0x%lx, property=%s)\n",
- (long)me, property));
node = device_find_property(me, property);
if (node == (device_property*)0
|| node->type != array_property)
- device_error(me, "property %s not found or of wrong type\n", property);
+ device_error(me, "property %s not found or of wrong type", property);
return node;
}
-STATIC_INLINE_DEVICE\
+INLINE_DEVICE\
(void)
device_add_boolean_property(device *me,
- const char *property,
- int boolean)
+ const char *property,
+ int boolean)
{
signed32 new_boolean = (boolean ? -1 : 0);
- TRACE(trace_devices,
- ("device_add_boolean(me=0x%lx, property=%s, boolean=%d)\n",
- (long)me, property, boolean));
device_add_property(me, property, boolean_property,
- &new_boolean, sizeof(new_boolean),
- &new_boolean, sizeof(new_boolean),
- NULL, permenant_object);
+ &new_boolean, sizeof(new_boolean),
+ &new_boolean, sizeof(new_boolean),
+ NULL, permenant_object);
}
INLINE_DEVICE\
@@ -1135,108 +1017,427 @@ device_find_boolean_property(device *me,
const char *property)
{
const device_property *node;
- unsigned32 boolean;
- TRACE(trace_devices,
- ("device_find_boolean(me=0x%lx, property=%s)\n",
- (long)me, property));
+ unsigned_cell boolean;
node = device_find_property(me, property);
if (node == (device_property*)0
|| node->type != boolean_property)
- device_error(me, "property %s not found or of wrong type\n", property);
+ device_error(me, "property %s not found or of wrong type", property);
ASSERT(sizeof(boolean) == node->sizeof_array);
memcpy(&boolean, node->array, sizeof(boolean));
return boolean;
}
-STATIC_INLINE_DEVICE\
+
+INLINE_DEVICE\
(void)
-device_add_ihandle_property(device *me,
- const char *property,
- const char *path)
+device_add_ihandle_runtime_property(device *me,
+ const char *property,
+ const ihandle_runtime_property_spec *ihandle)
{
- TRACE(trace_devices,
- ("device_add_ihandle_property(me=0x%lx, property=%s, path=%s)\n",
- (long)me, property, path));
+ unsigned_cell *cells;
+ char *chp;
+ unsigned sizeof_cells = (sizeof(unsigned_cell) * 3
+ + (strlen(ihandle->full_path) + 1)
+ + (ihandle->args != NULL
+ ? (strlen(ihandle->args) + 1)
+ : 0));
+
+ /* the basics */
+ cells = zalloc(sizeof_cells);
+ cells[0] = H2BE_cell(device_to_external(ihandle->phandle));
+ cells[1] = (ihandle->full_path == NULL ? 0 : -1);
+ cells[2] = (ihandle->args == NULL ? 0 : -1);
+ chp = (char*)&cells[3];
+
+ /* the full path (if present) */
+ if (ihandle->full_path != NULL) {
+ strcpy(chp, ihandle->full_path);
+ chp += strlen(ihandle->full_path) + 1;
+ }
+
+ /* the args (if present) */
+ if (ihandle->args != NULL) {
+ strcpy(chp, ihandle->args);
+ chp += strlen(ihandle->args) + 1;
+ }
+
+ /* add it */
+ ASSERT(sizeof_cells == (chp - (char*)cells));
device_add_property(me, property, ihandle_property,
- path, strlen(path) + 1,
+ cells, sizeof_cells,
NULL, 0,
NULL, permenant_object);
}
INLINE_DEVICE\
+(void)
+device_find_ihandle_runtime_property(device *me,
+ const char *property,
+ ihandle_runtime_property_spec *ihandle)
+{
+ const unsigned_cell *cells;
+ const char *chp;
+ device_property_entry *entry = find_property_entry(me, property);
+ TRACE(trace_devices,
+ ("device_find_ihandle_runtime_property(me=0x%lx, property=%s)\n",
+ (long)me, property));
+ if (entry == NULL
+ || entry->value->type != ihandle_property
+ || entry->value->disposition != permenant_object)
+ device_error(me, "property %s not found or of wrong type", property);
+ cells = entry->init_array;
+ chp = (char*)&cells[3];
+ ASSERT(entry->init_array != NULL);
+ /* the device to be opened */
+ ihandle->phandle = external_to_device(me, BE2H_cell(cells[0]));
+ /* the full path */
+ if (cells[1] != 0) {
+ ihandle->full_path = chp;
+ chp += strlen(ihandle->full_path) + 1;
+ }
+ else
+ ihandle->full_path = NULL;
+ /* the args */
+ if (cells[2] != 0) {
+ ihandle->args = chp;
+ chp += strlen(ihandle->args) + 1;
+ }
+ else
+ ihandle->args = NULL;
+ /* reached the end? */
+ ASSERT(entry->sizeof_init_array
+ == (chp - (char*)cells));
+ return;
+}
+
+
+
+INLINE_DEVICE\
+(void)
+device_set_ihandle_property(device *me,
+ const char *property,
+ device_instance *ihandle)
+{
+ unsigned_cell cells;
+ cells = H2BE_cell(device_instance_to_external(ihandle));
+ device_set_property(me, property, ihandle_property,
+ &cells, sizeof(cells));
+
+}
+
+INLINE_DEVICE\
(device_instance *)
device_find_ihandle_property(device *me,
const char *property)
{
const device_property *node;
- unsigned32 ihandle;
+ unsigned_cell ihandle;
device_instance *instance;
- TRACE(trace_devices,
- ("device_find_ihandle_property(me=0x%lx, property=%s)\n",
- (long)me, property));
+
node = device_find_property(me, property);
if (node == NULL || node->type != ihandle_property)
- device_error(me, "property %s not found or of wrong type\n", property);
+ device_error(me, "property %s not found or of wrong type", property);
if (node->array == NULL)
- device_error(me, "property %s not yet initialized\n", property);
+ device_error(me, "runtime property %s not yet initialized", property);
+
ASSERT(sizeof(ihandle) == node->sizeof_array);
memcpy(&ihandle, node->array, sizeof(ihandle));
- BE2H(ihandle);
- instance = external_to_device_instance(me, ihandle);
+ instance = external_to_device_instance(me, BE2H_cell(ihandle));
ASSERT(instance != NULL);
return instance;
}
-STATIC_INLINE_DEVICE\
+
+INLINE_DEVICE\
(void)
device_add_integer_property(device *me,
const char *property,
- signed32 integer)
+ signed_cell integer)
{
- TRACE(trace_devices,
- ("device_add_integer_property(me=0x%lx, property=%s, integer=%ld)\n",
- (long)me, property, (long)integer));
H2BE(integer);
device_add_property(me, property, integer_property,
- &integer, sizeof(integer),
- &integer, sizeof(integer),
- NULL, permenant_object);
+ &integer, sizeof(integer),
+ &integer, sizeof(integer),
+ NULL, permenant_object);
}
INLINE_DEVICE\
-(signed_word)
+(signed_cell)
device_find_integer_property(device *me,
const char *property)
{
const device_property *node;
- signed32 integer;
+ signed_cell integer;
TRACE(trace_devices,
("device_find_integer(me=0x%lx, property=%s)\n",
(long)me, property));
node = device_find_property(me, property);
if (node == (device_property*)0
|| node->type != integer_property)
- device_error(me, "property %s not found or of wrong type\n", property);
+ device_error(me, "property %s not found or of wrong type", property);
ASSERT(sizeof(integer) == node->sizeof_array);
memcpy(&integer, node->array, sizeof(integer));
- BE2H(integer);
- return integer;
+ return BE2H_cell(integer);
+}
+
+INLINE_DEVICE\
+(int)
+device_find_integer_array_property(device *me,
+ const char *property,
+ unsigned index,
+ signed_cell *integer)
+{
+ const device_property *node;
+ int sizeof_integer = sizeof(*integer);
+ signed_cell *cell;
+ TRACE(trace_devices,
+ ("device_find_integer(me=0x%lx, property=%s)\n",
+ (long)me, property));
+
+ /* check things sane */
+ node = device_find_property(me, property);
+ if (node == (device_property*)0
+ || (node->type != integer_property
+ && node->type != array_property))
+ device_error(me, "property %s not found or of wrong type", property);
+ if ((node->sizeof_array % sizeof_integer) != 0)
+ device_error(me, "property %s contains an incomplete number of cells", property);
+ if (node->sizeof_array <= sizeof_integer * index)
+ return 0;
+
+ /* Find and convert the value */
+ cell = ((signed_cell*)node->array) + index;
+ *integer = BE2H_cell(*cell);
+
+ return node->sizeof_array / sizeof_integer;
}
+
STATIC_INLINE_DEVICE\
+(unsigned_cell *)
+unit_address_to_cells(const device_unit *unit,
+ unsigned_cell *cell,
+ int nr_cells)
+{
+ int i;
+ ASSERT(nr_cells == unit->nr_cells);
+ for (i = 0; i < unit->nr_cells; i++) {
+ *cell = H2BE_cell(unit->cells[i]);
+ cell += 1;
+ }
+ return cell;
+}
+
+
+STATIC_INLINE_DEVICE\
+(const unsigned_cell *)
+cells_to_unit_address(const unsigned_cell *cell,
+ device_unit *unit,
+ int nr_cells)
+{
+ int i;
+ memset(unit, 0, sizeof(*unit));
+ unit->nr_cells = nr_cells;
+ for (i = 0; i < unit->nr_cells; i++) {
+ unit->cells[i] = BE2H_cell(*cell);
+ cell += 1;
+ }
+ return cell;
+}
+
+
+STATIC_INLINE_DEVICE\
+(unsigned)
+nr_range_property_cells(device *me,
+ int nr_ranges)
+{
+ return ((device_nr_address_cells(me)
+ + device_nr_address_cells(device_parent(me))
+ + device_nr_size_cells(me))
+ ) * nr_ranges;
+}
+
+INLINE_DEVICE\
(void)
-device_add_string_property(device *me,
- const char *property,
- const char *string)
+device_add_range_array_property(device *me,
+ const char *property,
+ const range_property_spec *ranges,
+ unsigned nr_ranges)
+{
+ unsigned sizeof_cells = (nr_range_property_cells(me, nr_ranges)
+ * sizeof(unsigned_cell));
+ unsigned_cell *cells = zalloc(sizeof_cells);
+ unsigned_cell *cell;
+ int i;
+
+ /* copy the property elements over */
+ cell = cells;
+ for (i = 0; i < nr_ranges; i++) {
+ const range_property_spec *range = &ranges[i];
+ /* copy the child address */
+ cell = unit_address_to_cells(&range->child_address, cell,
+ device_nr_address_cells(me));
+ /* copy the parent address */
+ cell = unit_address_to_cells(&range->parent_address, cell,
+ device_nr_address_cells(device_parent(me)));
+ /* copy the size */
+ cell = unit_address_to_cells(&range->size, cell,
+ device_nr_size_cells(me));
+ }
+ ASSERT(cell == &cells[nr_range_property_cells(me, nr_ranges)]);
+
+ /* add it */
+ device_add_property(me, property, range_array_property,
+ cells, sizeof_cells,
+ cells, sizeof_cells,
+ NULL, permenant_object);
+
+ zfree(cells);
+}
+
+INLINE_DEVICE\
+(int)
+device_find_range_array_property(device *me,
+ const char *property,
+ unsigned index,
+ range_property_spec *range)
{
+ const device_property *node;
+ unsigned sizeof_entry = (nr_range_property_cells(me, 1)
+ * sizeof(unsigned_cell));
+ const unsigned_cell *cells;
- TRACE(trace_devices,
- ("device_add_property(me=0x%lx, property=%s, string=%s)\n",
- (long)me, property, string));
- device_add_property(me, property, string_property,
- string, strlen(string) + 1,
- string, strlen(string) + 1,
+ /* locate the property */
+ node = device_find_property(me, property);
+ if (node == (device_property*)0
+ || node->type != range_array_property)
+ device_error(me, "property %s not found or of wrong type", property);
+
+ /* aligned ? */
+ if ((node->sizeof_array % sizeof_entry) != 0)
+ device_error(me, "property %s contains an incomplete number of entries",
+ property);
+
+ /* within bounds? */
+ if (node->sizeof_array < sizeof_entry * (index + 1))
+ return 0;
+
+ /* find the range of interest */
+ cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
+
+ /* copy the child address out - converting as we go */
+ cells = cells_to_unit_address(cells, &range->child_address,
+ device_nr_address_cells(me));
+
+ /* copy the parent address out - converting as we go */
+ cells = cells_to_unit_address(cells, &range->parent_address,
+ device_nr_address_cells(device_parent(me)));
+
+ /* copy the size - converting as we go */
+ cells = cells_to_unit_address(cells, &range->size,
+ device_nr_size_cells(me));
+
+ return node->sizeof_array / sizeof_entry;
+}
+
+
+STATIC_INLINE_DEVICE\
+(unsigned)
+nr_reg_property_cells(device *me,
+ int nr_regs)
+{
+ return (device_nr_address_cells(device_parent(me))
+ + device_nr_size_cells(device_parent(me))
+ ) * nr_regs;
+}
+
+INLINE_DEVICE\
+(void)
+device_add_reg_array_property(device *me,
+ const char *property,
+ const reg_property_spec *regs,
+ unsigned nr_regs)
+{
+ unsigned sizeof_cells = (nr_reg_property_cells(me, nr_regs)
+ * sizeof(unsigned_cell));
+ unsigned_cell *cells = zalloc(sizeof_cells);
+ unsigned_cell *cell;
+ int i;
+
+ /* copy the property elements over */
+ cell = cells;
+ for (i = 0; i < nr_regs; i++) {
+ const reg_property_spec *reg = &regs[i];
+ /* copy the address */
+ cell = unit_address_to_cells(&reg->address, cell,
+ device_nr_address_cells(device_parent(me)));
+ /* copy the size */
+ cell = unit_address_to_cells(&reg->size, cell,
+ device_nr_size_cells(device_parent(me)));
+ }
+ ASSERT(cell == &cells[nr_reg_property_cells(me, nr_regs)]);
+
+ /* add it */
+ device_add_property(me, property, reg_array_property,
+ cells, sizeof_cells,
+ cells, sizeof_cells,
NULL, permenant_object);
+
+ zfree(cells);
+}
+
+INLINE_DEVICE\
+(int)
+device_find_reg_array_property(device *me,
+ const char *property,
+ unsigned index,
+ reg_property_spec *reg)
+{
+ const device_property *node;
+ unsigned sizeof_entry = (nr_reg_property_cells(me, 1)
+ * sizeof(unsigned_cell));
+ const unsigned_cell *cells;
+
+ /* locate the property */
+ node = device_find_property(me, property);
+ if (node == (device_property*)0
+ || node->type != reg_array_property)
+ device_error(me, "property %s not found or of wrong type", property);
+
+ /* aligned ? */
+ if ((node->sizeof_array % sizeof_entry) != 0)
+ device_error(me, "property %s contains an incomplete number of entries",
+ property);
+
+ /* within bounds? */
+ if (node->sizeof_array < sizeof_entry * (index + 1))
+ return 0;
+
+ /* find the range of interest */
+ cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
+
+ /* copy the address out - converting as we go */
+ cells = cells_to_unit_address(cells, &reg->address,
+ device_nr_address_cells(device_parent(me)));
+
+ /* copy the size out - converting as we go */
+ cells = cells_to_unit_address(cells, &reg->size,
+ device_nr_size_cells(device_parent(me)));
+
+ return node->sizeof_array / sizeof_entry;
+}
+
+
+INLINE_DEVICE\
+(void)
+device_add_string_property(device *me,
+ const char *property,
+ const char *string)
+{
+ device_add_property(me, property, string_property,
+ string, strlen(string) + 1,
+ string, strlen(string) + 1,
+ NULL, permenant_object);
}
INLINE_DEVICE\
@@ -1246,32 +1447,133 @@ device_find_string_property(device *me,
{
const device_property *node;
const char *string;
- TRACE(trace_devices,
- ("device_find_string(me=0x%lx, property=%s)\n",
- (long)me, property));
node = device_find_property(me, property);
if (node == (device_property*)0
|| node->type != string_property)
- device_error(me, "property %s not found or of wrong type\n", property);
+ device_error(me, "property %s not found or of wrong type", property);
string = node->array;
ASSERT(strlen(string) + 1 == node->sizeof_array);
return string;
}
-STATIC_INLINE_DEVICE\
+INLINE_DEVICE\
+(void)
+device_add_string_array_property(device *me,
+ const char *property,
+ const string_property_spec *strings,
+ unsigned nr_strings)
+{
+ int sizeof_array;
+ int string_nr;
+ char *array;
+ char *chp;
+ if (nr_strings == 0)
+ device_error(me, "property %s must be non-null", property);
+ /* total up the size of the needed array */
+ for (sizeof_array = 0, string_nr = 0;
+ string_nr < nr_strings;
+ string_nr ++) {
+ sizeof_array += strlen(strings[string_nr]) + 1;
+ }
+ /* create the array */
+ array = (char*)zalloc(sizeof_array);
+ chp = array;
+ for (string_nr = 0;
+ string_nr < nr_strings;
+ string_nr++) {
+ strcpy(chp, strings[string_nr]);
+ chp += strlen(chp) + 1;
+ }
+ ASSERT(chp == array + sizeof_array);
+ /* now enter it */
+ device_add_property(me, property, string_array_property,
+ array, sizeof_array,
+ array, sizeof_array,
+ NULL, permenant_object);
+}
+
+INLINE_DEVICE\
+(int)
+device_find_string_array_property(device *me,
+ const char *property,
+ unsigned index,
+ string_property_spec *string)
+{
+ const device_property *node;
+ node = device_find_property(me, property);
+ if (node == (device_property*)0)
+ device_error(me, "property %s not found", property);
+ switch (node->type) {
+ default:
+ device_error(me, "property %s of wrong type", property);
+ break;
+ case string_property:
+ if (index == 0) {
+ *string = node->array;
+ ASSERT(strlen(*string) + 1 == node->sizeof_array);
+ return 1;
+ }
+ break;
+ case array_property:
+ if (node->sizeof_array == 0
+ || ((char*)node->array)[node->sizeof_array - 1] != '\0')
+ device_error(me, "property %s invalid for string array", property);
+ /* FALL THROUGH */
+ case string_array_property:
+ ASSERT(node->sizeof_array > 0);
+ ASSERT(((char*)node->array)[node->sizeof_array - 1] == '\0');
+ {
+ const char *chp = node->array;
+ int nr_entries = 0;
+ /* count the number of strings, keeping an eye out for the one
+ we're looking for */
+ *string = chp;
+ do {
+ if (*chp == '\0') {
+ /* next string */
+ nr_entries++;
+ chp++;
+ if (nr_entries == index)
+ *string = chp;
+ }
+ else {
+ chp++;
+ }
+ } while (chp < (char*)node->array + node->sizeof_array);
+ if (index < nr_entries)
+ return nr_entries;
+ else {
+ *string = NULL;
+ return 0;
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+INLINE_DEVICE\
(void)
device_add_duplicate_property(device *me,
const char *property,
const device_property *original)
{
+ device_property_entry *master;
TRACE(trace_devices,
("device_add_duplicate_property(me=0x%lx, property=%s, ...)\n",
(long)me, property));
if (original->disposition != permenant_object)
- device_error(me, "Can only duplicate permenant objects\n");
+ device_error(me, "Can only duplicate permenant objects");
+ /* find the original's master */
+ master = original->owner->properties;
+ while (master->value != original) {
+ master = master->next;
+ ASSERT(master != NULL);
+ }
+ /* now duplicate it */
device_add_property(me, property,
original->type,
- original->array, original->sizeof_array,
+ master->init_array, master->sizeof_init_array,
original->array, original->sizeof_array,
original, permenant_object);
}
@@ -1291,7 +1593,7 @@ device_io_read_buffer(device *me,
unsigned_word cia)
{
if (me->callback->io.read_buffer == NULL)
- device_error(me, "no io_read_buffer method\n");
+ device_error(me, "no io.read_buffer method");
return me->callback->io.read_buffer(me, dest, space,
addr, nr_bytes,
processor, cia);
@@ -1308,7 +1610,7 @@ device_io_write_buffer(device *me,
unsigned_word cia)
{
if (me->callback->io.write_buffer == NULL)
- device_error(me, "no io_write_buffer method\n");
+ device_error(me, "no io.write_buffer method");
return me->callback->io.write_buffer(me, source, space,
addr, nr_bytes,
processor, cia);
@@ -1323,7 +1625,7 @@ device_dma_read_buffer(device *me,
unsigned nr_bytes)
{
if (me->callback->dma.read_buffer == NULL)
- device_error(me, "no dma_read_buffer method\n");
+ device_error(me, "no dma.read_buffer method");
return me->callback->dma.read_buffer(me, dest, space,
addr, nr_bytes);
}
@@ -1338,7 +1640,7 @@ device_dma_write_buffer(device *me,
int violate_read_only_section)
{
if (me->callback->dma.write_buffer == NULL)
- device_error(me, "no dma_write_buffer method\n");
+ device_error(me, "no dma.write_buffer method");
return me->callback->dma.write_buffer(me, source, space,
addr, nr_bytes,
violate_read_only_section);
@@ -1347,35 +1649,33 @@ device_dma_write_buffer(device *me,
INLINE_DEVICE\
(void)
device_attach_address(device *me,
- const char *name,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
- device *who) /*callback/default*/
+ device *client) /*callback/default*/
{
if (me->callback->address.attach == NULL)
- device_error(me, "no address_attach method\n");
- me->callback->address.attach(me, name, attach, space,
- addr, nr_bytes, access, who);
+ device_error(me, "no address.attach method");
+ me->callback->address.attach(me, attach, space,
+ addr, nr_bytes, access, client);
}
INLINE_DEVICE\
(void)
device_detach_address(device *me,
- const char *name,
attach_type attach,
int space,
unsigned_word addr,
unsigned nr_bytes,
access_type access,
- device *who) /*callback/default*/
+ device *client) /*callback/default*/
{
if (me->callback->address.detach == NULL)
- device_error(me, "no address_detach method\n");
- me->callback->address.detach(me, name, attach, space,
- addr, nr_bytes, access, who);
+ device_error(me, "no address.detach method");
+ me->callback->address.detach(me, attach, space,
+ addr, nr_bytes, access, client);
}
@@ -1397,7 +1697,7 @@ device_interrupt_event(device *me,
edge = edge->next) {
if (edge->my_port == my_port) {
if (edge->dest->callback->interrupt.event == NULL)
- device_error(me, "no interrupt method\n");
+ device_error(me, "no interrupt method");
edge->dest->callback->interrupt.event(edge->dest,
edge->dest_port,
me,
@@ -1408,7 +1708,7 @@ device_interrupt_event(device *me,
}
}
if (!found_an_edge) {
- device_error(me, "No interrupt edge for port %d\n", my_port);
+ device_error(me, "No interrupt edge for port %d", my_port);
}
}
@@ -1442,9 +1742,26 @@ device_interrupt_detach(device *me,
}
INLINE_DEVICE\
+(void)
+device_interrupt_traverse(device *me,
+ device_interrupt_traverse_function *handler,
+ void *data)
+{
+ device_interrupt_edge *interrupt_edge;
+ for (interrupt_edge = me->interrupt_destinations;
+ interrupt_edge != NULL;
+ interrupt_edge = interrupt_edge->next) {
+ handler(me, interrupt_edge->my_port,
+ interrupt_edge->dest, interrupt_edge->dest_port,
+ data);
+ }
+}
+
+INLINE_DEVICE\
(int)
device_interrupt_decode(device *me,
- const char *port_name)
+ const char *port_name,
+ port_direction direction)
{
if (port_name == NULL || port_name[0] == '\0')
return 0;
@@ -1456,27 +1773,30 @@ device_interrupt_decode(device *me,
me->callback->interrupt.ports;
if (ports != NULL) {
while (ports->name != NULL) {
- if (ports->bound > ports->number) {
- int len = strlen(ports->name);
- if (strncmp(port_name, ports->name, len) == 0) {
- if (port_name[len] == '\0')
- return ports->number;
- else if(isdigit(port_name[len])) {
- int port = ports->number + strtoul(&port_name[len], NULL, 0);
- if (port >= ports->bound)
- device_error(me, "Interrupt port %s out of range\n",
- port_name);
- return port;
+ if (ports->direction == bidirect_port
+ || ports->direction == direction) {
+ if (ports->nr_ports > 0) {
+ int len = strlen(ports->name);
+ if (strncmp(port_name, ports->name, len) == 0) {
+ if (port_name[len] == '\0')
+ return ports->number;
+ else if(isdigit(port_name[len])) {
+ int port = ports->number + strtoul(&port_name[len], NULL, 0);
+ if (port >= ports->number + ports->nr_ports)
+ device_error(me, "Interrupt port %s out of range",
+ port_name);
+ return port;
+ }
}
}
+ else if (strcmp(port_name, ports->name) == 0)
+ return ports->number;
}
- else if (strcmp(port_name, ports->name) == 0)
- return ports->number;
ports++;
}
}
}
- device_error(me, "Unreconized interrupt port %s\n", port_name);
+ device_error(me, "Unreconized interrupt port %s", port_name);
return 0;
}
@@ -1485,28 +1805,32 @@ INLINE_DEVICE\
device_interrupt_encode(device *me,
int port_number,
char *buf,
- int sizeof_buf)
+ int sizeof_buf,
+ port_direction direction)
{
const device_interrupt_port_descriptor *ports = NULL;
ports = me->callback->interrupt.ports;
if (ports != NULL) {
while (ports->name != NULL) {
- if (ports->bound > ports->number) {
- if (port_number >= ports->number
- && port_number < ports->bound) {
- strcpy(buf, ports->name);
- sprintf(buf + strlen(buf), "%d", port_number - ports->number);
- if (strlen(buf) >= sizeof_buf)
- error("device_interrupt_encode:buffer overflow\n");
- return strlen(buf);
+ if (ports->direction == bidirect_port
+ || ports->direction == direction) {
+ if (ports->nr_ports > 0) {
+ if (port_number >= ports->number
+ && port_number < ports->number + ports->nr_ports) {
+ strcpy(buf, ports->name);
+ sprintf(buf + strlen(buf), "%d", port_number - ports->number);
+ if (strlen(buf) >= sizeof_buf)
+ error("device_interrupt_encode: buffer overflow");
+ return strlen(buf);
+ }
}
- }
- else {
- if (ports->number == port_number) {
- if (strlen(ports->name) >= sizeof_buf)
- error("device_interrupt_encode: buffer overflow\n");
- strcpy(buf, ports->name);
- return strlen(buf);
+ else {
+ if (ports->number == port_number) {
+ if (strlen(ports->name) >= sizeof_buf)
+ error("device_interrupt_encode: buffer overflow");
+ strcpy(buf, ports->name);
+ return strlen(buf);
+ }
}
}
ports++;
@@ -1514,7 +1838,7 @@ device_interrupt_encode(device *me,
}
sprintf(buf, "%d", port_number);
if (strlen(buf) >= sizeof_buf)
- error("device_interrupt_encode: buffer overflow\n");
+ error("device_interrupt_encode: buffer overflow");
return strlen(buf);
}
@@ -1527,14 +1851,15 @@ EXTERN_DEVICE\
device_ioctl(device *me,
cpu *processor,
unsigned_word cia,
+ device_ioctl_request request,
...)
{
int status;
va_list ap;
- va_start(ap, cia);
+ va_start(ap, request);
if (me->callback->ioctl == NULL)
- device_error(me, "no ioctl method\n");
- status = me->callback->ioctl(me, processor, cia, ap);
+ device_error(me, "no ioctl method");
+ status = me->callback->ioctl(me, processor, cia, request, ap);
va_end(ap);
return status;
}
@@ -1557,413 +1882,170 @@ device_error(device *me,
va_end(ap);
/* sanity check */
if (strlen(message) >= sizeof(message))
- error("device_error: buffer overflow\n");
+ error("device_error: buffer overflow");
if (me == NULL)
- error("device: %s\n", message);
+ error("device: %s", message);
+ else if (me->path != NULL && me->path[0] != '\0')
+ error("%s: %s", me->path, message);
+ else if (me->name != NULL && me->name[0] != '\0')
+ error("%s: %s", me->name, message);
else
- error("%s: %s\n", me->path, message);
+ error("device: %s", message);
while(1);
}
+INLINE_DEVICE\
+(int)
+device_trace(device *me)
+{
+ return me->trace;
+}
+
-/* Tree utilities: */
+/* External representation */
-EXTERN_DEVICE\
+INLINE_DEVICE\
(device *)
-device_tree_add_parsed(device *current,
- const char *fmt,
- ...)
-{
- char device_specifier[1024];
- name_specifier spec;
-
- /* format the path */
- {
- va_list ap;
- va_start(ap, fmt);
- vsprintf(device_specifier, fmt, ap);
- va_end(ap);
- if (strlen(device_specifier) >= sizeof(device_specifier))
- error("device_tree_add_parsed: buffer overflow\n");
- }
-
- /* break it up */
- if (!split_device_specifier(device_specifier, &spec))
- device_error(current, "error parsing %s\n", device_specifier);
-
- /* fill our tree with its contents */
- current = split_find_device(current, &spec);
-
- /* add any additional devices as needed */
- if (spec.name != NULL) {
- do {
- current =
- device_template_create_device(current, spec.name, spec.unit, spec.args);
- } while (split_device_name(&spec));
- }
-
- /* is there an interrupt spec */
- if (spec.property == NULL
- && spec.value != NULL) {
- char *op = split_value(&spec);
- switch (op[0]) {
- case '>':
- {
- char *my_port_name = split_value(&spec);
- char *dest_port_name = split_value(&spec);
- device *dest = device_tree_find_device(current, split_value(&spec));
- int my_port = device_interrupt_decode(current, my_port_name);
- int dest_port = device_interrupt_decode(dest, dest_port_name);
- device_interrupt_attach(current,
- my_port,
- dest,
- dest_port,
- permenant_object);
- }
- break;
- default:
- device_error(current, "unreconised interrupt spec %s\n", spec.value);
- break;
- }
- }
-
- /* is there a property */
- if (spec.property != NULL) {
- if (strcmp(spec.value, "true") == 0)
- device_add_boolean_property(current, spec.property, 1);
- else if (strcmp(spec.value, "false") == 0)
- device_add_boolean_property(current, spec.property, 0);
- else {
- const device_property *property;
- switch (spec.value[0]) {
- case '*':
- {
- spec.value++;
- device_add_ihandle_property(current, spec.property, spec.value);
- }
- break;
- case '-': case '+':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- {
- unsigned long ul = strtoul(spec.value, &spec.value, 0);
- device_add_integer_property(current, spec.property, ul);
- }
- break;
- case '[':
- {
- unsigned8 words[1024];
- char *curr = spec.value + 1;
- int nr_words = 0;
- while (1) {
- char *next;
- words[nr_words] = H2BE_1(strtoul(curr, &next, 0));
- if (curr == next)
- break;
- curr = next;
- nr_words += 1;
- }
- device_add_array_property(current, spec.property,
- words, sizeof(words[0]) * nr_words);
- }
- break;
- case '{':
- {
- unsigned32 words[1024];
- char *curr = spec.value + 1;
- int nr_words = 0;
- while (1) {
- char *next;
- words[nr_words] = H2BE_4(strtoul(curr, &next, 0));
- if (curr == next)
- break;
- curr = next;
- nr_words += 1;
- }
- device_add_array_property(current, spec.property,
- words, sizeof(words[0]) * nr_words);
- }
- break;
- case '"':
- spec.value++;
- default:
- device_add_string_property(current, spec.property, spec.value);
- break;
- case '!':
- spec.value++;
- property = device_find_property(current, spec.value);
- if (property == NULL)
- device_error(current, "property %s not found\n", spec.value);
- device_add_duplicate_property(current,
- spec.property,
- property);
- break;
- }
- }
- }
- return current;
+external_to_device(device *tree_member,
+ unsigned_cell phandle)
+{
+ device *me = cap_internal(tree_member->phandles, phandle);
+ return me;
}
INLINE_DEVICE\
-(void)
-device_tree_traverse(device *root,
- device_tree_traverse_function *prefix,
- device_tree_traverse_function *postfix,
- void *data)
-{
- device *child;
- if (prefix != NULL)
- prefix(root, data);
- for (child = root->children; child != NULL; child = child->sibling) {
- device_tree_traverse(child, prefix, postfix, data);
- }
- if (postfix != NULL)
- postfix(root, data);
+(unsigned_cell)
+device_to_external(device *me)
+{
+ unsigned_cell phandle = cap_external(me->phandles, me);
+ return phandle;
}
INLINE_DEVICE\
-(void)
-device_tree_print_device(device *me,
- void *ignore_or_null)
+(device_instance *)
+external_to_device_instance(device *tree_member,
+ unsigned_cell ihandle)
{
- const device_property *property;
- device_interrupt_edge *interrupt_edge;
- /* output my name */
- printf_filtered("%s\n", me->path);
- /* properties */
- for (property = device_find_property(me, NULL);
- property != NULL;
- property = device_next_property(property)) {
- printf_filtered("%s/%s", me->path, property->name);
- if (property->original != NULL) {
- printf_filtered(" !");
- printf_filtered("%s/%s\n", property->original->owner->path,
- property->original->name);
- }
- else {
- switch (property->type) {
- case array_property:
- {
- if ((property->sizeof_array % sizeof(unsigned32)) == 0) {
- unsigned32 *w = (unsigned32*)property->array;
- printf_filtered(" {");
- while ((char*)w - (char*)property->array < property->sizeof_array) {
- printf_filtered(" 0x%lx", BE2H_4(*w));
- w++;
- }
- }
- else {
- unsigned8 *w = (unsigned8*)property->array;
- printf_filtered(" [");
- while ((char*)w - (char*)property->array < property->sizeof_array) {
- printf_filtered(" 0x%2x", BE2H_1(*w));
- w++;
- }
- }
- printf_filtered("\n");
- }
- break;
- case boolean_property:
- {
- int b = device_find_boolean_property(me, property->name);
- printf_filtered(" %s\n", b ? "true" : "false");
- }
- break;
- case ihandle_property:
- {
- if (property->array != NULL) {
- device_instance *i = device_find_ihandle_property(me, property->name);
- printf_filtered(" *%s\n", i->path);
- }
- else {
- /* drats, the instance hasn't yet been created. Grub
- around and find the path that will be used to create
- the ihandle */
- device_property_entry *entry = me->properties;
- while (entry->value != property) {
- entry = entry->next;
- ASSERT(entry != NULL);
- }
- ASSERT(entry->init_array != NULL);
- printf_filtered(" *%s\n", (char*)entry->init_array);
- }
- }
- break;
- case integer_property:
- {
- unsigned_word w = device_find_integer_property(me, property->name);
- printf_filtered(" 0x%lx\n", (unsigned long)w);
- }
- break;
- case string_property:
- {
- const char *s = device_find_string_property(me, property->name);
- printf_filtered(" \"%s\n", s);
- }
- break;
- }
- }
- }
- /* interrupts */
- for (interrupt_edge = me->interrupt_destinations;
- interrupt_edge != NULL;
- interrupt_edge = interrupt_edge->next) {
- char src[32];
- char dst[32];
- device_interrupt_encode(me, interrupt_edge->my_port, src, sizeof(src));
- device_interrupt_encode(interrupt_edge->dest,
- interrupt_edge->dest_port, dst, sizeof(dst));
- printf_filtered("%s > %s %s %s\n",
- me->path,
- src, dst,
- interrupt_edge->dest->path);
- }
+ device_instance *instance = cap_internal(tree_member->ihandles, ihandle);
+ return instance;
}
INLINE_DEVICE\
-(device *)
-device_tree_find_device(device *root,
- const char *path)
-{
- device *node;
- name_specifier spec;
- TRACE(trace_device_tree,
- ("device_tree_find_device_tree(root=0x%lx, path=%s)\n",
- (long)root, path));
- /* parse the path */
- split_device_specifier(path, &spec);
- if (spec.value != NULL)
- return NULL; /* something wierd */
-
- /* now find it */
- node = split_find_device(root, &spec);
- if (spec.name != NULL)
- return NULL; /* not a leaf */
+(unsigned_cell)
+device_instance_to_external(device_instance *instance)
+{
+ unsigned_cell ihandle = cap_external(instance->owner->ihandles, instance);
+ return ihandle;
+}
- return node;
+
+/* Map onto the event functions */
+
+INLINE_DEVICE\
+(event_entry_tag)
+device_event_queue_schedule(device *me,
+ signed64 delta_time,
+ device_event_handler *handler,
+ void *data)
+{
+ return event_queue_schedule(psim_event_queue(me->system),
+ delta_time,
+ handler,
+ data);
}
INLINE_DEVICE\
(void)
-device_usage(int verbose)
+device_event_queue_deschedule(device *me,
+ event_entry_tag event_to_remove)
{
- if (verbose == 1) {
- const device_descriptor *const *table;
- int pos;
- printf_filtered("\n");
- printf_filtered("A device/property specifier has the form:\n");
- printf_filtered("\n");
- printf_filtered(" /path/to/a/device [ property-value ]\n");
- printf_filtered("\n");
- printf_filtered("and a possible device is\n");
- printf_filtered("\n");
- pos = 0;
- for (table = device_table; *table != NULL; table++) {
- const device_descriptor *descr;
- for (descr = *table; descr->name != NULL; descr++) {
- pos += strlen(descr->name) + 2;
- if (pos > 75) {
- pos = strlen(descr->name) + 2;
- printf_filtered("\n");
- }
- printf_filtered(" %s", descr->name);
- }
- printf_filtered("\n");
- }
- }
- if (verbose > 1) {
- const device_descriptor *const *table;
- printf_filtered("\n");
- printf_filtered("A device/property specifier (<spec>) has the format:\n");
- printf_filtered("\n");
- printf_filtered(" <spec> ::= <path> [ <value> ] ;\n");
- printf_filtered(" <path> ::= { <prefix> } { <node> \"/\" } <node> ;\n");
- printf_filtered(" <prefix> ::= ( | \"/\" | \"../\" | \"./\" ) ;\n");
- printf_filtered(" <node> ::= <name> [ \"@\" <unit> ] [ \":\" <args> ] ;\n");
- printf_filtered(" <unit> ::= <number> { \",\" <number> } ;\n");
- printf_filtered("\n");
- printf_filtered("Where:\n");
- printf_filtered("\n");
- printf_filtered(" <name> is the name of a device (list below)\n");
- printf_filtered(" <unit> is the unit-address relative to the parent bus\n");
- printf_filtered(" <args> additional arguments used when creating the device\n");
- printf_filtered(" <value> ::= ( <number> # integer property\n");
- printf_filtered(" | \"[\" { <number> } # array property (byte)\n");
- printf_filtered(" | \"{\" { <number> } # array property (cell)\n");
- printf_filtered(" | [ \"true\" | \"false\" ] # boolean property\n");
- printf_filtered(" | \"*\" <path> # ihandle property\n");
- printf_filtered(" | \"!\" <path> # copy property\n");
- printf_filtered(" | \">\" [ <number> ] <path> # attach interrupt\n");
- printf_filtered(" | \"<\" <path> # attach child interrupt\n");
- printf_filtered(" | \"\\\"\" <text> # string property\n");
- printf_filtered(" | <text> # string property\n");
- printf_filtered(" ) ;\n");
- printf_filtered("\n");
- printf_filtered("And the following are valid device names:\n");
- printf_filtered("\n");
- for (table = device_table; *table != NULL; table++) {
- const device_descriptor *descr;
- for (descr = *table; descr->name != NULL; descr++) {
- printf_filtered(" %s:\n", descr->name);
- /* interrupt ports */
- if (descr->callbacks->interrupt.ports != NULL) {
- const device_interrupt_port_descriptor *ports =
- descr->callbacks->interrupt.ports;
- printf_filtered(" interrupt ports:");
- while (ports->name != NULL) {
- printf_filtered(" %s", ports->name);
- ports++;
- }
- printf_filtered("\n");
- }
- /* general info */
- if (descr->callbacks->usage != NULL)
- descr->callbacks->usage(verbose);
- }
- }
- }
+ event_queue_deschedule(psim_event_queue(me->system),
+ event_to_remove);
}
-
-
-/* External representation */
-
INLINE_DEVICE\
-(device *)
-external_to_device(device *tree_member,
- unsigned32 phandle)
+(signed64)
+device_event_queue_time(device *me)
{
- device *root = device_tree_find_device(tree_member, "/");
- device *me = cap_internal(root->phandles, phandle);
- return me;
+ return event_queue_time(psim_event_queue(me->system));
}
+
+/* Initialization: */
+
+
INLINE_DEVICE\
-(unsigned32)
-device_to_external(device *me)
+(void)
+device_clean(device *me,
+ void *data)
{
- device *root = device_tree_find_device(me, "/");
- unsigned32 phandle = cap_external(root->phandles, me);
- return phandle;
+ psim *system;
+ system = (psim*)data;
+ TRACE(trace_device_init, ("device_clean - initializing %s", me->path));
+ clean_device_interrupt_edges(&me->interrupt_destinations);
+ clean_device_instances(me);
+ clean_device_properties(me);
}
+/* Device initialization: */
+
INLINE_DEVICE\
-(device_instance *)
-external_to_device_instance(device *tree_member,
- unsigned32 ihandle)
+(void)
+device_init_address(device *me,
+ void *data)
{
- device *root = device_tree_find_device(tree_member, "/");
- device_instance *instance = cap_internal(root->ihandles, ihandle);
- return instance;
+ psim *system = (psim*)data;
+ int nr_address_cells;
+ int nr_size_cells;
+ TRACE(trace_device_init, ("device_init_address - initializing %s", me->path));
+
+ /* ensure the cap database is valid */
+ if (me->parent == NULL) {
+ cap_init(me->ihandles);
+ cap_init(me->phandles);
+ }
+
+ /* some basics */
+ me->system = system; /* misc things not known until now */
+ me->trace = (device_find_property(me, "trace")
+ ? device_find_integer_property(me, "trace")
+ : 0);
+
+ /* Ensure that the first address found in the reg property matches
+ anything that was specified as part of the devices name */
+ if (device_find_property(me, "reg") != NULL) {
+ reg_property_spec unit;
+ device_find_reg_array_property(me, "reg", 0, &unit);
+ if (memcmp(device_unit_address(me), &unit.address, sizeof(unit.address))
+ != 0)
+ device_error(me, "Unit address as specified by the reg property in conflict with the value previously specified in the devices path");
+ }
+
+ /* ensure that the devices #address/size-cells is consistent */
+ nr_address_cells = device_nr_address_cells(me);
+ if (device_find_property(me, "#address-cells") != NULL
+ && (nr_address_cells
+ != device_find_integer_property(me, "#address-cells")))
+ device_error(me, "#address-cells property used before defined");
+ nr_size_cells = device_nr_size_cells(me);
+ if (device_find_property(me, "#size-cells") != NULL
+ && (nr_size_cells
+ != device_find_integer_property(me, "#size-cells")))
+ device_error(me, "#size-cells property used before defined");
+
+ /* now init it */
+ if (me->callback->init.address != NULL)
+ me->callback->init.address(me);
}
INLINE_DEVICE\
-(unsigned32)
-device_instance_to_external(device_instance *instance)
+(void)
+device_init_data(device *me,
+ void *data)
{
- device *root = device_tree_find_device(instance->owner, "/");
- unsigned32 ihandle = cap_external(root->ihandles, instance);
- return ihandle;
+ TRACE(trace_device_init, ("device_init_data - initializing %s", me->path));
+ if (me->callback->init.data != NULL)
+ me->callback->init.data(me);
}
#endif /* _DEVICE_C_ */