Add hw_{malloc,zalloc,free} functions to hw_device. Any memory
[binutils-gdb.git] / sim / common / hw-device.c
1 /* This file is part of the program psim.
2
3 Copyright (C) 1994-1998, Andrew Cagney <cagney@highland.com.au>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20
21
22 #include "sim-main.h"
23
24 #include "hw-device.h"
25 #include "hw-properties.h"
26
27 #if HAVE_STDLIB_H
28 #include <stdlib.h>
29 #endif
30
31 \f
32 /* Address methods */
33
34 const hw_unit *
35 hw_unit_address (struct hw *me)
36 {
37 return &me->unit_address_of_hw;
38 }
39
40
41 \f
42 /* IOCTL: */
43
44 int
45 hw_ioctl (struct hw *me,
46 sim_cpu *processor,
47 sim_cia cia,
48 hw_ioctl_request request,
49 ...)
50 {
51 int status;
52 va_list ap;
53 va_start(ap, request);
54 status = me->to_ioctl (me, processor, cia, request, ap);
55 va_end(ap);
56 return status;
57 }
58
59 /* I/O */
60
61 void volatile
62 hw_abort (struct hw *me,
63 const char *fmt,
64 ...)
65 {
66 SIM_DESC sd;
67 const char *name;
68 va_list ap;
69 va_start(ap, fmt);
70 /* find a system to abort through */
71 if (me == NULL || hw_system (me) == NULL)
72 sd = NULL;
73 else
74 sd = hw_system (me);
75 /* find an identity */
76 if (me != NULL && hw_path (me) != NULL && hw_path (me) [0] != '\0')
77 name = hw_path (me);
78 else if (me != NULL && hw_name (me) != NULL && hw_name (me)[0] != '\0')
79 name = hw_name (me);
80 else if (me != NULL && hw_family (me) != NULL && hw_family (me)[0] != '\0')
81 name = hw_family (me);
82 else
83 name = "device";
84 /* report the problem */
85 sim_io_eprintf (sd, "%s: ", name);
86 sim_io_evprintf (sd, fmt, ap);
87 sim_io_error (sd, "%s", "");
88 }
89
90 \f
91 /* The event queue abstraction (for devices) */
92
93
94 struct _hw_event {
95 void *data;
96 struct hw *me;
97 hw_event_handler *handler;
98 sim_event *real;
99 };
100
101 /* Pass the H/W event onto the real handler */
102
103 static void
104 bounce_hw_event (SIM_DESC sd,
105 void *data)
106 {
107 hw_event event = * (hw_event*) data;
108 zfree (data);
109 event.handler (event.me, event.data);
110 }
111
112
113 /* Map onto the event functions */
114
115 hw_event *
116 hw_event_queue_schedule (struct hw *me,
117 signed64 delta_time,
118 hw_event_handler *handler,
119 void *data)
120 {
121 hw_event *event = ZALLOC (hw_event);
122 event->data = data;
123 event->handler = handler;
124 event->me = me;
125 event->real = sim_events_schedule (hw_system (me),
126 delta_time,
127 bounce_hw_event,
128 event);
129 return event;
130 }
131
132 void
133 hw_event_queue_deschedule (struct hw *me,
134 hw_event *event_to_remove)
135 {
136 sim_events_deschedule (hw_system (me),
137 event_to_remove->real);
138 zfree (event_to_remove);
139 }
140
141 signed64
142 hw_event_queue_time (struct hw *me)
143 {
144 return sim_events_time (hw_system (me));
145 }
146
147 \f
148 /* Mechanism for associating allocated memory regions to a device.
149 When a device is deleted any remaining memory regions are also
150 reclaimed.
151
152 FIXME: Perhaphs this can be generalized, perhaphs it should not
153 be. */
154
155 struct hw_alloc_data {
156 void *alloc;
157 int zalloc_p;
158 struct hw_alloc_data *next;
159 };
160
161 extern void *
162 hw_zalloc (struct hw *me, unsigned long size)
163 {
164 struct hw_alloc_data *memory = ZALLOC (struct hw_alloc_data);
165 memory->alloc = zalloc (size);
166 memory->zalloc_p = 1;
167 memory->next = me->alloc_of_hw;
168 me->alloc_of_hw = memory;
169 return memory->alloc;
170 }
171
172 extern void *
173 hw_malloc (struct hw *me, unsigned long size)
174 {
175 struct hw_alloc_data *memory = ZALLOC (struct hw_alloc_data);
176 memory->alloc = zalloc (size);
177 memory->zalloc_p = 0;
178 memory->next = me->alloc_of_hw;
179 me->alloc_of_hw = memory;
180 return memory->alloc;
181 }
182
183 extern void
184 hw_free (struct hw *me,
185 void *alloc)
186 {
187 struct hw_alloc_data **memory;
188 for (memory = &me->alloc_of_hw;
189 *memory != NULL;
190 memory = &(*memory)->next)
191 {
192 if ((*memory)->alloc == alloc)
193 {
194 struct hw_alloc_data *die = (*memory);
195 (*memory) = die->next;
196 if (die->zalloc_p)
197 zfree (die->alloc);
198 else
199 free (die->alloc);
200 zfree (die);
201 return;
202 }
203 }
204 hw_abort (me, "free of memory not belonging to a device");
205 }
206
207 extern void
208 hw_free_all (struct hw *me)
209 {
210 while (me->alloc_of_hw != NULL)
211 {
212 hw_free (me, me->alloc_of_hw->alloc);
213 }
214 }