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 38 * 39 * 5 - unused (?) 40 * [serial errors or special conditions seem to raise level 6 41 * interrupts on some models (LC4xx?)] 42 * 43 * 6 - off switch (?) 44 * 45 * For OSS Macintoshes (IIfx only at this point): 46 * 47 * 3 - Nubus interrupt 48 * - slot 0: Slot $9 49 * - slot 1: Slot $A 50 * - slot 2: Slot $B 51 * - slot 3: Slot $C 52 * - slot 4: Slot $D 53 * - slot 5: Slot $E 54 * 55 * 4 - SCC IOP 56 * 57 * 5 - ISM IOP (ADB?) 58 * 59 * 6 - unused 60 * 61 * For PSC Macintoshes (660AV, 840AV): 62 * 63 * 3 - PSC level 3 64 * - slot 0: MACE 65 * 66 * 4 - PSC level 4 67 * - slot 1: SCC channel A interrupt 68 * - slot 2: SCC channel B interrupt 69 * - slot 3: MACE DMA 70 * 71 * 5 - PSC level 5 72 * 73 * 6 - PSC level 6 74 * 75 * Finally we have good 'ole level 7, the non-maskable interrupt: 76 * 77 * 7 - NMI (programmer's switch on the back of some Macs) 78 * Also RAM parity error on models which support it (IIc, IIfx?) 79 * 80 * The current interrupt logic looks something like this: 81 * 82 * - We install dispatchers for the autovector interrupts (1-7). These 83 * dispatchers are responsible for querying the hardware (the 84 * VIA/RBV/OSS/PSC chips) to determine the actual interrupt source. Using 85 * this information a machspec interrupt number is generated by placing the 86 * index of the interrupt hardware into the low three bits and the original 87 * autovector interrupt number in the upper 5 bits. The handlers for the 88 * resulting machspec interrupt are then called. 89 * 90 * - Nubus is a special case because its interrupts are hidden behind two 91 * layers of hardware. Nubus interrupts come in as index 1 on VIA #2, 92 * which translates to IRQ number 17. In this spot we install _another_ 93 * dispatcher. This dispatcher finds the interrupting slot number (9-F) and 94 * then forms a new machspec interrupt number as above with the slot number 95 * minus 9 in the low three bits and the pseudo-level 7 in the upper five 96 * bits. The handlers for this new machspec interrupt number are then 97 * called. This puts Nubus interrupts into the range 56-62. 98 * 99 * - The Baboon interrupts (used on some PowerBooks) are an even more special 100 * case. They're hidden behind the Nubus slot $C interrupt thus adding a 101 * third layer of indirection. Why oh why did the Apple engineers do that? 102 * 103 * - We support "fast" and "slow" handlers, just like the Amiga port. The 104 * fast handlers are called first and with all interrupts disabled. They 105 * are expected to execute quickly (hence the name). The slow handlers are 106 * called last with interrupts enabled and the interrupt level restored. 107 * They must therefore be reentrant. 108 * 109 * TODO: 110 * 111 */ 112 113 #include <linux/module.h> 114 #include <linux/types.h> 115 #include <linux/kernel.h> 116 #include <linux/sched.h> 117 #include <linux/kernel_stat.h> 118 #include <linux/interrupt.h> /* for intr_count */ 119 #include <linux/delay.h> 120 #include <linux/seq_file.h> 121 122 #include <asm/system.h> 123 #include <asm/irq.h> 124 #include <asm/traps.h> 125 #include <asm/bootinfo.h> 126 #include <asm/macintosh.h> 127 #include <asm/mac_via.h> 128 #include <asm/mac_psc.h> 129 #include <asm/hwtest.h> 130 #include <asm/errno.h> 131 #include <asm/macints.h> 132 #include <asm/irq_regs.h> 133 #include <asm/mac_oss.h> 134 135 #define SHUTUP_SONIC 136 137 /* 138 * VIA/RBV hooks 139 */ 140 141 extern void via_register_interrupts(void); 142 extern void via_irq_enable(int); 143 extern void via_irq_disable(int); 144 extern void via_irq_clear(int); 145 extern int via_irq_pending(int); 146 147 /* 148 * OSS hooks 149 */ 150 151 extern void oss_register_interrupts(void); 152 extern void oss_irq_enable(int); 153 extern void oss_irq_disable(int); 154 extern void oss_irq_clear(int); 155 extern int oss_irq_pending(int); 156 157 /* 158 * PSC hooks 159 */ 160 161 extern void psc_register_interrupts(void); 162 extern void psc_irq_enable(int); 163 extern void psc_irq_disable(int); 164 extern void psc_irq_clear(int); 165 extern int psc_irq_pending(int); 166 167 /* 168 * IOP hooks 169 */ 170 171 extern void iop_register_interrupts(void); 172 173 /* 174 * Baboon hooks 175 */ 176 177 extern int baboon_present; 178 179 extern void baboon_register_interrupts(void); 180 extern void baboon_irq_enable(int); 181 extern void baboon_irq_disable(int); 182 extern void baboon_irq_clear(int); 183 184 /* 185 * console_loglevel determines NMI handler function 186 */ 187 188 irqreturn_t mac_nmi_handler(int, void *); 189 irqreturn_t mac_debug_handler(int, void *); 190 191 /* #define DEBUG_MACINTS */ 192 193 void mac_enable_irq(unsigned int irq); 194 void mac_disable_irq(unsigned int irq); 195 196 static void mac_irq_enable(struct irq_data *data) 197 { 198 mac_enable_irq(data->irq); 199 } 200 201 static void mac_irq_disable(struct irq_data *data) 202 { 203 mac_disable_irq(data->irq); 204 } 205 206 static struct irq_chip mac_irq_chip = { 207 .name = "mac", 208 .irq_enable = mac_irq_enable, 209 .irq_disable = mac_irq_disable, 210 }; 211 212 void __init mac_init_IRQ(void) 213 { 214 #ifdef DEBUG_MACINTS 215 printk("mac_init_IRQ(): Setting things up...\n"); 216 #endif 217 m68k_setup_irq_chip(&mac_irq_chip, IRQ_USER, 218 NUM_MAC_SOURCES - IRQ_USER); 219 /* Make sure the SONIC interrupt is cleared or things get ugly */ 220 #ifdef SHUTUP_SONIC 221 printk("Killing onboard sonic... "); 222 /* This address should hopefully be mapped already */ 223 if (hwreg_present((void*)(0x50f0a000))) { 224 *(long *)(0x50f0a014) = 0x7fffL; 225 *(long *)(0x50f0a010) = 0L; 226 } 227 printk("Done.\n"); 228 #endif /* SHUTUP_SONIC */ 229 230 /* 231 * Now register the handlers for the master IRQ handlers 232 * at levels 1-7. Most of the work is done elsewhere. 233 */ 234 235 if (oss_present) 236 oss_register_interrupts(); 237 else 238 via_register_interrupts(); 239 if (psc_present) 240 psc_register_interrupts(); 241 if (baboon_present) 242 baboon_register_interrupts(); 243 iop_register_interrupts(); 244 if (request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI", 245 mac_nmi_handler)) 246 pr_err("Couldn't register NMI\n"); 247 #ifdef DEBUG_MACINTS 248 printk("mac_init_IRQ(): Done!\n"); 249 #endif 250 } 251 252 /* 253 * mac_enable_irq - enable an interrupt source 254 * mac_disable_irq - disable an interrupt source 255 * mac_clear_irq - clears a pending interrupt 256 * mac_pending_irq - Returns the pending status of an IRQ (nonzero = pending) 257 * 258 * These routines are just dispatchers to the VIA/OSS/PSC routines. 259 */ 260 261 void mac_enable_irq(unsigned int irq) 262 { 263 int irq_src = IRQ_SRC(irq); 264 265 switch(irq_src) { 266 case 1: 267 via_irq_enable(irq); 268 break; 269 case 2: 270 case 7: 271 if (oss_present) 272 oss_irq_enable(irq); 273 else 274 via_irq_enable(irq); 275 break; 276 case 3: 277 case 5: 278 case 6: 279 if (psc_present) 280 psc_irq_enable(irq); 281 else if (oss_present) 282 oss_irq_enable(irq); 283 break; 284 case 4: 285 if (psc_present) 286 psc_irq_enable(irq); 287 break; 288 case 8: 289 if (baboon_present) 290 baboon_irq_enable(irq); 291 break; 292 } 293 } 294 295 void mac_disable_irq(unsigned int irq) 296 { 297 int irq_src = IRQ_SRC(irq); 298 299 switch(irq_src) { 300 case 1: 301 via_irq_disable(irq); 302 break; 303 case 2: 304 case 7: 305 if (oss_present) 306 oss_irq_disable(irq); 307 else 308 via_irq_disable(irq); 309 break; 310 case 3: 311 case 5: 312 case 6: 313 if (psc_present) 314 psc_irq_disable(irq); 315 else if (oss_present) 316 oss_irq_disable(irq); 317 break; 318 case 4: 319 if (psc_present) 320 psc_irq_disable(irq); 321 break; 322 case 8: 323 if (baboon_present) 324 baboon_irq_disable(irq); 325 break; 326 } 327 } 328 329 void mac_clear_irq(unsigned int irq) 330 { 331 switch(IRQ_SRC(irq)) { 332 case 1: 333 via_irq_clear(irq); 334 break; 335 case 2: 336 case 7: 337 if (oss_present) 338 oss_irq_clear(irq); 339 else 340 via_irq_clear(irq); 341 break; 342 case 3: 343 case 5: 344 case 6: 345 if (psc_present) 346 psc_irq_clear(irq); 347 else if (oss_present) 348 oss_irq_clear(irq); 349 break; 350 case 4: 351 if (psc_present) 352 psc_irq_clear(irq); 353 break; 354 case 8: 355 if (baboon_present) 356 baboon_irq_clear(irq); 357 break; 358 } 359 } 360 361 int mac_irq_pending(unsigned int irq) 362 { 363 switch(IRQ_SRC(irq)) { 364 case 1: 365 return via_irq_pending(irq); 366 case 2: 367 case 7: 368 if (oss_present) 369 return oss_irq_pending(irq); 370 else 371 return via_irq_pending(irq); 372 case 3: 373 case 5: 374 case 6: 375 if (psc_present) 376 return psc_irq_pending(irq); 377 else if (oss_present) 378 return oss_irq_pending(irq); 379 break; 380 case 4: 381 if (psc_present) 382 return psc_irq_pending(irq); 383 break; 384 } 385 return 0; 386 } 387 EXPORT_SYMBOL(mac_irq_pending); 388 389 static int num_debug[8]; 390 391 irqreturn_t mac_debug_handler(int irq, void *dev_id) 392 { 393 if (num_debug[irq] < 10) { 394 printk("DEBUG: Unexpected IRQ %d\n", irq); 395 num_debug[irq]++; 396 } 397 return IRQ_HANDLED; 398 } 399 400 static int in_nmi; 401 static volatile int nmi_hold; 402 403 irqreturn_t mac_nmi_handler(int irq, void *dev_id) 404 { 405 int i; 406 /* 407 * generate debug output on NMI switch if 'debug' kernel option given 408 * (only works with Penguin!) 409 */ 410 411 in_nmi++; 412 for (i=0; i<100; i++) 413 udelay(1000); 414 415 if (in_nmi == 1) { 416 nmi_hold = 1; 417 printk("... pausing, press NMI to resume ..."); 418 } else { 419 printk(" ok!\n"); 420 nmi_hold = 0; 421 } 422 423 barrier(); 424 425 while (nmi_hold == 1) 426 udelay(1000); 427 428 if (console_loglevel >= 8) { 429 #if 0 430 struct pt_regs *fp = get_irq_regs(); 431 show_state(); 432 printk("PC: %08lx\nSR: %04x SP: %p\n", fp->pc, fp->sr, fp); 433 printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", 434 fp->d0, fp->d1, fp->d2, fp->d3); 435 printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", 436 fp->d4, fp->d5, fp->a0, fp->a1); 437 438 if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page) 439 printk("Corrupted stack page\n"); 440 printk("Process %s (pid: %d, stackpage=%08lx)\n", 441 current->comm, current->pid, current->kernel_stack_page); 442 if (intr_count == 1) 443 dump_stack((struct frame *)fp); 444 #else 445 /* printk("NMI "); */ 446 #endif 447 } 448 in_nmi--; 449 return IRQ_HANDLED; 450 } 451