aboutsummaryrefslogtreecommitdiff
path: root/sim/ppc/device.c
diff options
context:
space:
mode:
authorMichael Meissner <gnu@the-meissners.org>1996-07-23 15:42:42 +0000
committerMichael Meissner <gnu@the-meissners.org>1996-07-23 15:42:42 +0000
commit30c87b55ec44de3a56cecf41fc7c93ed0c4005ca (patch)
tree5752ad56a8e4c990eb02b12f68d486415c79c41b /sim/ppc/device.c
parent856bcbcbbc01a252a8df2221038100e9a33f87ff (diff)
downloadgdb-30c87b55ec44de3a56cecf41fc7c93ed0c4005ca.zip
gdb-30c87b55ec44de3a56cecf41fc7c93ed0c4005ca.tar.gz
gdb-30c87b55ec44de3a56cecf41fc7c93ed0c4005ca.tar.bz2
New simulator changes from Andrew
Diffstat (limited to 'sim/ppc/device.c')
-rw-r--r--sim/ppc/device.c2459
1 files changed, 1599 insertions, 860 deletions
diff --git a/sim/ppc/device.c b/sim/ppc/device.c
index 618c5a4..83d9e3f 100644
--- a/sim/ppc/device.c
+++ b/sim/ppc/device.c
@@ -1,6 +1,6 @@
/* This file is part of the program psim.
- Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
+ Copyright (C) 1994-1996, 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
@@ -25,6 +25,7 @@
#include <stdio.h>
#include "device_table.h"
+#include "cap.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@@ -40,72 +41,141 @@
#include <ctype.h>
+STATIC_INLINE_DEVICE (void) clean_device_properties(device *);
+STATIC_INLINE_DEVICE (void) init_device_properties(device *, void*);
+/* property entries */
typedef struct _device_property_entry device_property_entry;
struct _device_property_entry {
- const char *name;
device_property_entry *next;
device_property *value;
+ const void *init_array;
+ unsigned sizeof_init_array;
};
+/* Interrupt edges */
+
+typedef struct _device_interrupt_edge device_interrupt_edge;
+struct _device_interrupt_edge {
+ int my_port;
+ device *dest;
+ int dest_port;
+ device_interrupt_edge *next;
+ object_disposition disposition;
+};
+
+STATIC_INLINE_DEVICE\
+(void)
+attach_device_interrupt_edge(device_interrupt_edge **list,
+ int my_port,
+ device *dest,
+ int dest_port,
+ object_disposition disposition)
+{
+ device_interrupt_edge *new_edge = ZALLOC(device_interrupt_edge);
+ new_edge->my_port = my_port;
+ new_edge->dest = dest;
+ new_edge->dest_port = dest_port;
+ new_edge->next = *list;
+ new_edge->disposition = disposition;
+ *list = new_edge;
+}
+
+STATIC_INLINE_DEVICE\
+(void)
+detach_device_interrupt_edge(device *me,
+ device_interrupt_edge **list,
+ int my_port,
+ device *dest,
+ int dest_port)
+{
+ while (*list != NULL) {
+ device_interrupt_edge *old_edge = *list;
+ if (old_edge->dest == dest
+ && 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");
+ *list = old_edge->next;
+ zfree(old_edge);
+ return;
+ }
+ }
+ device_error(me, "attempt to delete unattached interrupt\n");
+}
+
+STATIC_INLINE_DEVICE\
+(void)
+clean_device_interrupt_edges(device_interrupt_edge **list)
+{
+ while (*list != NULL) {
+ device_interrupt_edge *old_edge = *list;
+ switch (old_edge->disposition) {
+ case permenant_object:
+ list = &old_edge->next;
+ break;
+ case tempoary_object:
+ *list = old_edge->next;
+ zfree(old_edge);
+ break;
+ }
+ }
+}
+
+
/* A device */
+
struct _device {
+
/* my name is ... */
const char *name;
- const char *full_name;
+ device_unit unit_address;
+ const char *path;
+
/* device tree */
device *parent;
device *children;
device *sibling;
- /* hw/sw callbacks */
+
+ /* its template methods */
void *data; /* device specific data */
const device_callbacks *callback;
+
/* device properties */
device_property_entry *properties;
+
+ /* interrupts */
+ device_interrupt_edge *interrupt_destinations;
+
+ /* any open instances of this device */
+ device_instance *instances;
+
+ /* the internal/external mappings and other global requirements */
+ cap *ihandles;
+ cap *phandles;
+ psim *system;
};
-INLINE_DEVICE\
-(device *)
-device_create(const char *name,
- device *parent)
-{
- device_descriptor *descr;
- int name_len;
- char *chp;
- chp = strchr(name, '@');
- name_len = (chp == NULL ? strlen(name) : chp - name);
- for (descr = device_table; descr->name != NULL; descr++) {
- if (strncmp(name, descr->name, name_len) == 0
- && (descr->name[name_len] == '\0'
- || descr->name[name_len] == '@')) {
- void *data = (descr->creator != NULL
- ? descr->creator(name, parent)
- : NULL);
- return device_create_from(name, data, descr->callbacks, parent);
- }
- }
- error("device_create() unknown device %s\n", name);
- return NULL;
-}
+/* an instance of a device */
+struct _device_instance {
+ void *data;
+ char *args;
+ char *path;
+ const device_instance_callbacks *callback;
+ /* the root instance */
+ device *owner;
+ device_instance *next;
+ /* interposed instance */
+ device_instance *parent;
+ device_instance *child;
+};
-INLINE_DEVICE\
-(device *)
-device_create_from(const char *name,
- void *data,
- const device_callbacks *callbacks,
- device *parent)
-{
- device *new_device = ZALLOC(device);
- new_device->data = data;
- new_device->name = strdup(name);
- new_device->callback = callbacks;
- new_device->parent = parent;
- return new_device;
-}
+
+/* Device node: */
INLINE_DEVICE\
(device *)
@@ -136,6 +206,13 @@ device_name(device *me)
}
INLINE_DEVICE\
+(const char *)
+device_path(device *me)
+{
+ return me->path;
+}
+
+INLINE_DEVICE\
(void *)
device_data(device *me)
{
@@ -143,208 +220,855 @@ device_data(device *me)
}
INLINE_DEVICE\
-(void)
-device_traverse_properties(device *me,
- device_traverse_property_function *traverse,
- void *data)
+(psim *)
+device_system(device *me)
{
- device_property_entry *entry = me->properties;
- while (entry != NULL) {
- traverse(me, entry->name, data);
- entry = entry->next;
+ 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 */
+
+STATIC_INLINE_DEVICE\
+(const char *)
+device_full_name(device *leaf,
+ char *buf,
+ unsigned sizeof_buf)
+{
+ /* get a buffer */
+ char full_name[1024];
+ if (buf == (char*)0) {
+ buf = full_name;
+ sizeof_buf = sizeof(full_name);
}
+
+ /* construct a name */
+ if (leaf->parent == NULL) {
+ if (sizeof_buf < 1)
+ error("device_full_name: buffer overflow\n");
+ *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)
+ unit[0] = '@';
+ else
+ unit[0] = '\0';
+ if (strlen(buf) + strlen("/") + strlen(leaf->name) + strlen(unit)
+ >= sizeof_buf)
+ error("device_full_name: buffer overflow\n");
+ strcat(buf, "/");
+ strcat(buf, leaf->name);
+ strcat (buf, unit);
+ }
+
+ /* return it usefully */
+ if (buf == full_name)
+ buf = 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,
+ const device_unit *unit_address,
+ void *data,
+ const device_callbacks *callbacks,
+ device *parent)
+{
+ device *new_device = ZALLOC(device);
+
+ /* 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);
+
+ /* its template */
+ new_device->data = data;
+ new_device->callback = callbacks;
+
+ /* its properties - already null */
+ /* interrupts - already null */
+
+ /* mappings - if needed */
+ if (parent == NULL) {
+ new_device->ihandles = cap_create(name);
+ new_device->phandles = cap_create(name);
+ }
+
+ return new_device;
+}
+
+
+STATIC_INLINE_DEVICE\
+(device *)
+device_template_create_device(device *parent,
+ 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] == '@')) {
+ 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);
+ }
+ }
+ }
+ device_error(parent, "attempt to attach unknown device %s\n", name);
+ return NULL;
+}
+
+
+/* device-instance: */
+
INLINE_DEVICE\
-(void)
-device_init(device *me,
- psim *system)
+(device_instance *)
+device_create_instance_from(device *me,
+ device_instance *parent,
+ void *data,
+ const char *path,
+ const char *args,
+ const device_instance_callbacks *callbacks)
{
- me->callback->init(me, system);
+ 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;
+ /*instance->unit*/
+ if (me != NULL) {
+ instance->next = me->instances;
+ me->instances = instance;
+ }
+ if (parent != NULL) {
+ device_instance **previous;
+ parent->child = instance;
+ instance->owner = parent->owner;
+ instance->next = parent->next;
+ /* replace parent with this new node */
+ previous = &instance->owner->instances;
+ while (*previous != parent)
+ previous = &(*previous)->next;
+ *previous = instance;
+ }
+ return instance;
}
+
INLINE_DEVICE\
+(device_instance *)
+device_create_instance(device *me,
+ const char *device_specifier)
+{
+ /* 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);
+}
+
+STATIC_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*/
+clean_device_instances(device *me)
{
- me->callback->attach_address(me, name, attach, space,
- addr, nr_bytes, access, who);
+ device_instance **instance = &me->instances;
+ while (*instance != NULL) {
+ device_instance *old_instance = *instance;
+ device_instance_delete(old_instance);
+ instance = &me->instances;
+ }
}
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_instance_delete(device_instance *instance)
{
- me->callback->detach_address(me, name, attach, space,
- addr, nr_bytes, access, who);
+ device *me = instance->owner;
+ device_instance **curr;
+ if (instance->callback->delete == NULL)
+ device_error(me, "no delete method\n");
+ 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;
+ zfree(instance);
}
INLINE_DEVICE\
-(unsigned)
-device_io_read_buffer(device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
+(int)
+device_instance_read(device_instance *instance,
+ void *addr,
+ unsigned_word len)
{
- return me->callback->io_read_buffer(me, dest, space,
- addr, nr_bytes,
- processor, cia);
+ device *me = instance->owner;
+ if (instance->callback->read == NULL)
+ device_error(me, "no read method\n");
+ return instance->callback->read(instance, addr, len);
}
INLINE_DEVICE\
-(unsigned)
-device_io_write_buffer(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- cpu *processor,
- unsigned_word cia)
+(int)
+device_instance_write(device_instance *instance,
+ const void *addr,
+ unsigned_word len)
{
- return me->callback->io_write_buffer(me, source, space,
- addr, nr_bytes,
- processor, cia);
+ device *me = instance->owner;
+ if (instance->callback->write == NULL)
+ device_error(me, "no write method\n");
+ return instance->callback->write(instance, addr, len);
}
INLINE_DEVICE\
-(unsigned)
-device_dma_read_buffer(device *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes)
+(int)
+device_instance_seek(device_instance *instance,
+ unsigned_word pos_hi,
+ unsigned_word pos_lo)
{
- return me->callback->dma_read_buffer(me, dest, space,
- addr, nr_bytes);
+ device *me = instance->owner;
+ if (instance->callback->seek == NULL)
+ device_error(me, "no seek method\n");
+ return instance->callback->seek(instance, pos_hi, pos_lo);
}
INLINE_DEVICE\
-(unsigned)
-device_dma_write_buffer(device *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- int violate_read_only_section)
+(unsigned_word)
+device_instance_claim(device_instance *instance,
+ unsigned_word address,
+ unsigned_word length,
+ unsigned_word alignment)
{
- return me->callback->dma_write_buffer(me, source, space,
- addr, nr_bytes,
- violate_read_only_section);
+ device *me = instance->owner;
+ if (instance->callback->claim == NULL)
+ device_error(me, "no claim method\n");
+ return instance->callback->claim(instance, address, length, alignment);
}
INLINE_DEVICE\
(void)
-device_attach_interrupt(device *me,
- device *who,
- int interrupt_line,
- const char *name)
+device_instance_release(device_instance *instance,
+ unsigned_word address,
+ unsigned_word length)
{
- me->callback->attach_interrupt(me, who, interrupt_line, name);
+ device *me = instance->owner;
+ if (instance->callback->release == NULL)
+ device_error(me, "no release method\n");
+ instance->callback->release(instance, address, length);
}
INLINE_DEVICE\
-(void)
-device_detach_interrupt(device *me,
- device *who,
- int interrupt_line,
- const char *name)
+(device *)
+device_instance_device(device_instance *instance)
{
- me->callback->detach_interrupt(me, who, interrupt_line, name);
+ return instance->owner;
}
INLINE_DEVICE\
-(void)
-device_interrupt(device *me,
- device *who,
- int interrupt_line,
- int interrupt_status,
- cpu *processor,
- unsigned_word cia)
+(const char *)
+device_instance_path(device_instance *instance)
{
- me->callback->interrupt(me, who, interrupt_line, interrupt_status,
- processor, cia);
+ return instance->path;
}
INLINE_DEVICE\
+(void *)
+device_instance_data(device_instance *instance)
+{
+ return instance->data;
+}
+
+
+
+/* Device initialization: */
+
+STATIC_INLINE_DEVICE\
(void)
-device_interrupt_ack(device *me,
- int interrupt_line,
- int interrupt_status)
+clean_device(device *root,
+ void *data)
{
- me->callback->interrupt_ack(me, interrupt_line, interrupt_status);
+ psim *system;
+ system = (psim*)data;
+ clean_device_interrupt_edges(&root->interrupt_destinations);
+ clean_device_instances(root);
+ clean_device_properties(root);
}
-EXTERN_DEVICE\
+STATIC_INLINE_DEVICE\
(void)
-device_ioctl(device *me,
- psim *system,
- cpu *processor,
- unsigned_word cia,
- ...)
+init_device_address(device *me,
+ void *data)
{
- va_list ap;
- va_start(ap, cia);
- me->callback->ioctl(me, system, processor, cia, ap);
- va_end(ap);
+ 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);
}
-
-/* Manipulate properties attached to devices */
+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)
+{
+ 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 Properties: */
+/* local - not available externally */
STATIC_INLINE_DEVICE\
-(device_property *)
+(void)
device_add_property(device *me,
const char *property,
device_property_type type,
+ const void *init_array,
+ unsigned sizeof_init_array,
const void *array,
- int sizeof_array)
+ unsigned sizeof_array,
+ const device_property *original,
+ object_disposition disposition)
{
- device_property_entry *new_entry = 0;
- device_property *new_value = 0;
- void *new_array = 0;
+ 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;
while (*insertion_point != NULL) {
- if (strcmp((**insertion_point).name, property) == 0)
- return (**insertion_point).value;
- insertion_point = &(**insertion_point).next;
+ if (strcmp((*insertion_point)->value->name, property) == 0)
+ return;
+ insertion_point = &(*insertion_point)->next;
}
- /* alloc data for the new property */
- new_entry = ZALLOC(device_property_entry);
+
+ /* create a new value */
new_value = ZALLOC(device_property);
- new_array = (sizeof_array > 0
- ? zalloc(sizeof_array)
- : (void*)0);
- /* insert the new property into the list */
- *insertion_point = new_entry;
- new_entry->name = strdup(property);
- new_entry->value = new_value;
+ new_value->name = 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;
+ new_value->owner = me;
+ new_value->original = original;
+ new_value->disposition = disposition;
if (sizeof_array > 0)
memcpy(new_array, array, sizeof_array);
- return new_value;
+
+ /* 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)
+ memcpy(new_init_array, init_array, sizeof_init_array);
+
+}
+
+
+/* local - not available externally */
+STATIC_INLINE_DEVICE\
+(void)
+device_set_property(device *me,
+ const char *property,
+ device_property_type type,
+ const void *array,
+ int sizeof_array,
+ const device_property *original)
+{
+ /* 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_add_property(me, property, type,
+ NULL, 0, array, sizeof_array,
+ original, tempoary_object);
+}
+
+
+STATIC_INLINE_DEVICE\
+(void)
+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;
+ }
+ 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);
+ }
+ break;
+ }
+ }
+}
+
+
+STATIC_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);
+ }
+ 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);
+ }
+ }
+ property = property->next;
+ }
}
+
INLINE_DEVICE\
+(const device_property *)
+device_next_property(const device_property *property)
+{
+ /* find the property in the list */
+ device *owner = property->owner;
+ device_property_entry *entry = owner->properties;
+ while (entry != NULL && entry->value != property)
+ entry = entry->next;
+ /* now return the following property */
+ ASSERT(entry != NULL); /* must be a member! */
+ if (entry->next != NULL)
+ return entry->next->value;
+ else
+ return NULL;
+}
+
+INLINE_DEVICE\
+(const device_property *)
+device_find_property(device *me,
+ const char *property)
+{
+ name_specifier spec;
+ if (me == NULL) {
+ return NULL;
+ }
+ else if (property == NULL || strcmp(property, "") == 0) {
+ if (me->properties == 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;
+ }
+ }
+ }
+ return NULL;
+}
+
+STATIC_INLINE_DEVICE\
(void)
device_add_array_property(device *me,
const char *property,
@@ -354,25 +1078,42 @@ device_add_array_property(device *me,
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);
+ device_add_property(me, property, array_property,
+ array, sizeof_array, array, sizeof_array,
+ NULL, permenant_object);
}
INLINE_DEVICE\
(void)
-device_add_integer_property(device *me,
- const char *property,
- signed32 integer)
+device_set_array_property(device *me,
+ const char *property,
+ const void *array,
+ int sizeof_array)
{
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));
+ ("device_set_array_property(me=0x%lx, property=%s, ...)\n",
+ (long)me, property));
+ device_set_property(me, property, array_property, array, sizeof_array, NULL);
}
INLINE_DEVICE\
+(const device_property *)
+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);
+ return node;
+}
+
+
+STATIC_INLINE_DEVICE\
(void)
device_add_boolean_property(device *me,
const char *property,
@@ -383,91 +1124,83 @@ device_add_boolean_property(device *me,
("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),
+ &new_boolean, sizeof(new_boolean),
+ NULL, permenant_object);
}
INLINE_DEVICE\
-(void)
-device_add_null_property(device *me,
- const char *property)
+(int)
+device_find_boolean_property(device *me,
+ const char *property)
{
+ const device_property *node;
+ unsigned32 boolean;
TRACE(trace_devices,
- ("device_add_null(me=0x%lx, property=%s)\n",
+ ("device_find_boolean(me=0x%lx, property=%s)\n",
(long)me, property));
- device_add_property(me, property, null_property,
- NULL, 0);
+ 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);
+ ASSERT(sizeof(boolean) == node->sizeof_array);
+ memcpy(&boolean, node->array, sizeof(boolean));
+ return boolean;
}
-INLINE_DEVICE\
+STATIC_INLINE_DEVICE\
(void)
-device_add_string_property(device *me,
- const char *property,
- const char *string)
+device_add_ihandle_property(device *me,
+ const char *property,
+ const char *path)
{
-
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);
+ ("device_add_ihandle_property(me=0x%lx, property=%s, path=%s)\n",
+ (long)me, property, path));
+ device_add_property(me, property, ihandle_property,
+ path, strlen(path) + 1,
+ NULL, 0,
+ NULL, permenant_object);
}
INLINE_DEVICE\
-(const device_property *)
-device_find_property(device *me,
- const char *property)
-{
- if (me != (device*)0) {
- device_property_entry *entry = me->properties;
- while (entry != (device_property_entry*)0) {
- if (strcmp(entry->name, property) == 0)
- return entry->value;
- entry = entry->next;
- }
- }
- return (device_property*)0;
-}
-
-INLINE_DEVICE\
-(const char *)
-device_find_next_property(device *me,
- const char *property)
-{
- if (me != NULL) {
- if (property == NULL || strcmp(property, "") == 0) {
- return (me->properties != NULL
- ? me->properties->name
- : NULL);
- }
- else {
- device_property_entry *entry = me->properties;
- while (entry != NULL) {
- if (strcmp(entry->name, property) == 0)
- return (entry->next != NULL
- ? entry->next->name
- : NULL);
- entry = entry->next;
- }
- }
- }
- return NULL;
-}
-
-INLINE_DEVICE\
-(const device_property *)
-device_find_array_property(device *me,
- const char *property)
+(device_instance *)
+device_find_ihandle_property(device *me,
+ const char *property)
{
const device_property *node;
+ unsigned32 ihandle;
+ device_instance *instance;
TRACE(trace_devices,
- ("device_find_integer(me=0x%lx, property=%s)\n",
+ ("device_find_ihandle_property(me=0x%lx, property=%s)\n",
(long)me, property));
node = device_find_property(me, property);
- if (node == (device_property*)0
- || node->type != array_property)
- error("%s property %s not found or of wrong type\n",
- me->name, property);
- return node;
+ if (node == NULL || node->type != ihandle_property)
+ device_error(me, "property %s not found or of wrong type\n", property);
+ if (node->array == NULL)
+ device_error(me, "property %s not yet initialized\n", property);
+ ASSERT(sizeof(ihandle) == node->sizeof_array);
+ memcpy(&ihandle, node->array, sizeof(ihandle));
+ BE2H(ihandle);
+ instance = external_to_device_instance(me, ihandle);
+ ASSERT(instance != NULL);
+ return instance;
+}
+
+STATIC_INLINE_DEVICE\
+(void)
+device_add_integer_property(device *me,
+ const char *property,
+ signed32 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);
}
INLINE_DEVICE\
@@ -483,32 +1216,27 @@ device_find_integer_property(device *me,
node = device_find_property(me, property);
if (node == (device_property*)0
|| node->type != integer_property)
- error("%s property %s not found or of wrong type\n",
- me->name, 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;
}
-INLINE_DEVICE\
-(int)
-device_find_boolean_property(device *me,
- const char *property)
+STATIC_INLINE_DEVICE\
+(void)
+device_add_string_property(device *me,
+ const char *property,
+ const char *string)
{
- const device_property *node;
- unsigned32 boolean;
+
TRACE(trace_devices,
- ("device_find_boolean(me=0x%lx, property=%s)\n",
- (long)me, property));
- node = device_find_property(me, property);
- if (node == (device_property*)0
- || node->type != boolean_property)
- error("%s property %s not found or of wrong type\n",
- me->name, property);
- ASSERT(sizeof(boolean) == node->sizeof_array);
- memcpy(&boolean, node->array, sizeof(boolean));
- return boolean;
+ ("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);
}
INLINE_DEVICE\
@@ -524,707 +1252,718 @@ device_find_string_property(device *me,
node = device_find_property(me, property);
if (node == (device_property*)0
|| node->type != string_property)
- error("%s property %s not found or of wrong type\n",
- me->name, property);
+ device_error(me, "property %s not found or of wrong type\n", property);
string = node->array;
ASSERT(strlen(string) + 1 == node->sizeof_array);
return string;
}
-
-/* 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 */
STATIC_INLINE_DEVICE\
-(const char *)
-device_tree_full_name(device *leaf,
- char *buf,
- unsigned sizeof_buf)
+(void)
+device_add_duplicate_property(device *me,
+ const char *property,
+ const device_property *original)
{
- /* get a buffer */
- char full_name[1024];
- if (buf == (char*)0) {
- buf = full_name;
- sizeof_buf = sizeof(full_name);
- }
-
- /* construct a name */
- if (leaf->parent == NULL) {
- if (sizeof_buf < 1)
- error("device_full_name() buffer overflow\n");
- *buf = '\0';
- }
- else {
- device_tree_full_name(leaf->parent, buf, sizeof_buf);
- if (strlen(buf) + strlen("/") + strlen(leaf->name) + 1 > sizeof_buf)
- error("device_full_name() buffer overflow\n");
- strcat(buf, "/");
- strcat(buf, leaf->name);
- }
-
- /* return it usefully */
- if (buf == full_name)
- buf = strdup(full_name);
- return buf;
+ 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_add_property(me, property,
+ original->type,
+ original->array, original->sizeof_array,
+ original->array, original->sizeof_array,
+ original, permenant_object);
}
-/* find/create a node in the device tree */
-
-typedef enum {
- device_tree_return_null = 2,
- device_tree_abort = 3,
-} device_tree_action;
+
+/* Device Hardware: */
-STATIC_INLINE_DEVICE\
-(device *)
-device_tree_find_node(device *root,
- const char *path,
- const char *full_path,
- device_tree_action action)
+INLINE_DEVICE\
+(unsigned)
+device_io_read_buffer(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
{
- const char *name;
- int strlen_name;
- device *child;
-
- /* strip off any leading `/', `../' or `./' */
- while (1) {
- if (strncmp(path, "/", strlen("/")) == 0) {
- while (root != NULL && root->parent != NULL)
- root = root->parent;
- path += strlen("/");
- }
- else if (strncmp(path, "./", strlen("./")) == 0) {
- root = root;
- path += strlen("./");
- }
- else if (strncmp(path, "../", strlen("../")) == 0) {
- if (root != NULL && root->parent != NULL)
- root = root->parent;
- path += strlen("../");
- }
- else {
- break;
- }
- }
-
- /* parse the driver_name/unit-address */
- ASSERT(*path != '/');
- name = path;
- while (isalnum(*path)
- || *path == ',' || *path == ',' || *path == '_'
- || *path == '+' || *path == '-')
- path++;
- if ((*path != '/' && *path != '@' && *path != ':' && *path != '\0')
- || (name == path && *name != '\0'))
- error("device_tree: path %s invalid at %s\n", full_path, path);
-
- /* parse the unit-address */
- if (*path == '@') {
- path++;
- while ((*path != '\0' && *path != ':' && *path != '/')
- || (*path == ':' && path[-1] == '\\')
- || (*path == '/' && path[-1] == '\\'))
- path++;
- }
- strlen_name = path - name;
-
- /* skip the device-arguments */
- if (*path == ':') {
- path++;
- while ((*path != '\0' && *path != '/' && *path != ':' && *path != '@')
- || (*path == '/' && path[-1] == '\\')
- || (*path == ':' && path[-1] == '\\')
- || (*path == '@' && path[-1] == '\\'))
- path++;
- }
-
- /* sanity checks */
- if (*path != '\0' && *path != '/')
- error("device_tree: path %s invalid at %s\n", full_path, path);
-
- /* leaf? and growing? */
- if (name[0] == '\0') {
- return root;
- }
- else if (root != NULL) {
- for (child = root->children;
- child != NULL;
- child = child->sibling) {
- if (strncmp(name, child->name, strlen_name) == 0
- && strlen(child->name) >= strlen_name
- && (child->name[strlen_name] == '\0'
- || child->name[strlen_name] == '@')) {
- if (*path == '\0')
- return child;
- else
- return device_tree_find_node(child,
- path + 1/* / */,
- full_path,
- action);
- }
- }
- }
-
- /* search failed, take default action */
- switch (action) {
- case device_tree_return_null:
- return NULL;
- case device_tree_abort:
- error("device_tree_find_node() could not find %s in tree\n",
- full_path);
- return NULL;
- default:
- error("device_tree_find_node() invalid default action %d\n", action);
- return NULL;
- }
+ if (me->callback->io.read_buffer == NULL)
+ device_error(me, "no io_read_buffer method\n");
+ return me->callback->io.read_buffer(me, dest, space,
+ addr, nr_bytes,
+ processor, cia);
}
-
-/* grow the device tree */
-
INLINE_DEVICE\
-(device *)
-device_tree_add_device(device *root,
- const char *prefix,
- device *new_sub_tree)
+(unsigned)
+device_io_write_buffer(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia)
{
- device *parent;
- TRACE(trace_device_tree,
- ("device_tree_add_device(root=0x%lx, prefix=%s, dev=0x%lx)\n",
- (long)root, prefix, (long)new_sub_tree));
-
- /* find our parent */
- parent = device_tree_find_node(root,
- prefix,
- prefix, /* full-path */
- device_tree_abort);
-
- /* create/insert a new child */
- new_sub_tree->parent = parent;
- if (parent != NULL) {
- device **sibling = &parent->children;
- while ((*sibling) != NULL)
- sibling = &(*sibling)->sibling;
- *sibling = new_sub_tree;
- }
-
- return new_sub_tree;
+ if (me->callback->io.write_buffer == NULL)
+ device_error(me, "no io_write_buffer method\n");
+ return me->callback->io.write_buffer(me, source, space,
+ addr, nr_bytes,
+ processor, cia);
}
INLINE_DEVICE\
-(device *)
-device_tree_find_device(device *root,
- const char *path)
+(unsigned)
+device_dma_read_buffer(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes)
{
- device *node;
- TRACE(trace_device_tree,
- ("device_tree_find_device_tree(root=0x%lx, path=%s)\n",
- (long)root, path));
- node = device_tree_find_node(root,
- path,
- path, /* full-name */
- device_tree_return_null);
- return node;
+ if (me->callback->dma.read_buffer == NULL)
+ device_error(me, "no dma_read_buffer method\n");
+ return me->callback->dma.read_buffer(me, dest, space,
+ addr, nr_bytes);
}
-
-/* init all the devices */
-
-STATIC_INLINE_DEVICE\
-(void)
-device_tree_init_device(device *root,
- void *data)
+INLINE_DEVICE\
+(unsigned)
+device_dma_write_buffer(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ int violate_read_only_section)
{
- psim *system;
- system = (psim*)data;
- TRACE(trace_device_tree,
- ("device_tree_init() initializing device=0x%lx:%s\n",
- (long)root, root->full_name));
- device_init(root, system);
+ if (me->callback->dma.write_buffer == NULL)
+ device_error(me, "no dma_write_buffer method\n");
+ return me->callback->dma.write_buffer(me, source, space,
+ addr, nr_bytes,
+ violate_read_only_section);
}
-
INLINE_DEVICE\
(void)
-device_tree_init(device *root,
- psim *system)
+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*/
{
- TRACE(trace_device_tree,
- ("device_tree_init(root=0x%lx, system=0x%lx)\n", (long)root, (long)system));
- device_tree_traverse(root, device_tree_init_device, NULL, system);
- TRACE(trace_device_tree,
- ("device_tree_init() = void\n"));
+ 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);
}
-
-/* traverse a device tree applying prefix/postfix functions to it */
-
INLINE_DEVICE\
(void)
-device_tree_traverse(device *root,
- device_tree_traverse_function *prefix,
- device_tree_traverse_function *postfix,
- void *data)
+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 *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);
+ 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);
}
-/* dump out a device node and addresses */
+
+/* Interrupts: */
-INLINE_DEVICE\
-(void)
-device_tree_dump(device *device,
- void *ignore_data_argument)
+INLINE_DEVICE(void)
+device_interrupt_event(device *me,
+ int my_port,
+ int level,
+ cpu *processor,
+ unsigned_word cia)
{
- printf_filtered("(device_tree@0x%lx\n", (long)device);
- printf_filtered(" (parent 0x%lx)\n", (long)device->parent);
- printf_filtered(" (children 0x%lx)\n", (long)device->children);
- printf_filtered(" (sibling 0x%lx)\n", (long)device->sibling);
- printf_filtered(" (name %s)\n", device->name);
- error("FIXME - need to print out properties\n");
- printf_filtered(")\n");
+ int found_an_edge = 0;
+ device_interrupt_edge *edge;
+ /* device's interrupt lines directly connected */
+ for (edge = me->interrupt_destinations;
+ edge != NULL;
+ edge = edge->next) {
+ if (edge->my_port == my_port) {
+ if (edge->dest->callback->interrupt.event == NULL)
+ device_error(me, "no interrupt method\n");
+ edge->dest->callback->interrupt.event(edge->dest,
+ edge->dest_port,
+ me,
+ my_port,
+ level,
+ processor, cia);
+ found_an_edge = 1;
+ }
+ }
+ if (!found_an_edge) {
+ device_error(me, "No interrupt edge for port %d\n", my_port);
+ }
}
-
-/* lookup/create a device various formats */
-
-STATIC_INLINE_DEVICE\
+INLINE_DEVICE\
(void)
-u_strcat(char *buf,
- unsigned_word uw)
+device_interrupt_attach(device *me,
+ int my_port,
+ device *dest,
+ int dest_port,
+ object_disposition disposition)
{
- if (MASKED64(uw, 32, 63) == uw
- || WITH_HOST_WORD_BITSIZE == 64) {
- char *end = strchr(buf, '\0');
- sprintf(end, "0x%x", (unsigned)uw);
- }
- else {
- char *end = strchr(buf, '\0');
- sprintf(end, "0x%x%08x",
- (unsigned)EXTRACTED64(uw, 0, 31),
- (unsigned)EXTRACTED64(uw, 32, 63));
- }
+ attach_device_interrupt_edge(&me->interrupt_destinations,
+ my_port,
+ dest,
+ dest_port,
+ disposition);
}
-STATIC_INLINE_DEVICE\
+INLINE_DEVICE\
(void)
-c_strcat(char *buf,
- const char *c)
-{
- char *end = strchr(buf, '\0');
- while (*c) {
- if (*c == '/' || *c == ',')
- *end++ = '\\';
- *end++ = *c++;
- }
- *end = '\0';
+device_interrupt_detach(device *me,
+ int my_port,
+ device *dest,
+ int dest_port)
+{
+ detach_device_interrupt_edge(me,
+ &me->interrupt_destinations,
+ my_port,
+ dest,
+ dest_port);
}
INLINE_DEVICE\
-(device *)
-device_tree_add_found(device *root,
- const char *prefix,
- const char *name)
+(int)
+device_interrupt_decode(device *me,
+ const char *port_name)
{
- device *parent;
- device *new_device;
- device *new_node;
- TRACE(trace_device_tree,
- ("device_tree_add_found(root=0x%lx, prefix=%s, name=%lx)\n",
- (unsigned long)root, prefix, (unsigned long)name));
- parent = device_tree_find_node(root, prefix, prefix,
- device_tree_abort);
- new_device = device_tree_find_device(parent, name);
- if (new_device != NULL)
- return new_device;
+ if (port_name == NULL || port_name[0] == '\0')
+ return 0;
+ if (isdigit(port_name[0])) {
+ return strtoul(port_name, NULL, 0);
+ }
else {
- new_device = device_create(name, parent);
- new_node = device_tree_add_device(parent, "", new_device);
- ASSERT(new_device == new_node);
- return new_node;
+ const device_interrupt_port_descriptor *ports =
+ 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;
+ }
+ }
+ }
+ else if (strcmp(port_name, ports->name) == 0)
+ return ports->number;
+ ports++;
+ }
+ }
}
+ device_error(me, "Unreconized interrupt port %s\n", port_name);
+ return 0;
}
INLINE_DEVICE\
-(device *)
-device_tree_add_found_c(device *root,
- const char *prefix,
- const char *name,
- const char *c1)
+(int)
+device_interrupt_encode(device *me,
+ int port_number,
+ char *buf,
+ int sizeof_buf)
{
- char buf[1024];
- strcpy(buf, name);
- strcat(buf, "@");
- c_strcat(buf, c1);
- if (strlen(buf) + 1 >= sizeof(buf))
- error("device_tree_add_found_c - buffer overflow\n");
- return device_tree_add_found(root, prefix, buf);
+ 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);
+ }
+ }
+ 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);
+ }
+ }
+ ports++;
+ }
+ }
+ sprintf(buf, "%d", port_number);
+ if (strlen(buf) >= sizeof_buf)
+ error("device_interrupt_encode: buffer overflow\n");
+ return strlen(buf);
}
-INLINE_DEVICE\
-(device *)
-device_tree_add_found_c_uw(device *root,
- const char *prefix,
- const char *name,
- const char *c1,
- unsigned_word uw2)
+
+
+/* IOCTL: */
+
+EXTERN_DEVICE\
+(int)
+device_ioctl(device *me,
+ cpu *processor,
+ unsigned_word cia,
+ ...)
{
- char buf[1024];
- strcpy(buf, name);
- strcat(buf, "@");
- c_strcat(buf, c1);
- strcat(buf, ",");
- u_strcat(buf, uw2);
- if (strlen(buf) + 1 >= sizeof(buf))
- error("device_tree_add_found_* - buffer overflow\n");
- return device_tree_add_found(root, prefix, buf);
+ int status;
+ va_list ap;
+ va_start(ap, cia);
+ if (me->callback->ioctl == NULL)
+ device_error(me, "no ioctl method\n");
+ status = me->callback->ioctl(me, processor, cia, ap);
+ va_end(ap);
+ return status;
}
+
-INLINE_DEVICE\
-(device *)
-device_tree_add_found_uw_u(device *root,
- const char *prefix,
- const char *name,
- unsigned_word uw1,
- unsigned u2)
+
+/* I/O */
+
+EXTERN_DEVICE\
+(void volatile)
+device_error(device *me,
+ const char *fmt,
+ ...)
{
- char buf[1024];
- strcpy(buf, name);
- strcat(buf, "@");
- u_strcat(buf, uw1);
- strcat(buf, ",");
- u_strcat(buf, u2);
- if (strlen(buf) + 1 >= sizeof(buf))
- error("device_tree_add_found_* - buffer overflow\n");
- return device_tree_add_found(root, prefix, buf);
+ char message[1024];
+ va_list ap;
+ /* format the message */
+ va_start(ap, fmt);
+ vsprintf(message, fmt, ap);
+ va_end(ap);
+ /* sanity check */
+ if (strlen(message) >= sizeof(message))
+ error("device_error: buffer overflow\n");
+ if (me == NULL)
+ error("device: %s\n", message);
+ else
+ error("%s: %s\n", me->path, message);
+ while(1);
}
-INLINE_DEVICE\
+
+/* Tree utilities: */
+
+EXTERN_DEVICE\
(device *)
-device_tree_add_found_uw_u_u(device *root,
- const char *prefix,
- const char *name,
- unsigned_word uw1,
- unsigned u2,
- unsigned u3)
+device_tree_add_parsed(device *current,
+ const char *fmt,
+ ...)
{
- char buf[1024];
- strcpy(buf, name);
- strcat(buf, "@");
- u_strcat(buf, uw1);
- strcat(buf, ",");
- u_strcat(buf, u2);
- strcat(buf, ",");
- u_strcat(buf, u3);
- if (strlen(buf) + 1 >= sizeof(buf))
- error("device_tree_add_found_* - buffer overflow\n");
- return device_tree_add_found(root, prefix, buf);
+ 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;
}
INLINE_DEVICE\
-(device *)
-device_tree_add_found_uw_u_u_c(device *root,
- const char *prefix,
- const char *name,
- unsigned_word uw1,
- unsigned u2,
- unsigned u3,
- const char *c4)
+(void)
+device_tree_traverse(device *root,
+ device_tree_traverse_function *prefix,
+ device_tree_traverse_function *postfix,
+ void *data)
{
- char buf[1024];
- strcpy(buf, name);
- strcat(buf, "@");
- u_strcat(buf, uw1);
- strcat(buf, ",");
- u_strcat(buf, u2);
- strcat(buf, ",");
- u_strcat(buf, u3);
- strcat(buf, ",");
- c_strcat(buf, c4);
- if (strlen(buf) + 1 >= sizeof(buf))
- error("device_tree_add_found_* - buffer overflow\n");
- return device_tree_add_found(root, prefix, buf);
+ 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);
}
INLINE_DEVICE\
-(device *)
-device_tree_add_found_uw_uw_u_u_c(device *root,
- const char *prefix,
- const char *name,
- unsigned_word uw1,
- unsigned_word uw2,
- unsigned u3,
- unsigned u4,
- const char *c5)
+(void)
+device_tree_print_device(device *me,
+ void *ignore_or_null)
{
- char buf[1024];
- strcpy(buf, name);
- strcat(buf, "@");
- u_strcat(buf, uw1);
- strcat(buf, ",");
- u_strcat(buf, uw2);
- strcat(buf, ",");
- u_strcat(buf, u3);
- strcat(buf, ",");
- u_strcat(buf, u4);
- strcat(buf, ",");
- c_strcat(buf, c5);
- if (strlen(buf) + 1 >= sizeof(buf))
- error("device_tree_add_found_* - buffer overflow\n");
- return device_tree_add_found(root, prefix, buf);
+ 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);
+ }
}
INLINE_DEVICE\
(device *)
-device_tree_add_found_uw_uw_u_u_u(device *root,
- const char *prefix,
- const char *name,
- unsigned_word uw1,
- unsigned_word uw2,
- unsigned u3,
- unsigned u4,
- unsigned u5)
+device_tree_find_device(device *root,
+ const char *path)
{
- char buf[1024];
- strcpy(buf, name);
- strcat(buf, "@");
- u_strcat(buf, uw1);
- strcat(buf, ",");
- u_strcat(buf, uw2);
- strcat(buf, ",");
- u_strcat(buf, u3);
- strcat(buf, ",");
- u_strcat(buf, u4);
- strcat(buf, ",");
- u_strcat(buf, u5);
- if (strlen(buf) + 1 >= sizeof(buf))
- error("device_tree_add_found_* - buffer overflow\n");
- return device_tree_add_found(root, prefix, buf);
-}
-
-
-/* Parse a device name, various formats */
-
-#define SCAN_INIT(NAME) \
- char *START = (char*)0; \
- char *END = (char*)0; \
- int COUNT = -1; \
- /* find the first element */ \
- END = strchr(NAME, '@'); \
- if (END == (char*)0) \
- return COUNT; \
- COUNT += 1; \
- START = END + 1
-
-#define SCAN_END \
- return COUNT
-
-#define SCAN_U(U) \
-do { \
- *U = strtoul(START, &END, 0); \
- if (START == END) \
- return COUNT; \
- COUNT += 1; \
- if (*END != ',') \
- return COUNT; \
- START = END + 1; \
-} while (0)
-
-#define SCAN_P(P) \
-do { \
- *P = (void*)(unsigned)strtouq(START, END, 0); \
- if (START == END) \
- return COUNT; \
- COUNT += 1; \
- if (*END != ',') \
- return COUNT; \
- START = END + 1; \
-} while (0)
-
-#define SCAN_C(C, SIZE) \
-do { \
- char *chp = C; \
- END = START; \
- while (*END != '\0' && *END != ',') { \
- if (*END == '\\') \
- END += 1; \
- *chp = *END; \
- chp += 1; \
- END += 1; \
- if ((SIZE) <= ((END) - (START))) \
- return COUNT; /* overflow */ \
- } \
- *chp = '\0'; \
- if (START == END) \
- return COUNT; \
- COUNT += 1; \
- if (*END != ',') \
- return COUNT; \
- START = END + 1; \
-} while (0)
+ 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 */
-INLINE_DEVICE\
-(int)
-scand_c(const char *name,
- char *c1,
- unsigned c1size)
-{
- SCAN_INIT(name);
- SCAN_C(c1, c1size);
- SCAN_END;
-}
+ /* now find it */
+ node = split_find_device(root, &spec);
+ if (spec.name != NULL)
+ return NULL; /* not a leaf */
-INLINE_DEVICE\
-(int)
-scand_c_uw_u(const char *name,
- char *c1,
- unsigned c1size,
- unsigned_word *uw2,
- unsigned *u3)
-{
- SCAN_INIT(name);
- SCAN_C(c1, c1size);
- SCAN_U(uw2);
- SCAN_U(u3);
- SCAN_END;
+ return node;
}
INLINE_DEVICE\
-(int)
-scand_uw(const char *name,
- unsigned_word *uw1)
+(void)
+device_usage(int verbose)
{
- SCAN_INIT(name);
- SCAN_U(uw1);
- SCAN_END;
+ 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);
+ }
+ }
+ }
}
-INLINE_DEVICE\
-(int)
-scand_uw_c(const char *name,
- unsigned_word *uw1,
- char *c2,
- unsigned c2size)
-{
- SCAN_INIT(name);
- SCAN_U(uw1);
- SCAN_C(c2, c2size);
- SCAN_END;
-}
-INLINE_DEVICE\
-(int)
-scand_uw_u(const char *name,
- unsigned_word *uw1,
- unsigned *u2)
-{
- SCAN_INIT(name);
- SCAN_U(uw1);
- SCAN_U(u2);
- SCAN_END;
-}
+
+/* External representation */
INLINE_DEVICE\
-(int)
-scand_uw_u_u(const char *name,
- unsigned_word *uw1,
- unsigned *u2,
- unsigned *u3)
+(device *)
+external_to_device(device *tree_member,
+ unsigned32 phandle)
{
- SCAN_INIT(name);
- SCAN_U(uw1);
- SCAN_U(u2);
- SCAN_U(u3);
- SCAN_END;
+ device *root = device_tree_find_device(tree_member, "/");
+ device *me = cap_internal(root->phandles, phandle);
+ return me;
}
INLINE_DEVICE\
-(int)
-scand_uw_u_u_c(const char *name,
- unsigned_word *uw1,
- unsigned *u2,
- unsigned *u3,
- char *c4,
- unsigned c4size)
+(unsigned32)
+device_to_external(device *me)
{
- SCAN_INIT(name);
- SCAN_U(uw1);
- SCAN_U(u2);
- SCAN_U(u3);
- SCAN_C(c4, c4size);
- SCAN_END;
+ device *root = device_tree_find_device(me, "/");
+ unsigned32 phandle = cap_external(root->phandles, me);
+ return phandle;
}
INLINE_DEVICE\
-(int)
-scand_uw_uw(const char *name,
- unsigned_word *uw1,
- unsigned_word *uw2)
+(device_instance *)
+external_to_device_instance(device *tree_member,
+ unsigned32 ihandle)
{
- SCAN_INIT(name);
- SCAN_U(uw1);
- SCAN_U(uw2);
- SCAN_END;
+ device *root = device_tree_find_device(tree_member, "/");
+ device_instance *instance = cap_internal(root->ihandles, ihandle);
+ return instance;
}
INLINE_DEVICE\
-(int)
-scand_uw_uw_u(const char *name,
- unsigned_word *uw1,
- unsigned_word *uw2,
- unsigned *u3)
+(unsigned32)
+device_instance_to_external(device_instance *instance)
{
- SCAN_INIT(name);
- SCAN_U(uw1);
- SCAN_U(uw2);
- SCAN_U(u3);
- SCAN_END;
-}
-
-INLINE_DEVICE\
-(int)
-scand_uw_uw_u_u_c(const char *name,
- unsigned_word *uw1,
- unsigned_word *uw2,
- unsigned *u3,
- unsigned *u4,
- char *c5,
- unsigned c5size)
-{
- SCAN_INIT(name);
- SCAN_U(uw1);
- SCAN_U(uw2);
- SCAN_U(u3);
- SCAN_U(u4);
- SCAN_C(c5, c5size);
- SCAN_END;
-}
-
-INLINE_DEVICE\
-(int)
-scand_uw_uw_u_u_u(const char *name,
- unsigned_word *uw1,
- unsigned_word *uw2,
- unsigned *u3,
- unsigned *u4,
- unsigned *u5)
-{
- SCAN_INIT(name);
- SCAN_U(uw1);
- SCAN_U(uw2);
- SCAN_U(u3);
- SCAN_U(u4);
- SCAN_U(u5);
- SCAN_END;
+ device *root = device_tree_find_device(instance->owner, "/");
+ unsigned32 ihandle = cap_external(root->ihandles, instance);
+ return ihandle;
}
-
#endif /* _DEVICE_C_ */