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/module.h> 118 #include <linux/types.h> 119 #include <linux/kernel.h> 120 #include <linux/sched.h> 121 #include <linux/kernel_stat.h> 122 #include <linux/interrupt.h> /* for intr_count */ 123 #include <linux/delay.h> 124 #include <linux/seq_file.h> 125 126 #include <asm/system.h> 127 #include <asm/irq.h> 128 #include <asm/traps.h> 129 #include <asm/bootinfo.h> 130 #include <asm/machw.h> 131 #include <asm/macintosh.h> 132 #include <asm/mac_via.h> 133 #include <asm/mac_psc.h> 134 #include <asm/hwtest.h> 135 #include <asm/errno.h> 136 #include <asm/macints.h> 137 #include <asm/irq_regs.h> 138 139 #define DEBUG_SPURIOUS 140 #define SHUTUP_SONIC 141 142 /* SCC interrupt mask */ 143 144 static int scc_mask; 145 146 /* 147 * VIA/RBV hooks 148 */ 149 150 extern void via_init(void); 151 extern void via_register_interrupts(void); 152 extern void via_irq_enable(int); 153 extern void via_irq_disable(int); 154 extern void via_irq_clear(int); 155 extern int via_irq_pending(int); 156 157 /* 158 * OSS hooks 159 */ 160 161 extern int oss_present; 162 163 extern void oss_init(void); 164 extern void oss_register_interrupts(void); 165 extern void oss_irq_enable(int); 166 extern void oss_irq_disable(int); 167 extern void oss_irq_clear(int); 168 extern int oss_irq_pending(int); 169 170 /* 171 * PSC hooks 172 */ 173 174 extern int psc_present; 175 176 extern void psc_init(void); 177 extern void psc_register_interrupts(void); 178 extern void psc_irq_enable(int); 179 extern void psc_irq_disable(int); 180 extern void psc_irq_clear(int); 181 extern int psc_irq_pending(int); 182 183 /* 184 * IOP hooks 185 */ 186 187 extern void iop_register_interrupts(void); 188 189 /* 190 * Baboon hooks 191 */ 192 193 extern int baboon_present; 194 195 extern void baboon_init(void); 196 extern void baboon_register_interrupts(void); 197 extern void baboon_irq_enable(int); 198 extern void baboon_irq_disable(int); 199 extern void baboon_irq_clear(int); 200 extern int baboon_irq_pending(int); 201 202 /* 203 * SCC interrupt routines 204 */ 205 206 static void scc_irq_enable(unsigned int); 207 static void scc_irq_disable(unsigned int); 208 209 /* 210 * console_loglevel determines NMI handler function 211 */ 212 213 irqreturn_t mac_nmi_handler(int, void *); 214 irqreturn_t mac_debug_handler(int, void *); 215 216 /* #define DEBUG_MACINTS */ 217 218 static void mac_enable_irq(unsigned int irq); 219 static void mac_disable_irq(unsigned int irq); 220 221 static struct irq_controller mac_irq_controller = { 222 .name = "mac", 223 .lock = __SPIN_LOCK_UNLOCKED(mac_irq_controller.lock), 224 .enable = mac_enable_irq, 225 .disable = mac_disable_irq, 226 }; 227 228 void __init mac_init_IRQ(void) 229 { 230 #ifdef DEBUG_MACINTS 231 printk("mac_init_IRQ(): Setting things up...\n"); 232 #endif 233 scc_mask = 0; 234 235 m68k_setup_irq_controller(&mac_irq_controller, IRQ_USER, 236 NUM_MAC_SOURCES - IRQ_USER); 237 /* Make sure the SONIC interrupt is cleared or things get ugly */ 238 #ifdef SHUTUP_SONIC 239 printk("Killing onboard sonic... "); 240 /* This address should hopefully be mapped already */ 241 if (hwreg_present((void*)(0x50f0a000))) { 242 *(long *)(0x50f0a014) = 0x7fffL; 243 *(long *)(0x50f0a010) = 0L; 244 } 245 printk("Done.\n"); 246 #endif /* SHUTUP_SONIC */ 247 248 /* 249 * Now register the handlers for the master IRQ handlers 250 * at levels 1-7. Most of the work is done elsewhere. 251 */ 252 253 if (oss_present) 254 oss_register_interrupts(); 255 else 256 via_register_interrupts(); 257 if (psc_present) 258 psc_register_interrupts(); 259 if (baboon_present) 260 baboon_register_interrupts(); 261 iop_register_interrupts(); 262 request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI", 263 mac_nmi_handler); 264 #ifdef DEBUG_MACINTS 265 printk("mac_init_IRQ(): Done!\n"); 266 #endif 267 } 268 269 /* 270 * mac_enable_irq - enable an interrupt source 271 * mac_disable_irq - disable an interrupt source 272 * mac_clear_irq - clears a pending interrupt 273 * mac_pending_irq - Returns the pending status of an IRQ (nonzero = pending) 274 * 275 * These routines are just dispatchers to the VIA/OSS/PSC routines. 276 */ 277 278 static void mac_enable_irq(unsigned int irq) 279 { 280 int irq_src = IRQ_SRC(irq); 281 282 switch(irq_src) { 283 case 1: 284 via_irq_enable(irq); 285 break; 286 case 2: 287 case 7: 288 if (oss_present) 289 oss_irq_enable(irq); 290 else 291 via_irq_enable(irq); 292 break; 293 case 3: 294 case 4: 295 case 5: 296 case 6: 297 if (psc_present) 298 psc_irq_enable(irq); 299 else if (oss_present) 300 oss_irq_enable(irq); 301 else if (irq_src == 4) 302 scc_irq_enable(irq); 303 break; 304 case 8: 305 if (baboon_present) 306 baboon_irq_enable(irq); 307 break; 308 } 309 } 310 311 static void mac_disable_irq(unsigned int irq) 312 { 313 int irq_src = IRQ_SRC(irq); 314 315 switch(irq_src) { 316 case 1: 317 via_irq_disable(irq); 318 break; 319 case 2: 320 case 7: 321 if (oss_present) 322 oss_irq_disable(irq); 323 else 324 via_irq_disable(irq); 325 break; 326 case 3: 327 case 4: 328 case 5: 329 case 6: 330 if (psc_present) 331 psc_irq_disable(irq); 332 else if (oss_present) 333 oss_irq_disable(irq); 334 else if (irq_src == 4) 335 scc_irq_disable(irq); 336 break; 337 case 8: 338 if (baboon_present) 339 baboon_irq_disable(irq); 340 break; 341 } 342 } 343 344 void mac_clear_irq(unsigned int irq) 345 { 346 switch(IRQ_SRC(irq)) { 347 case 1: 348 via_irq_clear(irq); 349 break; 350 case 2: 351 case 7: 352 if (oss_present) 353 oss_irq_clear(irq); 354 else 355 via_irq_clear(irq); 356 break; 357 case 3: 358 case 4: 359 case 5: 360 case 6: 361 if (psc_present) 362 psc_irq_clear(irq); 363 else if (oss_present) 364 oss_irq_clear(irq); 365 break; 366 case 8: 367 if (baboon_present) 368 baboon_irq_clear(irq); 369 break; 370 } 371 } 372 373 int mac_irq_pending(unsigned int irq) 374 { 375 switch(IRQ_SRC(irq)) { 376 case 1: 377 return via_irq_pending(irq); 378 case 2: 379 case 7: 380 if (oss_present) 381 return oss_irq_pending(irq); 382 else 383 return via_irq_pending(irq); 384 case 3: 385 case 4: 386 case 5: 387 case 6: 388 if (psc_present) 389 return psc_irq_pending(irq); 390 else if (oss_present) 391 return oss_irq_pending(irq); 392 } 393 return 0; 394 } 395 EXPORT_SYMBOL(mac_irq_pending); 396 397 static int num_debug[8]; 398 399 irqreturn_t mac_debug_handler(int irq, void *dev_id) 400 { 401 if (num_debug[irq] < 10) { 402 printk("DEBUG: Unexpected IRQ %d\n", irq); 403 num_debug[irq]++; 404 } 405 return IRQ_HANDLED; 406 } 407 408 static int in_nmi; 409 static volatile int nmi_hold; 410 411 irqreturn_t mac_nmi_handler(int irq, void *dev_id) 412 { 413 int i; 414 /* 415 * generate debug output on NMI switch if 'debug' kernel option given 416 * (only works with Penguin!) 417 */ 418 419 in_nmi++; 420 for (i=0; i<100; i++) 421 udelay(1000); 422 423 if (in_nmi == 1) { 424 nmi_hold = 1; 425 printk("... pausing, press NMI to resume ..."); 426 } else { 427 printk(" ok!\n"); 428 nmi_hold = 0; 429 } 430 431 barrier(); 432 433 while (nmi_hold == 1) 434 udelay(1000); 435 436 if (console_loglevel >= 8) { 437 #if 0 438 struct pt_regs *fp = get_irq_regs(); 439 show_state(); 440 printk("PC: %08lx\nSR: %04x SP: %p\n", fp->pc, fp->sr, fp); 441 printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", 442 fp->d0, fp->d1, fp->d2, fp->d3); 443 printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", 444 fp->d4, fp->d5, fp->a0, fp->a1); 445 446 if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page) 447 printk("Corrupted stack page\n"); 448 printk("Process %s (pid: %d, stackpage=%08lx)\n", 449 current->comm, current->pid, current->kernel_stack_page); 450 if (intr_count == 1) 451 dump_stack((struct frame *)fp); 452 #else 453 /* printk("NMI "); */ 454 #endif 455 } 456 in_nmi--; 457 return IRQ_HANDLED; 458 } 459 460 /* 461 * Simple routines for masking and unmasking 462 * SCC interrupts in cases where this can't be 463 * done in hardware (only the PSC can do that.) 464 */ 465 466 static void scc_irq_enable(unsigned int irq) 467 { 468 int irq_idx = IRQ_IDX(irq); 469 470 scc_mask |= (1 << irq_idx); 471 } 472 473 static void scc_irq_disable(unsigned int irq) 474 { 475 int irq_idx = IRQ_IDX(irq); 476 477 scc_mask &= ~(1 << irq_idx); 478 } 479 480 /* 481 * SCC master interrupt handler. We have to do a bit of magic here 482 * to figure out what channel gave us the interrupt; putting this 483 * here is cleaner than hacking it into drivers/char/macserial.c. 484 */ 485 486 void mac_scc_dispatch(int irq, void *dev_id) 487 { 488 volatile unsigned char *scc = (unsigned char *) mac_bi_data.sccbase + 2; 489 unsigned char reg; 490 unsigned long flags; 491 492 /* Read RR3 from the chip. Always do this on channel A */ 493 /* This must be an atomic operation so disable irqs. */ 494 495 local_irq_save(flags); 496 *scc = 3; 497 reg = *scc; 498 local_irq_restore(flags); 499 500 /* Now dispatch. Bits 0-2 are for channel B and */ 501 /* bits 3-5 are for channel A. We can safely */ 502 /* ignore the remaining bits here. */ 503 /* */ 504 /* Note that we're ignoring scc_mask for now. */ 505 /* If we actually mask the ints then we tend to */ 506 /* get hammered by very persistent SCC irqs, */ 507 /* and since they're autovector interrupts they */ 508 /* pretty much kill the system. */ 509 510 if (reg & 0x38) 511 m68k_handle_int(IRQ_SCCA); 512 if (reg & 0x07) 513 m68k_handle_int(IRQ_SCCB); 514 } 515