/[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 32 - (show annotations)
Mon Oct 8 16:20:58 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 26216 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1421 2006/11/06 05:32:37 debug Exp $
20060816	Adding a framework for emulated/virtual timers (src/timer.c),
		using only setitimer().
		Rewriting the mc146818 to use the new timer framework.
20060817	Adding a call to gettimeofday() every now and then (once every
		second, at the moment) to resynch the timer if it drifts.
		Beginning to convert the ISA timer interrupt mechanism (8253
		and 8259) to use the new timer framework.
		Removing the -I command line option.
20060819	Adding the -I command line option again, with new semantics.
		Working on Footbridge timer interrupts; NetBSD/NetWinder and
		NetBSD/CATS now run at correct speed, but unfortunately with
		HUGE delays during bootup.
20060821	Some minor m68k updates. Adding the first instruction: nop. :)
		Minor Alpha emulation updates.
20060822	Adding a FreeBSD development specific YAMON environment
		variable ("khz") (as suggested by Bruce M. Simpson).
		Moving YAMON environment variable initialization from
		machine_evbmips.c into promemul/yamon.c, and adding some more
		variables.
		Continuing on the LCA PCI bus controller (for Alpha machines).
20060823	Continuing on the timer stuff: experimenting with MIPS count/
		compare interrupts connected to the timer framework.
20060825	Adding bogus SCSI commands 0x51 (SCSICDROM_READ_DISCINFO) and
		0x52 (SCSICDROM_READ_TRACKINFO) to the SCSI emulation layer,
		to allow NetBSD/pmax 4.0_BETA to be installed from CDROM.
		Minor updates to the LCA PCI controller.
20060827	Implementing a CHIP8 cpu mode, and a corresponding CHIP8
		machine, for fun. Disassembly support for all instructions,
		and most of the common instructions have been implemented: mvi,
		mov_imm, add_imm, jmp, rand, cls, sprite, skeq_imm, jsr,
		skne_imm, bcd, rts, ldr, str, mov, or, and, xor, add, sub,
		font, ssound, sdelay, gdelay, bogus skup/skpr, skeq, skne.
20060828	Beginning to convert the CHIP8 cpu in the CHIP8 machine to a
		(more correct) RCA 180x cpu. (Disassembly for all 1802
		instructions has been implemented, but no execution yet, and
		no 1805 extended instructions.)
20060829	Minor Alpha emulation updates.
20060830	Beginning to experiment a little with PCI IDE for SGI O2.
		Fixing the cursor key mappings for MobilePro 770 emulation.
		Fixing the LK201 warning caused by recent NetBSD/pmax.
		The MIPS R41xx standby, suspend, and hibernate instructions now
		behave like the RM52xx/MIPS32/MIPS64 wait instruction.
		Fixing dev_wdc so it calculates correct (64-bit) offsets before
		giving them to diskimage_access().
20060831	Continuing on Alpha emulation (OSF1 PALcode).
20060901	Minor Alpha updates; beginning on virtual memory pagetables.
		Removed the limit for max nr of devices (in preparation for
		allowing devices' base addresses to be changed during runtime).
		Adding a hack for MIPS [d]mfc0 select 0 (except the count
		register), so that the coproc register is simply copied.
		The MIPS suspend instruction now exits the emulator, instead
		of being treated as a wait instruction (this causes NetBSD/
		hpcmips to get correct 'halt' behavior).
		The VR41xx RTC now returns correct time.
		Connecting the VR41xx timer to the timer framework (fixed at
		128 Hz, for now).
		Continuing on SPARC emulation, adding more instructions:
		restore, ba_xcc, ble. The rectangle drawing demo works :)
		Removing the last traces of the old ENABLE_CACHE_EMULATION
		MIPS stuff (not usable with dyntrans anyway).
20060902	Splitting up src/net.c into several smaller files in its own
		subdirectory (src/net/).
20060903	Cleanup of the files in src/net/, to make them less ugly.
20060904	Continuing on the 'settings' subsystem.
		Minor progress on the SPARC emulation mode.
20060905	Cleanup of various things, and connecting the settings
		infrastructure to various subsystems (emul, machine, cpu, etc).
		Changing the lk201 mouse update routine to not rely on any
		emulated hardware framebuffer cursor coordinates, but instead
		always do (semi-usable) relative movements.
20060906	Continuing on the lk201 mouse stuff. Mouse behaviour with
		multiple framebuffers (which was working in Ultrix) is now
		semi-broken (but it still works, in a way).
		Moving the documentation about networking into its own file
		(networking.html), and refreshing it a bit. Adding an example
		of how to use ethernet frame direct-access (udp_snoop).
20060907	Continuing on the settings infrastructure.
20060908	Minor updates to SH emulation: for 32-bit emulation: delay
		slots and the 'jsr @Rn' instruction. I'm putting 64-bit SH5 on
		ice, for now.
20060909-10	Implementing some more 32-bit SH instructions. Removing the
		64-bit mode completely. Enough has now been implemented to run
		the rectangle drawing demo. :-)
20060912	Adding more SH instructions.
20060916	Continuing on SH emulation (some more instructions: div0u,
		div1, rotcl/rotcr, more mov instructions, dt, braf, sets, sett,
		tst_imm, dmuls.l, subc, ldc_rm_vbr, movt, clrt, clrs, clrmac).
		Continuing on the settings subsystem (beginning on reading/
		writing settings, removing bugs, and connecting more cpus to
		the framework).
20060919	More work on SH emulation; adding an ldc banked instruction,
		and attaching a 640x480 framebuffer to the Dreamcast machine
		mode (NetBSD/dreamcast prints the NetBSD copyright banner :-),
		and then panics).
20060920	Continuing on the settings subsystem.
20060921	Fixing the Footbridge timer stuff so that NetBSD/cats and
		NetBSD/netwinder boot up without the delays.
20060922	Temporarily hardcoding MIPS timer interrupt to 100 Hz. With
		'wait' support disabled, NetBSD/malta and Linux/malta run at
		correct speed.
20060923	Connecting dev_gt to the timer framework, so that NetBSD/cobalt
		runs at correct speed.
		Moving SH4-specific memory mapped registers into its own
		device (dev_sh4.c).
		Running with -N now prints "idling" instead of bogus nr of
		instrs/second (which isn't valid anyway) while idling.
20060924	Algor emulation should now run at correct speed.
		Adding disassembly support for some MIPS64 revision 2
		instructions: ext, dext, dextm, dextu.
20060926	The timer framework now works also when the MIPS wait
		instruction is used.
20060928	Re-implementing checks for coprocessor availability for MIPS
		cop0 instructions. (Thanks to Carl van Schaik for noticing the
		lack of cop0 availability checks.)
20060929	Implementing an instruction combination hack which treats
		NetBSD/pmax' idle loop as a wait-like instruction.
20060930	The ENTRYHI_R_MASK was missing in (at least) memory_mips_v2p.c,
		causing TLB lookups to sometimes succeed when they should have
		failed. (A big thank you to Juli Mallett for noticing the
		problem.)
		Adding disassembly support for more MIPS64 revision 2 opcodes
		(seb, seh, wsbh, jalr.hb, jr.hb, synci, ins, dins, dinsu,
		dinsm, dsbh, dshd, ror, dror, rorv, drorv, dror32). Also
		implementing seb, seh, dsbh, dshd, and wsbh.
		Implementing an instruction combination hack for Linux/pmax'
		idle loop, similar to the NetBSD/pmax case.
20061001	Changing the NetBSD/sgimips install instructions to extract
		files from an iso image, instead of downloading them via ftp.
20061002	More-than-31-bit userland addresses in memory_mips_v2p.c were
		not actually working; applying a fix from Carl van Schaik to
		enable them to work + making some other updates (adding kuseg
		support).
		Fixing hpcmips (vr41xx) timer initialization.
		Experimenting with O(n)->O(1) reduction in the MIPS TLB lookup
		loop. Seems to work both for R3000 and non-R3000.
20061003	Continuing a little on SH emulation (adding more control
		registers; mini-cleanup of memory_sh.c).
20061004	Beginning on a dev_rtc, a clock/timer device for the test
		machines; also adding a demo, and some documentation.
		Fixing a bug in SH "mov.w @(disp,pc),Rn" (the result wasn't
		sign-extended), and adding the addc and ldtlb instructions.
20061005	Contining on SH emulation: virtual to physical address
		translation, and a skeleton exception mechanism.
20061006	Adding more SH instructions (various loads and stores, rte,
		negc, muls.w, various privileged register-move instructions).
20061007	More SH instructions: various move instructions, trapa, div0s,
		float, fdiv, ftrc.
		Continuing on dev_rtc; removing the rtc demo.
20061008	Adding a dummy Dreamcast PROM module. (Homebrew Dreamcast
		programs using KOS libs need this.)
		Adding more SH instructions: "stc vbr,rn", rotl, rotr, fsca,
		fmul, fadd, various floating-point moves, etc. A 256-byte
		demo for Dreamcast runs :-)
20061012	Adding the SH "lds Rm,pr" and bsr instructions.
20061013	More SH instructions: "sts fpscr,rn", tas.b, and some more
		floating point instructions, cmp/str, and more moves.
		Adding a dummy dev_pvr (Dreamcast graphics controller).
20061014	Generalizing the expression evaluator (used in the built-in
		debugger) to support parentheses and +-*/%^&|.
20061015	Removing the experimental tlb index hint code in
		mips_memory_v2p.c, since it didn't really have any effect.
20061017	Minor SH updates; adding the "sts pr,Rn", fcmp/gt, fneg,
		frchg, and some other instructions. Fixing missing sign-
		extension in an 8-bit load instruction.
20061019	Adding a simple dev_dreamcast_rtc.
		Implementing memory-mapped access to the SH ITLB/UTLB arrays.
20061021	Continuing on various SH and Dreamcast things: sh4 timers,
		debug messages for dev_pvr, fixing some virtual address
		translation bugs, adding the bsrf instruction.
		The NetBSD/dreamcast GENERIC_MD kernel now reaches userland :)
		Adding a dummy dev_dreamcast_asic.c (not really useful yet).
		Implementing simple support for Store Queues.
		Beginning on the PVR Tile Accelerator.
20061022	Generalizing the PVR framebuffer to support off-screen drawing,
		multiple bit-depths, etc. (A small speed penalty, but most
		likely worth it.)
		Adding more SH instructions (mulu.w, fcmp/eq, fsub, fmac,
		fschg, and some more); correcting bugs in "fsca" and "float".
20061024	Adding the SH ftrv (matrix * vector) instruction. Marcus
		Comstedt's "tatest" example runs :) (wireframe only).
		Correcting disassembly for SH floating point instructions that
		use the xd* registers.
		Adding the SH fsts instruction.
		In memory_device_dyntrans_access(), only the currently used
		range is now invalidated, and not the entire device range.
20061025	Adding a dummy AVR32 cpu mode skeleton.
20061026	Various Dreamcast updates; beginning on a Maple bus controller.
20061027	Continuing on the Maple bus. A bogus Controller, Keyboard, and
		Mouse can now be detected by NetBSD and KOS homebrew programs.
		Cleaning up the SH4 Timer Management Unit, and beginning on
		SH4 interrupts.
		Implementing the Dreamcast SYSASIC.
20061028	Continuing on the SYSASIC.
		Adding the SH fsqrt instruction.
		memory_sh.c now actually scans the ITLB.
		Fixing a bug in dev_sh4.c, related to associative writes into
		the memory-mapped UTLB array. NetBSD/dreamcast now reaches
		userland stably, and prints the "Terminal type?" message :-]
		Implementing enough of the Dreamcast keyboard to make NetBSD
		accept it for input.
		Enabling SuperH for stable (non-development) builds.
		Adding NetBSD/dreamcast to the documentation, although it
		doesn't support root-on-nfs yet.
20061029	Changing usleep(1) calls in the debugger to to usleep(10000)
		(according to Brian Foley, this makes GXemul run better on
		MacOS X).
		Making the Maple "Controller" do something (enough to barely
		interact with dcircus.elf).
20061030-31	Some progress on the PVR. More test programs start running (but
		with strange output).
		Various other SH4-related updates.
20061102	Various Dreamcast and SH4 updates; more KOS demos run now.
20061104	Adding a skeleton dev_mb8696x.c (the Dreamcast's LAN adapter).
20061105	Continuing on the MB8696x; NetBSD/dreamcast detects it as mbe0.
		Testing for the release.

==============  RELEASE 0.4.3  ==============


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.11 2006/08/17 16:49:22 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), Algor, and QEMU_MIPS.
709 *
710 * Most machines will not use secondary_mask1 and native_secondary_irq.
711 * Algor, however, routes COM1 and COM2 interrupts to MIPS CPU interrupt 4
712 * (called "secondary" here), and IDE interrupts to CPU interrupt 2.
713 *
714 * (irq_nr = 8 + 16 can be used to just reassert/deassert interrupts.)
715 */
716 void isa8_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
717 {
718 int mask, x;
719 int old_isa_assert, new_isa_assert;
720 uint8_t old_irr1 = m->isa_pic_data.pic1->irr;
721 old_isa_assert = old_irr1 & ~m->isa_pic_data.pic1->ier;
722
723 irq_nr -= 8;
724 mask = 1 << (irq_nr & 7);
725
726 if (irq_nr < 8) {
727 if (assrt)
728 m->isa_pic_data.pic1->irr |= mask;
729 else
730 m->isa_pic_data.pic1->irr &= ~mask;
731 } else if (irq_nr < 16) {
732 if (assrt)
733 m->isa_pic_data.pic2->irr |= mask;
734 else
735 m->isa_pic_data.pic2->irr &= ~mask;
736 }
737
738 /*
739 * If bit 0 in the IRR has been cleared, then we need to acknowledge
740 * a 8253 timer interrupt.
741 */
742 if (old_irr1 & 1 && !(m->isa_pic_data.pic1->irr & 1) &&
743 m->isa_pic_data.pending_timer_interrupts != NULL &&
744 (*m->isa_pic_data.pending_timer_interrupts) > 0)
745 (*m->isa_pic_data.pending_timer_interrupts) --;
746
747 /* Any interrupt assertions on PIC2 go to irq 2 on PIC1 */
748 /* (TODO: don't hardcode this here) */
749 if (m->isa_pic_data.pic2->irr & ~m->isa_pic_data.pic2->ier)
750 m->isa_pic_data.pic1->irr |= 0x04;
751 else
752 m->isa_pic_data.pic1->irr &= ~0x04;
753
754 /* Now, PIC1: */
755 new_isa_assert = m->isa_pic_data.pic1->irr & ~m->isa_pic_data.pic1->ier;
756 if (old_isa_assert != new_isa_assert) {
757 for (x=0; x<16; x++) {
758 if (x == 2)
759 continue;
760 if (x < 8 && (m->isa_pic_data.pic1->irr &
761 ~m->isa_pic_data.pic1->ier & (1 << x)))
762 break;
763 if (x >= 8 && (m->isa_pic_data.pic2->irr &
764 ~m->isa_pic_data.pic2->ier & (1 << (x&7))))
765 break;
766 }
767 m->isa_pic_data.last_int = x;
768 }
769
770 if (m->isa_pic_data.secondary_mask1 &
771 m->isa_pic_data.pic1->irr & ~m->isa_pic_data.pic1->ier)
772 cpu_interrupt(cpu, m->isa_pic_data.native_secondary_irq);
773 else
774 cpu_interrupt_ack(cpu, m->isa_pic_data.native_secondary_irq);
775
776 if (~m->isa_pic_data.secondary_mask1 &
777 m->isa_pic_data.pic1->irr & ~m->isa_pic_data.pic1->ier)
778 cpu_interrupt(cpu, m->isa_pic_data.native_irq);
779 else
780 cpu_interrupt_ack(cpu, m->isa_pic_data.native_irq);
781 }
782
783
784 /*
785 * x86 (PC) interrupts:
786 *
787 * (irq_nr = 16 can be used to just reassert/deassert interrupts.)
788 */
789 void x86_pc_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
790 {
791 uint8_t old_irr1 = m->isa_pic_data.pic1->irr;
792 int mask = 1 << (irq_nr & 7);
793
794 if (irq_nr < 8) {
795 if (assrt)
796 m->isa_pic_data.pic1->irr |= mask;
797 else
798 m->isa_pic_data.pic1->irr &= ~mask;
799 } else if (irq_nr < 16) {
800 if (m->isa_pic_data.pic2 == NULL) {
801 fatal("x86_pc_interrupt(): pic2 used (irq_nr = %i), "
802 "but we are emulating an XT?\n", irq_nr);
803 return;
804 }
805 if (assrt)
806 m->isa_pic_data.pic2->irr |= mask;
807 else
808 m->isa_pic_data.pic2->irr &= ~mask;
809 }
810
811 /*
812 * If bit 0 in the IRR has been cleared, then we need to acknowledge
813 * a 8253 timer interrupt.
814 */
815 if (old_irr1 & 1 && !(m->isa_pic_data.pic1->irr & 1) &&
816 m->isa_pic_data.pending_timer_interrupts != NULL &&
817 (*m->isa_pic_data.pending_timer_interrupts) > 0)
818 (*m->isa_pic_data.pending_timer_interrupts) --;
819
820 if (m->isa_pic_data.pic2 != NULL) {
821 /* Any interrupt assertions on PIC2 go to irq 2 on PIC1 */
822 /* (TODO: don't hardcode this here) */
823 if (m->isa_pic_data.pic2->irr & ~m->isa_pic_data.pic2->ier)
824 m->isa_pic_data.pic1->irr |= 0x04;
825 else
826 m->isa_pic_data.pic1->irr &= ~0x04;
827 }
828
829 /* Now, PIC1: */
830 if (m->isa_pic_data.pic1->irr & ~m->isa_pic_data.pic1->ier)
831 cpu->cd.x86.interrupt_asserted = 1;
832 else
833 cpu->cd.x86.interrupt_asserted = 0;
834 }
835
836
837 /*
838 * "Generic" ISA interrupt management, 32 native interrupts, 16 ISA
839 * interrupts. So far: Footbridge (CATS, NetWinder), BeBox, and PReP.
840 *
841 * 0..31 = footbridge interrupt
842 * 32..47 = ISA interrupts
843 * 48 = ISA reassert
844 * 64 = reassert (non-ISA)
845 */
846 void isa32_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
847 {
848 uint32_t mask = 1 << (irq_nr & 31);
849 int old_isa_assert, new_isa_assert;
850 uint8_t old_irr1 = m->isa_pic_data.pic1->irr;
851
852 old_isa_assert = old_irr1 & ~m->isa_pic_data.pic1->ier;
853
854 if (irq_nr >= 32 && irq_nr < 32 + 8) {
855 int mm = 1 << (irq_nr & 7);
856 if (assrt)
857 m->isa_pic_data.pic1->irr |= mm;
858 else
859 m->isa_pic_data.pic1->irr &= ~mm;
860 } else if (irq_nr >= 32+8 && irq_nr < 32+16) {
861 int mm = 1 << (irq_nr & 7);
862 if (assrt)
863 m->isa_pic_data.pic2->irr |= mm;
864 else
865 m->isa_pic_data.pic2->irr &= ~mm;
866 }
867
868 /*
869 * If bit 0 in the IRR has been cleared, then we need to acknowledge
870 * a 8253 timer interrupt.
871 */
872 if (old_irr1 & 1 && !(m->isa_pic_data.pic1->irr & 1) &&
873 m->isa_pic_data.pending_timer_interrupts != NULL &&
874 (*m->isa_pic_data.pending_timer_interrupts) > 0)
875 (*m->isa_pic_data.pending_timer_interrupts) --;
876
877 /* Any interrupt assertions on PIC2 go to irq 2 on PIC1 */
878 /* (TODO: don't hardcode this here) */
879 if (m->isa_pic_data.pic2->irr & ~m->isa_pic_data.pic2->ier)
880 m->isa_pic_data.pic1->irr |= 0x04;
881 else
882 m->isa_pic_data.pic1->irr &= ~0x04;
883
884 /* Now, PIC1: */
885 new_isa_assert = m->isa_pic_data.pic1->irr & ~m->isa_pic_data.pic1->ier;
886 if (old_isa_assert != new_isa_assert || irq_nr == 48) {
887 if (new_isa_assert) {
888 int x;
889 for (x=0; x<16; x++) {
890 if (x == 2)
891 continue;
892 if (x < 8 && (m->isa_pic_data.pic1->irr &
893 ~m->isa_pic_data.pic1->ier & (1 << x)))
894 break;
895 if (x >= 8 && (m->isa_pic_data.pic2->irr &
896 ~m->isa_pic_data.pic2->ier & (1 << (x&7))))
897 break;
898 }
899 m->isa_pic_data.last_int = x;
900 cpu_interrupt(cpu, m->isa_pic_data.native_irq);
901 } else
902 cpu_interrupt_ack(cpu, m->isa_pic_data.native_irq);
903 return;
904 }
905
906 switch (m->machine_type) {
907 case MACHINE_CATS:
908 case MACHINE_NETWINDER:
909 if (irq_nr < 32) {
910 if (assrt)
911 m->md_int.footbridge_data->irq_status |= mask;
912 else
913 m->md_int.footbridge_data->irq_status &= ~mask;
914 }
915 if (m->md_int.footbridge_data->irq_status &
916 m->md_int.footbridge_data->irq_enable)
917 cpu_interrupt(cpu, 65);
918 else
919 cpu_interrupt_ack(cpu, 65);
920 break;
921 case MACHINE_BEBOX:
922 if (irq_nr < 32) {
923 if (assrt)
924 m->md_int.bebox_data->int_status |= mask;
925 else
926 m->md_int.bebox_data->int_status &= ~mask;
927 }
928 if (m->md_int.bebox_data->int_status &
929 m->md_int.bebox_data->cpu0_int_mask)
930 cpu_interrupt(m->cpus[0], 65);
931 else
932 cpu_interrupt_ack(m->cpus[0], 65);
933 if (m->ncpus > 1 &&
934 m->md_int.bebox_data->int_status &
935 m->md_int.bebox_data->cpu1_int_mask)
936 cpu_interrupt(m->cpus[1], 65);
937 else
938 cpu_interrupt_ack(m->cpus[1], 65);
939 break;
940 case MACHINE_PREP:
941 case MACHINE_MVMEPPC:
942 if (irq_nr < 32) {
943 if (assrt)
944 m->md_int.prep_data->int_status |= mask;
945 else
946 m->md_int.prep_data->int_status &= ~mask;
947 }
948 if (m->md_int.prep_data->int_status & 2)
949 cpu_interrupt(cpu, 65);
950 else
951 cpu_interrupt_ack(cpu, 65);
952 break;
953 }
954 }
955
956
957 /*
958 * Grand Central interrupt handler.
959 *
960 * (Used by MacPPC.)
961 */
962 void gc_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
963 {
964 uint32_t mask = 1 << (irq_nr & 31);
965 if (irq_nr < 32) {
966 if (assrt)
967 m->md_int.gc_data->status_lo |= mask;
968 else
969 m->md_int.gc_data->status_lo &= ~mask;
970 }
971 if (irq_nr >= 32 && irq_nr < 64) {
972 if (assrt)
973 m->md_int.gc_data->status_hi |= mask;
974 else
975 m->md_int.gc_data->status_hi &= ~mask;
976 }
977
978 #if 0
979 printf("status = %08x %08x enable = %08x %08x\n",
980 m->md_int.gc_data->status_hi, m->md_int.gc_data->status_lo,
981 m->md_int.gc_data->enable_hi, m->md_int.gc_data->enable_lo);
982 #endif
983
984 if (m->md_int.gc_data->status_lo & m->md_int.gc_data->enable_lo ||
985 m->md_int.gc_data->status_hi & m->md_int.gc_data->enable_hi)
986 cpu_interrupt(m->cpus[0], 65);
987 else
988 cpu_interrupt_ack(m->cpus[0], 65);
989 }
990
991
992 /*
993 * i80321 (ARM) Interrupt Controller.
994 *
995 * (Used by the IQ80321 machine.)
996 */
997 void i80321_interrupt(struct machine *m, struct cpu *cpu, int irq_nr, int assrt)
998 {
999 uint32_t mask = 1 << (irq_nr & 31);
1000 if (irq_nr < 32) {
1001 if (assrt)
1002 cpu->cd.arm.i80321_isrc |= mask;
1003 else
1004 cpu->cd.arm.i80321_isrc &= ~mask;
1005 }
1006
1007 /* fatal("isrc = %08x inten = %08x\n",
1008 cpu->cd.arm.i80321_isrc, cpu->cd.arm.i80321_inten); */
1009
1010 if (cpu->cd.arm.i80321_isrc & cpu->cd.arm.i80321_inten)
1011 cpu_interrupt(m->cpus[0], 65);
1012 else
1013 cpu_interrupt_ack(m->cpus[0], 65);
1014 }
1015

  ViewVC Help
Powered by ViewVC 1.1.26