/* This file is part of the program psim.
- Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
+ Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "device_table.h"
#include "cap.h"
+#include "events.h"
+#include "psim.h"
+
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <ctype.h>
STATIC_INLINE_DEVICE (void) clean_device_properties(device *);
-STATIC_INLINE_DEVICE (void) init_device_properties(device *, void*);
/* property entries */
&& 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);
+ free(old_edge);
return;
}
}
- device_error(me, "attempt to delete unattached interrupt\n");
+ device_error(me, "attempt to delete unattached interrupt");
}
STATIC_INLINE_DEVICE\
break;
case tempoary_object:
*list = old_edge->next;
- zfree(old_edge);
+ free(old_edge);
break;
}
}
const char *name;
device_unit unit_address;
const char *path;
+ int nr_address_cells;
+ int nr_size_cells;
/* device tree */
device *parent;
cap *ihandles;
cap *phandles;
psim *system;
+
+ /* debugging */
+ int trace;
};
\f
-/* 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;
-}
-
-
-\f
-/* 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];
/* 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);
/* 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)
+(device *)
+device_create_from(const char *name,
+ const device_unit *unit_address,
+ void *data,
+ const device_callbacks *callbacks,
+ device *parent)
{
- char *chp;
- if (strlen(device_specifier) >= sizeof(spec->buf))
- error("split_device_specifier: buffer overflow\n");
+ device *new_device = ZALLOC(device);
- /* expand aliases (later) */
- strcpy(spec->buf, device_specifier);
+ /* insert it into the device tree */
+ new_device->parent = parent;
+ new_device->children = NULL;
+ if (parent != NULL) {
+ device **sibling = &parent->children;
+ while ((*sibling) != NULL)
+ sibling = &(*sibling)->sibling;
+ *sibling = new_device;
+ }
- /* 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;
+ /* give it a name */
+ new_device->name = (char *) strdup(name);
+ new_device->unit_address = *unit_address;
+ new_device->path = device_full_name(new_device, NULL, 0);
- /* find the path and terminate it with null */
- spec->path = chp;
- while (*chp != '\0' && !isspace(*chp))
- chp++;
- if (*chp != '\0') {
- *chp = '\0';
- chp++;
- }
+ /* its template */
+ new_device->data = data;
+ new_device->callback = callbacks;
- /* and any value */
- while (*chp != '\0' && isspace(*chp))
- chp++;
- spec->value = chp;
+ /* its properties - already null */
+ /* interrupts - already null */
- /* 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;
+ /* mappings - if needed */
+ if (parent == NULL) {
+ new_device->ihandles = cap_create(name);
+ new_device->phandles = cap_create(name);
}
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;
- }
+ new_device->ihandles = device_root(parent)->ihandles;
+ new_device->phandles = device_root(parent)->phandles;
}
- /* 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;
+ cap_add(new_device->phandles, new_device);
+ return new_device;
}
-/* 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;
+
+
+INLINE_DEVICE\
+(device *)
+device_create(device *parent,
+ const char *base,
+ const char *name,
+ const char *unit_address,
+ const char *args)
+{
+ const device_descriptor *const *table;
+ for (table = device_table; *table != NULL; table++) {
+ const device_descriptor *descr;
+ for (descr = *table; descr->name != NULL; descr++) {
+ if (strcmp(base, descr->name) == 0) {
+ device_unit address = { 0 };
+ void *data = NULL;
+ 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,
+ descr->callbacks, parent);
}
}
- return 1;
}
- else
- return 0;
+ device_error(parent, "attempt to attach unknown device %s", name);
+ return NULL;
}
-/* 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)
+
+
+INLINE_DEVICE\
+(void)
+device_usage(int verbose)
{
- 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;
+ 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");
+ }
}
- /* finally any args */
- chp = strchr(chp, ':');
- if (chp == NULL)
- spec->args = NULL;
- else {
- *chp = '\0';
- spec->args = chp+1;
+ 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);
+ }
+ }
}
- return 1;
}
+
-/* parse the value, returning the next non-space token */
-STATIC_INLINE_DEVICE\
-(char *)
-split_value(name_specifier *spec)
+
+\f
+/* Device node: */
+
+INLINE_DEVICE\
+(device *)
+device_parent(device *me)
{
- 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;
+ 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;
+}
-/* traverse the path specified by spec starting at current */
-
-STATIC_INLINE_DEVICE\
+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;
- }
+device_child(device *me)
+{
+ return me->children;
+}
- /* now go through the path proper */
+INLINE_DEVICE\
+(const char *)
+device_name(device *me)
+{
+ return me->name;
+}
- if (current == NULL) {
- split_device_name(spec);
- return current;
- }
+INLINE_DEVICE\
+(const char *)
+device_path(device *me)
+{
+ return me->path;
+}
- 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;
- }
+INLINE_DEVICE\
+(void *)
+device_data(device *me)
+{
+ return me->data;
+}
- return current;
+INLINE_DEVICE\
+(psim *)
+device_system(device *me)
+{
+ return me->system;
+}
+
+INLINE_DEVICE\
+(const device_unit *)
+device_unit_address(device *me)
+{
+ return &me->unit_address;
}
-STATIC_INLINE_DEVICE\
-(device *)
-device_create_from(const char *name,
- const device_unit *unit_address,
- void *data,
- const device_callbacks *callbacks,
- device *parent)
+INLINE_DEVICE\
+(int)
+device_address_to_attach_address(device *me,
+ const device_unit *address,
+ int *attach_space,
+ unsigned_word *attach_address,
+ device *client)
{
- device *new_device = ZALLOC(device);
+ 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);
+}
- /* insert it into the device tree */
- new_device->parent = parent;
- new_device->children = NULL;
- if (parent != NULL) {
- device **sibling = &parent->children;
- while ((*sibling) != NULL)
- sibling = &(*sibling)->sibling;
- *sibling = new_device;
- }
- /* give it a name */
- new_device->name = strdup(name);
- new_device->unit_address = *unit_address;
- new_device->path = device_full_name(new_device, NULL, 0);
+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);
+}
- /* its template */
- new_device->data = data;
- new_device->callback = callbacks;
- /* its properties - already null */
- /* interrupts - already null */
+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);
+}
- /* mappings - if needed */
- if (parent == NULL) {
- new_device->ihandles = cap_create(name);
- new_device->phandles = cap_create(name);
- }
- return new_device;
+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;
+}
-STATIC_INLINE_DEVICE\
-(device *)
-device_template_create_device(device *parent,
- const char *name,
- const char *unit_address,
- const char *args)
+INLINE_DEVICE\
+(unsigned)
+device_nr_size_cells(device *me)
{
- 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] == '@')) {
- 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 (descr->creator != NULL)
- data = descr->creator(name, &address, args);
- return device_create_from(name, &address, data,
- descr->callbacks, parent);
- }
- }
+ 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;
}
- device_error(parent, "attempt to attach unknown device %s\n", name);
- return NULL;
+ return me->nr_size_cells;
}
+
\f
/* device-instance: */
{
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;
}
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)
}
}
+
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);
+ free(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;
- zfree(instance);
+ free(instance->path);
+ 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);
+ free(instance);
}
INLINE_DEVICE\
{
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);
}
{
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);
}
{
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 *)
\f
-/* 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;
}
-
-\f
-/* Device Properties: */
-
-/* local - not available externally */
STATIC_INLINE_DEVICE\
(void)
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;
/* 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;
}
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)
+ free((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);
}
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) {
+ free((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)
+ free((void*)current->value->array);
+ free(current->value);
+ free(current);
break;
}
}
}
-STATIC_INLINE_DEVICE\
+INLINE_DEVICE\
+(void)
+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)
-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_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 = tree_instance(me, spec.full_path);
+ 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;
}
}
return NULL;
}
+
INLINE_DEVICE\
(const device_property *)
device_find_property(device *me,
const char *property)
{
- name_specifier spec;
if (me == NULL) {
return NULL;
}
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\
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\
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\
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));
+ /* enter the full path as the init array */
device_add_property(me, property, ihandle_property,
- path, strlen(path) + 1,
+ ihandle->full_path, strlen(ihandle->full_path) + 1,
NULL, 0,
NULL, permenant_object);
}
INLINE_DEVICE\
+(void)
+device_find_ihandle_runtime_property(device *me,
+ const char *property,
+ ihandle_runtime_property_spec *ihandle)
+{
+ 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);
+ ASSERT(entry->init_array != NULL);
+ /* the full path */
+ ihandle->full_path = entry->init_array;
+}
+
+
+
+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;
}
+
+INLINE_DEVICE\
+(void)
+device_add_integer_property(device *me,
+ const char *property,
+ signed_cell integer)
+{
+ H2BE(integer);
+ device_add_property(me, property, integer_property,
+ &integer, sizeof(integer),
+ &integer, sizeof(integer),
+ NULL, permenant_object);
+}
+
+INLINE_DEVICE\
+(signed_cell)
+device_find_integer_property(device *me,
+ const char *property)
+{
+ const device_property *node;
+ 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", property);
+ ASSERT(sizeof(integer) == node->sizeof_array);
+ memcpy(&integer, node->array, sizeof(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_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);
+
+ free(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;
+
+ /* 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\
-(void)
-device_add_integer_property(device *me,
- const char *property,
- signed32 integer)
+(unsigned)
+nr_reg_property_cells(device *me,
+ int nr_regs)
{
- 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),
+ 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 = ®s[i];
+ /* copy the address */
+ cell = unit_address_to_cells(®->address, cell,
+ device_nr_address_cells(device_parent(me)));
+ /* copy the size */
+ cell = unit_address_to_cells(®->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);
+
+ free(cells);
}
INLINE_DEVICE\
-(signed_word)
-device_find_integer_property(device *me,
- const char *property)
+(int)
+device_find_reg_array_property(device *me,
+ const char *property,
+ unsigned index,
+ reg_property_spec *reg)
{
const device_property *node;
- signed32 integer;
- TRACE(trace_devices,
- ("device_find_integer(me=0x%lx, property=%s)\n",
- (long)me, property));
+ 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 != integer_property)
- device_error(me, "property %s not found or of wrong type\n", property);
- ASSERT(sizeof(integer) == node->sizeof_array);
- memcpy(&integer, node->array, sizeof(integer));
- BE2H(integer);
- return integer;
+ || 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, ®->address,
+ device_nr_address_cells(device_parent(me)));
+
+ /* copy the size out - converting as we go */
+ cells = cells_to_unit_address(cells, ®->size,
+ device_nr_size_cells(device_parent(me)));
+
+ return node->sizeof_array / sizeof_entry;
}
-STATIC_INLINE_DEVICE\
+
+INLINE_DEVICE\
(void)
device_add_string_property(device *me,
- const char *property,
- const char *string)
+ const char *property,
+ const char *string)
{
-
- 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,
- NULL, permenant_object);
+ string, strlen(string) + 1,
+ string, strlen(string) + 1,
+ NULL, permenant_object);
}
INLINE_DEVICE\
{
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);
}
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);
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);
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);
}
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);
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);
}
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,
}
}
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);
}
}
}
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;
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;
}
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++;
}
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);
}
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;
}
/* I/O */
EXTERN_DEVICE\
-(void volatile)
+(void)
device_error(device *me,
const char *fmt,
...)
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;
+}
+
\f
-/* 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);
}
-
-\f
-/* 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_ */