/[gxemul]/trunk/src/machines/interrupts.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 /trunk/src/machines/interrupts.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 22 - (show annotations)
Mon Oct 8 16:19:37 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 24613 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


1 /*
2 * Copyright (C) 2003-2006 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: interrupts.c,v 1.6 2006/02/18 13:42:39 debug Exp $
29 *
30 * Machine-dependent interrupt glue.
31 */
32
33 #include <stdio.h>
34 #include <string.h>
35
36 #include "cpu.h"
37 #include "devices.h"
38 #include "machine.h"
39 #include "machine_interrupts.h"
40 #include "misc.h"
41
42 #include "crimereg.h"
43
44 #include "dec_kmin.h"
45 #include "dec_kn01.h"
46 #include "dec_kn02.h"
47 #include "dec_kn03.h"
48 #include "dec_5100.h"
49 #include "dec_maxine.h"
50
51
52 /*
53 * DECstation KN02 interrupts:
54 */
55 void kn02_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
56 {
57 int current;
58
59 irq_nr -= 8;
60 irq_nr &= 0xff;
61
62 if (assrt) {
63 /* OR in the irq_nr into the CSR: */
64 m->md_int.kn02_csr->csr[0] |= irq_nr;
65 } else {
66 /* AND out the irq_nr from the CSR: */
67 m->md_int.kn02_csr->csr[0] &= ~irq_nr;
68 }
69
70 current = m->md_int.kn02_csr->csr[0] & m->md_int.kn02_csr->csr[2];
71 if (current == 0)
72 cpu_interrupt_ack(cpu, 2);
73 else
74 cpu_interrupt(cpu, 2);
75 }
76
77
78 /*
79 * DECstation KMIN interrupts:
80 *
81 * TC slot 3 = system slot.
82 */
83 void kmin_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
84 {
85 irq_nr -= 8;
86 /* debug("kmin_interrupt(): irq_nr=%i assrt=%i\n", irq_nr, assrt); */
87
88 if (assrt)
89 m->md_int.dec_ioasic_data->reg[(IOASIC_INTR -
90 IOASIC_SLOT_1_START) / 0x10] |= irq_nr;
91 else
92 m->md_int.dec_ioasic_data->reg[(IOASIC_INTR -
93 IOASIC_SLOT_1_START) / 0x10] &= ~irq_nr;
94
95 if (m->md_int.dec_ioasic_data->reg[(IOASIC_INTR - IOASIC_SLOT_1_START)
96 / 0x10] & m->md_int.dec_ioasic_data->reg[(IOASIC_IMSK -
97 IOASIC_SLOT_1_START) / 0x10])
98 cpu_interrupt(cpu, KMIN_INT_TC3);
99 else
100 cpu_interrupt_ack(cpu, KMIN_INT_TC3);
101 }
102
103
104 /*
105 * DECstation KN03 interrupts:
106 */
107 void kn03_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
108 {
109 irq_nr -= 8;
110 /* debug("kn03_interrupt(): irq_nr=0x%x assrt=%i\n",
111 irq_nr, assrt); */
112
113 if (assrt)
114 m->md_int.dec_ioasic_data->reg[(IOASIC_INTR -
115 IOASIC_SLOT_1_START) / 0x10] |= irq_nr;
116 else
117 m->md_int.dec_ioasic_data->reg[(IOASIC_INTR -
118 IOASIC_SLOT_1_START) / 0x10] &= ~irq_nr;
119
120 if (m->md_int.dec_ioasic_data->reg[(IOASIC_INTR - IOASIC_SLOT_1_START)
121 / 0x10] & m->md_int.dec_ioasic_data->reg[(IOASIC_IMSK -
122 IOASIC_SLOT_1_START) / 0x10])
123 cpu_interrupt(cpu, KN03_INT_ASIC);
124 else
125 cpu_interrupt_ack(cpu, KN03_INT_ASIC);
126 }
127
128
129 /*
130 * DECstation MAXINE interrupts:
131 */
132 void maxine_interrupt(struct machine *m, struct cpu *cpu,
133 int irq_nr, int assrt)
134 {
135 irq_nr -= 8;
136 debug("maxine_interrupt(): irq_nr=0x%x assrt=%i\n", irq_nr, assrt);
137
138 if (assrt)
139 m->md_int.dec_ioasic_data->reg[(IOASIC_INTR -
140 IOASIC_SLOT_1_START) / 0x10] |= irq_nr;
141 else
142 m->md_int.dec_ioasic_data->reg[(IOASIC_INTR -
143 IOASIC_SLOT_1_START) / 0x10] &= ~irq_nr;
144
145 if (m->md_int.dec_ioasic_data->reg[(IOASIC_INTR - IOASIC_SLOT_1_START)
146 / 0x10] & m->md_int.dec_ioasic_data->reg[(IOASIC_IMSK -
147 IOASIC_SLOT_1_START) / 0x10])
148 cpu_interrupt(cpu, XINE_INT_TC3);
149 else
150 cpu_interrupt_ack(cpu, XINE_INT_TC3);
151 }
152
153
154 /*
155 * DECstation KN230 interrupts:
156 */
157 void kn230_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
158 {
159 int r2 = 0;
160
161 m->md_int.kn230_csr->csr |= irq_nr;
162
163 switch (irq_nr) {
164 case KN230_CSR_INTR_SII:
165 case KN230_CSR_INTR_LANCE:
166 r2 = 3;
167 break;
168 case KN230_CSR_INTR_DZ0:
169 case KN230_CSR_INTR_OPT0:
170 case KN230_CSR_INTR_OPT1:
171 r2 = 2;
172 break;
173 default:
174 fatal("kn230_interrupt(): irq_nr = %i ?\n", irq_nr);
175 }
176
177 if (assrt) {
178 /* OR in the irq_nr mask into the CSR: */
179 m->md_int.kn230_csr->csr |= irq_nr;
180
181 /* Assert MIPS interrupt 2 or 3: */
182 cpu_interrupt(cpu, r2);
183 } else {
184 /* AND out the irq_nr mask from the CSR: */
185 m->md_int.kn230_csr->csr &= ~irq_nr;
186
187 /* If the CSR interrupt bits are all zero,
188 clear the bit in the cause register as well. */
189 if (r2 == 2) {
190 /* irq 2: */
191 if ((m->md_int.kn230_csr->csr & (KN230_CSR_INTR_DZ0
192 | KN230_CSR_INTR_OPT0 | KN230_CSR_INTR_OPT1)) == 0)
193 cpu_interrupt_ack(cpu, r2);
194 } else {
195 /* irq 3: */
196 if ((m->md_int.kn230_csr->csr & (KN230_CSR_INTR_SII |
197 KN230_CSR_INTR_LANCE)) == 0)
198 cpu_interrupt_ack(cpu, r2);
199 }
200 }
201 }
202
203
204 /*
205 * Jazz interrupts (for Acer PICA-61 etc):
206 *
207 * 0..7 MIPS interrupts
208 * 8 + x, where x = 0..15 Jazz interrupts
209 * 8 + x, where x = 16..31 ISA interrupt (irq nr + 16)
210 */
211 void jazz_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
212 {
213 uint32_t irq;
214 int isa = 0;
215
216 irq_nr -= 8;
217
218 /* debug("jazz_interrupt() irq_nr = %i, assrt = %i\n",
219 irq_nr, assrt); */
220
221 if (irq_nr >= 16) {
222 isa = 1;
223 irq_nr -= 16;
224 }
225
226 irq = 1 << irq_nr;
227
228 if (isa) {
229 if (assrt)
230 m->md_int.jazz_data->isa_int_asserted |= irq;
231 else
232 m->md_int.jazz_data->isa_int_asserted &= ~irq;
233 } else {
234 if (assrt)
235 m->md_int.jazz_data->int_asserted |= irq;
236 else
237 m->md_int.jazz_data->int_asserted &= ~irq;
238 }
239
240 /* debug(" %08x %08x\n", m->md_int.jazz_data->int_asserted,
241 m->md_int.jazz_data->int_enable_mask); */
242 /* debug(" %08x %08x\n", m->md_int.jazz_data->isa_int_asserted,
243 m->md_int.jazz_data->isa_int_enable_mask); */
244
245 if (m->md_int.jazz_data->int_asserted
246 /* & m->md_int.jazz_data->int_enable_mask */ & ~0x8000 )
247 cpu_interrupt(cpu, 3);
248 else
249 cpu_interrupt_ack(cpu, 3);
250
251 if (m->md_int.jazz_data->isa_int_asserted &
252 m->md_int.jazz_data->isa_int_enable_mask)
253 cpu_interrupt(cpu, 4);
254 else
255 cpu_interrupt_ack(cpu, 4);
256
257 /* TODO: this "15" (0x8000) is the timer... fix this? */
258 if (m->md_int.jazz_data->int_asserted & 0x8000)
259 cpu_interrupt(cpu, 6);
260 else
261 cpu_interrupt_ack(cpu, 6);
262 }
263
264
265 /*
266 * VR41xx interrupt routine:
267 *
268 * irq_nr = 8 + x
269 * x = 0..15 for level1
270 * x = 16..31 for level2
271 * x = 32+y for GIU interrupt y
272 */
273 void vr41xx_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
274 {
275 int giu_irq = 0;
276
277 irq_nr -= 8;
278 if (irq_nr >= 32) {
279 giu_irq = irq_nr - 32;
280
281 if (assrt)
282 m->md_int.vr41xx_data->giuint |= (1 << giu_irq);
283 else
284 m->md_int.vr41xx_data->giuint &= ~(1 << giu_irq);
285 }
286
287 /* TODO: This is wrong. What about GIU bit 8? */
288
289 if (irq_nr != 8) {
290 /* If any GIU bit is asserted, then assert the main
291 GIU interrupt: */
292 if (m->md_int.vr41xx_data->giuint &
293 m->md_int.vr41xx_data->giumask)
294 vr41xx_interrupt(m, cpu, 8 + 8, 1);
295 else
296 vr41xx_interrupt(m, cpu, 8 + 8, 0);
297 }
298
299 /* debug("vr41xx_interrupt(): irq_nr=%i assrt=%i\n",
300 irq_nr, assrt); */
301
302 if (irq_nr < 16) {
303 if (assrt)
304 m->md_int.vr41xx_data->sysint1 |= (1 << irq_nr);
305 else
306 m->md_int.vr41xx_data->sysint1 &= ~(1 << irq_nr);
307 } else if (irq_nr < 32) {
308 irq_nr -= 16;
309 if (assrt)
310 m->md_int.vr41xx_data->sysint2 |= (1 << irq_nr);
311 else
312 m->md_int.vr41xx_data->sysint2 &= ~(1 << irq_nr);
313 }
314
315 /* TODO: Which hardware interrupt pin? */
316
317 /* debug(" sysint1=%04x mask=%04x, sysint2=%04x mask=%04x\n",
318 m->md_int.vr41xx_data->sysint1, m->md_int.vr41xx_data->msysint1,
319 m->md_int.vr41xx_data->sysint2, m->md_int.vr41xx_data->msysint2); */
320
321 if ((m->md_int.vr41xx_data->sysint1 & m->md_int.vr41xx_data->msysint1) |
322 (m->md_int.vr41xx_data->sysint2 & m->md_int.vr41xx_data->msysint2))
323 cpu_interrupt(cpu, 2);
324 else
325 cpu_interrupt_ack(cpu, 2);
326 }
327
328
329 /*
330 * Playstation 2 interrupt routine:
331 *
332 * irq_nr = 8 + x normal irq x
333 * 8 + 16 + y dma irq y
334 * 8 + 32 + 0 sbus irq 0 (pcmcia)
335 * 8 + 32 + 1 sbus irq 1 (usb)
336 */
337 void ps2_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
338 {
339 irq_nr -= 8;
340 debug("ps2_interrupt(): irq_nr=0x%x assrt=%i\n", irq_nr, assrt);
341
342 if (irq_nr >= 32) {
343 int msk = 0;
344 switch (irq_nr - 32) {
345 case 0: /* PCMCIA: */
346 msk = 0x100;
347 break;
348 case 1: /* USB: */
349 msk = 0x400;
350 break;
351 default:
352 fatal("ps2_interrupt(): bad irq_nr %i\n", irq_nr);
353 }
354
355 if (assrt)
356 m->md_int.ps2_data->sbus_smflg |= msk;
357 else
358 m->md_int.ps2_data->sbus_smflg &= ~msk;
359
360 if (m->md_int.ps2_data->sbus_smflg != 0)
361 cpu_interrupt(cpu, 8 + 1);
362 else
363 cpu_interrupt_ack(cpu, 8 + 1);
364 return;
365 }
366
367 if (assrt) {
368 /* OR into the INTR: */
369 if (irq_nr < 16)
370 m->md_int.ps2_data->intr |= (1 << irq_nr);
371 else
372 m->md_int.ps2_data->dmac_reg[0x601] |=
373 (1 << (irq_nr-16));
374 } else {
375 /* AND out of the INTR: */
376 if (irq_nr < 16)
377 m->md_int.ps2_data->intr &= ~(1 << irq_nr);
378 else
379 m->md_int.ps2_data->dmac_reg[0x601] &=
380 ~(1 << (irq_nr-16));
381 }
382
383 /* TODO: Hm? How about the mask? */
384 if (m->md_int.ps2_data->intr /* & m->md_int.ps2_data->imask */ )
385 cpu_interrupt(cpu, 2);
386 else
387 cpu_interrupt_ack(cpu, 2);
388
389 /* TODO: mask? */
390 if (m->md_int.ps2_data->dmac_reg[0x601] & 0xffff)
391 cpu_interrupt(cpu, 3);
392 else
393 cpu_interrupt_ack(cpu, 3);
394 }
395
396
397 /*
398 * SGI "IP22" interrupt routine:
399 */
400 void sgi_ip22_interrupt(struct machine *m, struct cpu *cpu,
401 int irq_nr, int assrt)
402 {
403 /*
404 * SGI-IP22 specific interrupt stuff:
405 *
406 * irq_nr should be 8 + x, where x = 0..31 for local0,
407 * and 32..63 for local1 interrupts.
408 * Add 64*y for "mappable" interrupts, where 1<<y is
409 * the mappable interrupt bitmask. TODO: this misses 64*0 !
410 */
411
412 uint32_t newmask;
413 uint32_t stat, mask;
414
415 irq_nr -= 8;
416 newmask = 1 << (irq_nr & 31);
417
418 if (irq_nr >= 64) {
419 int ms = irq_nr / 64;
420 uint32_t new = 1 << ms;
421 if (assrt)
422 m->md_int.sgi_ip22_data->reg[4] |= new;
423 else
424 m->md_int.sgi_ip22_data->reg[4] &= ~new;
425 /* TODO: is this enough? */
426 irq_nr &= 63;
427 }
428
429 if (irq_nr < 32) {
430 if (assrt)
431 m->md_int.sgi_ip22_data->reg[0] |= newmask;
432 else
433 m->md_int.sgi_ip22_data->reg[0] &= ~newmask;
434 } else {
435 if (assrt)
436 m->md_int.sgi_ip22_data->reg[2] |= newmask;
437 else
438 m->md_int.sgi_ip22_data->reg[2] &= ~newmask;
439 }
440
441 /* Read stat and mask for local0: */
442 stat = m->md_int.sgi_ip22_data->reg[0];
443 mask = m->md_int.sgi_ip22_data->reg[1];
444 if ((stat & mask) == 0)
445 cpu_interrupt_ack(cpu, 2);
446 else
447 cpu_interrupt(cpu, 2);
448
449 /* Read stat and mask for local1: */
450 stat = m->md_int.sgi_ip22_data->reg[2];
451 mask = m->md_int.sgi_ip22_data->reg[3];
452 if ((stat & mask) == 0)
453 cpu_interrupt_ack(cpu, 3);
454 else
455 cpu_interrupt(cpu, 3);
456 }
457
458
459 /*
460 * SGI "IP30" interrupt routine:
461 *
462 * irq_nr = 8 + 1 + nr, where nr is:
463 * 0..49 HEART irqs hardware irq 2,3,4
464 * 50 HEART timer hardware irq 5
465 * 51..63 HEART errors hardware irq 6
466 *
467 * according to Linux/IP30.
468 */
469 void sgi_ip30_interrupt(struct machine *m, struct cpu *cpu,
470 int irq_nr, int assrt)
471 {
472 uint64_t newmask;
473 uint64_t stat, mask;
474
475 irq_nr -= 8;
476 if (irq_nr == 0)
477 goto just_assert_and_such;
478 irq_nr --;
479
480 newmask = (int64_t)1 << irq_nr;
481
482 if (assrt)
483 m->md_int.sgi_ip30_data->isr |= newmask;
484 else
485 m->md_int.sgi_ip30_data->isr &= ~newmask;
486
487 just_assert_and_such:
488
489 cpu_interrupt_ack(cpu, 2);
490 cpu_interrupt_ack(cpu, 3);
491 cpu_interrupt_ack(cpu, 4);
492 cpu_interrupt_ack(cpu, 5);
493 cpu_interrupt_ack(cpu, 6);
494
495 stat = m->md_int.sgi_ip30_data->isr;
496 mask = m->md_int.sgi_ip30_data->imask0;
497
498 if ((stat & mask) & 0x000000000000ffffULL)
499 cpu_interrupt(cpu, 2);
500 if ((stat & mask) & 0x00000000ffff0000ULL)
501 cpu_interrupt(cpu, 3);
502 if ((stat & mask) & 0x0003ffff00000000ULL)
503 cpu_interrupt(cpu, 4);
504 if ((stat & mask) & 0x0004000000000000ULL)
505 cpu_interrupt(cpu, 5);
506 if ((stat & mask) & 0xfff8000000000000ULL)
507 cpu_interrupt(cpu, 6);
508 }
509
510
511 /*
512 * SGI "IP32" interrupt routine:
513 */
514 void sgi_ip32_interrupt(struct machine *m, struct cpu *cpu,
515 int irq_nr, int assrt)
516 {
517 /*
518 * The 64-bit word at crime offset 0x10 is CRIME_INTSTAT,
519 * which contains the current interrupt bits. CRIME_INTMASK
520 * contains a mask of which bits are actually in use.
521 *
522 * crime hardcoded at 0x14000000, for SGI-IP32.
523 * If any of these bits are asserted, then physical MIPS
524 * interrupt 2 should be asserted.
525 *
526 * TODO: how should all this be done nicely?
527 */
528
529 uint64_t crime_addr = CRIME_INTSTAT;
530 uint64_t mace_addr = 0x10;
531 uint64_t crime_interrupts, crime_interrupts_mask;
532 uint64_t mace_interrupts, mace_interrupt_mask;
533 unsigned int i;
534 unsigned char x[8];
535
536 /* Read current MACE interrupt assertions: */
537 memcpy(x, m->md_int.ip32.mace_data->reg + mace_addr,
538 sizeof(uint64_t));
539 mace_interrupts = 0;
540 for (i=0; i<sizeof(uint64_t); i++) {
541 mace_interrupts <<= 8;
542 mace_interrupts |= x[i];
543 }
544
545 /* Read current MACE interrupt mask: */
546 memcpy(x, m->md_int.ip32.mace_data->reg + mace_addr + 8,
547 sizeof(uint64_t));
548 mace_interrupt_mask = 0;
549 for (i=0; i<sizeof(uint64_t); i++) {
550 mace_interrupt_mask <<= 8;
551 mace_interrupt_mask |= x[i];
552 }
553
554 /*
555 * This mapping of both MACE and CRIME interrupts into the same
556 * 'int' is really ugly.
557 *
558 * If MACE_PERIPH_MISC or MACE_PERIPH_SERIAL is set, then mask
559 * that bit out and treat the rest of the word as the mace interrupt
560 * bitmask.
561 *
562 * TODO: fix.
563 */
564 if (irq_nr & MACE_PERIPH_SERIAL) {
565 if (assrt)
566 mace_interrupts |= (irq_nr & ~MACE_PERIPH_SERIAL);
567 else
568 mace_interrupts &= ~(irq_nr & ~MACE_PERIPH_SERIAL);
569
570 irq_nr = MACE_PERIPH_SERIAL;
571 if ((mace_interrupts & mace_interrupt_mask) == 0)
572 assrt = 0;
573 else
574 assrt = 1;
575 }
576
577 /* Hopefully _MISC and _SERIAL will not be both on at the same time. */
578 if (irq_nr & MACE_PERIPH_MISC) {
579 if (assrt)
580 mace_interrupts |= (irq_nr & ~MACE_PERIPH_MISC);
581 else
582 mace_interrupts &= ~(irq_nr & ~MACE_PERIPH_MISC);
583
584 irq_nr = MACE_PERIPH_MISC;
585 if ((mace_interrupts & mace_interrupt_mask) == 0)
586 assrt = 0;
587 else
588 assrt = 1;
589 }
590
591 /* Write back MACE interrupt assertions: */
592 for (i=0; i<sizeof(uint64_t); i++)
593 x[7-i] = mace_interrupts >> (i*8);
594 memcpy(m->md_int.ip32.mace_data->reg + mace_addr, x, sizeof(uint64_t));
595
596 /* Read CRIME_INTSTAT: */
597 memcpy(x, m->md_int.ip32.crime_data->reg + crime_addr,
598 sizeof(uint64_t));
599 crime_interrupts = 0;
600 for (i=0; i<sizeof(uint64_t); i++) {
601 crime_interrupts <<= 8;
602 crime_interrupts |= x[i];
603 }
604
605 if (assrt)
606 crime_interrupts |= irq_nr;
607 else
608 crime_interrupts &= ~irq_nr;
609
610 /* Write back CRIME_INTSTAT: */
611 for (i=0; i<sizeof(uint64_t); i++)
612 x[7-i] = crime_interrupts >> (i*8);
613 memcpy(m->md_int.ip32.crime_data->reg + crime_addr, x,
614 sizeof(uint64_t));
615
616 /* Read CRIME_INTMASK: */
617 memcpy(x, m->md_int.ip32.crime_data->reg + CRIME_INTMASK,
618 sizeof(uint64_t));
619 crime_interrupts_mask = 0;
620 for (i=0; i<sizeof(uint64_t); i++) {
621 crime_interrupts_mask <<= 8;
622 crime_interrupts_mask |= x[i];
623 }
624
625 if ((crime_interrupts & crime_interrupts_mask) == 0)
626 cpu_interrupt_ack(cpu, 2);
627 else
628 cpu_interrupt(cpu, 2);
629
630 /* printf("sgi_crime_machine_irq(%i,%i): new interrupts = 0x%08x\n",
631 assrt, irq_nr, crime_interrupts); */
632 }
633
634
635 /*
636 * Au1x00 interrupt routine:
637 *
638 * TODO: This is just bogus so far. For more info, read this:
639 * http://www.meshcube.org/cgi-bin/viewcvs.cgi/kernel/linux/arch/
640 * mips/au1000/common/
641 *
642 * CPU int 2 = IC 0, request 0
643 * CPU int 3 = IC 0, request 1
644 * CPU int 4 = IC 1, request 0
645 * CPU int 5 = IC 1, request 1
646 *
647 * Interrupts 0..31 are on interrupt controller 0, interrupts 32..63 are
648 * on controller 1.
649 *
650 * Special case: if irq_nr == 64+8, then this just updates the CPU
651 * interrupt assertions.
652 */
653 void au1x00_interrupt(struct machine *m, struct cpu *cpu,
654 int irq_nr, int assrt)
655 {
656 uint32_t ms;
657
658 irq_nr -= 8;
659 debug("au1x00_interrupt(): irq_nr=%i assrt=%i\n", irq_nr, assrt);
660
661 if (irq_nr < 64) {
662 ms = 1 << (irq_nr & 31);
663
664 if (assrt)
665 m->md_int.au1x00_ic_data->request0_int |= ms;
666 else
667 m->md_int.au1x00_ic_data->request0_int &= ~ms;
668
669 /* TODO: Controller 1 */
670 }
671
672 if ((m->md_int.au1x00_ic_data->request0_int &
673 m->md_int.au1x00_ic_data->mask) != 0)
674 cpu_interrupt(cpu, 2);
675 else
676 cpu_interrupt_ack(cpu, 2);
677
678 /* TODO: What _is_ request1? */
679
680 /* TODO: Controller 1 */
681 }
682
683
684 /*
685 * CPC700 interrupt routine:
686 *
687 * irq_nr should be 0..31. (32 means reassertion.)
688 */
689 void cpc700_interrupt(struct machine *m, struct cpu *cpu,
690 int irq_nr, int assrt)
691 {
692 if (irq_nr < 32) {
693 uint32_t mask = 1 << (irq_nr & 31);
694 if (assrt)
695 m->md_int.cpc700_data->sr |= mask;
696 else
697 m->md_int.cpc700_data->sr &= ~mask;
698 }
699
700 if ((m->md_int.cpc700_data->sr & m->md_int.cpc700_data->er) != 0)
701 cpu_interrupt(cpu, 65);
702 else
703 cpu_interrupt_ack(cpu, 65);
704 }
705
706
707 /*
708 * Interrupt function for Cobalt, evbmips (Malta), and Algor.
709 *
710 * (irq_nr = 8 + 16 can be used to just reassert/deassert interrupts.)
711 */
712 void isa8_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
713 {
714 int mask, x;
715 int old_isa_assert, new_isa_assert;
716
717 old_isa_assert = m->isa_pic_data.pic1->irr & ~m->isa_pic_data.pic1->ier;
718
719 irq_nr -= 8;
720 mask = 1 << (irq_nr & 7);
721
722 if (irq_nr < 8) {
723 if (assrt)
724 m->isa_pic_data.pic1->irr |= mask;
725 else
726 m->isa_pic_data.pic1->irr &= ~mask;
727 } else if (irq_nr < 16) {
728 if (assrt)
729 m->isa_pic_data.pic2->irr |= mask;
730 else
731 m->isa_pic_data.pic2->irr &= ~mask;
732 }
733
734 /* Any interrupt assertions on PIC2 go to irq 2 on PIC1 */
735 /* (TODO: don't hardcode this here) */
736 if (m->isa_pic_data.pic2->irr & ~m->isa_pic_data.pic2->ier)
737 m->isa_pic_data.pic1->irr |= 0x04;
738 else
739 m->isa_pic_data.pic1->irr &= ~0x04;
740
741 /* Now, PIC1: */
742 new_isa_assert = m->isa_pic_data.pic1->irr & ~m->isa_pic_data.pic1->ier;
743 if (old_isa_assert != new_isa_assert) {
744 for (x=0; x<16; x++) {
745 if (x == 2)
746 continue;
747 if (x < 8 && (m->isa_pic_data.pic1->irr &
748 ~m->isa_pic_data.pic1->ier & (1 << x)))
749 break;
750 if (x >= 8 && (m->isa_pic_data.pic2->irr &
751 ~m->isa_pic_data.pic2->ier & (1 << (x&7))))
752 break;
753 }
754 m->isa_pic_data.last_int = x;
755 }
756
757 if (m->isa_pic_data.pic1->irr & ~m->isa_pic_data.pic1->ier)
758 cpu_interrupt(cpu, m->isa_pic_data.native_irq);
759 else
760 cpu_interrupt_ack(cpu, m->isa_pic_data.native_irq);
761 }
762
763
764 /*
765 * x86 (PC) interrupts:
766 *
767 * (irq_nr = 16 can be used to just reassert/deassert interrupts.)
768 */
769 void x86_pc_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
770 {
771 int mask = 1 << (irq_nr & 7);
772
773 if (irq_nr < 8) {
774 if (assrt)
775 m->isa_pic_data.pic1->irr |= mask;
776 else
777 m->isa_pic_data.pic1->irr &= ~mask;
778 } else if (irq_nr < 16) {
779 if (m->isa_pic_data.pic2 == NULL) {
780 fatal("x86_pc_interrupt(): pic2 used (irq_nr = %i), "
781 "but we are emulating an XT?\n", irq_nr);
782 return;
783 }
784 if (assrt)
785 m->isa_pic_data.pic2->irr |= mask;
786 else
787 m->isa_pic_data.pic2->irr &= ~mask;
788 }
789
790 if (m->isa_pic_data.pic2 != NULL) {
791 /* Any interrupt assertions on PIC2 go to irq 2 on PIC1 */
792 /* (TODO: don't hardcode this here) */
793 if (m->isa_pic_data.pic2->irr & ~m->isa_pic_data.pic2->ier)
794 m->isa_pic_data.pic1->irr |= 0x04;
795 else
796 m->isa_pic_data.pic1->irr &= ~0x04;
797 }
798
799 /* Now, PIC1: */
800 if (m->isa_pic_data.pic1->irr & ~m->isa_pic_data.pic1->ier)
801 cpu->cd.x86.interrupt_asserted = 1;
802 else
803 cpu->cd.x86.interrupt_asserted = 0;
804 }
805
806
807 /*
808 * "Generic" ISA interrupt management, 32 native interrupts, 16 ISA
809 * interrupts. So far: Footbridge (CATS, NetWinder), BeBox, and PReP.
810 *
811 * 0..31 = footbridge interrupt
812 * 32..47 = ISA interrupts
813 * 48 = ISA reassert
814 * 64 = reassert (non-ISA)
815 */
816 void isa32_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
817 {
818 uint32_t mask = 1 << (irq_nr & 31);
819 int old_isa_assert, new_isa_assert;
820
821 old_isa_assert = m->isa_pic_data.pic1->irr & ~m->isa_pic_data.pic1->ier;
822
823 if (irq_nr >= 32 && irq_nr < 32 + 8) {
824 int mm = 1 << (irq_nr & 7);
825 if (assrt)
826 m->isa_pic_data.pic1->irr |= mm;
827 else
828 m->isa_pic_data.pic1->irr &= ~mm;
829 } else if (irq_nr >= 32+8 && irq_nr < 32+16) {
830 int mm = 1 << (irq_nr & 7);
831 if (assrt)
832 m->isa_pic_data.pic2->irr |= mm;
833 else
834 m->isa_pic_data.pic2->irr &= ~mm;
835 }
836
837 /* Any interrupt assertions on PIC2 go to irq 2 on PIC1 */
838 /* (TODO: don't hardcode this here) */
839 if (m->isa_pic_data.pic2->irr & ~m->isa_pic_data.pic2->ier)
840 m->isa_pic_data.pic1->irr |= 0x04;
841 else
842 m->isa_pic_data.pic1->irr &= ~0x04;
843
844 /* Now, PIC1: */
845 new_isa_assert = m->isa_pic_data.pic1->irr & ~m->isa_pic_data.pic1->ier;
846 if (old_isa_assert != new_isa_assert || irq_nr == 48) {
847 if (new_isa_assert) {
848 int x;
849 for (x=0; x<16; x++) {
850 if (x == 2)
851 continue;
852 if (x < 8 && (m->isa_pic_data.pic1->irr &
853 ~m->isa_pic_data.pic1->ier & (1 << x)))
854 break;
855 if (x >= 8 && (m->isa_pic_data.pic2->irr &
856 ~m->isa_pic_data.pic2->ier & (1 << (x&7))))
857 break;
858 }
859 m->isa_pic_data.last_int = x;
860 cpu_interrupt(cpu, m->isa_pic_data.native_irq);
861 } else
862 cpu_interrupt_ack(cpu, m->isa_pic_data.native_irq);
863 return;
864 }
865
866 switch (m->machine_type) {
867 case MACHINE_CATS:
868 case MACHINE_NETWINDER:
869 if (irq_nr < 32) {
870 if (assrt)
871 m->md_int.footbridge_data->irq_status |= mask;
872 else
873 m->md_int.footbridge_data->irq_status &= ~mask;
874 }
875 if (m->md_int.footbridge_data->irq_status &
876 m->md_int.footbridge_data->irq_enable)
877 cpu_interrupt(cpu, 65);
878 else
879 cpu_interrupt_ack(cpu, 65);
880 break;
881 case MACHINE_BEBOX:
882 if (irq_nr < 32) {
883 if (assrt)
884 m->md_int.bebox_data->int_status |= mask;
885 else
886 m->md_int.bebox_data->int_status &= ~mask;
887 }
888 if (m->md_int.bebox_data->int_status &
889 m->md_int.bebox_data->cpu0_int_mask)
890 cpu_interrupt(m->cpus[0], 65);
891 else
892 cpu_interrupt_ack(m->cpus[0], 65);
893 if (m->ncpus > 1 &&
894 m->md_int.bebox_data->int_status &
895 m->md_int.bebox_data->cpu1_int_mask)
896 cpu_interrupt(m->cpus[1], 65);
897 else
898 cpu_interrupt_ack(m->cpus[1], 65);
899 break;
900 case MACHINE_PREP:
901 case MACHINE_MVMEPPC:
902 if (irq_nr < 32) {
903 if (assrt)
904 m->md_int.prep_data->int_status |= mask;
905 else
906 m->md_int.prep_data->int_status &= ~mask;
907 }
908 if (m->md_int.prep_data->int_status & 2)
909 cpu_interrupt(cpu, 65);
910 else
911 cpu_interrupt_ack(cpu, 65);
912 break;
913 }
914 }
915
916
917 /*
918 * Grand Central interrupt handler.
919 *
920 * (Used by MacPPC.)
921 */
922 void gc_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
923 {
924 uint32_t mask = 1 << (irq_nr & 31);
925 if (irq_nr < 32) {
926 if (assrt)
927 m->md_int.gc_data->status_lo |= mask;
928 else
929 m->md_int.gc_data->status_lo &= ~mask;
930 }
931 if (irq_nr >= 32 && irq_nr < 64) {
932 if (assrt)
933 m->md_int.gc_data->status_hi |= mask;
934 else
935 m->md_int.gc_data->status_hi &= ~mask;
936 }
937
938 #if 1
939 printf("status = %08x %08x enable = %08x %08x\n",
940 m->md_int.gc_data->status_hi, m->md_int.gc_data->status_lo,
941 m->md_int.gc_data->enable_hi, m->md_int.gc_data->enable_lo);
942 #endif
943
944 if (m->md_int.gc_data->status_lo & m->md_int.gc_data->enable_lo ||
945 m->md_int.gc_data->status_hi & m->md_int.gc_data->enable_hi)
946 cpu_interrupt(m->cpus[0], 65);
947 else
948 cpu_interrupt_ack(m->cpus[0], 65);
949 }
950
951
952 /*
953 * i80321 (ARM) Interrupt Controller.
954 *
955 * (Used by the IQ80321 machine.)
956 */
957 void i80321_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
958 {
959 uint32_t mask = 1 << (irq_nr & 31);
960 if (irq_nr < 32) {
961 if (assrt)
962 cpu->cd.arm.i80321_isrc |= mask;
963 else
964 cpu->cd.arm.i80321_isrc &= ~mask;
965 }
966
967 /* debug("isrc = %08x inten = %08x\n",
968 cpu->cd.arm.i80321_isrc, cpu->cd.arm.i80321_inten); */
969
970 if (cpu->cd.arm.i80321_isrc & cpu->cd.arm.i80321_inten)
971 cpu_interrupt(m->cpus[0], 65);
972 else
973 cpu_interrupt_ack(m->cpus[0], 65);
974 }
975

  ViewVC Help
Powered by ViewVC 1.1.26