summaryrefslogtreecommitdiff
path: root/sim/common/hw-base.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/common/hw-base.c')
-rw-r--r--sim/common/hw-base.c571
1 files changed, 0 insertions, 571 deletions
diff --git a/sim/common/hw-base.c b/sim/common/hw-base.c
deleted file mode 100644
index a13ac64ba3b..00000000000
--- a/sim/common/hw-base.c
+++ /dev/null
@@ -1,571 +0,0 @@
-/* This file is part of the program psim.
-
- Copyright (C) 1994-1996, 1998, Andrew Cagney <cagney@highland.com.au>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- */
-
-
-#include "hw-main.h"
-#include "hw-base.h"
-
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#endif
-
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#include <ctype.h>
-
-#include "hw-config.h"
-
-struct hw_base_data {
- int finished_p;
- const struct hw_descriptor *descriptor;
- hw_delete_callback *to_delete;
-};
-
-static int
-generic_hw_unit_decode (struct hw *bus,
- const char *unit,
- hw_unit *phys)
-{
- memset (phys, 0, sizeof (*phys));
- if (unit == NULL)
- return 0;
- else
- {
- int nr_cells = 0;
- const int max_nr_cells = hw_unit_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;
- }
-}
-
-static int
-generic_hw_unit_encode (struct hw *bus,
- const hw_unit *phys,
- char *buf,
- int sizeof_buf)
-{
- 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)
- hw_abort (NULL, "generic_unit_encode - buffer overflow\n");
- return len;
-}
-
-static int
-generic_hw_unit_address_to_attach_address (struct hw *me,
- const hw_unit *address,
- int *attach_space,
- unsigned_word *attach_address,
- struct hw *client)
-{
- int i;
- for (i = 0; i < address->nr_cells - 2; i++)
- {
- if (address->cells[i] != 0)
- hw_abort (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;
-}
-
-static int
-generic_hw_unit_size_to_attach_size (struct hw *me,
- const hw_unit *size,
- unsigned *nr_bytes,
- struct hw *client)
-{
- int i;
- for (i = 0; i < size->nr_cells - 1; i++)
- {
- if (size->cells[i] != 0)
- hw_abort (me, "Only 32bit sizes supported");
- }
- *nr_bytes = size->cells[0];
- return *nr_bytes;
-}
-
-
-/* ignore/passthrough versions of each function */
-
-static void
-passthrough_hw_attach_address (struct hw *me,
- int level,
- int space,
- address_word addr,
- address_word nr_bytes,
- struct hw *client) /*callback/default*/
-{
- if (hw_parent (me) == NULL)
- hw_abort (client, "hw_attach_address: no parent attach method");
- hw_attach_address (hw_parent (me), level,
- space, addr, nr_bytes,
- client);
-}
-
-static void
-passthrough_hw_detach_address (struct hw *me,
- int level,
- int space,
- address_word addr,
- address_word nr_bytes,
- struct hw *client) /*callback/default*/
-{
- if (hw_parent (me) == NULL)
- hw_abort (client, "hw_attach_address: no parent attach method");
- hw_detach_address (hw_parent (me), level,
- space, addr, nr_bytes,
- client);
-}
-
-static unsigned
-panic_hw_io_read_buffer (struct hw *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes)
-{
- hw_abort (me, "no io-read method");
- return 0;
-}
-
-static unsigned
-panic_hw_io_write_buffer (struct hw *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes)
-{
- hw_abort (me, "no io-write method");
- return 0;
-}
-
-static unsigned
-passthrough_hw_dma_read_buffer (struct hw *me,
- void *dest,
- int space,
- unsigned_word addr,
- unsigned nr_bytes)
-{
- if (hw_parent (me) == NULL)
- hw_abort (me, "no parent dma-read method");
- return hw_dma_read_buffer (hw_parent (me), dest,
- space, addr, nr_bytes);
-}
-
-static unsigned
-passthrough_hw_dma_write_buffer (struct hw *me,
- const void *source,
- int space,
- unsigned_word addr,
- unsigned nr_bytes,
- int violate_read_only_section)
-{
- if (hw_parent (me) == NULL)
- hw_abort (me, "no parent dma-write method");
- return hw_dma_write_buffer (hw_parent (me), source,
- space, addr,
- nr_bytes,
- violate_read_only_section);
-}
-
-static void
-ignore_hw_delete (struct hw *me)
-{
- /* NOP */
-}
-
-
-
-
-static const char *
-full_name_of_hw (struct hw *leaf,
- char *buf,
- unsigned sizeof_buf)
-{
- /* get a buffer */
- char full_name[1024];
- if (buf == (char*)0)
- {
- buf = full_name;
- sizeof_buf = sizeof (full_name);
- }
-
- /* use head recursion to construct the path */
-
- if (hw_parent (leaf) == NULL)
- /* root */
- {
- if (sizeof_buf < 1)
- hw_abort (leaf, "buffer overflow");
- *buf = '\0';
- }
- else
- /* sub node */
- {
- char unit[1024];
- full_name_of_hw (hw_parent (leaf), buf, sizeof_buf);
- if (hw_unit_encode (hw_parent (leaf),
- hw_unit_address (leaf),
- unit + 1,
- sizeof (unit) - 1)
- > 0)
- unit[0] = '@';
- else
- unit[0] = '\0';
- if (strlen (buf) + strlen ("/") + strlen (hw_name (leaf)) + strlen (unit)
- >= sizeof_buf)
- hw_abort (leaf, "buffer overflow");
- strcat (buf, "/");
- strcat (buf, hw_name (leaf));
- strcat (buf, unit);
- }
-
- /* return it usefully */
- if (buf == full_name)
- buf = hw_strdup (leaf, full_name);
- return buf;
-}
-
-struct hw *
-hw_create (struct sim_state *sd,
- struct hw *parent,
- const char *family,
- const char *name,
- const char *unit,
- const char *args)
-{
- /* NOTE: HW must be allocated using ZALLOC, others use HW_ZALLOC */
- struct hw *hw = ZALLOC (struct hw);
-
- /* our identity */
- hw->family_of_hw = hw_strdup (hw, family);
- hw->name_of_hw = hw_strdup (hw, name);
- hw->args_of_hw = hw_strdup (hw, args);
-
- /* a hook into the system */
- if (sd != NULL)
- hw->system_of_hw = sd;
- else if (parent != NULL)
- hw->system_of_hw = hw_system (parent);
- else
- hw_abort (parent, "No system found");
-
- /* in a tree */
- if (parent != NULL)
- {
- struct hw **sibling = &parent->child_of_hw;
- while ((*sibling) != NULL)
- sibling = &(*sibling)->sibling_of_hw;
- *sibling = hw;
- hw->parent_of_hw = parent;
- }
-
- /* top of tree */
- if (parent != NULL)
- {
- struct hw *root = parent;
- while (root->parent_of_hw != NULL)
- root = root->parent_of_hw;
- hw->root_of_hw = root;
- }
-
- /* a unique identifier for the device on the parents bus */
- if (parent != NULL)
- {
- hw_unit_decode (parent, unit, &hw->unit_address_of_hw);
- }
-
- /* Determine our path */
- if (parent != NULL)
- hw->path_of_hw = full_name_of_hw (hw, NULL, 0);
- else
- hw->path_of_hw = "/";
-
- /* create our base type */
- hw->base_of_hw = HW_ZALLOC (hw, struct hw_base_data);
- hw->base_of_hw->finished_p = 0;
-
- /* our callbacks */
- set_hw_io_read_buffer (hw, panic_hw_io_read_buffer);
- set_hw_io_write_buffer (hw, panic_hw_io_write_buffer);
- set_hw_dma_read_buffer (hw, passthrough_hw_dma_read_buffer);
- set_hw_dma_write_buffer (hw, passthrough_hw_dma_write_buffer);
- set_hw_unit_decode (hw, generic_hw_unit_decode);
- set_hw_unit_encode (hw, generic_hw_unit_encode);
- set_hw_unit_address_to_attach_address (hw, generic_hw_unit_address_to_attach_address);
- set_hw_unit_size_to_attach_size (hw, generic_hw_unit_size_to_attach_size);
- set_hw_attach_address (hw, passthrough_hw_attach_address);
- set_hw_detach_address (hw, passthrough_hw_detach_address);
- set_hw_delete (hw, ignore_hw_delete);
-
- /* locate a descriptor */
- {
- const struct hw_descriptor **table;
- for (table = hw_descriptors;
- *table != NULL;
- table++)
- {
- const struct hw_descriptor *entry;
- for (entry = *table;
- entry->family != NULL;
- entry++)
- {
- if (strcmp (family, entry->family) == 0)
- {
- hw->base_of_hw->descriptor = entry;
- break;
- }
- }
- }
- if (hw->base_of_hw->descriptor == NULL)
- {
- hw_abort (parent, "Unknown device `%s'", family);
- }
- }
-
- /* Attach dummy ports */
- create_hw_alloc_data (hw);
- create_hw_property_data (hw);
- create_hw_port_data (hw);
- create_hw_event_data (hw);
- create_hw_handle_data (hw);
- create_hw_instance_data (hw);
-
- return hw;
-}
-
-
-int
-hw_finished_p (struct hw *me)
-{
- return (me->base_of_hw->finished_p);
-}
-
-void
-hw_finish (struct hw *me)
-{
- if (hw_finished_p (me))
- hw_abort (me, "Attempt to finish finished device");
-
- /* Fill in the (hopefully) defined address/size cells values */
- if (hw_find_property (me, "#address-cells") != NULL)
- me->nr_address_cells_of_hw_unit =
- hw_find_integer_property (me, "#address-cells");
- else
- me->nr_address_cells_of_hw_unit = 2;
- if (hw_find_property (me, "#size-cells") != NULL)
- me->nr_size_cells_of_hw_unit =
- hw_find_integer_property (me, "#size-cells");
- else
- me->nr_size_cells_of_hw_unit = 1;
-
- /* Fill in the (hopefully) defined trace variable */
- if (hw_find_property (me, "trace?") != NULL)
- me->trace_of_hw_p = hw_find_boolean_property (me, "trace?");
- /* allow global variable to define default tracing */
- else if (! hw_trace_p (me)
- && hw_find_property (hw_root (me), "global-trace?") != NULL
- && hw_find_boolean_property (hw_root (me), "global-trace?"))
- me->trace_of_hw_p = 1;
-
-
- /* Allow the real device to override any methods */
- me->base_of_hw->descriptor->to_finish (me);
- me->base_of_hw->finished_p = 1;
-}
-
-
-void
-hw_delete (struct hw *me)
-{
- /* give the object a chance to tidy up */
- me->base_of_hw->to_delete (me);
-
- delete_hw_instance_data (me);
- delete_hw_handle_data (me);
- delete_hw_event_data (me);
- delete_hw_port_data (me);
- delete_hw_property_data (me);
-
- /* now unlink us from the tree */
- if (hw_parent (me))
- {
- struct hw **sibling = &hw_parent (me)->child_of_hw;
- while (*sibling != NULL)
- {
- if (*sibling == me)
- {
- *sibling = me->sibling_of_hw;
- me->sibling_of_hw = NULL;
- me->parent_of_hw = NULL;
- break;
- }
- }
- }
-
- /* some sanity checks */
- if (hw_child (me) != NULL)
- {
- hw_abort (me, "attempt to delete device with children");
- }
- if (hw_sibling (me) != NULL)
- {
- hw_abort (me, "attempt to delete device with siblings");
- }
-
- /* blow away all memory belonging to the device */
- delete_hw_alloc_data (me);
-
- /* finally */
- zfree (me->base_of_hw);
- zfree (me);
-}
-
-
-/* Go through the devices various reg properties for those that
- specify attach addresses */
-
-
-void
-do_hw_attach_regs (struct hw *hw)
-{
- 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 (hw_find_property (hw, *reg_property_name) != NULL)
- {
- reg_property_spec reg;
- int reg_entry;
- for (reg_entry = 0;
- hw_find_reg_array_property (hw, *reg_property_name, reg_entry,
- &reg);
- reg_entry++)
- {
- unsigned_word attach_address;
- int attach_space;
- unsigned attach_size;
- if (!hw_unit_address_to_attach_address (hw_parent (hw),
- &reg.address,
- &attach_space,
- &attach_address,
- hw))
- continue;
- if (!hw_unit_size_to_attach_size (hw_parent (hw),
- &reg.size,
- &attach_size, hw))
- continue;
- hw_attach_address (hw_parent (hw),
- 0,
- attach_space, attach_address, attach_size,
- hw);
- nr_valid_reg_properties++;
- }
- /* if first option matches don't try for any others */
- if (reg_property_name == reg_property_names)
- break;
- }
- }
-}