1 /* 2 * Macintosh interrupts 3 * 4 * General design: 5 * In contrary to the Amiga and Atari platforms, the Mac hardware seems to 6 * exclusively use the autovector interrupts (the 'generic level0-level7' 7 * interrupts with exception vectors 0x19-0x1f). The following interrupt levels 8 * are used: 9 * 1 - VIA1 10 * - slot 0: one second interrupt (CA2) 11 * - slot 1: VBlank (CA1) 12 * - slot 2: ADB data ready (SR full) 13 * - slot 3: ADB data (CB2) 14 * - slot 4: ADB clock (CB1) 15 * - slot 5: timer 2 16 * - slot 6: timer 1 17 * - slot 7: status of IRQ; signals 'any enabled int.' 18 * 19 * 2 - VIA2 or RBV 20 * - slot 0: SCSI DRQ (CA2) 21 * - slot 1: NUBUS IRQ (CA1) need to read port A to find which 22 * - slot 2: /EXP IRQ (only on IIci) 23 * - slot 3: SCSI IRQ (CB2) 24 * - slot 4: ASC IRQ (CB1) 25 * - slot 5: timer 2 (not on IIci) 26 * - slot 6: timer 1 (not on IIci) 27 * - slot 7: status of IRQ; signals 'any enabled int.' 28 * 29 * 2 - OSS (IIfx only?) 30 * - slot 0: SCSI interrupt 31 * - slot 1: Sound interrupt 32 * 33 * Levels 3-6 vary by machine type. For VIA or RBV Macintoshes: 34 * 35 * 3 - unused (?) 36 * 37 * 4 - SCC (slot number determined by reading RR3 on the SSC itself) 38 * - slot 1: SCC channel A 39 * - slot 2: SCC channel B 40 * 41 * 5 - unused (?) 42 * [serial errors or special conditions seem to raise level 6 43 * interrupts on some models (LC4xx?)] 44 * 45 * 6 - off switch (?) 46 * 47 * For OSS Macintoshes (IIfx only at this point): 48 * 49 * 3 - Nubus interrupt 50 * - slot 0: Slot $9 51 * - slot 1: Slot $A 52 * - slot 2: Slot $B 53 * - slot 3: Slot $C 54 * - slot 4: Slot $D 55 * - slot 5: Slot $E 56 * 57 * 4 - SCC IOP 58 * - slot 1: SCC channel A 59 * - slot 2: SCC channel B 60 * 61 * 5 - ISM IOP (ADB?) 62 * 63 * 6 - unused 64 * 65 * For PSC Macintoshes (660AV, 840AV): 66 * 67 * 3 - PSC level 3 68 * - slot 0: MACE 69 * 70 * 4 - PSC level 4 71 * - slot 1: SCC channel A interrupt 72 * - slot 2: SCC channel B interrupt 73 * - slot 3: MACE DMA 74 * 75 * 5 - PSC level 5 76 * 77 * 6 - PSC level 6 78 * 79 * Finally we have good 'ole level 7, the non-maskable interrupt: 80 * 81 * 7 - NMI (programmer's switch on the back of some Macs) 82 * Also RAM parity error on models which support it (IIc, IIfx?) 83 * 84 * The current interrupt logic looks something like this: 85 * 86 * - We install dispatchers for the autovector interrupts (1-7). These 87 * dispatchers are responsible for querying the hardware (the 88 * VIA/RBV/OSS/PSC chips) to determine the actual interrupt source. Using 89 * this information a machspec interrupt number is generated by placing the 90 * index of the interrupt hardware into the low three bits and the original 91 * autovector interrupt number in the upper 5 bits. The handlers for the 92 * resulting machspec interrupt are then called. 93 * 94 * - Nubus is a special case because its interrupts are hidden behind two 95 * layers of hardware. Nubus interrupts come in as index 1 on VIA #2, 96 * which translates to IRQ number 17. In this spot we install _another_ 97 * dispatcher. This dispatcher finds the interrupting slot number (9-F) and 98 * then forms a new machspec interrupt number as above with the slot number 99 * minus 9 in the low three bits and the pseudo-level 7 in the upper five 100 * bits. The handlers for this new machspec interrupt number are then 101 * called. This puts Nubus interrupts into the range 56-62. 102 * 103 * - The Baboon interrupts (used on some PowerBooks) are an even more special 104 * case. They're hidden behind the Nubus slot $C interrupt thus adding a 105 * third layer of indirection. Why oh why did the Apple engineers do that? 106 * 107 * - We support "fast" and "slow" handlers, just like the Amiga port. The 108 * fast handlers are called first and with all interrupts disabled. They 109 * are expected to execute quickly (hence the name). The slow handlers are 110 * called last with interrupts enabled and the interrupt level restored. 111 * They must therefore be reentrant. 112 * 113 * TODO: 114 * 115 */ 116 117 #include <linux/types.h> 118 #include <linux/kernel.h> 119 #include <linux/sched.h> 120 #include <linux/kernel_stat.h> 121 #include <linux/interrupt.h> /* for intr_count */ 122 #include <linux/delay.h> 123 #include <linux/seq_file.h> 124 125 #include <asm/system.h> 126 #include <asm/irq.h> 127 #include <asm/traps.h> 128 #include <asm/bootinfo.h> 129 #include <asm/machw.h> 130 #include <asm/macintosh.h> 131 #include <asm/mac_via.h> 132 #include <asm/mac_psc.h> 133 #include <asm/hwtest.h> 134 #include <asm/errno.h> 135 #include <asm/macints.h> 136 137 #define DEBUG_SPURIOUS 138 #define SHUTUP_SONIC 139 140 /* SCC interrupt mask */ 141 142 static int scc_mask; 143 144 /* 145 * VIA/RBV hooks 146 */ 147 148 extern void via_init(void); 149 extern void via_register_interrupts(void); 150 extern void via_irq_enable(int); 151 extern void via_irq_disable(int); 152 extern void via_irq_clear(int); 153 extern int via_irq_pending(int); 154 155 /* 156 * OSS hooks 157 */ 158 159 extern int oss_present; 160 161 extern void oss_init(void); 162 extern void oss_register_interrupts(void); 163 extern void oss_irq_enable(int); 164 extern void oss_irq_disable(int); 165 extern void oss_irq_clear(int); 166 extern int oss_irq_pending(int); 167 168 /* 169 * PSC hooks 170 */ 171 172 extern int psc_present; 173 174 extern void psc_init(void); 175 extern void psc_register_interrupts(void); 176 extern void psc_irq_enable(int); 177 extern void psc_irq_disable(int); 178 extern void psc_irq_clear(int); 179 extern int psc_irq_pending(int); 180 181 /* 182 * IOP hooks 183 */ 184 185 extern void iop_register_interrupts(void); 186 187 /* 188 * Baboon hooks 189 */ 190 191 extern int baboon_present; 192 193 extern void baboon_init(void); 194 extern void baboon_register_interrupts(void); 195 extern void baboon_irq_enable(int); 196 extern void baboon_irq_disable(int); 197 extern void baboon_irq_clear(int); 198 extern int baboon_irq_pending(int); 199 200 /* 201 * SCC interrupt routines 202 */ 203 204 static void scc_irq_enable(unsigned int); 205 static void scc_irq_disable(unsigned int); 206 207 /* 208 * console_loglevel determines NMI handler function 209 */ 210 211 irqreturn_t mac_nmi_handler(int, void *, struct pt_regs *); 212 irqreturn_t mac_debug_handler(int, void *, struct pt_regs *); 213 214 /* #define DEBUG_MACINTS */ 215 216 static void mac_enable_irq(unsigned int irq); 217 static void mac_disable_irq(unsigned int irq); 218 219 static struct irq_controller mac_irq_controller = { 220 .name = "mac", 221 .lock = SPIN_LOCK_UNLOCKED, 222 .enable = mac_enable_irq, 223 .disable = mac_disable_irq, 224 }; 225 226 void mac_init_IRQ(void) 227 { 228 #ifdef DEBUG_MACINTS 229 printk("mac_init_IRQ(): Setting things up...\n"); 230 #endif 231 scc_mask = 0; 232 233 m68k_setup_irq_controller(&mac_irq_controller, IRQ_USER, 234 NUM_MAC_SOURCES - IRQ_USER); 235 /* Make sure the SONIC interrupt is cleared or things get ugly */ 236 #ifdef SHUTUP_SONIC 237 printk("Killing onboard sonic... "); 238 /* This address should hopefully be mapped already */ 239 if (hwreg_present((void*)(0x50f0a000))) { 240 *(long *)(0x50f0a014) = 0x7fffL; 241 *(long *)(0x50f0a010) = 0L; 242 } 243 printk("Done.\n"); 244 #endif /* SHUTUP_SONIC */ 245 246 /* 247 * Now register the handlers for the master IRQ handlers 248 * at levels 1-7. Most of the work is done elsewhere. 249 */ 250 251 if (oss_present) 252 oss_register_interrupts(); 253 else 254 via_register_interrupts(); 255 if (psc_present) 256 psc_register_interrupts(); 257 if (baboon_present) 258 baboon_register_interrupts(); 259 iop_register_interrupts(); 260 request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI", 261 mac_nmi_handler); 262 #ifdef DEBUG_MACINTS 263 printk("mac_init_IRQ(): Done!\n"); 264 #endif 265 } 266 267 /* 268 * mac_enable_irq - enable an interrupt source 269 * mac_disable_irq - disable an interrupt source 270 * mac_clear_irq - clears a pending interrupt 271 * mac_pending_irq - Returns the pending status of an IRQ (nonzero = pending) 272 * 273 * These routines are just dispatchers to the VIA/OSS/PSC routines. 274 */ 275 276 static void mac_enable_irq(unsigned int irq) 277 { 278 int irq_src = IRQ_SRC(irq); 279 280 switch(irq_src) { 281 case 1: 282 via_irq_enable(irq); 283 break; 284 case 2: 285 case 7: 286 if (oss_present) 287 oss_irq_enable(irq); 288 else 289 via_irq_enable(irq); 290 break; 291 case 3: 292 case 4: 293 case 5: 294 case 6: 295 if (psc_present) 296 psc_irq_enable(irq); 297 else if (oss_present) 298 oss_irq_enable(irq); 299 else if (irq_src == 4) 300 scc_irq_enable(irq); 301 break; 302 case 8: 303 if (baboon_present) 304 baboon_irq_enable(irq); 305 break; 306 } 307 } 308 309 static void mac_disable_irq(unsigned int irq) 310 { 311 int irq_src = IRQ_SRC(irq); 312 313 switch(irq_src) { 314 case 1: 315 via_irq_disable(irq); 316 break; 317 case 2: 318 case 7: 319 if (oss_present) 320 oss_irq_disable(irq); 321 else 322 via_irq_disable(irq); 323 break; 324 case 3: 325 case 4: 326 case 5: 327 case 6: 328 if (psc_present) 329 psc_irq_disable(irq); 330 else if (oss_present) 331 oss_irq_disable(irq); 332 else if (irq_src == 4) 333 scc_irq_disable(irq); 334 break; 335 case 8: 336 if (baboon_present) 337 baboon_irq_disable(irq); 338 break; 339 } 340 } 341 342 void mac_clear_irq(unsigned int irq) 343 { 344 switch(IRQ_SRC(irq)) { 345 case 1: 346 via_irq_clear(irq); 347 break; 348 case 2: 349 case 7: 350 if (oss_present) 351 oss_irq_clear(irq); 352 else 353 via_irq_clear(irq); 354 break; 355 case 3: 356 case 4: 357 case 5: 358 case 6: 359 if (psc_present) 360 psc_irq_clear(irq); 361 else if (oss_present) 362 oss_irq_clear(irq); 363 break; 364 case 8: 365 if (baboon_present) 366 baboon_irq_clear(irq); 367 break; 368 } 369 } 370 371 int mac_irq_pending(unsigned int irq) 372 { 373 switch(IRQ_SRC(irq)) { 374 case 1: 375 return via_irq_pending(irq); 376 case 2: 377 case 7: 378 if (oss_present) 379 return oss_irq_pending(irq); 380 else 381 return via_irq_pending(irq); 382 case 3: 383 case 4: 384 case 5: 385 case 6: 386 if (psc_present) 387 return psc_irq_pending(irq); 388 else if (oss_present) 389 return oss_irq_pending(irq); 390 } 391 return 0; 392 } 393 394 static int num_debug[8]; 395 396 irqreturn_t mac_debug_handler(int irq, void *dev_id, struct pt_regs *regs) 397 { 398 if (num_debug[irq] < 10) { 399 printk("DEBUG: Unexpected IRQ %d\n", irq); 400 num_debug[irq]++; 401 } 402 return IRQ_HANDLED; 403 } 404 405 static int in_nmi; 406 static volatile int nmi_hold; 407 408 irqreturn_t mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp) 409 { 410 int i; 411 /* 412 * generate debug output on NMI switch if 'debug' kernel option given 413 * (only works with Penguin!) 414 */ 415 416 in_nmi++; 417 for (i=0; i<100; i++) 418 udelay(1000); 419 420 if (in_nmi == 1) { 421 nmi_hold = 1; 422 printk("... pausing, press NMI to resume ..."); 423 } else { 424 printk(" ok!\n"); 425 nmi_hold = 0; 426 } 427 428 barrier(); 429 430 while (nmi_hold == 1) 431 udelay(1000); 432 433 if (console_loglevel >= 8) { 434 #if 0 435 show_state(); 436 printk("PC: %08lx\nSR: %04x SP: %p\n", fp->pc, fp->sr, fp); 437 printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", 438 fp->d0, fp->d1, fp->d2, fp->d3); 439 printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", 440 fp->d4, fp->d5, fp->a0, fp->a1); 441 442 if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page) 443 printk("Corrupted stack page\n"); 444 printk("Process %s (pid: %d, stackpage=%08lx)\n", 445 current->comm, current->pid, current->kernel_stack_page); 446 if (intr_count == 1) 447 dump_stack((struct frame *)fp); 448 #else 449 /* printk("NMI "); */ 450 #endif 451 } 452 in_nmi--; 453 return IRQ_HANDLED; 454 } 455 456 /* 457 * Simple routines for masking and unmasking 458 * SCC interrupts in cases where this can't be 459 * done in hardware (only the PSC can do that.) 460 */ 461 462 static void scc_irq_enable(unsigned int irq) 463 { 464 int irq_idx = IRQ_IDX(irq); 465 466 scc_mask |= (1 << irq_idx); 467 } 468 469 static void scc_irq_disable(unsigned int irq) 470 { 471 int irq_idx = IRQ_IDX(irq); 472 473 scc_mask &= ~(1 << irq_idx); 474 } 475 476 /* 477 * SCC master interrupt handler. We have to do a bit of magic here 478 * to figure out what channel gave us the interrupt; putting this 479 * here is cleaner than hacking it into drivers/char/macserial.c. 480 */ 481 482 void mac_scc_dispatch(int irq, void *dev_id, struct pt_regs *regs) 483 { 484 volatile unsigned char *scc = (unsigned char *) mac_bi_data.sccbase + 2; 485 unsigned char reg; 486 unsigned long flags; 487 488 /* Read RR3 from the chip. Always do this on channel A */ 489 /* This must be an atomic operation so disable irqs. */ 490 491 local_irq_save(flags); 492 *scc = 3; 493 reg = *scc; 494 local_irq_restore(flags); 495 496 /* Now dispatch. Bits 0-2 are for channel B and */ 497 /* bits 3-5 are for channel A. We can safely */ 498 /* ignore the remaining bits here. */ 499 /* */ 500 /* Note that we're ignoring scc_mask for now. */ 501 /* If we actually mask the ints then we tend to */ 502 /* get hammered by very persistent SCC irqs, */ 503 /* and since they're autovector interrupts they */ 504 /* pretty much kill the system. */ 505 506 if (reg & 0x38) 507 m68k_handle_int(IRQ_SCCA, regs); 508 if (reg & 0x07) 509 m68k_handle_int(IRQ_SCCB, regs); 510 } 511