Change decode_compound_collector to use std::vector
[deliverable/binutils-gdb.git] / sim / ppc / device.h
index cc6bd5373edb28e76e038025e65cdf984a98fd67..6fd198de70dd52a36e2df9a07495fe3665d9a19c 100644 (file)
@@ -1,10 +1,10 @@
 /*  This file is part of the program psim.
 
-    Copyright (C) 1994-1995, 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/>.
  
     */
 
 
-#ifndef _DEVICE_TREE_H_
-#define _DEVICE_TREE_H_
+#ifndef _DEVICE_H_
+#define _DEVICE_H_
 
 #ifndef INLINE_DEVICE
 #define INLINE_DEVICE
 #endif
 
-
-
 /* declared in basics.h, this object is used everywhere */
 /* typedef struct _device device; */
 
 
+/* Introduction:
 
-\f
-/* Device Tree:
+   As explained in earlier sections, the device, device instance,
+   property and interrupts lie at the heart of PSIM's device model.
 
-   All the devices in this model live in a tree. The following allow
-   the location/manipulation of this tree */
+   In the below a synopsis of the device object and the operations it
+   supports are given.  Details of this object can be found in the
+   files <<device.h>> and <<device.c>>.
 
-INLINE_DEVICE(device *) device_parent
-(device *me);
+   */
 
-INLINE_DEVICE(device *) device_sibling
-(device *me);
 
-INLINE_DEVICE(device *) device_child
+/* Device creation: */
+
+INLINE_DEVICE\
+(device *) device_create
+(device *parent,
+ const char *base,
+ const char *name,
+ const char *unit_address,
+ const char *args);
+
+INLINE_DEVICE\
+(void) device_usage
+(int verbose);
+
+
+/* Device initialization: */
+
+INLINE_DEVICE\
+(void) device_clean
+(device *root,
+ void *data);
+
+INLINE_DEVICE\
+(void) device_init_static_properties
+(device *me,
+ void *data);
+
+INLINE_DEVICE\
+(void) device_init_address
+(device *me,
+ void *data);
+
+INLINE_DEVICE\
+(void) device_init_runtime_properties
+(device *me,
+ void *data);
+
+INLINE_DEVICE\
+(void) device_init_data
+(device *me,
+ void *data);
+
+
+/* Relationships:
+
+   A device is able to determine its relationship to other devices
+   within the tree.  Operations include querying for a devices parent,
+   sibling, child, name, and path (from the root).
+
+   */
+
+INLINE_DEVICE\
+(device *) device_parent
 (device *me);
 
-INLINE_DEVICE(const char *) device_name
+INLINE_DEVICE\
+(device *) device_root
 (device *me);
 
-INLINE_DEVICE(void *) device_data
+INLINE_DEVICE\
+(device *) device_sibling
 (device *me);
 
+INLINE_DEVICE\
+(device *) device_child
+(device *me);
 
-/* Grow the device tree adding either a specific device or
-   alternativly a device found in the device table */
+INLINE_DEVICE\
+(const char *) device_name
+(device *me);
 
-INLINE_DEVICE(device *)device_tree_add_device
-(device *root,
- const char *prefix,
- device *new_sub_tree);
+INLINE_DEVICE\
+(const char *) device_base
+(device *me);
 
-INLINE_DEVICE(device *) device_tree_add_found
-(device *root,
- const char *prefix,
- const char *name);
+INLINE_DEVICE\
+(const char *) device_path
+(device *me);
 
-INLINE_DEVICE(device *) device_tree_add_found_c
-(device *root,
- const char *prefix,
- const char *name,
- const char *c1);
+INLINE_DEVICE\
+(void *) device_data
+(device *me);
 
-INLINE_DEVICE(device *) device_tree_add_found_c_uw
-(device *root,
- const char *prefix,
- const char *name,
- const char *c1,
- unsigned_word uw2);
+INLINE_DEVICE\
+(psim *) device_system
+(device *me);
 
-INLINE_DEVICE(device *) device_tree_add_found_uw_u
-(device *root,
- const char *prefix,
- const char *name,
- unsigned_word uw1,
- unsigned u2);
+typedef struct _device_unit {
+  int nr_cells;
+  unsigned_cell cells[4]; /* unused cells are zero */
+} device_unit;
 
-INLINE_DEVICE(device *) device_tree_add_found_uw_u_u
-(device *root,
- const char *prefix,
- const char *name,
- unsigned_word uw1,
- unsigned u2,
- unsigned u3);
+INLINE_DEVICE\
+(const device_unit *) device_unit_address
+(device *me);
 
-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);
+INLINE_DEVICE\
+(int) device_decode_unit
+(device *bus,
+ const char *unit,
+ device_unit *address);
 
-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);
+INLINE_DEVICE\
+(int) device_encode_unit
+(device *bus,
+ const device_unit *unit_address,
+ char *buf,
+ int sizeof_buf);
 
-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);
 
+/* Convert an Open Firmware size into a form suitable for attach
+   address calls.
 
-/* Query the device tree, null is returned if the specified device is
-   not found */
+   Return a zero result if the address should be ignored when looking
+   for attach addresses */
 
-INLINE_DEVICE(device *) device_tree_find_device
-(device *root,
- const char *path);
+INLINE_DEVICE\
+(int) device_address_to_attach_address
+(device *me,
+ const device_unit *address,
+ int *attach_space,
+ unsigned_word *attach_address,
+ device *client);
 
 
-/* traverse the device tree visiting all notes (either pre or post
-   fix) */
+/* Convert an Open Firmware size into a form suitable for attach
+   address calls
 
-typedef void (device_tree_traverse_function)
-     (device *device,
-      void *data);
+   Return a zero result if the address should be ignored */
 
-INLINE_DEVICE(void) device_tree_traverse
-(device *root,
- device_tree_traverse_function *prefix,
- device_tree_traverse_function *postfix,
- void *data);
+INLINE_DEVICE\
+(int) device_size_to_attach_size
+(device *me,
+ const device_unit *size,
+ unsigned *nr_bytes,
+ device *client);
 
 
-/* dump a node, this can be passed to the device_tree_traverse()
-   function to dump out the entire device tree */
+INLINE_DEVICE\
+(unsigned) device_nr_address_cells
+(device *me);
 
-INLINE_DEVICE(void) device_tree_dump
-(device *device,
- void *ignore_data_argument);
+INLINE_DEVICE\
+(unsigned) device_nr_size_cells
+(device *me);
 
 
+/* Properties:
 
-\f
-/* Device Properties:
+   Attached to a device are a number of properties.  Each property has
+   a size and type (both of which can be queried).  A device is able
+   to iterate over or query and set a properties value.
 
-   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 */
+/* The following are valid property types.  The property `array' is
+   for generic untyped data. */
 
 typedef enum {
-  integer_property,
+  array_property,
   boolean_property,
+  ihandle_property, /*runtime*/
+  integer_property,
+  range_array_property,
+  reg_array_property,
   string_property,
-  array_property,
-  null_property,
+  string_array_property,
 } device_property_type;
 
 typedef struct _device_property device_property;
 struct _device_property {
   device *owner;
+  const char *name;
   device_property_type type;
   unsigned sizeof_array;
   const void *array;
+  const device_property *original;
+  object_disposition disposition;
 };
 
 
-/* Basic operations used by software */
+/* iterate through the properties attached to a device */
+
+INLINE_DEVICE\
+(const device_property *) device_next_property
+(const device_property *previous);
 
-INLINE_DEVICE(const char *) device_find_next_property
+INLINE_DEVICE\
+(const device_property *) device_find_property
 (device *me,
- const char *previous);
+ const char *property); /* NULL for first property */
 
-/* INLINE_DEVICE void device_add_property
-   No such external function, all properties, when added are explictly
-   typed */
 
-INLINE_DEVICE(void) device_add_array_property
+/* Manipulate the properties belonging to a given device.
+
+   SET on the other hand will force the properties value.  The
+   simulation is aborted if the property was present but of a
+   conflicting type.
+
+   FIND returns the specified properties value, aborting the
+   simulation if the property is missing.  Code locating a property
+   should first check its type (using device_find_property above) and
+   then obtain its value using the below.
+
+   void device_add_<type>_property(device *, const char *, <type>)
+   void device_add_*_array_property(device *, const char *, const <type>*, int)
+   void device_set_*_property(device *, const char *, <type>)
+   void device_set_*_array_property(device *, const char *, const <type>*, int)
+   <type> device_find_*_property(device *, const char *)
+   int device_find_*_array_property(device *, const char *, int, <type>*)
+
+   */
+
+
+INLINE_DEVICE\
+(void) device_add_array_property
 (device *me,
  const char *property,
  const void *array,
  int sizeof_array);
 
-INLINE_DEVICE(void) device_add_integer_property
+INLINE_DEVICE\
+(void) device_set_array_property
 (device *me,
  const char *property,
- signed_word integer);
+ const void *array,
+ int sizeof_array);
 
-INLINE_DEVICE(void) device_add_boolean_property
+INLINE_DEVICE\
+(const device_property *) device_find_array_property
+(device *me,
+ const char *property);
+
+
+
+INLINE_DEVICE\
+(void) device_add_boolean_property
 (device *me,
  const char *property,
  int bool);
 
-INLINE_DEVICE(void) device_add_null_property
+INLINE_DEVICE\
+(int) device_find_boolean_property
 (device *me,
  const char *property);
 
-INLINE_DEVICE(void) device_add_string_property
+
+
+typedef struct _ihandle_runtime_property_spec {
+  const char *full_path;
+} ihandle_runtime_property_spec;
+
+INLINE_DEVICE\
+(void) device_add_ihandle_runtime_property
 (device *me,
  const char *property,
- const char *string);
+ const ihandle_runtime_property_spec *ihandle);
 
+INLINE_DEVICE\
+(void) device_find_ihandle_runtime_property
+(device *me,
+ const char *property,
+ ihandle_runtime_property_spec *ihandle);
 
-/* Locate a property returning its description.  Return NULL if the
-   named property is not found */
+INLINE_DEVICE\
+(void) device_set_ihandle_property
+(device *me,
+ const char *property,
+ device_instance *ihandle);
 
-INLINE_DEVICE(const device_property *) device_find_property
+INLINE_DEVICE\
+(device_instance *) device_find_ihandle_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);
+INLINE_DEVICE\
+(void) device_add_integer_property
+(device *me,
+ const char *property,
+ signed_cell integer);
 
-INLINE_DEVICE(void) device_traverse_properties
+INLINE_DEVICE\
+(signed_cell) device_find_integer_property
 (device *me,
- device_traverse_property_function *traverse,
- void *data);
+ const char *property);
+
+INLINE_DEVICE\
+(int) device_find_integer_array_property
+(device *me,
+ const char *property,
+ unsigned index,
+ signed_cell *integer);
+
+
 
-/* Similar to above except that the property *must* be in the device
-   tree and *must* be of the specified type. */
+typedef struct _range_property_spec {
+  device_unit child_address;
+  device_unit parent_address;
+  device_unit size;
+} range_property_spec;
 
-INLINE_DEVICE(const device_property *) device_find_array_property
+INLINE_DEVICE\
+(void) device_add_range_array_property
 (device *me,
- const char *property);
+ const char *property,
+ const range_property_spec *ranges,
+ unsigned nr_ranges);
 
-INLINE_DEVICE(signed_word) device_find_integer_property
+INLINE_DEVICE\
+(int) device_find_range_array_property
 (device *me,
- const char *property);
+ const char *property,
+ unsigned index,
+ range_property_spec *range);
+
 
-INLINE_DEVICE(const char *) device_find_string_property
+
+typedef struct _reg_property_spec {
+  device_unit address;
+  device_unit size;
+} reg_property_spec;
+
+INLINE_DEVICE\
+(void) device_add_reg_array_property
 (device *me,
- const char *property);
+ const char *property,
+ const reg_property_spec *reg,
+ unsigned nr_regs);
+
+INLINE_DEVICE\
+(int) device_find_reg_array_property
+(device *me,
+ const char *property,
+ unsigned index,
+ reg_property_spec *reg);
+
+
+
+INLINE_DEVICE\
+(void) device_add_string_property
+(device *me,
+ const char *property,
+ const char *string);
 
-INLINE_DEVICE(int) device_find_boolean_property
+INLINE_DEVICE\
+(const char *) device_find_string_property
 (device *me,
  const char *property);
 
 
-\f
-/* 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. */
+typedef const char *string_property_spec;
 
-/* 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;
+INLINE_DEVICE\
+(void) device_add_string_array_property
+(device *me,
+ const char *property,
+ const string_property_spec *strings,
+ unsigned nr_strings);
 
+INLINE_DEVICE\
+(int) device_find_string_array_property
+(device *me,
+ const char *property,
+ unsigned index,
+ string_property_spec *string);
 
-/* Address attachement types */
-typedef enum _attach_type {
-  attach_invalid,
-  attach_callback,
-  attach_default,
-  attach_raw_memory,
-} attach_type;
 
 
-/* Initialization:
+INLINE_DEVICE\
+(void) device_add_duplicate_property
+(device *me,
+ const char *property,
+ const device_property *original);
 
-   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.
+/* Instances:
 
-   */
+   As with IEEE1275, a device can be opened, creating an instance.
+   Instances provide more abstract interfaces to the underlying
+   hardware.  For example, the instance methods for a disk may include
+   code that is able to interpret file systems found on disks.  Such
+   methods would there for allow the manipulation of files on the
+   disks file system.  The operations would be implemented using the
+   basic block I/O model provided by the disk.
 
-INLINE_DEVICE(device *) device_create
-(const char *name,
- device *parent);
+   This model includes methods that faciliate the creation of device
+   instance and (should a given device support it) standard operations
+   on those instances.
+
+   */
 
-/* some external functions want to create things */
-typedef struct _device_callbacks device_callbacks;
+typedef struct _device_instance_callbacks device_instance_callbacks;
 
-INLINE_DEVICE(device *) device_create_from
-(const char *name,
+INLINE_DEVICE\
+(device_instance *) device_create_instance_from
+(device *me, /*OR*/ device_instance *parent,
  void *data,
- const device_callbacks *callbacks,
- device *parent);
+ const char *path,
+ const char *args,
+ const device_instance_callbacks *callbacks);
 
-INLINE_DEVICE(void) device_init
+INLINE_DEVICE\
+(device_instance *) device_create_instance
 (device *me,
- psim *system);
+ const char *full_path,
+ const char *args);
 
-/* initialize the entire tree */
+INLINE_DEVICE\
+(void) device_instance_delete
+(device_instance *instance);
 
-INLINE_DEVICE(void) device_tree_init
-(device *root,
- psim *system);
+INLINE_DEVICE\
+(int) device_instance_read
+(device_instance *instance,
+ void *addr,
+ unsigned_word len);
+
+INLINE_DEVICE\
+(int) device_instance_write
+(device_instance *instance,
+ const void *addr,
+ unsigned_word len);
 
+INLINE_DEVICE\
+(int) device_instance_seek
+(device_instance *instance,
+ unsigned_word pos_hi,
+ unsigned_word pos_lo);
 
-/* Data transfers:
+INLINE_DEVICE\
+(int) device_instance_call_method
+(device_instance *instance,
+ const char *method,
+ int n_stack_args,
+ unsigned_cell stack_args[/*n_stack_args*/],
+ int n_stack_returns,
+ unsigned_cell stack_returns[/*n_stack_returns*/]);
+
+INLINE_DEVICE\
+(device *) device_instance_device
+(device_instance *instance);
 
-   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.
+INLINE_DEVICE\
+(const char *) device_instance_path
+(device_instance *instance);
 
-   Similarly, a device may initiate a data transfer (DMA) by passing
-   such a request up to its parent.
+INLINE_DEVICE\
+(void *) device_instance_data
+(device_instance *instance);
 
-   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.
+/* Interrupts:
 
-   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.
+   */
+
+/* Interrupt Source
 
-   To perform these operations, a device will call upon its parent
-   using either device_attach_address or device_detach_address.
+   A device drives its interrupt line using the call
 
-   * Any address specified is according to what the device expects to
-   see.
+   */
 
-   * Any detach operation must exactly match a previous attach.
+INLINE_DEVICE\
+(void) device_interrupt_event
+(device *me,
+ int my_port,
+ int value,
+ cpu *processor,
+ unsigned_word cia);
 
-   * 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.
+/* This interrupt event will then be propogated to any attached
+   interrupt destinations.
 
-   * at any time, at most one device can have a default mapping
-   registered.
+   Any interpretation of PORT and VALUE is model dependant.  However
+   as guidelines the following are recommended: PCI interrupts a-d
+   correspond to lines 0-3; level sensative interrupts be requested
+   with a value of one and withdrawn with a value of 0; edge sensative
+   interrupts always have a value of 1, the event its self is treated
+   as the interrupt.
 
 
-   IO:
+   Interrupt Destinations
 
-   A device receives requests to perform reads/writes to its registers
-   or memory either A. from a processor or B. from a parent device.
+   Attached to each interrupt line of a device can be zero or more
+   desitinations.  These destinations consist of a device/port pair.
+   A destination is attached/detached to a device line using the
+   attach and detach calls. */
 
-   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.
+INLINE_DEVICE\
+(void) device_interrupt_attach
+(device *me,
+ int my_port,
+ device *dest,
+ int dest_port,
+ object_disposition disposition);
 
-   * 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.
+INLINE_DEVICE\
+(void) device_interrupt_detach
+(device *me,
+ int my_port,
+ device *dest,
+ int dest_port);
 
-   * 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.
+typedef void (device_interrupt_traverse_function)
+     (device *me,
+      int my_port,
+      device *dest,
+      int my_dest,
+      void *data);
 
-   * Any exception situtation trigered by a non IO operation
-   (processor == NULL) is handled buy returning 0.
+INLINE_DEVICE\
+(void) device_interrupt_traverse
+(device *me,
+ device_interrupt_traverse_function *handler,
+ void *data);
 
-   * Transfers of size <= 8 and of a power of 2 *must* be correctly
-   aligned and should be treated as a `single cycle' transfer.
+/* DESTINATION is attached (detached) to LINE of the device ME
 
-   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.
+   Interrupt conversion
 
-   This function is subject to change ...
+   Users refer to interrupt port numbers symbolically.  For instance a
+   device may refer to its `INT' signal which is internally
+   represented by port 3.
 
-   */
+   To convert to/from the symbolic and internal representation of a
+   port name/number.  The following functions are available. */
 
-INLINE_DEVICE(void) device_attach_address
+INLINE_DEVICE\
+(int) device_interrupt_decode
 (device *me,
- const char *name,
- attach_type attach,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- access_type access,
- device *who); /*callback/default*/
+ const char *symbolic_name,
+ port_direction direction);
 
-INLINE_DEVICE(void) device_detach_address
+INLINE_DEVICE\
+(int) device_interrupt_encode
 (device *me,
- const char *name,
- attach_type attach,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- access_type access,
- device *who); /*callback/default*/
+ int port_number,
+ char *buf,
+ int sizeof_buf,
+ port_direction direction);
+
+/* Hardware operations:
+
+   */
 
-INLINE_DEVICE(unsigned) device_io_read_buffer
+INLINE_DEVICE\
+(unsigned) device_io_read_buffer
 (device *me,
  void *dest,
  int space,
@@ -438,7 +602,8 @@ INLINE_DEVICE(unsigned) device_io_read_buffer
  cpu *processor,
  unsigned_word cia);
 
-INLINE_DEVICE(unsigned) device_io_write_buffer
+INLINE_DEVICE\
+(unsigned) device_io_write_buffer
 (device *me,
  const void *source,
  int space,
@@ -447,14 +612,23 @@ INLINE_DEVICE(unsigned) device_io_write_buffer
  cpu *processor,
  unsigned_word cia);
 
-INLINE_DEVICE(unsigned) device_dma_read_buffer
+
+/* Conversly, the device pci1000,1@1 my need to perform a dma transfer
+   into the cpu/memory core.  Just as I/O moves towards the leaves,
+   dma transfers move towards the core via the initiating devices
+   parent nodes.  The root device (special) converts the DMA transfer
+   into reads/writes to memory */
+
+INLINE_DEVICE\
+(unsigned) device_dma_read_buffer
 (device *me,
  void *dest,
  int space,
  unsigned_word addr,
  unsigned nr_bytes);
 
-INLINE_DEVICE(unsigned) device_dma_write_buffer
+INLINE_DEVICE\
+(unsigned) device_dma_write_buffer
 (device *me,
  const void *source,
  int space,
@@ -462,184 +636,161 @@ INLINE_DEVICE(unsigned) device_dma_write_buffer
  unsigned nr_bytes,
  int violate_read_only_section);
 
+/* To avoid the need for an intermediate (bridging) node to ask each
+   of its child devices in turn if an IO access is intended for them,
+   parent nodes maintain a table mapping addresses directly to
+   specific devices.  When a device is `connected' to its bus it
+   attaches its self to its parent. */
 
-/* Interrupts:
+/* Address access attributes */
+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;
 
-   As mentioned above.  Instead of handling an interrupt directly, a
-   device may instead pass the need to interrupt on to its parent.
+/* Address attachement types */
+typedef enum _attach_type {
+  attach_invalid,
+  attach_raw_memory,
+  attach_callback,
+  /* ... */
+} attach_type;
 
-   Init:
+INLINE_DEVICE\
+(void) device_attach_address
+(device *me,
+ attach_type attach,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ access_type access,
+ device *client); /*callback/default*/
 
-   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:
+INLINE_DEVICE\
+(void) device_detach_address
+(device *me,
+ attach_type attach,
+ int space,
+ unsigned_word addr,
+ unsigned nr_bytes,
+ access_type access,
+ device *client); /*callback/default*/
 
-   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.
+/* Utilities:
 
    */
 
-INLINE_DEVICE(void) device_attach_interrupt
-(device *me,
- device *who,
- int interrupt_line,
- const char *name);
+/* IOCTL::
 
-INLINE_DEVICE(void) device_detach_interrupt
-(device *me,
- device *who,
- int interrupt_line,
- const char *name);
+   Often devices require `out of band' operations to be performed.
+   For instance a pal device may need to notify a PCI bridge device
+   that an interrupt ack cycle needs to be performed on the PCI bus.
+   Within PSIM such operations are performed by using the generic
+   ioctl call <<device_ioctl()>>.
 
-INLINE_DEVICE(void) device_interrupt
+   */
+
+typedef enum {
+  device_ioctl_break, /* unsigned_word requested_break */
+  device_ioctl_set_trace, /* void */
+  device_ioctl_create_stack, /* unsigned_word *sp, char **argv, char **envp */
+  device_ioctl_change_media, /* const char *new_image (possibly NULL) */
+  nr_device_ioctl_requests,
+} device_ioctl_request;
+
+EXTERN_DEVICE\
+(int) device_ioctl
 (device *me,
- device *who,
- int interrupt_line,
- int interrupt_status,
  cpu *processor,
- unsigned_word cia);
+ unsigned_word cia,
+ device_ioctl_request request,
+ ...);
 
-INLINE_DEVICE(void) device_interrupt_ack
-(device *me,
- int interrupt_line,
- int interrupt_status);
 
+/* Error reporting::
 
-/* IOCTL:
+   So that errors originating from devices appear in a consistent
+   format, the <<device_error()>> function can be used.  Formats and
+   outputs the error message before aborting the simulation
 
-   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. */
+   Devices should use this function to abort the simulation except
+   when the abort reason leaves the simulation in a hazardous
+   condition (for instance a failed malloc).
+
+   */
 
 EXTERN_DEVICE\
-(void) device_ioctl
+(void) device_error
 (device *me,
- psim *system,
- cpu *processor,
- unsigned_word cia,
- ...);
-      
+ const char *fmt,
+ ...) __attribute__ ((format (printf, 2, 3)));
 
-\f
-/* Device software - the instance
+INLINE_DEVICE\
+(int) device_trace
+(device *me);
 
-   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 */
 
-#if 0
-INLINE_DEVICE(device_instance *)device_instance_open
-(device *me,
- const char *device_specifier);
+/* External representation:
 
-INLINE_DEVICE(void) device_instance_close
-(device_instance *instance);
+   Both device nodes and device instances, in OpenBoot firmware have
+   an external representation (phandles and ihandles) and these values
+   are both stored in the device tree in property nodes and passed
+   between the client program and the simulator during emulation
+   calls.
 
-INLINE_DEVICE(int) device_instance_read
-(device_instance *instance,
- void *addr,
- unsigned_word len);
+   To limit the potential risk associated with trusing `data' from the
+   client program, the following mapping operators `safely' convert
+   between the two representations
 
-INLINE_DEVICE(int) device_instance_write
-(device_instance *instance,
- const void *addr,
- unsigned_word len);
+   */
 
-INLINE_DEVICE(int) device_instance_seek
-(device_instance *instance,
- unsigned_word pos_hi,
- unsigned_word pos_lo);
+INLINE_DEVICE\
+(device *) external_to_device
+(device *tree_member,
+ unsigned_cell phandle);
 
-INLINE_DEVICE(device *) device_instance_device
-(device_instance *instance);
+INLINE_DEVICE\
+(unsigned_cell) device_to_external
+(device *me);
 
-INLINE_DEVICE(const char *) device_instance_name
-(device_instance *instance);
-#endif
+INLINE_DEVICE\
+(device_instance *) external_to_device_instance
+(device *tree_member,
+ unsigned_cell ihandle);
 
+INLINE_DEVICE\
+(unsigned_cell) device_instance_to_external
+(device_instance *me);
 
 
-\f
-/* Device dregs... */
+/* Event queue:
 
-/* Parse a device name, various formats:
+   The device inherets certain event queue operations from the main
+   simulation. */
 
-   uw: unsigned_word
-   u: unsigned
-   c: string */
+typedef void device_event_handler(void *data);
 
-INLINE_DEVICE(int) scand_c
-(const char *name,
- char *c1,
- unsigned c1size);
+INLINE_DEVICE\
+(event_entry_tag) device_event_queue_schedule
+(device *me,
+ signed64 delta_time,
+ device_event_handler *handler,
+ void *data);
 
-INLINE_DEVICE(int) scand_c_uw_u
-(const char *name,
- char *c1,
- unsigned c1size,
- unsigned_word *uw2,
- unsigned *u3);
-INLINE_DEVICE(int) scand_uw
-(const char *name,
- unsigned_word *uw1);
-INLINE_DEVICE(int) scand_uw_c
-(const char *name,
- unsigned_word *uw1,
- char *c2,
- unsigned c2size);
-INLINE_DEVICE(int) scand_uw_u
-(const char *name,
- unsigned_word *uw1,
- unsigned *u2);
-INLINE_DEVICE(int) scand_uw_u_u
-(const char *name,
- unsigned_word *uw1,
- unsigned *u2,
- unsigned *u3);
-INLINE_DEVICE(int) scand_uw_u_u_c
-(const char *name,
- unsigned_word *uw1,
- unsigned *u2,
- unsigned *u3,
- char *c4,
- unsigned c4size);
-INLINE_DEVICE(int) scand_uw_uw
-(const char *name,
- unsigned_word *uw1,
- unsigned_word *uw2);
-
-INLINE_DEVICE(int) scand_uw_uw_u
-(const char *name,
- unsigned_word *uw1,
- unsigned_word *uw2,
- unsigned *u3);
-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);
-INLINE_DEVICE(int) 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_ */
+INLINE_EVENTS\
+(void) device_event_queue_deschedule
+(device *me,
+ event_entry_tag event_to_remove);
+
+INLINE_EVENTS\
+(signed64) device_event_queue_time
+(device *me);
+
+#endif /* _DEVICE_H_ */
This page took 0.033525 seconds and 4 git commands to generate.