/[gxemul]/trunk/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

Annotation of /trunk/src/interrupt.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 70 - (hide annotations)
Sun Oct 14 16:53:24 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 8030 byte(s)
debug interrupts
1 dpavlin 34 /*
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 dpavlin 44 * $Id: interrupt.c,v 1.13 2007/08/29 20:36:49 debug Exp $
29 dpavlin 34 *
30     * The interrupt subsystem.
31     *
32 dpavlin 44 * Interrupts have a "path", e.g. "machine[0].cpu.5". A device which
33 dpavlin 34 * 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 dpavlin 42 /* #define INTERRUPT_DEBUG */
53 dpavlin 70 #define INTERRUPT_DEBUG 1
54 dpavlin 42
55    
56 dpavlin 34 struct interrupt_handler {
57     struct interrupt template;
58     int nr_of_exclusive_users;
59     int nr_of_nonexclusive_users;
60     };
61    
62    
63     static int nr_of_interrupt_handlers = 0;
64     static struct interrupt_handler *interrupt_handlers = NULL;
65    
66    
67     /*
68     * Dummy interrupt assert/deassert for "no interrupt" interrupts:
69     */
70     static void no_interrupt_assert(struct interrupt *i) { }
71     static void no_interrupt_deassert(struct interrupt *i) { }
72    
73    
74     /*
75     * interrupt_handler_register():
76     *
77     * Add an interrupt handler to the interrupt subsystem. The 'template'
78     * needs to have all members set.
79     *
80 dpavlin 44 * Name is of the form "machine[0].cpu[0].irq[3].isa[14]" etc.
81 dpavlin 34 *
82     * If there already is a handler with this name, the emulator aborts.
83     */
84     void interrupt_handler_register(struct interrupt *template)
85     {
86     int i;
87    
88 dpavlin 42 #ifdef INTERRUPT_DEBUG
89 dpavlin 34 printf("interrupt_handler_register(\"%s\")\n", template->name);
90     #endif
91    
92     /* See if the name is already registered: */
93     for (i=0; i<nr_of_interrupt_handlers; i++) {
94     if (strcmp(template->name,
95     interrupt_handlers[i].template.name) != 0)
96     continue;
97    
98     fatal("\ninterrupt_handler_register(): An interrupt handler"
99     " using the name '%s' is already registered.\n",
100     template->name);
101     exit(1);
102     }
103    
104     nr_of_interrupt_handlers ++;
105 dpavlin 42 CHECK_ALLOCATION(interrupt_handlers = realloc(interrupt_handlers,
106     nr_of_interrupt_handlers * sizeof(struct interrupt_handler)));
107 dpavlin 34
108     interrupt_handlers[nr_of_interrupt_handlers-1].template = *template;
109 dpavlin 42 CHECK_ALLOCATION(interrupt_handlers[nr_of_interrupt_handlers-1].
110     template.name = strdup(template->name));
111 dpavlin 34 }
112    
113    
114     /*
115     * interrupt_handler_remove():
116     *
117     * Remove an interrupt handler from the interrupt subsystem. If there are
118     * still connected users of this interrupt, then an error message is printed
119     * and the emulator aborts.
120     */
121     void interrupt_handler_remove(char *name)
122     {
123     int i;
124    
125 dpavlin 42 #ifdef INTERRUPT_DEBUG
126 dpavlin 34 printf("interrupt_handler_remove(\"%s\")\n", name);
127     #endif
128    
129     for (i=0; i<nr_of_interrupt_handlers; i++) {
130     if (strcmp(name, interrupt_handlers[i].template.name) != 0)
131     continue;
132    
133     /*
134     * Remove handler i, and return:
135     */
136     if (interrupt_handlers[i].nr_of_exclusive_users > 0 ||
137     interrupt_handlers[i].nr_of_nonexclusive_users > 0) {
138     fatal("interrupt_handler_remove(): Attempt to "
139     "remove interrupt handler '%s' which has %i "
140     "exclusive and %i non-exclusive users. Aborting.\n",
141     name, interrupt_handlers[i].nr_of_exclusive_users,
142     interrupt_handlers[i].nr_of_nonexclusive_users);
143     exit(1);
144     }
145    
146     if (i != nr_of_interrupt_handlers-1)
147     memcpy(&interrupt_handlers[i],
148     &interrupt_handlers[i + 1],
149     nr_of_interrupt_handlers - i - 1);
150    
151     nr_of_interrupt_handlers --;
152    
153     return;
154     }
155    
156     fatal("interrupt_handler_remove(): '%s' not found? Aborting.\n", name);
157     exit(1);
158     }
159    
160    
161     /*
162     * interrupt_handler_lookup():
163     *
164     * Scans the list of registered interrupt handlers for a given name. If the
165     * name is found, the template is filled with valid data, and 1 is returned.
166     * If the name is not found, 0 is returned.
167     */
168     int interrupt_handler_lookup(char *name, struct interrupt *template)
169     {
170     int i;
171    
172 dpavlin 42 #ifdef INTERRUPT_DEBUG
173 dpavlin 34 printf("interrupt_handler_lookup(\"%s\")\n", name);
174     #endif
175    
176     if (name[0] == '\0') {
177     /* No interrupt: */
178     memset(template, 0, sizeof(struct interrupt));
179     template->interrupt_assert = no_interrupt_assert;
180     template->interrupt_deassert = no_interrupt_deassert;
181     }
182    
183     for (i=0; i<nr_of_interrupt_handlers; i++) {
184     if (strcmp(name, interrupt_handlers[i].template.name) != 0)
185     continue;
186    
187     *template = interrupt_handlers[i].template;
188     return 1;
189     }
190    
191 dpavlin 42 /* The 'if' is an ugly hack to prevent a Compaq CC warning. */
192     if (i >= nr_of_interrupt_handlers) {
193     printf("interrupt_handler_lookup(\"%s\") failed. "
194     "Aborting.\n", name);
195     abort();
196     }
197 dpavlin 34
198     return 0;
199     }
200    
201    
202     /*
203     * interrupt_connect():
204     *
205     * Increases the exclusive or nonexclusive nr or users of an interrupt.
206     */
207     void interrupt_connect(struct interrupt *in, int exclusive)
208     {
209     int i;
210    
211 dpavlin 42 #ifdef INTERRUPT_DEBUG
212 dpavlin 34 printf("interrupt_connect(\"%s\")\n", in->name);
213     #endif
214    
215     if (in->name == NULL || in->name[0] == '\0')
216     return;
217    
218     for (i=0; i<nr_of_interrupt_handlers; i++) {
219     if (strcmp(in->name, interrupt_handlers[i].template.name) != 0)
220     continue;
221    
222     if (exclusive) {
223     interrupt_handlers[i].nr_of_exclusive_users ++;
224     if (interrupt_handlers[i].nr_of_exclusive_users > 1) {
225     fatal("Fatal error in interrupt_connect(): "
226     "more than 1 exclusive user. Dumping "
227     "core for backtrace.\n");
228     abort();
229     }
230     } else {
231     interrupt_handlers[i].nr_of_nonexclusive_users ++;
232     }
233    
234     return;
235     }
236    
237     fatal("Internal error in interrupt_connect(): name '%s' not "
238     "found? Dumping core for debugging.\n", in->name);
239     abort();
240     }
241    
242    
243     /*
244     * interrupt_disconnect():
245     *
246     * Decreases the exclusive or nonexclusive nr or users of an interrupt.
247     */
248     void interrupt_disconnect(struct interrupt *in, int exclusive)
249     {
250     int i;
251    
252     if (in->name == NULL || in->name[0] == '\0')
253     return;
254    
255     for (i=0; i<nr_of_interrupt_handlers; i++) {
256     if (strcmp(in->name, interrupt_handlers[i].template.name) != 0)
257     continue;
258    
259     if (exclusive) {
260     interrupt_handlers[i].nr_of_exclusive_users --;
261     if (interrupt_handlers[i].nr_of_exclusive_users < 0) {
262     fatal("Fatal error in interrupt_disconnect():"
263     "nr of exclusive users < 0?\n");
264     exit(1);
265     }
266     } else {
267     interrupt_handlers[i].nr_of_nonexclusive_users --;
268     if (interrupt_handlers[i].nr_of_nonexclusive_users<0) {
269     fatal("Fatal error in interrupt_disconnect():"
270     "nr of non-exclusive users < 0?\n");
271     exit(1);
272     }
273     }
274    
275     return;
276     }
277    
278     fatal("Internal error in interrupt_disconnect(): name '%s' not "
279     "found?\n", in->name);
280     exit(1);
281     }
282    
283    

  ViewVC Help
Powered by ViewVC 1.1.26