/[gxemul]/upstream/0.4.4/src/interrupt.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.4.4/src/interrupt.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 35 - (show annotations)
Mon Oct 8 16:21:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 7955 byte(s)
0.4.4
1 /*
2 * Copyright (C) 2006-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: interrupt.c,v 1.7 2007/02/03 16:41:42 debug Exp $
29 *
30 * The interrupt subsystem.
31 *
32 * Interrupts have a "path", e.g. "emul[0].machine[0].cpu.5". A device which
33 * wishes to cause this interrupt needs to connect to it.
34 *
35 * The possible interrupt paths are registered by CPUs, interrupt controllers,
36 * etc., that have a way of receiving interrupt requests. The physical
37 * version of an interrupt path is usually a "pin" on the CPU, or similar.
38 *
39 * Once connected, the interrupt can be asserted or deasserted.
40 *
41 * For examples on how it is used, see the various devices in src/devices/.
42 */
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47
48 #include "interrupt.h"
49 #include "misc.h"
50
51
52 struct interrupt_handler {
53 struct interrupt template;
54 int nr_of_exclusive_users;
55 int nr_of_nonexclusive_users;
56 };
57
58
59 static int nr_of_interrupt_handlers = 0;
60 static struct interrupt_handler *interrupt_handlers = NULL;
61
62
63 /*
64 * Dummy interrupt assert/deassert for "no interrupt" interrupts:
65 */
66 static void no_interrupt_assert(struct interrupt *i) { }
67 static void no_interrupt_deassert(struct interrupt *i) { }
68
69
70 /*
71 * interrupt_handler_register():
72 *
73 * Add an interrupt handler to the interrupt subsystem. The 'template'
74 * needs to have all members set.
75 *
76 * Name is of the form "emul[0].machine[0].cpu[0].irq[3].isa[14]" etc.
77 *
78 * If there already is a handler with this name, the emulator aborts.
79 */
80 void interrupt_handler_register(struct interrupt *template)
81 {
82 int i;
83
84 #ifdef UNSTABLE_DEVEL
85 printf("interrupt_handler_register(\"%s\")\n", template->name);
86 #endif
87
88 /* See if the name is already registered: */
89 for (i=0; i<nr_of_interrupt_handlers; i++) {
90 if (strcmp(template->name,
91 interrupt_handlers[i].template.name) != 0)
92 continue;
93
94 fatal("\ninterrupt_handler_register(): An interrupt handler"
95 " using the name '%s' is already registered.\n",
96 template->name);
97 exit(1);
98 }
99
100 nr_of_interrupt_handlers ++;
101 interrupt_handlers = realloc(interrupt_handlers,
102 nr_of_interrupt_handlers * sizeof(struct interrupt_handler));
103 if (interrupt_handlers == NULL) {
104 fprintf(stderr, "out of memory in "
105 "ninterrupt_handler_register().\n");
106 exit(1);
107 }
108
109 interrupt_handlers[nr_of_interrupt_handlers-1].template = *template;
110 interrupt_handlers[nr_of_interrupt_handlers-1].template.name =
111 strdup(template->name);
112 }
113
114
115 /*
116 * interrupt_handler_remove():
117 *
118 * Remove an interrupt handler from the interrupt subsystem. If there are
119 * still connected users of this interrupt, then an error message is printed
120 * and the emulator aborts.
121 */
122 void interrupt_handler_remove(char *name)
123 {
124 int i;
125
126 #ifdef UNSTABLE_DEVEL
127 printf("interrupt_handler_remove(\"%s\")\n", name);
128 #endif
129
130 for (i=0; i<nr_of_interrupt_handlers; i++) {
131 if (strcmp(name, interrupt_handlers[i].template.name) != 0)
132 continue;
133
134 /*
135 * Remove handler i, and return:
136 */
137 if (interrupt_handlers[i].nr_of_exclusive_users > 0 ||
138 interrupt_handlers[i].nr_of_nonexclusive_users > 0) {
139 fatal("interrupt_handler_remove(): Attempt to "
140 "remove interrupt handler '%s' which has %i "
141 "exclusive and %i non-exclusive users. Aborting.\n",
142 name, interrupt_handlers[i].nr_of_exclusive_users,
143 interrupt_handlers[i].nr_of_nonexclusive_users);
144 exit(1);
145 }
146
147 if (i != nr_of_interrupt_handlers-1)
148 memcpy(&interrupt_handlers[i],
149 &interrupt_handlers[i + 1],
150 nr_of_interrupt_handlers - i - 1);
151
152 nr_of_interrupt_handlers --;
153
154 return;
155 }
156
157 fatal("interrupt_handler_remove(): '%s' not found? Aborting.\n", name);
158 exit(1);
159 }
160
161
162 /*
163 * interrupt_handler_lookup():
164 *
165 * Scans the list of registered interrupt handlers for a given name. If the
166 * name is found, the template is filled with valid data, and 1 is returned.
167 * If the name is not found, 0 is returned.
168 */
169 int interrupt_handler_lookup(char *name, struct interrupt *template)
170 {
171 int i;
172
173 #ifdef UNSTABLE_DEVEL
174 printf("interrupt_handler_lookup(\"%s\")\n", name);
175 #endif
176
177 if (name[0] == '\0') {
178 /* No interrupt: */
179 memset(template, 0, sizeof(struct interrupt));
180 template->interrupt_assert = no_interrupt_assert;
181 template->interrupt_deassert = no_interrupt_deassert;
182 }
183
184 for (i=0; i<nr_of_interrupt_handlers; i++) {
185 if (strcmp(name, interrupt_handlers[i].template.name) != 0)
186 continue;
187
188 *template = interrupt_handlers[i].template;
189 return 1;
190 }
191
192 printf("interrupt_handler_lookup(\"%s\") failed. Aborting.\n", name);
193 abort();
194
195 return 0;
196 }
197
198
199 /*
200 * interrupt_connect():
201 *
202 * Increases the exclusive or nonexclusive nr or users of an interrupt.
203 */
204 void interrupt_connect(struct interrupt *in, int exclusive)
205 {
206 int i;
207
208 #ifdef UNSTABLE_DEVEL
209 printf("interrupt_connect(\"%s\")\n", in->name);
210 #endif
211
212 if (in->name == NULL || in->name[0] == '\0')
213 return;
214
215 for (i=0; i<nr_of_interrupt_handlers; i++) {
216 if (strcmp(in->name, interrupt_handlers[i].template.name) != 0)
217 continue;
218
219 if (exclusive) {
220 interrupt_handlers[i].nr_of_exclusive_users ++;
221 if (interrupt_handlers[i].nr_of_exclusive_users > 1) {
222 fatal("Fatal error in interrupt_connect(): "
223 "more than 1 exclusive user. Dumping "
224 "core for backtrace.\n");
225 abort();
226 }
227 } else {
228 interrupt_handlers[i].nr_of_nonexclusive_users ++;
229 }
230
231 return;
232 }
233
234 fatal("Internal error in interrupt_connect(): name '%s' not "
235 "found? Dumping core for debugging.\n", in->name);
236 abort();
237 }
238
239
240 /*
241 * interrupt_disconnect():
242 *
243 * Decreases the exclusive or nonexclusive nr or users of an interrupt.
244 */
245 void interrupt_disconnect(struct interrupt *in, int exclusive)
246 {
247 int i;
248
249 if (in->name == NULL || in->name[0] == '\0')
250 return;
251
252 for (i=0; i<nr_of_interrupt_handlers; i++) {
253 if (strcmp(in->name, interrupt_handlers[i].template.name) != 0)
254 continue;
255
256 if (exclusive) {
257 interrupt_handlers[i].nr_of_exclusive_users --;
258 if (interrupt_handlers[i].nr_of_exclusive_users < 0) {
259 fatal("Fatal error in interrupt_disconnect():"
260 "nr of exclusive users < 0?\n");
261 exit(1);
262 }
263 } else {
264 interrupt_handlers[i].nr_of_nonexclusive_users --;
265 if (interrupt_handlers[i].nr_of_nonexclusive_users<0) {
266 fatal("Fatal error in interrupt_disconnect():"
267 "nr of non-exclusive users < 0?\n");
268 exit(1);
269 }
270 }
271
272 return;
273 }
274
275 fatal("Internal error in interrupt_disconnect(): name '%s' not "
276 "found?\n", in->name);
277 exit(1);
278 }
279
280

  ViewVC Help
Powered by ViewVC 1.1.26