/[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 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 25115 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26