diff options
author | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:34:07 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:34:07 +0000 |
commit | 071ea11e85eb9d529cc5eb3d35f6247466a21b99 (patch) | |
tree | 5deda65b8d7b04d1f4cbc534c3206d328e1267ec /sim/common/hw-base.c | |
parent | 1730ec6b1848f0f32154277f788fb29f88d8475b (diff) | |
download | gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.zip gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.gz gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.bz2 |
Initial creation of sourceware repository
Diffstat (limited to 'sim/common/hw-base.c')
-rw-r--r-- | sim/common/hw-base.c | 567 |
1 files changed, 0 insertions, 567 deletions
diff --git a/sim/common/hw-base.c b/sim/common/hw-base.c deleted file mode 100644 index 05255b0..0000000 --- a/sim/common/hw-base.c +++ /dev/null @@ -1,567 +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); - - 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_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_entry++) - { - unsigned_word attach_address; - int attach_space; - unsigned attach_size; - if (!hw_unit_address_to_attach_address (hw_parent (hw), - ®.address, - &attach_space, - &attach_address, - hw)) - continue; - if (!hw_unit_size_to_attach_size (hw_parent (hw), - ®.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; - } - } -} |