#include "hw-base.h"
-/* LATER: #include "hwconfig.h" */
-extern const struct hw_device_descriptor dv_core_descriptor[];
-extern const struct hw_device_descriptor dv_pal_descriptor[];
-const struct hw_device_descriptor *hw_descriptors[] = {
- dv_core_descriptor,
- dv_pal_descriptor,
- NULL,
-};
-
#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <ctype.h>
+#include "hw-config.h"
+
struct hw_base_data {
int finished_p;
const struct hw_device_descriptor *descriptor;
void *dest,
int space,
unsigned_word addr,
- unsigned nr_bytes,
- sim_cpu *processor,
- sim_cia cia)
+ unsigned nr_bytes)
{
hw_abort (me, "no io-read method");
return 0;
const void *source,
int space,
unsigned_word addr,
- unsigned nr_bytes,
- sim_cpu *processor,
- sim_cia cia)
+ unsigned nr_bytes)
{
hw_abort (me, "no io-write method");
return 0;
violate_read_only_section);
}
-const struct hw_port_descriptor empty_hw_ports[] = {
- { NULL, },
-};
-
-static void
-panic_hw_port_event (struct hw *me,
- int my_port,
- struct hw *source,
- int source_port,
- int level,
- sim_cpu *processor,
- sim_cia cia)
-{
- hw_abort (me, "no port method");
-}
-
static void
ignore_hw_delete (struct hw *me)
{
/* return it usefully */
if (buf == full_name)
- buf = (char *) strdup (full_name);
+ buf = hw_strdup (leaf, full_name);
return buf;
}
struct hw *
-hw_create (SIM_DESC sd,
+hw_create (struct sim_state *sd,
struct hw *parent,
const char *family,
const char *name,
struct hw *hw = ZALLOC (struct hw);
/* our identity */
- hw->family_of_hw = family;
- hw->name_of_hw = name;
- hw->args_of_hw = args;
+ 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)
if (strcmp (family, entry->family) == 0)
{
hw->base_of_hw->descriptor = entry;
+ break;
}
}
}
}
/* Attach dummy ports */
- set_hw_ports (hw, empty_hw_ports);
- set_hw_port_event (hw, panic_hw_port_event);
+ create_hw_port_data (hw);
return hw;
}
/* 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);
/* give the object a chance to tidy up */
me->base_of_hw->to_delete (me);
+ delete_hw_port_data (me);
+
/* now unlink us from the tree */
if (hw_parent (me))
{
--- /dev/null
+/* Common hardware.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+ Contributed by Andrew Cagney and Cygnus Solutions.
+
+This file is part of GDB, the GNU debugger.
+
+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, 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 "sim-main.h"
+#include "hw-base.h"
+
+#ifdef 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 <ctype.h>
+
+#define TRACE(x,y)
+
+
+struct hw_port_edge {
+ int my_port;
+ struct hw *dest;
+ int dest_port;
+ struct hw_port_edge *next;
+ object_disposition disposition;
+};
+
+struct hw_port_data {
+ hw_port_event_callback *to_port_event;
+ const struct hw_port_descriptor *ports;
+ struct hw_port_edge *edges;
+};
+
+const struct hw_port_descriptor empty_hw_ports[] = {
+ { NULL, },
+};
+
+static void
+panic_hw_port_event (struct hw *me,
+ int my_port,
+ struct hw *source,
+ int source_port,
+ int level)
+{
+ hw_abort (me, "no port method");
+}
+
+void
+create_hw_port_data (struct hw *me)
+{
+ me->ports_of_hw = HW_ZALLOC (me, struct hw_port_data);
+ set_hw_port_event (me, panic_hw_port_event);
+ set_hw_ports (me, empty_hw_ports);
+}
+
+void
+delete_hw_port_data (struct hw *me)
+{
+ hw_free (me, me->ports_of_hw);
+ me->ports_of_hw = NULL;
+}
+
+void
+set_hw_ports (struct hw *me,
+ const struct hw_port_descriptor ports[])
+{
+ me->ports_of_hw->ports = ports;
+}
+
+void
+set_hw_port_event (struct hw *me,
+ hw_port_event_callback *port_event)
+{
+ me->ports_of_hw->to_port_event = port_event;
+}
+
+
+static void
+attach_hw_port_edge (struct hw *me,
+ struct hw_port_edge **list,
+ int my_port,
+ struct hw *dest,
+ int dest_port,
+ object_disposition disposition)
+{
+ struct hw_port_edge *new_edge = HW_ZALLOC (me, struct hw_port_edge);
+ new_edge->my_port = my_port;
+ new_edge->dest = dest;
+ new_edge->dest_port = dest_port;
+ new_edge->next = *list;
+ new_edge->disposition = disposition;
+ *list = new_edge;
+}
+
+
+static void
+detach_hw_port_edge (struct hw *me,
+ struct hw_port_edge **list,
+ int my_port,
+ struct hw *dest,
+ int dest_port)
+{
+ while (*list != NULL)
+ {
+ struct hw_port_edge *old_edge = *list;
+ if (old_edge->dest == dest
+ && old_edge->dest_port == dest_port
+ && old_edge->my_port == my_port)
+ {
+ if (old_edge->disposition == permenant_object)
+ hw_abort (me, "attempt to delete permenant port edge");
+ *list = old_edge->next;
+ hw_free (me, old_edge);
+ return;
+ }
+ }
+ hw_abort (me, "attempt to delete unattached port");
+}
+
+
+#if 0
+static void
+clean_hw_port_edges (struct hw_port_edge **list)
+{
+ while (*list != NULL)
+ {
+ struct hw_port_edge *old_edge = *list;
+ switch (old_edge->disposition)
+ {
+ case permenant_object:
+ list = &old_edge->next;
+ break;
+ case temporary_object:
+ *list = old_edge->next;
+ hw_free (me, old_edge);
+ break;
+ }
+ }
+}
+#endif
+
+
+/* Ports: */
+
+void
+hw_port_event (struct hw *me,
+ int my_port,
+ int level)
+{
+ int found_an_edge = 0;
+ struct hw_port_edge *edge;
+ /* device's lines directly connected */
+ for (edge = me->ports_of_hw->edges;
+ edge != NULL;
+ edge = edge->next)
+ {
+ if (edge->my_port == my_port)
+ {
+ edge->dest->ports_of_hw->to_port_event (edge->dest,
+ edge->dest_port,
+ me,
+ my_port,
+ level);
+ found_an_edge = 1;
+ }
+ }
+ if (!found_an_edge)
+ hw_abort (me, "No edge for port %d", my_port);
+}
+
+
+void
+hw_port_attach (struct hw *me,
+ int my_port,
+ struct hw *dest,
+ int dest_port,
+ object_disposition disposition)
+{
+ attach_hw_port_edge (me,
+ &me->ports_of_hw->edges,
+ my_port,
+ dest,
+ dest_port,
+ disposition);
+}
+
+
+void
+hw_port_detach (struct hw *me,
+ int my_port,
+ struct hw *dest,
+ int dest_port)
+{
+ detach_hw_port_edge (me,
+ &me->ports_of_hw->edges,
+ my_port,
+ dest,
+ dest_port);
+}
+
+
+void
+hw_port_traverse (struct hw *me,
+ hw_port_traverse_function *handler,
+ void *data)
+{
+ struct hw_port_edge *port_edge;
+ for (port_edge = me->ports_of_hw->edges;
+ port_edge != NULL;
+ port_edge = port_edge->next)
+ {
+ handler (me, port_edge->my_port,
+ port_edge->dest, port_edge->dest_port,
+ data);
+ }
+}
+
+
+int
+hw_port_decode (struct hw *me,
+ const char *port_name,
+ port_direction direction)
+{
+ if (port_name == NULL || port_name[0] == '\0')
+ return 0;
+ if (isdigit(port_name[0]))
+ {
+ return strtoul (port_name, NULL, 0);
+ }
+ else
+ {
+ const struct hw_port_descriptor *ports =
+ me->ports_of_hw->ports;
+ if (ports != NULL)
+ {
+ while (ports->name != NULL)
+ {
+ if (ports->direction == bidirect_port
+ || ports->direction == direction)
+ {
+ if (ports->nr_ports > 0)
+ {
+ int len = strlen (ports->name);
+ if (strncmp (port_name, ports->name, len) == 0)
+ {
+ if (port_name[len] == '\0')
+ return ports->number;
+ else if(isdigit (port_name[len]))
+ {
+ int port = (ports->number
+ + strtoul (&port_name[len], NULL, 0));
+ if (port >= ports->number + ports->nr_ports)
+ hw_abort (me,
+ "Port %s out of range",
+ port_name);
+ return port;
+ }
+ }
+ }
+ else if (strcmp (port_name, ports->name) == 0)
+ return ports->number;
+ }
+ ports++;
+ }
+ }
+ }
+ hw_abort (me, "Unreconized port %s", port_name);
+ return 0;
+}
+
+
+int
+hw_port_encode (struct hw *me,
+ int port_number,
+ char *buf,
+ int sizeof_buf,
+ port_direction direction)
+{
+ const struct hw_port_descriptor *ports = NULL;
+ ports = me->ports_of_hw->ports;
+ if (ports != NULL) {
+ while (ports->name != NULL)
+ {
+ if (ports->direction == bidirect_port
+ || ports->direction == direction)
+ {
+ if (ports->nr_ports > 0)
+ {
+ if (port_number >= ports->number
+ && port_number < ports->number + ports->nr_ports)
+ {
+ strcpy (buf, ports->name);
+ sprintf (buf + strlen(buf), "%d", port_number - ports->number);
+ if (strlen (buf) >= sizeof_buf)
+ hw_abort (me, "hw_port_encode: buffer overflow");
+ return strlen (buf);
+ }
+ }
+ else
+ {
+ if (ports->number == port_number)
+ {
+ if (strlen(ports->name) >= sizeof_buf)
+ hw_abort (me, "hw_port_encode: buffer overflow");
+ strcpy(buf, ports->name);
+ return strlen(buf);
+ }
+ }
+ }
+ ports++;
+ }
+ }
+ sprintf (buf, "%d", port_number);
+ if (strlen(buf) >= sizeof_buf)
+ hw_abort (me, "hw_port_encode: buffer overflow");
+ return strlen(buf);
+}
--- /dev/null
+/* Common hardware.
+ Copyright (C) 1998 Free Software Foundation, Inc.
+ Contributed by Andrew Cagney and Cygnus Solutions.
+
+This file is part of GDB, the GNU debugger.
+
+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, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#ifndef HW_PORTS_H
+#define HW_PORTS_H
+
+/* Initialize a port */
+
+struct hw_port_descriptor {
+ const char *name;
+ int number;
+ int nr_ports;
+ port_direction direction;
+};
+
+void set_hw_ports (struct hw *hw, const struct hw_port_descriptor ports[]);
+
+typedef void (hw_port_event_callback)
+ (struct hw *me,
+ int my_port,
+ struct hw *source,
+ int source_port,
+ int level);
+
+void set_hw_port_event (struct hw *hw, hw_port_event_callback *to_port_event);
+
+
+/* Port source
+
+ A device drives its output ports using the call
+
+ */
+
+void hw_port_event
+(struct hw *me,
+ int my_port,
+ int value);
+
+/* This port event will then be propogated to any attached
+ destination ports.
+
+ Any interpretation of PORT and VALUE is model dependant. As a
+ guideline the following are recommended: PCI interrupts A-D should
+ correspond to ports 0-3; level sensative interrupts be requested
+ with a value of one and withdrawn with a value of 0; edge sensative
+ interrupts always have a value of 1, the event its self is treated
+ as the interrupt.
+
+
+ Port destinations
+
+ Attached to each port of a device can be zero or more
+ desitinations. These destinations consist of a device/port pair.
+ A destination is attached/detached to a device line using the
+ attach and detach calls. */
+
+void hw_port_attach
+(struct hw *me,
+ int my_port,
+ struct hw *dest,
+ int dest_port,
+ object_disposition disposition);
+
+void hw_port_detach
+(struct hw *me,
+ int my_port,
+ struct hw *dest,
+ int dest_port);
+
+
+/* Iterate over the list of ports attached to a device */
+
+typedef void (hw_port_traverse_function)
+ (struct hw *me,
+ int my_port,
+ struct hw *dest,
+ int dest_port,
+ void *data);
+
+void hw_port_traverse
+(struct hw *me,
+ hw_port_traverse_function *handler,
+ void *data);
+
+
+/* DESTINATION is attached (detached) to LINE of the device ME
+
+
+ Port conversion
+
+ Users refer to port numbers symbolically. For instance a device
+ may refer to its `INT' signal which is internally represented by
+ port 3.
+
+ To convert to/from the symbolic and internal representation of a
+ port name/number. The following functions are available. */
+
+int hw_port_decode
+(struct hw *me,
+ const char *symbolic_name,
+ port_direction direction);
+
+int hw_port_encode
+(struct hw *me,
+ int port_number,
+ char *buf,
+ int sizeof_buf,
+ port_direction direction);
+
+
+#endif