aboutsummaryrefslogtreecommitdiff
path: root/sim/common/hw-device.c
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>1998-03-22 05:06:27 +0000
committerAndrew Cagney <cagney@redhat.com>1998-03-22 05:06:27 +0000
commite5f0d498af49da4680564df06b9709423523ba6e (patch)
tree0e052b4638713a10794e9fbd11df0651dcf974c7 /sim/common/hw-device.c
parentb1e9223cee0728b89f6b909c445a896d9fe41452 (diff)
downloadgdb-e5f0d498af49da4680564df06b9709423523ba6e.zip
gdb-e5f0d498af49da4680564df06b9709423523ba6e.tar.gz
gdb-e5f0d498af49da4680564df06b9709423523ba6e.tar.bz2
Add hw_{malloc,zalloc,free} functions to hw_device. Any memory
allocated using these functions is reclaimed when the corresponding device is deleted.
Diffstat (limited to 'sim/common/hw-device.c')
-rw-r--r--sim/common/hw-device.c214
1 files changed, 214 insertions, 0 deletions
diff --git a/sim/common/hw-device.c b/sim/common/hw-device.c
new file mode 100644
index 0000000..3f57190
--- /dev/null
+++ b/sim/common/hw-device.c
@@ -0,0 +1,214 @@
+/* This file is part of the program psim.
+
+ Copyright (C) 1994-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 "sim-main.h"
+
+#include "hw-device.h"
+#include "hw-properties.h"
+
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+
+/* Address methods */
+
+const hw_unit *
+hw_unit_address (struct hw *me)
+{
+ return &me->unit_address_of_hw;
+}
+
+
+
+/* IOCTL: */
+
+int
+hw_ioctl (struct hw *me,
+ sim_cpu *processor,
+ sim_cia cia,
+ hw_ioctl_request request,
+ ...)
+{
+ int status;
+ va_list ap;
+ va_start(ap, request);
+ status = me->to_ioctl (me, processor, cia, request, ap);
+ va_end(ap);
+ return status;
+}
+
+/* I/O */
+
+void volatile
+hw_abort (struct hw *me,
+ const char *fmt,
+ ...)
+{
+ SIM_DESC sd;
+ const char *name;
+ va_list ap;
+ va_start(ap, fmt);
+ /* find a system to abort through */
+ if (me == NULL || hw_system (me) == NULL)
+ sd = NULL;
+ else
+ sd = hw_system (me);
+ /* find an identity */
+ if (me != NULL && hw_path (me) != NULL && hw_path (me) [0] != '\0')
+ name = hw_path (me);
+ else if (me != NULL && hw_name (me) != NULL && hw_name (me)[0] != '\0')
+ name = hw_name (me);
+ else if (me != NULL && hw_family (me) != NULL && hw_family (me)[0] != '\0')
+ name = hw_family (me);
+ else
+ name = "device";
+ /* report the problem */
+ sim_io_eprintf (sd, "%s: ", name);
+ sim_io_evprintf (sd, fmt, ap);
+ sim_io_error (sd, "%s", "");
+}
+
+
+/* The event queue abstraction (for devices) */
+
+
+struct _hw_event {
+ void *data;
+ struct hw *me;
+ hw_event_handler *handler;
+ sim_event *real;
+};
+
+/* Pass the H/W event onto the real handler */
+
+static void
+bounce_hw_event (SIM_DESC sd,
+ void *data)
+{
+ hw_event event = * (hw_event*) data;
+ zfree (data);
+ event.handler (event.me, event.data);
+}
+
+
+/* Map onto the event functions */
+
+hw_event *
+hw_event_queue_schedule (struct hw *me,
+ signed64 delta_time,
+ hw_event_handler *handler,
+ void *data)
+{
+ hw_event *event = ZALLOC (hw_event);
+ event->data = data;
+ event->handler = handler;
+ event->me = me;
+ event->real = sim_events_schedule (hw_system (me),
+ delta_time,
+ bounce_hw_event,
+ event);
+ return event;
+}
+
+void
+hw_event_queue_deschedule (struct hw *me,
+ hw_event *event_to_remove)
+{
+ sim_events_deschedule (hw_system (me),
+ event_to_remove->real);
+ zfree (event_to_remove);
+}
+
+signed64
+hw_event_queue_time (struct hw *me)
+{
+ return sim_events_time (hw_system (me));
+}
+
+
+/* Mechanism for associating allocated memory regions to a device.
+ When a device is deleted any remaining memory regions are also
+ reclaimed.
+
+ FIXME: Perhaphs this can be generalized, perhaphs it should not
+ be. */
+
+struct hw_alloc_data {
+ void *alloc;
+ int zalloc_p;
+ struct hw_alloc_data *next;
+};
+
+extern void *
+hw_zalloc (struct hw *me, unsigned long size)
+{
+ struct hw_alloc_data *memory = ZALLOC (struct hw_alloc_data);
+ memory->alloc = zalloc (size);
+ memory->zalloc_p = 1;
+ memory->next = me->alloc_of_hw;
+ me->alloc_of_hw = memory;
+ return memory->alloc;
+}
+
+extern void *
+hw_malloc (struct hw *me, unsigned long size)
+{
+ struct hw_alloc_data *memory = ZALLOC (struct hw_alloc_data);
+ memory->alloc = zalloc (size);
+ memory->zalloc_p = 0;
+ memory->next = me->alloc_of_hw;
+ me->alloc_of_hw = memory;
+ return memory->alloc;
+}
+
+extern void
+hw_free (struct hw *me,
+ void *alloc)
+{
+ struct hw_alloc_data **memory;
+ for (memory = &me->alloc_of_hw;
+ *memory != NULL;
+ memory = &(*memory)->next)
+ {
+ if ((*memory)->alloc == alloc)
+ {
+ struct hw_alloc_data *die = (*memory);
+ (*memory) = die->next;
+ if (die->zalloc_p)
+ zfree (die->alloc);
+ else
+ free (die->alloc);
+ zfree (die);
+ return;
+ }
+ }
+ hw_abort (me, "free of memory not belonging to a device");
+}
+
+extern void
+hw_free_all (struct hw *me)
+{
+ while (me->alloc_of_hw != NULL)
+ {
+ hw_free (me, me->alloc_of_hw->alloc);
+ }
+}