aboutsummaryrefslogtreecommitdiff
path: root/sim/ppc/device.h
diff options
context:
space:
mode:
authorMichael Meissner <gnu@the-meissners.org>1995-12-15 20:20:13 +0000
committerMichael Meissner <gnu@the-meissners.org>1995-12-15 20:20:13 +0000
commit93fac32455bb5f7277b85fec5ead13f7abb9fde8 (patch)
treeed4ba905547982e681b142bc025ee5b78fe8af7f /sim/ppc/device.h
parentee68a042d20897e3164f96954612ccba80d70426 (diff)
downloadgdb-93fac32455bb5f7277b85fec5ead13f7abb9fde8.zip
gdb-93fac32455bb5f7277b85fec5ead13f7abb9fde8.tar.gz
gdb-93fac32455bb5f7277b85fec5ead13f7abb9fde8.tar.bz2
Changes from Andrew
Diffstat (limited to 'sim/ppc/device.h')
-rw-r--r--sim/ppc/device.h660
1 files changed, 660 insertions, 0 deletions
diff --git a/sim/ppc/device.h b/sim/ppc/device.h
new file mode 100644
index 0000000..f5d5136
--- /dev/null
+++ b/sim/ppc/device.h
@@ -0,0 +1,660 @@
+/* This file is part of the program psim.
+
+ Copyright (C) 1994-1995, 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
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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.
+
+ */
+
+
+#ifndef _DEVICE_TREE_H_
+#define _DEVICE_TREE_H_
+
+#ifndef INLINE_DEVICE
+#define INLINE_DEVICE
+#endif
+
+
+
+/* declared in basics.h, this object is used everywhere */
+/* typedef struct _device device; */
+
+
+
+
+/* Device Tree:
+
+ All the devices in this model live in a tree. The following allow
+ the location/manipulation of this tree */
+
+device INLINE_DEVICE *device_sibling
+(device *me);
+
+device INLINE_DEVICE *device_child
+(device *me);
+
+device INLINE_DEVICE *device_parent
+(device *me);
+
+const char INLINE_DEVICE *device_name
+(device *me);
+
+void INLINE_DEVICE *device_data
+(device *me);
+
+
+/* Grow the device tree adding either a specific device or
+ alternativly a device found in the device table */
+
+device INLINE_DEVICE *device_tree_add_device
+(device *root,
+ const char *prefix,
+ device *new_sub_tree);
+
+device INLINE_DEVICE *device_tree_add_found
+(device *root,
+ const char *prefix,
+ const char *name);
+
+device INLINE_DEVICE *device_tree_add_found_c
+(device *root,
+ const char *prefix,
+ const char *name,
+ const char *c1);
+
+device INLINE_DEVICE *device_tree_add_found_c_uw
+(device *root,
+ const char *prefix,
+ const char *name,
+ const char *c1,
+ unsigned_word uw2);
+
+device INLINE_DEVICE *device_tree_add_found_uw_u
+(device *root,
+ const char *prefix,
+ const char *name,
+ unsigned_word uw1,
+ unsigned u2);
+
+device INLINE_DEVICE *device_tree_add_found_uw_u_u
+(device *root,
+ const char *prefix,
+ const char *name,
+ unsigned_word uw1,
+ unsigned u2,
+ unsigned u3);
+
+device INLINE_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);
+
+device INLINE_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);
+
+device INLINE_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);
+
+
+/* Query the device tree, null is returned if the specified device is
+ not found */
+
+device INLINE_DEVICE *device_tree_find_device
+(device *root,
+ const char *path);
+
+
+/* traverse the device tree visiting all notes (either pre or post
+ fix) */
+
+typedef void (device_tree_traverse_function)
+ (device *device,
+ void *data);
+
+void INLINE_DEVICE device_tree_traverse
+(device *root,
+ device_tree_traverse_function *prefix,
+ device_tree_traverse_function *postfix,
+ void *data);
+
+
+/* dump a node, this can be passed to the device_tree_traverse()
+ function to dump out the entire device tree */
+
+void INLINE_DEVICE device_tree_dump
+(device *device,
+ void *ignore_data_argument);
+
+
+
+
+/* Device Properties:
+
+ Attached to a device (typically by open boot firmware) are
+ properties that profile the devices features. The below allow the
+ manipulation of device properties */
+
+/* Each device can have associated properties. Internal to
+ psim those properties are strictly typed. Within the simulation,
+ no such control exists */
+
+typedef enum {
+ integer_property,
+ boolean_property,
+ string_property,
+ array_property,
+ null_property,
+} device_property_type;
+
+typedef struct _device_property device_property;
+struct _device_property {
+ device *owner;
+ device_property_type type;
+ unsigned sizeof_array;
+ const void *array;
+};
+
+
+/* Basic operations used by software */
+
+const char INLINE_DEVICE *device_find_next_property
+(device *me,
+ const char *previous);
+
+void INLINE_DEVICE device_set_property
+(device *me,
+ const char *property,
+ const void *array,
+ int sizeof_array);
+
+
+/* INLINE_DEVICE void device_add_property
+ No such external function, all properties, when added are explictly
+ typed */
+
+void INLINE_DEVICE device_add_array_property
+(device *me,
+ const char *property,
+ const void *array,
+ int sizeof_array);
+
+void INLINE_DEVICE device_add_integer_property
+(device *me,
+ const char *property,
+ signed_word integer);
+
+void INLINE_DEVICE device_add_boolean_property
+(device *me,
+ const char *property,
+ int bool);
+
+void INLINE_DEVICE device_add_null_property
+(device *me,
+ const char *property);
+
+void INLINE_DEVICE device_add_string_property
+(device *me,
+ const char *property,
+ const char *string);
+
+
+/* Locate a property returning its description. Return NULL if the
+ named property is not found */
+
+const device_property INLINE_DEVICE *device_find_property
+(device *me,
+ const char *property);
+
+
+/* Process all properties attached to the named device */
+
+typedef void (device_traverse_property_function)
+ (device *me,
+ const char *name,
+ void *data);
+
+void INLINE_DEVICE device_traverse_properties
+(device *me,
+ device_traverse_property_function *traverse,
+ void *data);
+
+
+/* Similar to above except that the property *must* be in the device
+ tree and *must* be of the specified type. */
+
+const device_property INLINE_DEVICE *device_find_array_property
+(device *me,
+ const char *property);
+
+signed_word INLINE_DEVICE device_find_integer_property
+(device *me,
+ const char *property);
+
+const char INLINE_DEVICE *device_find_string_property
+(device *me,
+ const char *property);
+
+int INLINE_DEVICE device_find_boolean_property
+(device *me,
+ const char *property);
+
+
+
+/* Device Hardware:
+
+ A device principaly is modeling real hardware that a processor can
+ directly interact with via load/stores dma's and interrupts. The
+ interface below is used by the hardware side of the device
+ model. */
+
+/* Address access attributes that can be attached to a devices address
+ range */
+typedef enum _access_type {
+ access_invalid = 0,
+ access_read = 1,
+ access_write = 2,
+ access_read_write = 3,
+ access_exec = 4,
+ access_read_exec = 5,
+ access_write_exec = 6,
+ access_read_write_exec = 7,
+} access_type;
+
+
+/* Address attachement types */
+typedef enum _attach_type {
+ attach_invalid,
+ attach_callback,
+ attach_default,
+ attach_raw_memory,
+} attach_type;
+
+
+/* Initialization:
+
+ A device is made fully functional in two stages.
+
+ 1. It is created. A device is created _before_ it is entered into
+ the device tree. During creation any permenant structures needed
+ by the device should be created/initialized.
+
+ 2. It is initialized. Before a simulation run, each device in the
+ device tree is initialized in prefix order. As part of this
+ initialization, a device should (re)attach its self to its parent
+ as needed.
+
+ */
+
+device INLINE_DEVICE *device_create
+(const char *name,
+ device *parent);
+
+/* some external functions want to create things */
+typedef struct _device_callbacks device_callbacks;
+
+device INLINE_DEVICE *device_create_from
+(const char *name,
+ void *data,
+ const device_callbacks *callbacks,
+ device *parent);
+
+void INLINE_DEVICE device_init
+(device *me,
+ psim *system);
+
+/* initialize the entire tree */
+
+void INLINE_DEVICE device_tree_init
+(device *root,
+ psim *system);
+
+
+/* Data transfers:
+
+ A device may permit the reading/writing (IO) of its registers in
+ one or more address spaces. For instance, a PCI device may have
+ config registers in its config space and control registers in both
+ the io and memory spaces of a PCI bus.
+
+ Similarly, a device may initiate a data transfer (DMA) by passing
+ such a request up to its parent.
+
+ Init:
+
+ As part of its initialization (not creation) and possibly also as a
+ consequence of IO a device may attach its self to one or more of
+ the address spaces of its parent device.
+
+ For instance, a PCI device, during initialization would attach its
+ config registers (space=0?, base=0, nr_bytes=64) to its parent PCI
+ bridge. Later, due to a write to this config space, the same
+ device may in turn find it necessary to also attach its self to
+ it's parent's `memory' or `io' space.
+
+ To perform these operations, a device will call upon its parent
+ using either device_attach_address or device_detach_address.
+
+ * Any address specified is according to what the device expects to
+ see.
+
+ * Any detach operation must exactly match a previous attach.
+
+ * included with the attach or detach is the devices name, the
+ parent may use this as part of determining how to map map between a
+ child's address + space and its own.
+
+ * at any time, at most one device can have a default mapping
+ registered.
+
+
+ IO:
+
+ A device receives requests to perform reads/writes to its registers
+ or memory either A. from a processor or B. from a parent device.
+
+ The device may then in turn either A. resolve the IO request
+ locally by processing the data or trigering an exception or
+ B. re-mapping the access onto one of its local address spaces and
+ then in turn passing that on to one of its children.
+
+ * Any address passed is relative to the local device. Eg for PCI
+ config registers, the address would (normally) be in the range of 0
+ to 63.
+
+ * Any exception situtation triggered by an IO operation (processor
+ != NULL) is handled in one of the following ways: 1. Machine check
+ (and similar): issued immediatly by restarting the cpu; 2. External
+ exception: issue delayed (using events.h) until the current
+ instruction execution cycle is completed; 3. Slave device (and
+ similar): the need for the interrupt is passed on to the devices
+ parent (which being an interrupt control unit will in turn take one
+ of the actions described here); 4. Forget it.
+
+ * Any exception situtation trigered by a non IO operation
+ (processor == NULL) is handled buy returning 0.
+
+ * Transfers of size <= 8 and of a power of 2 *must* be correctly
+ aligned and should be treated as a `single cycle' transfer.
+
+ DMA:
+
+ A device initiates a DMA transfer by calling its parent with the
+ request. At the top level (if not done earlier) this is reflected
+ back down the tree as io read/writes to the target device.
+
+ This function is subject to change ...
+
+ */
+
+void INLINE_DEVICE 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*/
+
+void INLINE_DEVICE 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*/
+
+unsigned INLINE_DEVICE device_io_read_buffer
+(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia);
+
+unsigned INLINE_DEVICE device_io_write_buffer
+(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ cpu *processor,
+ unsigned_word cia);
+
+unsigned INLINE_DEVICE device_dma_read_buffer
+(device *me,
+ void *dest,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes);
+
+unsigned INLINE_DEVICE device_dma_write_buffer
+(device *me,
+ const void *source,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ int violate_read_only_section);
+
+
+/* Interrupts:
+
+ As mentioned above. Instead of handling an interrupt directly, a
+ device may instead pass the need to interrupt on to its parent.
+
+ Init:
+
+ Before passing interrupts up to is parent, a device must first
+ attach its interrupt lines to the parent device. To do this, the
+ device uses the parents attach/detach calls.
+
+ Interrupts:
+
+ A child notifies a parent of a change in an interrupt lines status
+ using the interrupt call. Similarly, a parent may notify a child
+ of any `interrupt ack' sequence using the interrupt_ack call.
+
+ */
+
+void INLINE_DEVICE device_attach_interrupt
+(device *me,
+ device *who,
+ int interrupt_line,
+ const char *name);
+
+void INLINE_DEVICE device_detach_interrupt
+(device *me,
+ device *who,
+ int interrupt_line,
+ const char *name);
+
+void INLINE_DEVICE device_interrupt
+(device *me,
+ device *who,
+ int interrupt_line,
+ int interrupt_status,
+ cpu *processor,
+ unsigned_word cia);
+
+void INLINE_DEVICE device_interrupt_ack
+(device *me,
+ int interrupt_line,
+ int interrupt_status);
+
+
+/* IOCTL:
+
+ Very simply, a catch all for any thing that turns up that until now
+ either hasn't been thought of or doesn't justify an extra function. */
+
+void EXTERN_DEVICE device_ioctl
+(device *me,
+ psim *system,
+ cpu *processor,
+ unsigned_word cia,
+ ...);
+
+
+
+/* Device software - the instance
+
+ Under development
+
+ In addition to the processor directly manipulating a device via
+ read/write operations. A program may manipulate a device
+ indirectly via OpenBoot calls. The following provide a higher
+ level software interface to the devices */
+
+device_instance INLINE_DEVICE *device_instance_open
+(device *me,
+ const char *device_specifier);
+
+void INLINE_DEVICE device_instance_close
+(device_instance *instance);
+
+int INLINE_DEVICE device_instance_read
+(device_instance *instance,
+ void *addr,
+ unsigned_word len);
+
+int INLINE_DEVICE device_instance_write
+(device_instance *instance,
+ const void *addr,
+ unsigned_word len);
+
+int INLINE_DEVICE device_instance_seek
+(device_instance *instance,
+ unsigned_word pos_hi,
+ unsigned_word pos_lo);
+
+device INLINE_DEVICE *device_instance_device
+(device_instance *instance);
+
+const char INLINE_DEVICE *device_instance_name
+(device_instance *instance);
+
+
+
+
+
+/* Device dregs... */
+
+/* Parse a device name */
+
+void INLINE_DEVICE device_tree_parse_name
+(const char *name,
+ const char **driver_name,
+ const char **unit_address,
+ const char **device_arguments,
+ const char **end);
+
+
+/* Parse a device name, various formats:
+
+ uw: unsigned_word
+ u: unsigned
+ c: string */
+
+int INLINE_DEVICE scand_c
+(const char *name,
+ char *c1,
+ unsigned c1size);
+
+int INLINE_DEVICE scand_c_uw_u
+(const char *name,
+ char *c1,
+ unsigned c1size,
+ unsigned_word *uw2,
+ unsigned *u3);
+
+int INLINE_DEVICE scand_uw
+(const char *name,
+ unsigned_word *uw1);
+
+int INLINE_DEVICE scand_uw_c
+(const char *name,
+ unsigned_word *uw1,
+ char *c2,
+ unsigned c2size);
+
+int INLINE_DEVICE scand_uw_u
+(const char *name,
+ unsigned_word *uw1,
+ unsigned *u2);
+
+int INLINE_DEVICE scand_uw_u_u
+(const char *name,
+ unsigned_word *uw1,
+ unsigned *u2,
+ unsigned *u3);
+
+int INLINE_DEVICE scand_uw_u_u_c
+(const char *name,
+ unsigned_word *uw1,
+ unsigned *u2,
+ unsigned *u3,
+ char *c4,
+ unsigned c4size);
+
+int INLINE_DEVICE scand_uw_uw
+(const char *name,
+ unsigned_word *uw1,
+ unsigned_word *uw2);
+
+int INLINE_DEVICE scand_uw_uw_u
+(const char *name,
+ unsigned_word *uw1,
+ unsigned_word *uw2,
+ unsigned *u3);
+
+int INLINE_DEVICE scand_uw_uw_u_u_c
+(const char *name,
+ unsigned_word *uw1,
+ unsigned_word *uw2,
+ unsigned *u3,
+ unsigned *u4,
+ char *c5,
+ unsigned c5size);
+
+int INLINE_DEVICE scand_uw_uw_u_u_u
+(const char *name,
+ unsigned_word *uw1,
+ unsigned_word *uw2,
+ unsigned *u3,
+ unsigned *u4,
+ unsigned *u5);
+
+#endif /* _DEVICE_TREE_H_ */