* configure.in: Remove target-libstdc++-v3 from noconfigdirs for
[deliverable/binutils-gdb.git] / sim / ppc / device_table.c
index 15ef95a842ff23d51230dbc8e7c85b572f987004..09772aba6b4adeb58b42d1b3fd51cec427624db4 100644 (file)
@@ -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
 #ifndef _DEVICE_TABLE_C_
 #define _DEVICE_TABLE_C_
 
-#ifndef STATIC_INLINE_DEVICE_TABLE
-#define STATIC_INLINE_DEVICE_TABLE STATIC_INLINE
-#endif
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <ctype.h>
-
 #include "device_table.h"
 
-#include "events.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_STDLIB_H
+#if HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
 
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-
-#include "cpu.h"
+#include <ctype.h>
 
-#include "bfd.h"
 
 /* Helper functions */
 
-/* Generic device init: Attaches the device of size <nr_bytes> (taken
-   from <name>@<int>,<nr_bytes>) to its parent at address zero and
-   with read/write access. */
-
-STATIC_INLINE_DEVICE_TABLE void
-generic_init_callback(device *me,
-                     psim *system)
-{
-  unsigned_word addr;
-  unsigned nr_bytes;
-  if (scand_uw_u(device_name(me), &addr, &nr_bytes) != 2)
-    error("generic_init_callback() invalid nr_bytes in %s\n", device_name(me));
-  device_attach_address(device_parent(me),
-                       device_name(me),
-                       attach_callback,
-                       0 /*space*/,
-                       addr,
-                       nr_bytes,
-                       access_read_write,
-                       me);
-}
-
 
-/* DMA a file into memory */
-STATIC_INLINE_DEVICE_TABLE int
-dma_file(device *me,
-        const char *file_name,
-        unsigned_word addr)
-{
-  int count;
-  int inc;
-  FILE *image;
-  char buf[1024];
+/* Go through the devices various reg properties for those that
+   specify attach addresses */
 
-  /* get it open */
-  image = fopen(file_name, "r");
-  if (image == NULL)
-    return -1;
 
-  /* read it in slowly */
-  count = 0;
-  while (1) {
-    inc = fread(buf, 1, sizeof(buf), image);
-    if (feof(image) || ferror(image))
-      break;
-    if (device_dma_write_buffer(device_parent(me),
-                               buf,
-                               0 /*address-space*/,
-                               addr+count,
-                               inc /*nr-bytes*/,
-                               1 /*violate ro*/) != inc) {
-      fclose(image);
-      return -1;
+void
+generic_device_init_address(device *me)
+{
+  static const char *(reg_property_names[]) = {
+    "attach-addresses",
+    "assigned-addresses",
+    "reg",
+    "alternate-reg" ,
+    NULL
+  };
+  const char **reg_property_name;
+  int nr_valid_reg_properties = 0;
+  for (reg_property_name = reg_property_names;
+       *reg_property_name != NULL;
+       reg_property_name++) {
+    if (device_find_property(me, *reg_property_name) != NULL) {
+      reg_property_spec reg;
+      int reg_entry;
+      for (reg_entry = 0;
+          device_find_reg_array_property(me, *reg_property_name, reg_entry,
+                                         &reg);
+          reg_entry++) {
+       unsigned_word attach_address;
+       int attach_space;
+       unsigned attach_size;
+       if (!device_address_to_attach_address(device_parent(me),
+                                             &reg.address,
+                                             &attach_space, &attach_address,
+                                             me))
+         continue;
+       if (!device_size_to_attach_size(device_parent(me),
+                                       &reg.size,
+                                       &attach_size, me))
+         continue;
+       device_attach_address(device_parent(me),
+                             attach_callback,
+                             attach_space, attach_address, attach_size,
+                             access_read_write_exec,
+                             me);
+       nr_valid_reg_properties++;
+      }
+      /* if first option matches don't try for any others */
+      if (reg_property_name == reg_property_names)
+       break;
     }
-    count += inc;
   }
-
-  /* close down again */
-  fclose(image);
-
-  return count;
-}
-
-
-\f
-/* inimplemented versions of each function */
-
-void
-unimp_device_init(device *me,
-                 psim *system)
-{
-  error("device_init_callback for %s not implemented\n", device_name(me));
-}
-
-void
-unimp_device_attach_address(device *me,
-                           const char *name,
-                           attach_type type,
-                           int space,
-                           unsigned_word addr,
-                           unsigned nr_bytes,
-                           access_type access,
-                           device *who) /*callback/default*/
-{
-  error("device_attach_address_callback for %s not implemented\n", device_name(me));
-}
-
-void
-unimp_device_detach_address(device *me,
-                           const char *name,
-                           attach_type type,
-                           int space,
-                           unsigned_word addr,
-                           unsigned nr_bytes,
-                           access_type access,
-                           device *who) /*callback/default*/
-{
-  error("device_detach_address_callback for %s not implemented\n", device_name(me));
-}
-
-unsigned
-unimp_device_io_read_buffer(device *me,
-                           void *dest,
-                           int space,
-                           unsigned_word addr,
-                           unsigned nr_bytes,
-                           cpu *processor,
-                           unsigned_word cia)
-{
-  error("device_io_read_buffer_callback for %s not implemented\n", device_name(me));
-  return 0;
-}
-
-unsigned
-unimp_device_io_write_buffer(device *me,
-                            const void *source,
-                            int space,
-                            unsigned_word addr,
-                            unsigned nr_bytes,
-                            cpu *processor,
-                            unsigned_word cia)
-{
-  error("device_io_write_buffer_callback for %s not implemented\n", device_name(me));
-  return 0;
-}
-
-unsigned
-unimp_device_dma_read_buffer(device *me,
-                            void *target,
-                            int space,
-                            unsigned_word addr,
-                            unsigned nr_bytes)
-{
-  error("device_dma_read_buffer_callback for %s not implemented\n", device_name(me));
-  return 0;
-}
-
-unsigned
-unimp_device_dma_write_buffer(device *me,
-                             const void *source,
-                             int space,
-                             unsigned_word addr,
-                             unsigned nr_bytes,
-                             int violate_read_only_section)
-{
-  error("device_dma_write_buffer_callback for %s not implemented\n", device_name(me));
-  return 0;
-}
-
-void
-unimp_device_attach_interrupt(device *me,
-                             device *who,
-                             int interrupt_line,
-                             const char *name)
-{
-  error("device_attach_interrupt_callback for %s not implemented\n", device_name(me));
 }
 
-void
-unimp_device_detach_interrupt(device *me,
-                             device *who,
-                             int interrupt_line,
-                             const char *name)
+int
+generic_device_unit_decode(device *bus,
+                          const char *unit,
+                          device_unit *phys)
 {
-  error("device_detach_interrupt_callback for %s not implemented\n", device_name(me));
-}
-
-void
-unimp_device_interrupt(device *me,
-                      device *who,
-                      int interrupt_line,
-                      int interrupt_status,
-                      cpu *processor,
-                      unsigned_word cia)
-{
-  error("device_interrupt_callback for %s not implemented\n", device_name(me));
+  memset(phys, 0, sizeof(device_unit));
+  if (unit == NULL)
+    return 0;
+  else {
+    int nr_cells = 0;
+    const int max_nr_cells = device_nr_address_cells(bus);
+    while (1) {
+      char *end = NULL;
+      unsigned long val;
+      val = strtoul(unit, &end, 0);
+      /* parse error? */
+      if (unit == end)
+       return -1;
+      /* two many cells? */
+      if (nr_cells >= max_nr_cells)
+       return -1;
+      /* save it */
+      phys->cells[nr_cells] = val;
+      nr_cells++;
+      unit = end;
+      /* more to follow? */
+      if (isspace(*unit) || *unit == '\0')
+       break;
+      if (*unit != ',')
+       return -1;
+      unit++;
+    }
+    if (nr_cells < max_nr_cells) {
+      /* shift everything to correct position */
+      int i;
+      for (i = 1; i <= nr_cells; i++)
+       phys->cells[max_nr_cells - i] = phys->cells[nr_cells - i];
+      for (i = 0; i < (max_nr_cells - nr_cells); i++)
+       phys->cells[i] = 0;
+    }
+    phys->nr_cells = max_nr_cells;
+    return max_nr_cells;
+  }
 }
 
-void
-unimp_device_interrupt_ack(device *me,
-                          int interrupt_line,
-                          int interrupt_status)
+int
+generic_device_unit_encode(device *bus,
+                          const device_unit *phys,
+                          char *buf,
+                          int sizeof_buf)
 {
-  error("device_interrupt_ack_callback for %s not implemented\n", device_name(me));
+  int i;
+  int len;
+  char *pos = buf;
+  /* skip leading zero's */
+  for (i = 0; i < phys->nr_cells; i++) {
+    if (phys->cells[i] != 0)
+      break;
+  }
+  /* don't output anything if empty */
+  if (phys->nr_cells == 0) {
+    strcpy(pos, "");
+    len = 0;
+  }
+  else if (i == phys->nr_cells) {
+    /* all zero */
+    strcpy(pos, "0");
+    len = 1;
+  }
+  else {
+    for (; i < phys->nr_cells; i++) {
+      if (pos != buf) {
+       strcat(pos, ",");
+       pos = strchr(pos, '\0');
+      }
+      if (phys->cells[i] < 10)
+       sprintf(pos, "%ld", (unsigned long)phys->cells[i]);
+      else
+       sprintf(pos, "0x%lx", (unsigned long)phys->cells[i]);
+      pos = strchr(pos, '\0');
+    }
+    len = pos - buf;
+  }
+  if (len >= sizeof_buf)
+    error("generic_unit_encode - buffer overflow\n");
+  return len;
+}
+
+int
+generic_device_address_to_attach_address(device *me,
+                                        const device_unit *address,
+                                        int *attach_space,
+                                        unsigned_word *attach_address,
+                                        device *client)
+{
+  int i;
+  for (i = 0; i < address->nr_cells - 2; i++) {
+    if (address->cells[i] != 0)
+      device_error(me, "Only 32bit addresses supported");
+  }
+  if (address->nr_cells >= 2)
+    *attach_space = address->cells[address->nr_cells - 2];
+  else
+    *attach_space = 0;
+  *attach_address = address->cells[address->nr_cells - 1];
+  return 1;
 }
 
-void
-unimp_device_ioctl(device *me,
-                  psim *system,
-                  cpu *processor,
-                  unsigned_word cia,
-                  va_list ap)
+int
+generic_device_size_to_attach_size(device *me,
+                                  const device_unit *size,
+                                  unsigned *nr_bytes,
+                                  device *client)
 {
-  error("device_ioctl_callback for %s not implemented\n", device_name(me));
+  int i;
+  for (i = 0; i < size->nr_cells - 1; i++) {
+    if (size->cells[i] != 0)
+      device_error(me, "Only 32bit sizes supported");
+  }
+  *nr_bytes = size->cells[0];
+  return *nr_bytes;
 }
 
 
-\f
 /* ignore/passthrough versions of each function */
 
 void
-ignore_device_init(device *me,
-                  psim *system)
-{
-  /*null*/
-}
-
-void
-passthrough_device_attach_address(device *me,
-                                 const char *name,
+passthrough_device_address_attach(device *me,
                                  attach_type attach,
                                  int space,
                                  unsigned_word addr,
                                  unsigned nr_bytes,
                                  access_type access,
-                                 device *who) /*callback/default*/
+                                 device *client) /*callback/default*/
 {
-  device_attach_address(device_parent(me), name, attach,
+  device_attach_address(device_parent(me), attach,
                        space, addr, nr_bytes,
                        access,
-                       who);
+                       client);
 }
 
 void
-passthrough_device_detach_address(device *me,
-                                 const char *name,
+passthrough_device_address_detach(device *me,
                                  attach_type attach,
                                  int space,
                                  unsigned_word addr,
-                          unsigned nr_bytes,
-                          access_type access,
-                          device *who) /*callback/default*/
+                                 unsigned nr_bytes,
+                                 access_type access,
+                                 device *client) /*callback/default*/
 {
-  device_detach_address(device_parent(me), name, attach,
+  device_detach_address(device_parent(me), attach,
                        space, addr, nr_bytes, access,
-                       who);
+                       client);
 }
 
 unsigned
 passthrough_device_dma_read_buffer(device *me,
-                           void *dest,
-                           int space,
-                           unsigned_word addr,
-                           unsigned nr_bytes)
+                                  void *dest,
+                                  int space,
+                                  unsigned_word addr,
+                                  unsigned nr_bytes)
 {
   return device_dma_read_buffer(device_parent(me), dest,
                                space, addr, nr_bytes);
@@ -321,1650 +266,45 @@ passthrough_device_dma_write_buffer(device *me,
                                 violate_read_only_section);
 }
 
-void
-passthrough_device_attach_interrupt(device *me,
-                                   device *who,
-                                   int interrupt_line,
-                                   const char *name)
-{
-  device_attach_interrupt(device_parent(me), who,
-                         interrupt_line, name);
-}
-
-void
-passthrough_device_detach_interrupt(device *me,
-                            device *who,
-                            int interrupt_line,
-                            const char *name)
-{
-  device_detach_interrupt(device_parent(me), who,
-                         interrupt_line, name);
-}
-
-
-void
-passthrough_device_interrupt(device *me,
-                     device *who,
-                     int interrupt_line,
-                     int interrupt_status,
-                     cpu *processor,
-                     unsigned_word cia)
-{
-  device_interrupt(device_parent(me), who,
-                                 interrupt_line, interrupt_status,
-                                 processor, cia);
-}
-
-
-static const device_callbacks passthrough_callbacks = {
-  ignore_device_init,
-  passthrough_device_attach_address,
-  passthrough_device_detach_address,
-  unimp_device_io_read_buffer,
-  unimp_device_io_write_buffer,
-  passthrough_device_dma_read_buffer,
-  passthrough_device_dma_write_buffer,
-  passthrough_device_attach_interrupt,
-  passthrough_device_detach_interrupt,
-  passthrough_device_interrupt,
-  unimp_device_interrupt_ack,
-  unimp_device_ioctl,
-};
-
-
-\f
-/* Simple console device: console@<address>,16
-
-   Input characters are taken from the keyboard, output characters
-   sent to the terminal.  Echoing of characters is not disabled.
-
-   The device has four registers:
-
-   0x0: read
-   0x4: read-status
-   0x8: write
-   0xC: write-status
-
-   Where a nonzero status register indicates that the device is ready
-   (input fifo contains a character or output fifo has space). */
-
-typedef struct _console_buffer {
-  char buffer;
-  int status;
-  event_entry_tag event_tag;
-} console_buffer;
-
-typedef struct _console_device {
-  console_buffer input;
-  console_buffer output;
-} console_device;
-
-typedef enum {
-  console_read_buffer = 0,
-  console_read_status = 4,
-  console_write_buffer = 8,
-  console_write_status = 12,
-  console_offset_mask = 0xc,
-  console_size = 16,
-} console_offsets;
-
-
-static unsigned
-console_io_read_buffer_callback(device *me,
-                               void *dest,
-                               int space,
-                               unsigned_word addr,
-                               unsigned nr_bytes,
-                               cpu *processor,
-                               unsigned_word cia)
-{
-  console_device *console = (console_device*)device_data(me);
-  unsigned_1 val;
-
-  /* determine what was read */
-
-  switch ((int)addr) {
-
-  case console_read_buffer:
-    val = console->input.buffer;
-    break;
-
-  case console_read_status:
-    { /* check for input */
-      int flags;
-      int status;
-      /* get the old status */
-      flags = fcntl(0, F_GETFL, 0);
-      if (flags == -1) {
-       perror("console");
-       val = 0;
-       break;
-      }
-      /* temp, disable blocking IO */
-      status = fcntl(0, F_SETFL, flags | O_NDELAY);
-      if (status == -1) {
-       perror("console");
-       val = 0;
-       break;
-      }
-      /* try for input */
-      status = read(0, &console->input.buffer, 1);
-      if (status == 1) {
-       console->input.status = 1;
-      }
-      else {
-       console->input.status = 0;
-      }
-      /* return to regular vewing */
-      fcntl(0, F_SETFL, flags);
-    }
-    val = console->input.status;
-    break;
-
-  case console_write_buffer:
-    val = console->output.buffer;
-    break;
-
-  case console_write_status:
-    val = console->output.status;
-    break;
-
-  default:
-    error("console_read_callback() internal error\n");
-    val = 0;
-    break;
-
-  }
-
-  memset(dest, 0, nr_bytes);
-  *(unsigned_1*)dest = val;
-  return nr_bytes;
-}
-
-static unsigned
-console_io_write_buffer_callback(device *me,
-                                const void *source,
-                                int space,
-                                unsigned_word addr,
-                                unsigned nr_bytes,
-                                cpu *processor,
-                                unsigned_word cia)
-{
-  console_device *console = (console_device*)device_data(me);
-  unsigned_1 val = *(unsigned_1*)source;
-
-  switch ((int)addr) {
-  case console_read_buffer:
-    console->input.buffer = val;
-    break;
-  case console_read_status:
-    console->input.status = val;
-    break;
-  case console_write_buffer:
-    DTRACE(console, ("<%c:%d>", val, val));
-    printf_filtered("%c",val) ;
-    console->output.buffer = val;
-    console->output.status = 1;
-    break;
-  case console_write_status:
-    console->output.status = val;
-    break;
-  default:
-    error("console_write_callback() internal error\n");
-  }
-        
-  return nr_bytes;
-}
-
-
-static device_callbacks const console_callbacks = {
-  generic_init_callback,
-  unimp_device_attach_address,
-  unimp_device_detach_address,
-  console_io_read_buffer_callback,
-  console_io_write_buffer_callback,
-  unimp_device_dma_read_buffer,
-  unimp_device_dma_write_buffer,
-  unimp_device_attach_interrupt,
-  unimp_device_detach_interrupt,
-  unimp_device_interrupt,
-  unimp_device_interrupt_ack,
-  unimp_device_ioctl,
-};
-
-
-static void *
-console_create(const char *name,
-              device *parent)
-{
-  /* create the descriptor */
-  console_device *console = ZALLOC(console_device);
-  console->output.status = 1;
-  console->output.buffer = '\0';
-  console->input.status = 0;
-  console->input.buffer = '\0';
-  return console;
-}
-
-
-\f
-/* ICU device: icu@0x<address>,4
-
-   Single 4 byte register.  Read returns processor number.  Write
-   interrupts specified processor.
-
-   Illustrates passing of events to parent device. Passing of
-   interrupts to parent bus.
-
-   NB: For the sake of illustrating the passing of interrupts.  This
-   device doesn't pass interrupt events to its parent.  Instead it
-   passes them back to its self. */
-
-static unsigned
-icu_io_read_buffer_callback(device *me,
-                           void *dest,
-                           int space,
-                           unsigned_word addr,
-                           unsigned nr_bytes,
-                           cpu *processor,
-                           unsigned_word cia)
-{
-  unsigned_1 val;
-  val = cpu_nr(processor);
-  memset(dest, 0, nr_bytes);
-  *(unsigned_1*)dest = val;
-  return nr_bytes;
-}
-
-
-static unsigned
-icu_io_write_buffer_callback(device *me,
-                            const void *source,
-                            int space,
-                            unsigned_word addr,
-                            unsigned nr_bytes,
-                            cpu *processor,
-                            unsigned_word cia)
-{
-  unsigned_1 val = H2T_1(*(unsigned_1*)source);
-  /* tell the parent device that the interrupt lines have changed.
-     For this fake ICU.  The interrupt lines just indicate the cpu to
-     interrupt next */
-  device_interrupt(device_parent(me), me,
-                  val, val,
-                  processor, cia);
-  return nr_bytes;
-}
-
-
-static device_callbacks const icu_callbacks = {
-  generic_init_callback,
-  unimp_device_attach_address,
-  unimp_device_detach_address,
-  icu_io_read_buffer_callback,
-  icu_io_write_buffer_callback,
-  unimp_device_dma_read_buffer,
-  unimp_device_dma_write_buffer,
-  unimp_device_attach_interrupt,
-  unimp_device_detach_interrupt,
-  unimp_device_interrupt,
-  unimp_device_interrupt_ack,
-  unimp_device_ioctl,
-};
-
-
-\f
-/* HALT device: halt@0x<address>,4
-
-   With real hardware, the processor operation is normally terminated
-   through a reset.  This device illustrates how a reset device could
-   be attached to an address */
-
-
-static unsigned
-halt_io_read_buffer_callback(device *me,
-                            void *dest,
-                            int space,
-                            unsigned_word addr,
-                            unsigned nr_bytes,
-                            cpu *processor,
-                            unsigned_word cia)
-{
-  cpu_halt(processor, cia, was_exited, 0);
-  return 0;
-}
-
-
-static unsigned
-halt_io_write_buffer_callback(device *me,
-                             const void *source,
-                             int space,
-                             unsigned_word addr,
-                             unsigned nr_bytes,
-                             cpu *processor,
-                             unsigned_word cia)
+int
+ignore_device_unit_decode(device *me,
+                         const char *unit,
+                         device_unit *phys)
 {
-  cpu_halt(processor, cia, was_exited, *(unsigned_1*)source);
+  memset(phys, 0, sizeof(device_unit));
   return 0;
 }
 
 
-static device_callbacks const halt_callbacks = {
-  generic_init_callback,
-  unimp_device_attach_address,
-  unimp_device_detach_address,
-  halt_io_read_buffer_callback,
-  halt_io_write_buffer_callback,
-  unimp_device_dma_read_buffer,
-  unimp_device_dma_write_buffer,
-  unimp_device_attach_interrupt,
-  unimp_device_detach_interrupt,
-  unimp_device_interrupt,
-  unimp_device_interrupt_ack,
-  unimp_device_ioctl,
-};
-
-
-\f
-/* Register init device: register
-
-   Properties attached to the register device specify the name/value
-   initialization pair for cpu registers.
-
-   FIXME: A specific processor can be initialized by creating a
-   property with a name like `0.pc'. */
-
-static void
-register_init(device *me,
-             const char *name,
-             void *data)
-{
-  psim *system = (psim*)data;
-  unsigned32 value = device_find_integer_property(me, name);
-  int processor;
-  if (isdigit(name[0]) && name[1] == '.') {
-    processor = atol(name);
-    name += 2;
-    DTRACE(register, ("%d.%s=0x%lx\n", processor, name, (unsigned long)value));
-  }    
-  else {
-    processor = -1;
-    DTRACE(register, ("%s=0x%lx\n", name, (unsigned long)value));
-  }
-  psim_write_register(system, processor, /* all processors */
-                     &value,
-                     name,
-                     cooked_transfer);
-}
-
-
-static void
-register_init_callback(device *me,
-                      psim *system)
-{
-  device_traverse_properties(me, register_init, system);
-}
-
-
-static device_callbacks const register_callbacks = {
-  register_init_callback,
-  unimp_device_attach_address,
-  unimp_device_detach_address,
-  unimp_device_io_read_buffer,
-  unimp_device_io_write_buffer,
-  unimp_device_dma_read_buffer,
-  unimp_device_dma_write_buffer,
-  unimp_device_attach_interrupt,
-  unimp_device_detach_interrupt,
-  unimp_device_interrupt,
-  unimp_device_interrupt_ack,
-  unimp_device_ioctl,
-};
-
-
-\f
-/* VEA VM device: vm@0x<stack-base>,<nr_bytes>
-
-   A VEA mode device. This sets its self up as the default memory
-   device capturing all accesses (reads/writes) to currently unmapped
-   addresses.  If the unmaped access falls within unallocated stack or
-   heap address ranges then memory is allocated and the access is
-   allowed to continue.
-
-   During init phase, this device expects to receive `attach' requests
-   from its children for the text/data/bss memory areas.  Typically,
-   this would be done by the binary device.
-
-   STACK: The location of the stack in memory is specified as part of
-   the devices name.  Unmaped accesses that fall within the stack
-   space result in the allocated stack being grown downwards so that
-   it includes the page of the culprit access.
-
-   HEAP: During initialization, the vm device monitors all `attach'
-   operations from its children using this to determine the initial
-   location of the heap.  The heap is then extended by system calls
-   that frob the heap upper bound variable (see system.c). */
-
-
-typedef struct _vm_device {
-  /* area of memory valid for stack addresses */
-  unsigned_word stack_base; /* min possible stack value */
-  unsigned_word stack_bound;
-  unsigned_word stack_lower_limit;
-  /* area of memory valid for heap addresses */
-  unsigned_word heap_base;
-  unsigned_word heap_bound;
-  unsigned_word heap_upper_limit;
-} vm_device;
-
-
-static void
-vm_init_callback(device *me,
-                psim *system)
-{
-  vm_device *vm = (vm_device*)device_data(me);
-
-  /* revert the stack/heap variables to their defaults */
-  vm->stack_lower_limit = vm->stack_bound;
-  vm->heap_base = 0;
-  vm->heap_bound = 0;
-  vm->heap_upper_limit = 0;
-
-  /* establish this device as the default memory handler */
-  device_attach_address(device_parent(me),
-                       device_name(me),
-                       attach_default,
-                       0 /*address space - ignore*/,
-                       0 /*addr - ignore*/,
-                       0 /*nr_bytes - ignore*/,
-                       access_read_write /*access*/,
-                       me);
-}
-
-
-static void
-vm_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*/
-{
-  vm_device *vm = (vm_device*)device_data(me);
-  /* update end of bss if necessary */
-  if (vm->heap_base < addr + nr_bytes) {
-    vm->heap_base = addr + nr_bytes;
-    vm->heap_bound = addr + nr_bytes;
-    vm->heap_upper_limit = addr + nr_bytes;
-  }
-  device_attach_address(device_parent(me),
-                       "vm@0x0,0", /* stop remap */
-                       attach_raw_memory,
-                       0 /*address space*/,
-                       addr,
-                       nr_bytes,
-                       access,
-                       me);
-}
-
-
-STATIC_INLINE_DEVICE_TABLE unsigned
-add_vm_space(device *me,
-            unsigned_word addr,
-            unsigned nr_bytes,
-            cpu *processor,
-            unsigned_word cia)
-{
-  vm_device *vm = (vm_device*)device_data(me);
-  unsigned_word block_addr;
-  unsigned block_nr_bytes;
-
-  /* an address in the stack area, allocate just down to the addressed
-     page */
-  if (addr >= vm->stack_base && addr < vm->stack_lower_limit) {
-    block_addr = FLOOR_PAGE(addr);
-    block_nr_bytes = vm->stack_lower_limit - block_addr;
-    vm->stack_lower_limit = block_addr;
-  }
-  /* an address in the heap area, allocate all of the required heap */
-  else if (addr >= vm->heap_upper_limit && addr < vm->heap_bound) {
-    block_addr = vm->heap_upper_limit;
-    block_nr_bytes = vm->heap_bound - vm->heap_upper_limit;
-    vm->heap_upper_limit = vm->heap_bound;
-  }
-  /* oops - an invalid address - abort the cpu */
-  else if (processor != NULL) {
-    cpu_halt(processor, cia, was_signalled, SIGSEGV);
-    return 0;
-  }
-  /* 2*oops - an invalid address and no processor */
-  else {
-    return 0;
-  }
-
-  /* got the parameters, allocate the space */
-  device_attach_address(device_parent(me),
-                       "vm@0x0,0", /* stop remap */
-                       attach_raw_memory,
-                       0 /*address space*/,
-                       block_addr,
-                       block_nr_bytes,
-                       access_read_write,
-                       me);
-  return block_nr_bytes;
-}
-
-
-static unsigned
-vm_io_read_buffer_callback(device *me,
-                          void *dest,
-                          int space,
-                          unsigned_word addr,
-                          unsigned nr_bytes,
-                          cpu *processor,
-                          unsigned_word cia)
-{
-  if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
-    memset(dest, 0, nr_bytes); /* always initialized to zero */
-    return nr_bytes;
-  }
-  else 
-    return 0;
-}
-
-
-static unsigned
-vm_io_write_buffer_callback(device *me,
-                           const void *source,
-                           int space,
-                           unsigned_word addr,
-                           unsigned nr_bytes,
-                           cpu *processor,
-                           unsigned_word cia)
-{
-  if (add_vm_space(me, addr, nr_bytes, processor, cia) >= nr_bytes) {
-    return device_dma_write_buffer(device_parent(me), source,
-                                  space, addr,
-                                  nr_bytes,
-                                  0/*violate_read_only*/);
-  }
-  else
-    return 0;
-}
-
-
-static void
-vm_ioctl_callback(device *me,
-                 psim *system,
-                 cpu *processor,
-                 unsigned_word cia,
-                 va_list ap)
-{
-  /* While the caller is notified that the heap has grown by the
-     requested amount, the heap is infact extended out to a page
-     boundary. */
-  vm_device *vm = (vm_device*)device_data(me);
-  unsigned_word new_break = ALIGN_8(cpu_registers(processor)->gpr[3]);
-  unsigned_word old_break = vm->heap_bound;
-  signed_word delta = new_break - old_break;
-  if (delta > 0)
-    vm->heap_bound = ALIGN_PAGE(new_break);
-  cpu_registers(processor)->gpr[0] = 0;
-  cpu_registers(processor)->gpr[3] = new_break;
-}
-
-
-static device_callbacks const vm_callbacks = {
-  vm_init_callback,
-  vm_attach_address,
-  passthrough_device_detach_address,
-  vm_io_read_buffer_callback,
-  vm_io_write_buffer_callback,
-  unimp_device_dma_read_buffer,
-  passthrough_device_dma_write_buffer,
-  unimp_device_attach_interrupt,
-  unimp_device_detach_interrupt,
-  unimp_device_interrupt,
-  unimp_device_interrupt_ack,
-  vm_ioctl_callback,
-};
-
-
-static void *
-vea_vm_create(const char *name,
-             device *parent)
-{
-  vm_device *vm = ZALLOC(vm_device);
-  unsigned_word addr;
-  unsigned nr_bytes;
-
-  /* extract out the stack parameters */
-  if (scand_uw_u(name, &addr, &nr_bytes) != 2)
-    error("vm_device_create() invalid vm device %s\n", name);
-  vm->stack_base = addr;
-  vm->stack_bound = addr + nr_bytes;
-  return vm;
-}
-
-
-\f
-/* Memory init device: memory@0x<addr>,<size>,<access>
-
-   This strange device is used create sections of memory */
-
-static void
-memory_init_callback(device *me,
-                    psim *system)
-{
-  unsigned_word addr;
-  unsigned nr_bytes;
-  unsigned access;
-  int nr_args;
-
-  nr_args = scand_uw_u_u(device_name(me), &addr, &nr_bytes, &access);
-  switch (nr_args) {
-  case 2:
-    access = access_read_write_exec;
-    break;
-  case 3:
-    break;
-  default:
-    error("memory_init_callback() invalid memory device %s\n", device_name(me));
-    break;
-  }
-
-  device_attach_address(device_parent(me),
-                       device_name(me),
-                       attach_raw_memory,
-                       0 /*address space*/,
-                       addr,
-                       nr_bytes,
-                       (access_type)access,
-                       me);
-}
-
-
-static device_callbacks const memory_callbacks = {
-  memory_init_callback,
-  unimp_device_attach_address,
-  unimp_device_detach_address,
-  unimp_device_io_read_buffer,
-  unimp_device_io_write_buffer,
-  unimp_device_dma_read_buffer,
-  unimp_device_dma_write_buffer,
-  unimp_device_attach_interrupt,
-  unimp_device_detach_interrupt,
-  unimp_device_interrupt,
-  unimp_device_interrupt_ack,
-  unimp_device_ioctl,
-};
-
-
-\f
-/* IOBUS device: iobus@<address>
-
-   Simple bus on which some IO devices live */
-
-static void
-iobus_attach_address_callback(device *me,
-                             const char *name,
-                             attach_type type,
-                             int space,
-                             unsigned_word addr,
-                             unsigned nr_bytes,
-                             access_type access,
-                             device *who) /*callback/default*/
-{
-  unsigned_word iobus_addr;
-  /* sanity check */
-  if (type == attach_default)
-    error("iobus_attach_address_callback() no default for %s/%s\n",
-         device_name(me), name);
-  if (space != 0)
-    error("iobus_attach_address_callback() no space for %s/%s\n",
-         device_name(me), name);
-  /* get the bus address */
-  if (scand_uw(device_name(me), &iobus_addr) != 1)
-    error("iobus_attach_address_callback() invalid address for %s\n",
-         device_name(me));
-  device_attach_address(device_parent(me),
-                       device_name(me),
-                       type,
-                       0 /*space*/,
-                       iobus_addr + addr,
-                       nr_bytes,
-                       access,
-                       who);
-}
-
-
-STATIC_INLINE_DEVICE_TABLE void
-iobus_do_interrupt(event_queue *queue,
-                  void *data)
-{
-  cpu *target = (cpu*)data;
-  /* try to interrupt the processor.  If the attempt fails, try again
-     on the next tick */
-  if (!external_interrupt(target))
-    event_queue_schedule(queue, 1, iobus_do_interrupt, target);
-}
-
-
-static void
-iobus_interrupt_callback(device *me,
-                        device *who,
-                        int interrupt_line,
-                        int interrupt_status,
-                        cpu *processor,
-                        unsigned_word cia)
-{
-  /* the interrupt controler can't interrupt a cpu at any time.
-     Rather it must synchronize with the system clock before
-     performing an interrupt on the given processor */
-  psim *system = cpu_system(processor);
-  cpu *target = psim_cpu(system, interrupt_status);
-  if (target != NULL) {
-    event_queue *events = cpu_event_queue(target);
-    event_queue_schedule(events, 1, iobus_do_interrupt, target);
-  }
-}
-
-
-static device_callbacks const iobus_callbacks = {
-  ignore_device_init,
-  iobus_attach_address_callback,
-  unimp_device_detach_address,
-  unimp_device_io_read_buffer,
-  unimp_device_io_write_buffer,
-  unimp_device_dma_read_buffer,
-  unimp_device_dma_write_buffer,
-  unimp_device_attach_interrupt,
-  unimp_device_detach_interrupt,
-  iobus_interrupt_callback,
-  unimp_device_interrupt_ack,
-  unimp_device_ioctl,
-};
-
-
-\f
-/* FILE device: file@0x<address>,<file-name>
-   (later - file@0x<address>,<size>,<file-offset>,<file-name>)
-
-   Specifies a file to read directly into memory starting at <address> */
-
-
-static void
-file_init_callback(device *me,
-                  psim *system)
-{
-  unsigned_word addr;
-  int count;
-  char file_name[1024];
-
-  if (scand_uw_c(device_name(me), &addr, file_name, sizeof(file_name)) != 2)
-    error("devices/file - Usage: file@<address>,<file-name>\n");
-  /* load the file */
-  count = dma_file(me, file_name, addr);
-  if (count < 0)
-    error("device_table/%s - Problem loading file %s\n", device_name(me), file_name);
-}
-
-
-static device_callbacks const file_callbacks = {
-  file_init_callback,
-  unimp_device_attach_address,
-  unimp_device_detach_address,
-  unimp_device_io_read_buffer,
-  unimp_device_io_write_buffer,
-  unimp_device_dma_read_buffer,
-  unimp_device_dma_write_buffer,
-  unimp_device_attach_interrupt,
-  unimp_device_detach_interrupt,
-  unimp_device_interrupt,
-  unimp_device_interrupt_ack,
-  unimp_device_ioctl,
-};
-
-
-\f
-/* DATA device: data@<address>,<count>,<value>
-
-   Store <value> at <address> using <count> size transfer */
-
-static void
-data_init_callback(device *me,
-                  psim *system)
-{
-  unsigned_word addr;
-  unsigned count;
-  unsigned value;
-  union {
-    unsigned_1 v1;
-    unsigned_2 v2;
-    unsigned_4 v4;
-    unsigned_8 v8;
-  } buf;
-
-  if (scand_uw_u_u(device_name(me), &addr, &count, &value) != 3)
-    error("devices/data - Usage: data@<address>,<count>,<value>\n");
-  /* store the data value */
-  switch (count) {
-  case 1:
-    buf.v1 = H2T_1(value);
-    break;
-  case 2:
-    buf.v2 = H2T_2(value);
-    break;
-  case 4:
-    buf.v4 = H2T_4(value);
-    break;
-  case 8:
-    buf.v8 = H2T_8(value);
-    break;
-  }
-  if (device_dma_write_buffer(device_parent(me),
-                             &buf,
-                             0 /*address-space*/,
-                             addr,
-                             count, /*nr-bytes*/
-                             1 /*violate ro*/) != count) {
-    error("devices/%s - Problem storing 0x%x at 0x%lx\n",
-         device_name(me), value, (long)addr);
-  }
-}
-
-
-static device_callbacks const data_callbacks = {
-  data_init_callback,
-  unimp_device_attach_address,
-  unimp_device_detach_address,
-  unimp_device_io_read_buffer,
-  unimp_device_io_write_buffer,
-  unimp_device_dma_read_buffer,
-  unimp_device_dma_write_buffer,
-  unimp_device_attach_interrupt,
-  unimp_device_detach_interrupt,
-  unimp_device_interrupt,
-  unimp_device_interrupt_ack,
-  unimp_device_ioctl,
-};
-
-
-\f
-/* HTAB: htab@<address>,<nr_bytes>
-   PTE: pte@<real-address>,<virtual-address>,<nr_bytes>,<wimg>,<pp>
-   PTE: pte@<real-address>,<wimg>,<pp>,<binary>
-
-   HTAB defines the location (in physical memory) of a HASH table.
-   PTE (as a child of HTAB) defines a mapping that is to be entered
-   into that table.
-
-   NB: All the work in this device is done during init by the PTE.
-   The pte, looks up its parent to determine the address of the HTAB
-   and then uses DMA calls to establish the required mapping. */
-
-
-STATIC_INLINE_DEVICE_TABLE void
-htab_decode_hash_table(device *parent,
-                      unsigned32 *htaborg,
-                      unsigned32 *htabmask)
-{
-  unsigned_word htab_ra;
-  unsigned htab_nr_bytes;
-  unsigned n;
-  /* determine the location/size of the hash table */
-  if (parent == NULL
-      || strncmp(device_name(parent), "htab@", strlen("htab@")) != 0)
-    error("devices/htab - missing htab device\n");
-  if (scand_uw_u(device_name(parent), &htab_ra, &htab_nr_bytes) != 2)
-    error("devices/%s - Usage: htab@<real-addr>,<nr_bytes>\n",
-         device_name(parent));
-  for (n = htab_nr_bytes; n > 1; n = n / 2) {
-    if (n % 2 != 0)
-      error("devices/%s - htab size 0x%x not a power of two\n",
-           device_name(parent), htab_nr_bytes);
-  }
-  *htaborg = htab_ra;
-  *htabmask = MASKED32(htab_nr_bytes - 1, 7, 31-6);
-  if ((htab_ra & INSERTED32(*htabmask, 7, 15)) != 0) {
-    error("devices/%s - htaborg 0x%x not aligned to htabmask 0x%x\n",
-         device_name(parent), *htaborg, *htabmask);
-  }
-  DTRACE(htab, ("htab - htaborg=0x%lx htabmask=0x%lx\n",
-               (unsigned long)*htaborg, (unsigned long)*htabmask));
-}
-
-
-STATIC_INLINE void
-htab_map_page(device *me,
-             unsigned_word ra,
-             unsigned64 va,
-             unsigned wimg,
-             unsigned pp,
-             unsigned32 htaborg,
-             unsigned32 htabmask)
-{
-  unsigned64 vpn = va << 12;
-  unsigned32 vsid = INSERTED32(EXTRACTED64(vpn, 0, 23), 0, 23);
-  unsigned32 page = INSERTED32(EXTRACTED64(vpn, 24, 39), 0, 15);
-  unsigned32 hash = INSERTED32(EXTRACTED32(vsid, 5, 23)
-                              ^ EXTRACTED32(page, 0, 15),
-                              7, 31-6);
-  int h;
-  for (h = 0; h < 2; h++) {
-    unsigned32 pteg = (htaborg | (hash & htabmask));
-    int pti;
-    for (pti = 0; pti < 8; pti++, pteg += 8) {
-      unsigned32 current_target_pte0;
-      unsigned32 current_pte0;
-      if (device_dma_read_buffer(device_parent(me),
-                                &current_target_pte0,
-                                0, /*space*/
-                                pteg,
-                                sizeof(current_target_pte0)) != 4)
-       error("htab_init_callback() failed to read a pte at 0x%x\n",
-             pteg);
-      current_pte0 = T2H_4(current_target_pte0);
-      if (!MASKED32(current_pte0, 0, 0)) {
-       /* empty pte fill it */
-       unsigned32 pte0 = (MASK32(0, 0)
-                          | INSERTED32(EXTRACTED32(vsid, 0, 23), 1, 24)
-                          | INSERTED32(h, 25, 25)
-                          | INSERTED32(EXTRACTED32(page, 0, 5), 26, 31));
-       unsigned32 target_pte0 = H2T_4(pte0);
-       unsigned32 pte1 = (INSERTED32(EXTRACTED32(ra, 0, 19), 0, 19)
-                          | INSERTED32(wimg, 25, 28)
-                          | INSERTED32(pp, 30, 31));
-       unsigned32 target_pte1 = H2T_4(pte1);
-       if (device_dma_write_buffer(device_parent(me),
-                                   &target_pte0,
-                                   0, /*space*/
-                                   pteg,
-                                   sizeof(target_pte0),
-                                   1/*ro?*/) != 4
-           || device_dma_write_buffer(device_parent(me),
-                                      &target_pte1,
-                                      0, /*space*/
-                                      pteg + 4,
-                                      sizeof(target_pte1),
-                                      1/*ro?*/) != 4)
-         error("htab_init_callback() failed to write a pte a 0x%x\n",
-               pteg);
-       DTRACE(htab, ("map - va=0x%lx ra=0x%lx &pte0=0x%lx pte0=0x%lx pte1=0x%lx\n",
-                     (unsigned long)va, (unsigned long)ra,
-                     (unsigned long)pteg,
-                     (unsigned long)pte0, (unsigned long)pte1));
-       return;
-      }
-    }
-    /* re-hash */
-    hash = MASKED32(~hash, 0, 18);
-  }
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-htab_map_region(device *me,
-               unsigned_word pte_ra,
-               unsigned_word pte_va,
-               unsigned nr_bytes,
-               unsigned wimg,
-               unsigned pp,
-               unsigned32 htaborg,
-               unsigned32 htabmask)
-{
-  unsigned_word ra;
-  unsigned64 va;
-  /* go through all pages and create a pte for each */
-  for (ra = pte_ra, va = (signed_word)pte_va;
-       ra < pte_ra + nr_bytes;
-       ra += 0x1000, va += 0x1000) {
-    htab_map_page(me, ra, va, wimg, pp, htaborg, htabmask);
-  }
-}
-  
-typedef struct _htab_binary_sizes {
-  unsigned_word text_ra;
-  unsigned_word text_base;
-  unsigned_word text_bound;
-  unsigned_word data_ra;
-  unsigned_word data_base;
-  unsigned data_bound;
-  device *me;
-} htab_binary_sizes;
-
-STATIC_INLINE_DEVICE_TABLE void
-htab_sum_binary(bfd *abfd,
-               sec_ptr sec,
-               PTR data)
-{
-  htab_binary_sizes *sizes = (htab_binary_sizes*)data;
-  unsigned_word size = bfd_get_section_size_before_reloc (sec);
-  unsigned_word vma = bfd_get_section_vma (abfd, sec);
-
-  /* skip the section if no memory to allocate */
-  if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
-    return;
-
-  if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
-      || (bfd_get_section_flags (abfd, sec) & SEC_READONLY)) {
-    if (sizes->text_bound < vma + size)
-      sizes->text_bound = ALIGN_PAGE(vma + size);
-    if (sizes->text_base > vma)
-      sizes->text_base = FLOOR_PAGE(vma);
-  }
-  else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA)
-          || (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)) {
-    if (sizes->data_bound < vma + size)
-      sizes->data_bound = ALIGN_PAGE(vma + size);
-    if (sizes->data_base > vma)
-      sizes->data_base = FLOOR_PAGE(vma);
-  }
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-htab_dma_binary(bfd *abfd,
-               sec_ptr sec,
-               PTR data)
-{
-  htab_binary_sizes *sizes = (htab_binary_sizes*)data;
-  void *section_init;
-  unsigned_word section_vma;
-  unsigned_word section_size;
-  unsigned_word section_ra;
-  device *me = sizes->me;
-
-  /* skip the section if no memory to allocate */
-  if (! (bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
-    return;
-
-  /* check/ignore any sections of size zero */
-  section_size = bfd_get_section_size_before_reloc(sec);
-  if (section_size == 0)
-    return;
-
-  /* if nothing to load, ignore this one */
-  if (! (bfd_get_section_flags(abfd, sec) & SEC_LOAD))
-    return;
-
-  /* find where it is to go */
-  section_vma = bfd_get_section_vma(abfd, sec);
-  section_ra = 0;
-  if ((bfd_get_section_flags (abfd, sec) & SEC_CODE)
-      || (bfd_get_section_flags (abfd, sec) & SEC_READONLY))
-    section_ra = (section_vma - sizes->text_base + sizes->text_ra);
-  else if ((bfd_get_section_flags (abfd, sec) & SEC_DATA))
-    section_ra = (section_vma - sizes->data_base + sizes->data_ra);
-  else 
-    return; /* just ignore it */
-
-  DTRACE(htab,
-        ("load - name=%-7s vma=0x%.8lx size=%6ld ra=0x%.8lx flags=%3lx(%s%s%s%s%s )\n",
-         bfd_get_section_name(abfd, sec),
-         (long)section_vma,
-         (long)section_size,
-         (long)section_ra,
-         (long)bfd_get_section_flags(abfd, sec),
-         bfd_get_section_flags(abfd, sec) & SEC_LOAD ? " LOAD" : "",
-         bfd_get_section_flags(abfd, sec) & SEC_CODE ? " CODE" : "",
-         bfd_get_section_flags(abfd, sec) & SEC_DATA ? " DATA" : "",
-         bfd_get_section_flags(abfd, sec) & SEC_ALLOC ? " ALLOC" : "",
-         bfd_get_section_flags(abfd, sec) & SEC_READONLY ? " READONLY" : ""
-         ));
-
-  /* dma in the sections data */
-  section_init = zalloc(section_size);
-  if (!bfd_get_section_contents(abfd,
-                               sec,
-                               section_init, 0,
-                               section_size)) {
-    bfd_perror("devices/pte");
-    error("devices/%s - no data loaded\n", device_name(me));
-  }
-  if (device_dma_write_buffer(device_parent(me),
-                             section_init,
-                             0 /*space*/,
-                             section_ra,
-                             section_size,
-                             1 /*violate_read_only*/)
-      != section_size)
-    error("devices/%s - broken dma transfer\n", device_name(me));
-  zfree(section_init); /* only free if load */
-}
-
-
-STATIC_INLINE_DEVICE_TABLE void
-htab_map_binary(device *me,
-               unsigned_word ra,
-               unsigned wimg,
-               unsigned pp,
-               char *file_name,
-               unsigned32 htaborg,
-               unsigned32 htabmask)
-{
-  htab_binary_sizes sizes;
-  bfd *image;
-  sizes.text_base = -1;
-  sizes.data_base = -1;
-  sizes.text_bound = 0;
-  sizes.data_bound = 0;
-  sizes.me = me;
-
-  /* open the file */
-  image = bfd_openr(file_name, NULL);
-  if (image == NULL) {
-    bfd_perror("devices/pte");
-    error("devices/%s - the file %s not loaded\n", device_name(me), file_name);
-  }
-
-  /* check it is valid */
-  if (!bfd_check_format(image, bfd_object)) {
-    bfd_close(image);
-    error("devices/%s - the file %s has an invalid binary format\n",
-         device_name(me), file_name);
-  }
-
-  /* determine the size of each of the files regions */
-  bfd_map_over_sections (image, htab_sum_binary, (PTR) &sizes);
-
-  /* determine the real addresses of the sections */
-  sizes.text_ra = ra;
-  sizes.data_ra = ALIGN_PAGE(sizes.text_ra + 
-                            (sizes.text_bound - sizes.text_base));
-
-  DTRACE(htab, ("text map - base=0x%lx bound=0x%lx ra=0x%lx\n",
-               (unsigned long)sizes.text_base,
-               (unsigned long)sizes.text_bound,
-               (unsigned long)sizes.text_ra));
-  DTRACE(htab, ("data map - base=0x%lx bound=0x%lx ra=0x%lx\n",
-               (unsigned long)sizes.data_base,
-               (unsigned long)sizes.data_bound,
-               (unsigned long)sizes.data_ra));
-
-  /* set up virtual memory maps for each of the regions */
-  htab_map_region(me, sizes.text_ra, sizes.text_base,
-                 sizes.text_bound - sizes.text_base,
-                 wimg, pp,
-                 htaborg, htabmask);
-  htab_map_region(me, sizes.data_ra, sizes.data_base,
-                 sizes.data_bound - sizes.data_base,
-                 wimg, pp,
-                 htaborg, htabmask);
-
-  /* dma the sections into physical memory */
-  bfd_map_over_sections (image, htab_dma_binary, (PTR) &sizes);
-}
-
-static void
-htab_init_callback(device *me,
-                  psim *system)
-{
-  if (WITH_TARGET_WORD_BITSIZE != 32)
-    error("devices/htab: only 32bit targets currently suported\n");
-
-  /* only the pte does work */
-  if (strncmp(device_name(me), "pte@", strlen("pte@")) == 0) {
-    unsigned32 htaborg;
-    unsigned32 htabmask;
-    signed32 pte_va; /* so that 0xff...0 is make 0xffffff00 */
-    unsigned32 pte_ra;
-    unsigned pte_nr_bytes;
-    unsigned pte_wimg;
-    unsigned pte_pp;
-    char file_name[1024];
-
-    htab_decode_hash_table(device_parent(me), &htaborg, &htabmask);
-
-    /* handle a normal mapping definition */
-    if (scand_uw_uw_u_u_u(device_name(me), &pte_ra, &pte_va, &pte_nr_bytes,
-                         &pte_wimg, &pte_pp) == 5) {
-      DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, va=0x%lx, nr_bytes=%ld\n",
-                   (unsigned long)pte_ra,
-                   (long)pte_wimg,
-                   (long)pte_pp,
-                   (unsigned long)pte_va,
-                   (long)pte_nr_bytes));
-      htab_map_region(me, pte_ra, pte_va, pte_nr_bytes, pte_wimg, pte_pp,
-                     htaborg, htabmask);
-    }
-    else if (scand_uw_u_u_c(device_name(me), &pte_ra, &pte_wimg, &pte_pp,
-                           file_name, sizeof(file_name)) == 4) {
-      DTRACE(htab, ("pte - ra=0x%lx, wimg=%ld, pp=%ld, binary=%s\n",
-                   (unsigned long)pte_ra,
-                   (unsigned long)pte_wimg,
-                   (long)pte_pp,
-                   file_name));
-      htab_map_binary(me, pte_ra, pte_wimg, pte_pp, file_name,
-                     htaborg, htabmask);
-    }
-    else {
-      error("devices/%s - Usage: %s\nor\t%s\n",
-           device_name(me),
-           "pte@,<real-addr>,<virtual-addr>,<nr-bytes>,<wimg>,<pp>",
-           "pte@<real-addr>,<wimg>,<pp>,<binary>");
-    }
-  }
-}
-
-
-static device_callbacks const htab_callbacks = {
-  htab_init_callback,
-  unimp_device_attach_address,
-  unimp_device_detach_address,
-  unimp_device_io_read_buffer,
-  unimp_device_io_write_buffer,
-  passthrough_device_dma_read_buffer,
-  passthrough_device_dma_write_buffer,
-  unimp_device_attach_interrupt,
-  unimp_device_detach_interrupt,
-  unimp_device_interrupt,
-  unimp_device_interrupt_ack,
-  unimp_device_ioctl,
-};
-
-
-\f
-/* Simulator device: sim@0x<address>,<nr_bytes>
-
-   Eventually gives access to the hardware configuration.  For
-   instance, it could allow the setting (on the fly) of variables such
-   as hardware floating-point or strict-alignment.
-
-   It's intended use is as part of testing the simulators
-   functionality */
-
-static device_callbacks const sim_callbacks = {
-  ignore_device_init,
-  unimp_device_attach_address,
-  unimp_device_detach_address,
-  unimp_device_io_read_buffer,
-  unimp_device_io_write_buffer,
-  unimp_device_dma_read_buffer,
-  unimp_device_dma_write_buffer,
-  unimp_device_attach_interrupt,
-  unimp_device_detach_interrupt,
-  unimp_device_interrupt,
-  unimp_device_interrupt_ack,
-  unimp_device_ioctl,
-};
-
-
-\f
-/* Load device: binary
-
-   Single property the name of which specifies the file (understood by
-   BFD) that is to be DMAed into memory as part of init */
-
-STATIC_INLINE_DEVICE_TABLE void
-update_for_binary_section(bfd *abfd,
-                         asection *the_section,
-                         PTR obj)
-{
-  unsigned_word section_vma;
-  unsigned_word section_size;
-  access_type access;
-  device *me = (device*)obj;
-
-  /* skip the section if no memory to allocate */
-  if (! (bfd_get_section_flags(abfd, the_section) & SEC_ALLOC))
-    return;
-
-  /* check/ignore any sections of size zero */
-  section_size = bfd_get_section_size_before_reloc(the_section);
-  if (section_size == 0)
-    return;
-
-  /* find where it is to go */
-  section_vma = bfd_get_section_vma(abfd, the_section);
-
-  DTRACE(binary,
-        ("name=%-7s, vma=0x%.8lx, size=%6ld, flags=%3lx(%s%s%s%s%s )\n",
-         bfd_get_section_name(abfd, the_section),
-         (long)section_vma,
-         (long)section_size,
-         (long)bfd_get_section_flags(abfd, the_section),
-         bfd_get_section_flags(abfd, the_section) & SEC_LOAD ? " LOAD" : "",
-         bfd_get_section_flags(abfd, the_section) & SEC_CODE ? " CODE" : "",
-         bfd_get_section_flags(abfd, the_section) & SEC_DATA ? " DATA" : "",
-         bfd_get_section_flags(abfd, the_section) & SEC_ALLOC ? " ALLOC" : "",
-         bfd_get_section_flags(abfd, the_section) & SEC_READONLY ? " READONLY" : ""
-         ));
-
-  /* determine the devices access */
-  access = access_read;
-  if (bfd_get_section_flags(abfd, the_section) & SEC_CODE)
-    access |= access_exec;
-  if (!(bfd_get_section_flags(abfd, the_section) & SEC_READONLY))
-    access |= access_write;
-
-  /* if a map, pass up a request to create the memory in core */
-  if (strncmp(device_name(me), "map-binary", strlen("map-binary")) == 0)
-    device_attach_address(device_parent(me),
-                         device_name(me),
-                         attach_raw_memory,
-                         0 /*address space*/,
-                         section_vma,
-                         section_size,
-                         access,
-                         me);
-
-  /* if a load dma in the required data */
-  if (bfd_get_section_flags(abfd, the_section) & SEC_LOAD) {
-    void *section_init = zalloc(section_size);
-    if (!bfd_get_section_contents(abfd,
-                                 the_section,
-                                 section_init, 0,
-                                 section_size)) {
-      bfd_perror("core:load_section()");
-      error("load of data failed");
-      return;
-    }
-    if (device_dma_write_buffer(device_parent(me),
-                               section_init,
-                               0 /*space*/,
-                               section_vma,
-                               section_size,
-                               1 /*violate_read_only*/)
-       != section_size)
-      error("data_init_callback() broken transfer for %s\n", device_name(me));
-    zfree(section_init); /* only free if load */
-  }
-}
-
-
-static void
-binary_init_callback(device *me,
-                    psim *system)
-{
-  const char *file_name;
-  bfd *image;
-
-
-  /* get the property specifying the file name */
-  file_name = device_find_next_property(me, NULL);
-
-  /* open the file */
-  image = bfd_openr(file_name, NULL);
-  if (image == NULL) {
-    bfd_perror("devices/binary");
-    error("devices/%s - the file %s not loaded\n", device_name(me), file_name);
-  }
-
-  /* check it is valid */
-  if (!bfd_check_format(image, bfd_object)) {
-    bfd_close(image);
-    error("devices/%s - the file %s has an invalid binary format\n",
-         device_name(me), file_name);
-  }
-
-  /* and the data sections */
-  bfd_map_over_sections(image,
-                       update_for_binary_section,
-                       (PTR)me);
-
-  bfd_close(image);
-}
-
-
-static device_callbacks const binary_callbacks = {
-  binary_init_callback,
-  unimp_device_attach_address,
-  unimp_device_detach_address,
-  unimp_device_io_read_buffer,
-  unimp_device_io_write_buffer,
-  unimp_device_dma_read_buffer,
-  unimp_device_dma_write_buffer,
-  unimp_device_attach_interrupt,
-  unimp_device_detach_interrupt,
-  unimp_device_interrupt,
-  unimp_device_interrupt_ack,
-  unimp_device_ioctl,
-};
-
-
-\f
-/* Stack device: stack@<type>
-
-   Has a single IOCTL to create a stack frame of the specified type.
-   If <type> is elf or xcoff then a corresponding stack is created.
-   Any other value of type is ignored.
-
-   The IOCTL takes the additional arguments:
-
-     unsigned_word stack_end -- where the stack should come down from
-     char **argv -- ...
-     char **envp -- ...
-
-   */
-
-STATIC_INLINE_DEVICE_TABLE int
-sizeof_argument_strings(char **arg)
-{
-  int sizeof_strings = 0;
-
-  /* robust */
-  if (arg == NULL)
-    return 0;
-
-  /* add up all the string sizes (padding as we go) */
-  for (; *arg != NULL; arg++) {
-    int len = strlen(*arg) + 1;
-    sizeof_strings += ALIGN_8(len);
-  }
-
-  return sizeof_strings;
-}
-
-STATIC_INLINE_DEVICE_TABLE int
-number_of_arguments(char **arg)
-{
-  int nr;
-  if (arg == NULL)
-    return 0;
-  for (nr = 0; *arg != NULL; arg++, nr++);
-  return nr;
-}
-
-STATIC_INLINE_DEVICE_TABLE int
-sizeof_arguments(char **arg)
-{
-  return ALIGN_8((number_of_arguments(arg) + 1) * sizeof(unsigned_word));
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-write_stack_arguments(psim *system,
-                     char **arg,
-                     unsigned_word start_block,
-                     unsigned_word end_block,
-                     unsigned_word start_arg,
-                     unsigned_word end_arg)
-{
-  DTRACE(stack,
-       ("write_stack_arguments(system=0x%lx, arg=0x%lx, start_block=0x%lx, end_block=0x%lx, start_arg=0x%lx, end_arg=0x%lx)\n",
-        (long)system, (long)arg, (long)start_block, (long)end_block, (long)start_arg, (long)end_arg));
-  if (arg == NULL)
-    error("write_arguments: character array NULL\n");
-  /* only copy in arguments, memory is already zero */
-  for (; *arg != NULL; arg++) {
-    int len = strlen(*arg)+1;
-    unsigned_word target_start_block;
-    DTRACE(stack,
-         ("write_stack_arguments() write %s=%s at %s=0x%lx %s=0x%lx %s=0x%lx\n",
-          "**arg", *arg, "start_block", (long)start_block,
-          "len", (long)len, "start_arg", (long)start_arg));
-    if (psim_write_memory(system, 0, *arg,
-                         start_block, len,
-                         0/*violate_readonly*/) != len)
-      error("write_stack_arguments() - write of **arg (%s) at 0x%x failed\n",
-           *arg, start_block);
-    target_start_block = H2T_word(start_block);
-    if (psim_write_memory(system, 0, &target_start_block,
-                         start_arg, sizeof(target_start_block),
-                         0) != sizeof(target_start_block))
-      error("write_stack_arguments() - write of *arg failed\n");
-    start_block += ALIGN_8(len);
-    start_arg += sizeof(start_block);
-  }
-  start_arg += sizeof(start_block); /*the null at the end*/
-  if (start_block != end_block
-      || ALIGN_8(start_arg) != end_arg)
-    error("write_stack_arguments - possible corruption\n");
-  DTRACE(stack,
-        ("write_stack_arguments() = void\n"));
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-create_elf_stack_frame(psim *system,
-                      unsigned_word bottom_of_stack,
-                      char **argv,
-                      char **envp)
-{
-  /* fixme - this is over aligned */
-
-  /* information block */
-  const unsigned sizeof_envp_block = sizeof_argument_strings(envp);
-  const unsigned_word start_envp_block = bottom_of_stack - sizeof_envp_block;
-  const unsigned sizeof_argv_block = sizeof_argument_strings(argv);
-  const unsigned_word start_argv_block = start_envp_block - sizeof_argv_block;
-
-  /* auxiliary vector - contains only one entry */
-  const unsigned sizeof_aux_entry = 2*sizeof(unsigned_word); /* magic */
-  const unsigned_word start_aux = start_argv_block - ALIGN_8(sizeof_aux_entry);
-
-  /* environment points (including null sentinal) */
-  const unsigned sizeof_envp = sizeof_arguments(envp);
-  const unsigned_word start_envp = start_aux - sizeof_envp;
-
-  /* argument pointers (including null sentinal) */
-  const int argc = number_of_arguments(argv);
-  const unsigned sizeof_argv = sizeof_arguments(argv);
-  const unsigned_word start_argv = start_envp - sizeof_argv;
-
-  /* link register save address - alligned to a 16byte boundary */
-  const unsigned_word top_of_stack = ((start_argv
-                                      - 2 * sizeof(unsigned_word))
-                                     & ~0xf);
-
-  /* install arguments on stack */
-  write_stack_arguments(system, envp,
-                       start_envp_block, bottom_of_stack,
-                       start_envp, start_aux);
-  write_stack_arguments(system, argv,
-                       start_argv_block, start_envp_block,
-                       start_argv, start_envp);
-
-  /* set up the registers */
-  psim_write_register(system, -1,
-                     &top_of_stack, "sp", cooked_transfer);
-  psim_write_register(system, -1,
-                     &argc, "r3", cooked_transfer);
-  psim_write_register(system, -1,
-                     &start_argv, "r4", cooked_transfer);
-  psim_write_register(system, -1,
-                     &start_envp, "r5", cooked_transfer);
-  psim_write_register(system, -1,
-                     &start_aux, "r6", cooked_transfer);
-}
-
-STATIC_INLINE_DEVICE_TABLE void
-create_aix_stack_frame(psim *system,
-                      unsigned_word bottom_of_stack,
-                      char **argv,
-                      char **envp)
-{
-  unsigned_word core_envp;
-  unsigned_word core_argv;
-  unsigned_word core_argc;
-  unsigned_word core_aux;
-  unsigned_word top_of_stack;
-
-  /* cheat - create an elf stack frame */
-  create_elf_stack_frame(system, bottom_of_stack, argv, envp);
-  
-  /* extract argument addresses from registers */
-  psim_read_register(system, 0, &top_of_stack, "r1", cooked_transfer);
-  psim_read_register(system, 0, &core_argc, "r3", cooked_transfer);
-  psim_read_register(system, 0, &core_argv, "r4", cooked_transfer);
-  psim_read_register(system, 0, &core_envp, "r5", cooked_transfer);
-  psim_read_register(system, 0, &core_aux, "r6", cooked_transfer);
-
-  /* extract arguments from registers */
-  error("create_aix_stack_frame() - what happens next?\n");
-}
-
-
-
-static void
-stack_ioctl_callback(device *me,
-                    psim *system,
-                    cpu *processor,
-                    unsigned_word cia,
-                    va_list ap)
-{
-  unsigned_word stack_pointer;
-  const char *stack_type;
-  char **argv;
-  char **envp;
-  stack_pointer = va_arg(ap, unsigned_word);
-  argv = va_arg(ap, char **);
-  envp = va_arg(ap, char **);
-  DTRACE(stack,
-        ("stack_ioctl_callback(me=0x%lx:%s, system=0x%lx, processor=0x%lx, cia=0x%lx, argv=0x%lx, envp=0x%lx)\n",
-         (long)me, device_name(me), (long)system, (long)processor, (long)cia, (long)argv, (long)envp));
-  stack_type  = device_find_next_property(me, NULL);
-  if (stack_type != NULL) {
-    if (strcmp(stack_type, "elf") == 0)
-      create_elf_stack_frame(system, stack_pointer, argv, envp);
-    else if (strcmp(stack_type, "xcoff") == 0)
-      create_aix_stack_frame(system, stack_pointer, argv, envp);
-  }
-  DTRACE(stack, 
-        ("stack_ioctl_callback() = void\n"));
-}
-
-\f
-
-
-static device_callbacks const stack_callbacks = {
-  ignore_device_init,
-  unimp_device_attach_address,
-  unimp_device_detach_address,
-  unimp_device_io_read_buffer,
-  unimp_device_io_write_buffer,
-  unimp_device_dma_read_buffer,
-  unimp_device_dma_write_buffer,
-  unimp_device_attach_interrupt,
-  unimp_device_detach_interrupt,
-  unimp_device_interrupt,
-  unimp_device_interrupt_ack,
-  stack_ioctl_callback,
+static const device_callbacks passthrough_callbacks = {
+  { NULL, }, /* init */
+  { passthrough_device_address_attach,
+    passthrough_device_address_detach, },
+  { NULL, }, /* IO */
+  { passthrough_device_dma_read_buffer, passthrough_device_dma_write_buffer, },
+  { NULL, }, /* interrupt */
+  { generic_device_unit_decode,
+    generic_device_unit_encode, },
 };
 
 
-\f
-device_descriptor device_table[] = {
-  { "console", console_create, &console_callbacks },
-  { "memory", NULL, &memory_callbacks },
-  { "vm", vea_vm_create, &vm_callbacks },
-  { "halt", NULL, &halt_callbacks },
-  { "icu", NULL, &icu_callbacks },
-  { "register", NULL, &register_callbacks },
-  { "iobus", NULL, &iobus_callbacks },
-  { "file", NULL, &file_callbacks },
-  { "data", NULL, &data_callbacks },
-  { "htab", NULL, &htab_callbacks },
-  { "pte", NULL, &htab_callbacks }, /* yep - uses htab's table */
-  { "stack", NULL, &stack_callbacks },
-  { "sim", NULL, &sim_callbacks },
-  { "load-binary", NULL, &binary_callbacks },
-  { "map-binary", NULL, &binary_callbacks },
+static const device_descriptor ob_device_table[] = {
+  /* standard OpenBoot devices */
+  { "aliases", NULL, &passthrough_callbacks },
   { "options", NULL, &passthrough_callbacks },
-  { "init", NULL, &passthrough_callbacks },
   { "chosen", NULL, &passthrough_callbacks },
+  { "packages", NULL, &passthrough_callbacks },
+  { "cpus", NULL, &passthrough_callbacks },
+  { "openprom", NULL, &passthrough_callbacks },
+  { "init", NULL, &passthrough_callbacks },
   { NULL },
 };
 
+const device_descriptor *const device_table[] = {
+  ob_device_table,
+#include "hw.c"
+  NULL,
+};
+
+
 #endif /* _DEVICE_TABLE_C_ */
This page took 0.043445 seconds and 4 git commands to generate.