Add function hw_trace() and macro HW_TRACE - provides trace support
[external/binutils.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 void
91 hw_trace (struct hw *me,
92           const char *fmt,
93           ...)
94 {
95   if (hw_trace_p (me)) /* to be sure, to be sure */
96     {
97       va_list ap;
98       va_start (ap, fmt);
99       sim_io_eprintf (hw_system (me), "%s: ", hw_path (me));
100       sim_io_evprintf (hw_system (me), fmt, ap);
101       sim_io_eprintf (hw_system (me), "\n");
102       va_end (ap);
103     }
104 }
105
106 \f
107 /* The event queue abstraction (for devices) */
108
109
110 struct _hw_event {
111   void *data;
112   struct hw *me;
113   hw_event_handler *handler;
114   sim_event *real;
115 };
116
117 /* Pass the H/W event onto the real handler */
118
119 static void
120 bounce_hw_event (SIM_DESC sd,
121                  void *data)
122 {
123   hw_event event = * (hw_event*) data;
124   zfree (data);
125   event.handler (event.me, event.data);
126 }
127
128
129 /* Map onto the event functions */
130
131 hw_event *
132 hw_event_queue_schedule (struct hw *me,
133                          signed64 delta_time,
134                          hw_event_handler *handler,
135                          void *data)
136 {
137   hw_event *event = ZALLOC (hw_event);
138   event->data = data;
139   event->handler = handler;
140   event->me = me;
141   event->real = sim_events_schedule (hw_system (me),
142                                      delta_time,
143                                      bounce_hw_event,
144                                      event);
145   return event;
146 }
147
148 void
149 hw_event_queue_deschedule (struct hw *me,
150                            hw_event *event_to_remove)
151 {
152   sim_events_deschedule (hw_system (me),
153                          event_to_remove->real);
154   zfree (event_to_remove);
155 }
156
157 signed64
158 hw_event_queue_time (struct hw *me)
159 {
160   return sim_events_time (hw_system (me));
161 }
162
163 \f
164 /* Mechanism for associating allocated memory regions to a device.
165    When a device is deleted any remaining memory regions are also
166    reclaimed.
167
168    FIXME: Perhaphs this can be generalized, perhaphs it should not
169    be. */
170
171 struct hw_alloc_data {
172   void *alloc;
173   int zalloc_p;
174   struct hw_alloc_data *next;
175 };
176
177 extern void *
178 hw_zalloc (struct hw *me, unsigned long size)
179 {
180   struct hw_alloc_data *memory = ZALLOC (struct hw_alloc_data);
181   memory->alloc = zalloc (size);
182   memory->zalloc_p = 1;
183   memory->next = me->alloc_of_hw;
184   me->alloc_of_hw = memory;
185   return memory->alloc;
186 }
187
188 extern void *
189 hw_malloc (struct hw *me, unsigned long size)
190 {
191   struct hw_alloc_data *memory = ZALLOC (struct hw_alloc_data);
192   memory->alloc = zalloc (size);
193   memory->zalloc_p = 0;
194   memory->next = me->alloc_of_hw;
195   me->alloc_of_hw = memory;
196   return memory->alloc;
197 }
198
199 extern void
200 hw_free (struct hw *me,
201          void *alloc)
202 {
203   struct hw_alloc_data **memory;
204   for (memory = &me->alloc_of_hw;
205        *memory != NULL;
206        memory = &(*memory)->next)
207     {
208       if ((*memory)->alloc == alloc)
209         {
210           struct hw_alloc_data *die = (*memory);
211           (*memory) = die->next;
212           if (die->zalloc_p)
213             zfree (die->alloc);
214           else
215             free (die->alloc);
216           zfree (die);
217           return;
218         }
219     }
220   hw_abort (me, "free of memory not belonging to a device");
221 }
222
223 extern void
224 hw_free_all (struct hw *me)
225 {
226   while (me->alloc_of_hw != NULL)
227     {
228       hw_free (me, me->alloc_of_hw->alloc);
229     }
230 }