1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * Macintosh interrupts 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * General design: 5*1da177e4SLinus Torvalds * In contrary to the Amiga and Atari platforms, the Mac hardware seems to 6*1da177e4SLinus Torvalds * exclusively use the autovector interrupts (the 'generic level0-level7' 7*1da177e4SLinus Torvalds * interrupts with exception vectors 0x19-0x1f). The following interrupt levels 8*1da177e4SLinus Torvalds * are used: 9*1da177e4SLinus Torvalds * 1 - VIA1 10*1da177e4SLinus Torvalds * - slot 0: one second interrupt (CA2) 11*1da177e4SLinus Torvalds * - slot 1: VBlank (CA1) 12*1da177e4SLinus Torvalds * - slot 2: ADB data ready (SR full) 13*1da177e4SLinus Torvalds * - slot 3: ADB data (CB2) 14*1da177e4SLinus Torvalds * - slot 4: ADB clock (CB1) 15*1da177e4SLinus Torvalds * - slot 5: timer 2 16*1da177e4SLinus Torvalds * - slot 6: timer 1 17*1da177e4SLinus Torvalds * - slot 7: status of IRQ; signals 'any enabled int.' 18*1da177e4SLinus Torvalds * 19*1da177e4SLinus Torvalds * 2 - VIA2 or RBV 20*1da177e4SLinus Torvalds * - slot 0: SCSI DRQ (CA2) 21*1da177e4SLinus Torvalds * - slot 1: NUBUS IRQ (CA1) need to read port A to find which 22*1da177e4SLinus Torvalds * - slot 2: /EXP IRQ (only on IIci) 23*1da177e4SLinus Torvalds * - slot 3: SCSI IRQ (CB2) 24*1da177e4SLinus Torvalds * - slot 4: ASC IRQ (CB1) 25*1da177e4SLinus Torvalds * - slot 5: timer 2 (not on IIci) 26*1da177e4SLinus Torvalds * - slot 6: timer 1 (not on IIci) 27*1da177e4SLinus Torvalds * - slot 7: status of IRQ; signals 'any enabled int.' 28*1da177e4SLinus Torvalds * 29*1da177e4SLinus Torvalds * 2 - OSS (IIfx only?) 30*1da177e4SLinus Torvalds * - slot 0: SCSI interrupt 31*1da177e4SLinus Torvalds * - slot 1: Sound interrupt 32*1da177e4SLinus Torvalds * 33*1da177e4SLinus Torvalds * Levels 3-6 vary by machine type. For VIA or RBV Macintoshes: 34*1da177e4SLinus Torvalds * 35*1da177e4SLinus Torvalds * 3 - unused (?) 36*1da177e4SLinus Torvalds * 37*1da177e4SLinus Torvalds * 4 - SCC (slot number determined by reading RR3 on the SSC itself) 38*1da177e4SLinus Torvalds * - slot 1: SCC channel A 39*1da177e4SLinus Torvalds * - slot 2: SCC channel B 40*1da177e4SLinus Torvalds * 41*1da177e4SLinus Torvalds * 5 - unused (?) 42*1da177e4SLinus Torvalds * [serial errors or special conditions seem to raise level 6 43*1da177e4SLinus Torvalds * interrupts on some models (LC4xx?)] 44*1da177e4SLinus Torvalds * 45*1da177e4SLinus Torvalds * 6 - off switch (?) 46*1da177e4SLinus Torvalds * 47*1da177e4SLinus Torvalds * For OSS Macintoshes (IIfx only at this point): 48*1da177e4SLinus Torvalds * 49*1da177e4SLinus Torvalds * 3 - Nubus interrupt 50*1da177e4SLinus Torvalds * - slot 0: Slot $9 51*1da177e4SLinus Torvalds * - slot 1: Slot $A 52*1da177e4SLinus Torvalds * - slot 2: Slot $B 53*1da177e4SLinus Torvalds * - slot 3: Slot $C 54*1da177e4SLinus Torvalds * - slot 4: Slot $D 55*1da177e4SLinus Torvalds * - slot 5: Slot $E 56*1da177e4SLinus Torvalds * 57*1da177e4SLinus Torvalds * 4 - SCC IOP 58*1da177e4SLinus Torvalds * - slot 1: SCC channel A 59*1da177e4SLinus Torvalds * - slot 2: SCC channel B 60*1da177e4SLinus Torvalds * 61*1da177e4SLinus Torvalds * 5 - ISM IOP (ADB?) 62*1da177e4SLinus Torvalds * 63*1da177e4SLinus Torvalds * 6 - unused 64*1da177e4SLinus Torvalds * 65*1da177e4SLinus Torvalds * For PSC Macintoshes (660AV, 840AV): 66*1da177e4SLinus Torvalds * 67*1da177e4SLinus Torvalds * 3 - PSC level 3 68*1da177e4SLinus Torvalds * - slot 0: MACE 69*1da177e4SLinus Torvalds * 70*1da177e4SLinus Torvalds * 4 - PSC level 4 71*1da177e4SLinus Torvalds * - slot 1: SCC channel A interrupt 72*1da177e4SLinus Torvalds * - slot 2: SCC channel B interrupt 73*1da177e4SLinus Torvalds * - slot 3: MACE DMA 74*1da177e4SLinus Torvalds * 75*1da177e4SLinus Torvalds * 5 - PSC level 5 76*1da177e4SLinus Torvalds * 77*1da177e4SLinus Torvalds * 6 - PSC level 6 78*1da177e4SLinus Torvalds * 79*1da177e4SLinus Torvalds * Finally we have good 'ole level 7, the non-maskable interrupt: 80*1da177e4SLinus Torvalds * 81*1da177e4SLinus Torvalds * 7 - NMI (programmer's switch on the back of some Macs) 82*1da177e4SLinus Torvalds * Also RAM parity error on models which support it (IIc, IIfx?) 83*1da177e4SLinus Torvalds * 84*1da177e4SLinus Torvalds * The current interrupt logic looks something like this: 85*1da177e4SLinus Torvalds * 86*1da177e4SLinus Torvalds * - We install dispatchers for the autovector interrupts (1-7). These 87*1da177e4SLinus Torvalds * dispatchers are responsible for querying the hardware (the 88*1da177e4SLinus Torvalds * VIA/RBV/OSS/PSC chips) to determine the actual interrupt source. Using 89*1da177e4SLinus Torvalds * this information a machspec interrupt number is generated by placing the 90*1da177e4SLinus Torvalds * index of the interrupt hardware into the low three bits and the original 91*1da177e4SLinus Torvalds * autovector interrupt number in the upper 5 bits. The handlers for the 92*1da177e4SLinus Torvalds * resulting machspec interrupt are then called. 93*1da177e4SLinus Torvalds * 94*1da177e4SLinus Torvalds * - Nubus is a special case because its interrupts are hidden behind two 95*1da177e4SLinus Torvalds * layers of hardware. Nubus interrupts come in as index 1 on VIA #2, 96*1da177e4SLinus Torvalds * which translates to IRQ number 17. In this spot we install _another_ 97*1da177e4SLinus Torvalds * dispatcher. This dispatcher finds the interrupting slot number (9-F) and 98*1da177e4SLinus Torvalds * then forms a new machspec interrupt number as above with the slot number 99*1da177e4SLinus Torvalds * minus 9 in the low three bits and the pseudo-level 7 in the upper five 100*1da177e4SLinus Torvalds * bits. The handlers for this new machspec interrupt number are then 101*1da177e4SLinus Torvalds * called. This puts Nubus interrupts into the range 56-62. 102*1da177e4SLinus Torvalds * 103*1da177e4SLinus Torvalds * - The Baboon interrupts (used on some PowerBooks) are an even more special 104*1da177e4SLinus Torvalds * case. They're hidden behind the Nubus slot $C interrupt thus adding a 105*1da177e4SLinus Torvalds * third layer of indirection. Why oh why did the Apple engineers do that? 106*1da177e4SLinus Torvalds * 107*1da177e4SLinus Torvalds * - We support "fast" and "slow" handlers, just like the Amiga port. The 108*1da177e4SLinus Torvalds * fast handlers are called first and with all interrupts disabled. They 109*1da177e4SLinus Torvalds * are expected to execute quickly (hence the name). The slow handlers are 110*1da177e4SLinus Torvalds * called last with interrupts enabled and the interrupt level restored. 111*1da177e4SLinus Torvalds * They must therefore be reentrant. 112*1da177e4SLinus Torvalds * 113*1da177e4SLinus Torvalds * TODO: 114*1da177e4SLinus Torvalds * 115*1da177e4SLinus Torvalds */ 116*1da177e4SLinus Torvalds 117*1da177e4SLinus Torvalds #include <linux/types.h> 118*1da177e4SLinus Torvalds #include <linux/kernel.h> 119*1da177e4SLinus Torvalds #include <linux/sched.h> 120*1da177e4SLinus Torvalds #include <linux/kernel_stat.h> 121*1da177e4SLinus Torvalds #include <linux/interrupt.h> /* for intr_count */ 122*1da177e4SLinus Torvalds #include <linux/delay.h> 123*1da177e4SLinus Torvalds #include <linux/seq_file.h> 124*1da177e4SLinus Torvalds 125*1da177e4SLinus Torvalds #include <asm/system.h> 126*1da177e4SLinus Torvalds #include <asm/irq.h> 127*1da177e4SLinus Torvalds #include <asm/traps.h> 128*1da177e4SLinus Torvalds #include <asm/bootinfo.h> 129*1da177e4SLinus Torvalds #include <asm/machw.h> 130*1da177e4SLinus Torvalds #include <asm/macintosh.h> 131*1da177e4SLinus Torvalds #include <asm/mac_via.h> 132*1da177e4SLinus Torvalds #include <asm/mac_psc.h> 133*1da177e4SLinus Torvalds #include <asm/hwtest.h> 134*1da177e4SLinus Torvalds #include <asm/errno.h> 135*1da177e4SLinus Torvalds #include <asm/macints.h> 136*1da177e4SLinus Torvalds 137*1da177e4SLinus Torvalds #define DEBUG_SPURIOUS 138*1da177e4SLinus Torvalds #define SHUTUP_SONIC 139*1da177e4SLinus Torvalds 140*1da177e4SLinus Torvalds /* 141*1da177e4SLinus Torvalds * The mac_irq_list array is an array of linked lists of irq_node_t nodes. 142*1da177e4SLinus Torvalds * Each node contains one handler to be called whenever the interrupt 143*1da177e4SLinus Torvalds * occurs, with fast handlers listed before slow handlers. 144*1da177e4SLinus Torvalds */ 145*1da177e4SLinus Torvalds 146*1da177e4SLinus Torvalds irq_node_t *mac_irq_list[NUM_MAC_SOURCES]; 147*1da177e4SLinus Torvalds 148*1da177e4SLinus Torvalds /* SCC interrupt mask */ 149*1da177e4SLinus Torvalds 150*1da177e4SLinus Torvalds static int scc_mask; 151*1da177e4SLinus Torvalds 152*1da177e4SLinus Torvalds /* 153*1da177e4SLinus Torvalds * VIA/RBV hooks 154*1da177e4SLinus Torvalds */ 155*1da177e4SLinus Torvalds 156*1da177e4SLinus Torvalds extern void via_init(void); 157*1da177e4SLinus Torvalds extern void via_register_interrupts(void); 158*1da177e4SLinus Torvalds extern void via_irq_enable(int); 159*1da177e4SLinus Torvalds extern void via_irq_disable(int); 160*1da177e4SLinus Torvalds extern void via_irq_clear(int); 161*1da177e4SLinus Torvalds extern int via_irq_pending(int); 162*1da177e4SLinus Torvalds 163*1da177e4SLinus Torvalds /* 164*1da177e4SLinus Torvalds * OSS hooks 165*1da177e4SLinus Torvalds */ 166*1da177e4SLinus Torvalds 167*1da177e4SLinus Torvalds extern int oss_present; 168*1da177e4SLinus Torvalds 169*1da177e4SLinus Torvalds extern void oss_init(void); 170*1da177e4SLinus Torvalds extern void oss_register_interrupts(void); 171*1da177e4SLinus Torvalds extern void oss_irq_enable(int); 172*1da177e4SLinus Torvalds extern void oss_irq_disable(int); 173*1da177e4SLinus Torvalds extern void oss_irq_clear(int); 174*1da177e4SLinus Torvalds extern int oss_irq_pending(int); 175*1da177e4SLinus Torvalds 176*1da177e4SLinus Torvalds /* 177*1da177e4SLinus Torvalds * PSC hooks 178*1da177e4SLinus Torvalds */ 179*1da177e4SLinus Torvalds 180*1da177e4SLinus Torvalds extern int psc_present; 181*1da177e4SLinus Torvalds 182*1da177e4SLinus Torvalds extern void psc_init(void); 183*1da177e4SLinus Torvalds extern void psc_register_interrupts(void); 184*1da177e4SLinus Torvalds extern void psc_irq_enable(int); 185*1da177e4SLinus Torvalds extern void psc_irq_disable(int); 186*1da177e4SLinus Torvalds extern void psc_irq_clear(int); 187*1da177e4SLinus Torvalds extern int psc_irq_pending(int); 188*1da177e4SLinus Torvalds 189*1da177e4SLinus Torvalds /* 190*1da177e4SLinus Torvalds * IOP hooks 191*1da177e4SLinus Torvalds */ 192*1da177e4SLinus Torvalds 193*1da177e4SLinus Torvalds extern void iop_register_interrupts(void); 194*1da177e4SLinus Torvalds 195*1da177e4SLinus Torvalds /* 196*1da177e4SLinus Torvalds * Baboon hooks 197*1da177e4SLinus Torvalds */ 198*1da177e4SLinus Torvalds 199*1da177e4SLinus Torvalds extern int baboon_present; 200*1da177e4SLinus Torvalds 201*1da177e4SLinus Torvalds extern void baboon_init(void); 202*1da177e4SLinus Torvalds extern void baboon_register_interrupts(void); 203*1da177e4SLinus Torvalds extern void baboon_irq_enable(int); 204*1da177e4SLinus Torvalds extern void baboon_irq_disable(int); 205*1da177e4SLinus Torvalds extern void baboon_irq_clear(int); 206*1da177e4SLinus Torvalds extern int baboon_irq_pending(int); 207*1da177e4SLinus Torvalds 208*1da177e4SLinus Torvalds /* 209*1da177e4SLinus Torvalds * SCC interrupt routines 210*1da177e4SLinus Torvalds */ 211*1da177e4SLinus Torvalds 212*1da177e4SLinus Torvalds static void scc_irq_enable(int); 213*1da177e4SLinus Torvalds static void scc_irq_disable(int); 214*1da177e4SLinus Torvalds 215*1da177e4SLinus Torvalds /* 216*1da177e4SLinus Torvalds * console_loglevel determines NMI handler function 217*1da177e4SLinus Torvalds */ 218*1da177e4SLinus Torvalds 219*1da177e4SLinus Torvalds extern irqreturn_t mac_bang(int, void *, struct pt_regs *); 220*1da177e4SLinus Torvalds irqreturn_t mac_nmi_handler(int, void *, struct pt_regs *); 221*1da177e4SLinus Torvalds irqreturn_t mac_debug_handler(int, void *, struct pt_regs *); 222*1da177e4SLinus Torvalds 223*1da177e4SLinus Torvalds /* #define DEBUG_MACINTS */ 224*1da177e4SLinus Torvalds 225*1da177e4SLinus Torvalds void mac_init_IRQ(void) 226*1da177e4SLinus Torvalds { 227*1da177e4SLinus Torvalds int i; 228*1da177e4SLinus Torvalds 229*1da177e4SLinus Torvalds #ifdef DEBUG_MACINTS 230*1da177e4SLinus Torvalds printk("mac_init_IRQ(): Setting things up...\n"); 231*1da177e4SLinus Torvalds #endif 232*1da177e4SLinus Torvalds /* Initialize the IRQ handler lists. Initially each list is empty, */ 233*1da177e4SLinus Torvalds 234*1da177e4SLinus Torvalds for (i = 0; i < NUM_MAC_SOURCES; i++) { 235*1da177e4SLinus Torvalds mac_irq_list[i] = NULL; 236*1da177e4SLinus Torvalds } 237*1da177e4SLinus Torvalds 238*1da177e4SLinus Torvalds scc_mask = 0; 239*1da177e4SLinus Torvalds 240*1da177e4SLinus Torvalds /* Make sure the SONIC interrupt is cleared or things get ugly */ 241*1da177e4SLinus Torvalds #ifdef SHUTUP_SONIC 242*1da177e4SLinus Torvalds printk("Killing onboard sonic... "); 243*1da177e4SLinus Torvalds /* This address should hopefully be mapped already */ 244*1da177e4SLinus Torvalds if (hwreg_present((void*)(0x50f0a000))) { 245*1da177e4SLinus Torvalds *(long *)(0x50f0a014) = 0x7fffL; 246*1da177e4SLinus Torvalds *(long *)(0x50f0a010) = 0L; 247*1da177e4SLinus Torvalds } 248*1da177e4SLinus Torvalds printk("Done.\n"); 249*1da177e4SLinus Torvalds #endif /* SHUTUP_SONIC */ 250*1da177e4SLinus Torvalds 251*1da177e4SLinus Torvalds /* 252*1da177e4SLinus Torvalds * Now register the handlers for the master IRQ handlers 253*1da177e4SLinus Torvalds * at levels 1-7. Most of the work is done elsewhere. 254*1da177e4SLinus Torvalds */ 255*1da177e4SLinus Torvalds 256*1da177e4SLinus Torvalds if (oss_present) { 257*1da177e4SLinus Torvalds oss_register_interrupts(); 258*1da177e4SLinus Torvalds } else { 259*1da177e4SLinus Torvalds via_register_interrupts(); 260*1da177e4SLinus Torvalds } 261*1da177e4SLinus Torvalds if (psc_present) psc_register_interrupts(); 262*1da177e4SLinus Torvalds if (baboon_present) baboon_register_interrupts(); 263*1da177e4SLinus Torvalds iop_register_interrupts(); 264*1da177e4SLinus Torvalds cpu_request_irq(7, mac_nmi_handler, IRQ_FLG_LOCK, "NMI", 265*1da177e4SLinus Torvalds mac_nmi_handler); 266*1da177e4SLinus Torvalds #ifdef DEBUG_MACINTS 267*1da177e4SLinus Torvalds printk("mac_init_IRQ(): Done!\n"); 268*1da177e4SLinus Torvalds #endif 269*1da177e4SLinus Torvalds } 270*1da177e4SLinus Torvalds 271*1da177e4SLinus Torvalds /* 272*1da177e4SLinus Torvalds * Routines to work with irq_node_t's on linked lists lifted from 273*1da177e4SLinus Torvalds * the Amiga code written by Roman Zippel. 274*1da177e4SLinus Torvalds */ 275*1da177e4SLinus Torvalds 276*1da177e4SLinus Torvalds static inline void mac_insert_irq(irq_node_t **list, irq_node_t *node) 277*1da177e4SLinus Torvalds { 278*1da177e4SLinus Torvalds unsigned long flags; 279*1da177e4SLinus Torvalds irq_node_t *cur; 280*1da177e4SLinus Torvalds 281*1da177e4SLinus Torvalds if (!node->dev_id) 282*1da177e4SLinus Torvalds printk("%s: Warning: dev_id of %s is zero\n", 283*1da177e4SLinus Torvalds __FUNCTION__, node->devname); 284*1da177e4SLinus Torvalds 285*1da177e4SLinus Torvalds local_irq_save(flags); 286*1da177e4SLinus Torvalds 287*1da177e4SLinus Torvalds cur = *list; 288*1da177e4SLinus Torvalds 289*1da177e4SLinus Torvalds if (node->flags & IRQ_FLG_FAST) { 290*1da177e4SLinus Torvalds node->flags &= ~IRQ_FLG_SLOW; 291*1da177e4SLinus Torvalds while (cur && cur->flags & IRQ_FLG_FAST) { 292*1da177e4SLinus Torvalds list = &cur->next; 293*1da177e4SLinus Torvalds cur = cur->next; 294*1da177e4SLinus Torvalds } 295*1da177e4SLinus Torvalds } else if (node->flags & IRQ_FLG_SLOW) { 296*1da177e4SLinus Torvalds while (cur) { 297*1da177e4SLinus Torvalds list = &cur->next; 298*1da177e4SLinus Torvalds cur = cur->next; 299*1da177e4SLinus Torvalds } 300*1da177e4SLinus Torvalds } else { 301*1da177e4SLinus Torvalds while (cur && !(cur->flags & IRQ_FLG_SLOW)) { 302*1da177e4SLinus Torvalds list = &cur->next; 303*1da177e4SLinus Torvalds cur = cur->next; 304*1da177e4SLinus Torvalds } 305*1da177e4SLinus Torvalds } 306*1da177e4SLinus Torvalds 307*1da177e4SLinus Torvalds node->next = cur; 308*1da177e4SLinus Torvalds *list = node; 309*1da177e4SLinus Torvalds 310*1da177e4SLinus Torvalds local_irq_restore(flags); 311*1da177e4SLinus Torvalds } 312*1da177e4SLinus Torvalds 313*1da177e4SLinus Torvalds static inline void mac_delete_irq(irq_node_t **list, void *dev_id) 314*1da177e4SLinus Torvalds { 315*1da177e4SLinus Torvalds unsigned long flags; 316*1da177e4SLinus Torvalds irq_node_t *node; 317*1da177e4SLinus Torvalds 318*1da177e4SLinus Torvalds local_irq_save(flags); 319*1da177e4SLinus Torvalds 320*1da177e4SLinus Torvalds for (node = *list; node; list = &node->next, node = *list) { 321*1da177e4SLinus Torvalds if (node->dev_id == dev_id) { 322*1da177e4SLinus Torvalds *list = node->next; 323*1da177e4SLinus Torvalds /* Mark it as free. */ 324*1da177e4SLinus Torvalds node->handler = NULL; 325*1da177e4SLinus Torvalds local_irq_restore(flags); 326*1da177e4SLinus Torvalds return; 327*1da177e4SLinus Torvalds } 328*1da177e4SLinus Torvalds } 329*1da177e4SLinus Torvalds local_irq_restore(flags); 330*1da177e4SLinus Torvalds printk ("%s: tried to remove invalid irq\n", __FUNCTION__); 331*1da177e4SLinus Torvalds } 332*1da177e4SLinus Torvalds 333*1da177e4SLinus Torvalds /* 334*1da177e4SLinus Torvalds * Call all the handlers for a given interrupt. Fast handlers are called 335*1da177e4SLinus Torvalds * first followed by slow handlers. 336*1da177e4SLinus Torvalds * 337*1da177e4SLinus Torvalds * This code taken from the original Amiga code written by Roman Zippel. 338*1da177e4SLinus Torvalds */ 339*1da177e4SLinus Torvalds 340*1da177e4SLinus Torvalds void mac_do_irq_list(int irq, struct pt_regs *fp) 341*1da177e4SLinus Torvalds { 342*1da177e4SLinus Torvalds irq_node_t *node, *slow_nodes; 343*1da177e4SLinus Torvalds unsigned long flags; 344*1da177e4SLinus Torvalds 345*1da177e4SLinus Torvalds kstat_cpu(0).irqs[irq]++; 346*1da177e4SLinus Torvalds 347*1da177e4SLinus Torvalds #ifdef DEBUG_SPURIOUS 348*1da177e4SLinus Torvalds if (!mac_irq_list[irq] && (console_loglevel > 7)) { 349*1da177e4SLinus Torvalds printk("mac_do_irq_list: spurious interrupt %d!\n", irq); 350*1da177e4SLinus Torvalds return; 351*1da177e4SLinus Torvalds } 352*1da177e4SLinus Torvalds #endif 353*1da177e4SLinus Torvalds 354*1da177e4SLinus Torvalds /* serve first fast and normal handlers */ 355*1da177e4SLinus Torvalds for (node = mac_irq_list[irq]; 356*1da177e4SLinus Torvalds node && (!(node->flags & IRQ_FLG_SLOW)); 357*1da177e4SLinus Torvalds node = node->next) 358*1da177e4SLinus Torvalds node->handler(irq, node->dev_id, fp); 359*1da177e4SLinus Torvalds if (!node) return; 360*1da177e4SLinus Torvalds local_save_flags(flags); 361*1da177e4SLinus Torvalds local_irq_restore((flags & ~0x0700) | (fp->sr & 0x0700)); 362*1da177e4SLinus Torvalds /* if slow handlers exists, serve them now */ 363*1da177e4SLinus Torvalds slow_nodes = node; 364*1da177e4SLinus Torvalds for (; node; node = node->next) { 365*1da177e4SLinus Torvalds node->handler(irq, node->dev_id, fp); 366*1da177e4SLinus Torvalds } 367*1da177e4SLinus Torvalds } 368*1da177e4SLinus Torvalds 369*1da177e4SLinus Torvalds /* 370*1da177e4SLinus Torvalds * mac_enable_irq - enable an interrupt source 371*1da177e4SLinus Torvalds * mac_disable_irq - disable an interrupt source 372*1da177e4SLinus Torvalds * mac_clear_irq - clears a pending interrupt 373*1da177e4SLinus Torvalds * mac_pending_irq - Returns the pending status of an IRQ (nonzero = pending) 374*1da177e4SLinus Torvalds * 375*1da177e4SLinus Torvalds * These routines are just dispatchers to the VIA/OSS/PSC routines. 376*1da177e4SLinus Torvalds */ 377*1da177e4SLinus Torvalds 378*1da177e4SLinus Torvalds void mac_enable_irq (unsigned int irq) 379*1da177e4SLinus Torvalds { 380*1da177e4SLinus Torvalds int irq_src = IRQ_SRC(irq); 381*1da177e4SLinus Torvalds 382*1da177e4SLinus Torvalds switch(irq_src) { 383*1da177e4SLinus Torvalds case 1: via_irq_enable(irq); 384*1da177e4SLinus Torvalds break; 385*1da177e4SLinus Torvalds case 2: 386*1da177e4SLinus Torvalds case 7: if (oss_present) { 387*1da177e4SLinus Torvalds oss_irq_enable(irq); 388*1da177e4SLinus Torvalds } else { 389*1da177e4SLinus Torvalds via_irq_enable(irq); 390*1da177e4SLinus Torvalds } 391*1da177e4SLinus Torvalds break; 392*1da177e4SLinus Torvalds case 3: 393*1da177e4SLinus Torvalds case 4: 394*1da177e4SLinus Torvalds case 5: 395*1da177e4SLinus Torvalds case 6: if (psc_present) { 396*1da177e4SLinus Torvalds psc_irq_enable(irq); 397*1da177e4SLinus Torvalds } else if (oss_present) { 398*1da177e4SLinus Torvalds oss_irq_enable(irq); 399*1da177e4SLinus Torvalds } else if (irq_src == 4) { 400*1da177e4SLinus Torvalds scc_irq_enable(irq); 401*1da177e4SLinus Torvalds } 402*1da177e4SLinus Torvalds break; 403*1da177e4SLinus Torvalds case 8: if (baboon_present) { 404*1da177e4SLinus Torvalds baboon_irq_enable(irq); 405*1da177e4SLinus Torvalds } 406*1da177e4SLinus Torvalds break; 407*1da177e4SLinus Torvalds } 408*1da177e4SLinus Torvalds } 409*1da177e4SLinus Torvalds 410*1da177e4SLinus Torvalds void mac_disable_irq (unsigned int irq) 411*1da177e4SLinus Torvalds { 412*1da177e4SLinus Torvalds int irq_src = IRQ_SRC(irq); 413*1da177e4SLinus Torvalds 414*1da177e4SLinus Torvalds switch(irq_src) { 415*1da177e4SLinus Torvalds case 1: via_irq_disable(irq); 416*1da177e4SLinus Torvalds break; 417*1da177e4SLinus Torvalds case 2: 418*1da177e4SLinus Torvalds case 7: if (oss_present) { 419*1da177e4SLinus Torvalds oss_irq_disable(irq); 420*1da177e4SLinus Torvalds } else { 421*1da177e4SLinus Torvalds via_irq_disable(irq); 422*1da177e4SLinus Torvalds } 423*1da177e4SLinus Torvalds break; 424*1da177e4SLinus Torvalds case 3: 425*1da177e4SLinus Torvalds case 4: 426*1da177e4SLinus Torvalds case 5: 427*1da177e4SLinus Torvalds case 6: if (psc_present) { 428*1da177e4SLinus Torvalds psc_irq_disable(irq); 429*1da177e4SLinus Torvalds } else if (oss_present) { 430*1da177e4SLinus Torvalds oss_irq_disable(irq); 431*1da177e4SLinus Torvalds } else if (irq_src == 4) { 432*1da177e4SLinus Torvalds scc_irq_disable(irq); 433*1da177e4SLinus Torvalds } 434*1da177e4SLinus Torvalds break; 435*1da177e4SLinus Torvalds case 8: if (baboon_present) { 436*1da177e4SLinus Torvalds baboon_irq_disable(irq); 437*1da177e4SLinus Torvalds } 438*1da177e4SLinus Torvalds break; 439*1da177e4SLinus Torvalds } 440*1da177e4SLinus Torvalds } 441*1da177e4SLinus Torvalds 442*1da177e4SLinus Torvalds void mac_clear_irq( unsigned int irq ) 443*1da177e4SLinus Torvalds { 444*1da177e4SLinus Torvalds switch(IRQ_SRC(irq)) { 445*1da177e4SLinus Torvalds case 1: via_irq_clear(irq); 446*1da177e4SLinus Torvalds break; 447*1da177e4SLinus Torvalds case 2: 448*1da177e4SLinus Torvalds case 7: if (oss_present) { 449*1da177e4SLinus Torvalds oss_irq_clear(irq); 450*1da177e4SLinus Torvalds } else { 451*1da177e4SLinus Torvalds via_irq_clear(irq); 452*1da177e4SLinus Torvalds } 453*1da177e4SLinus Torvalds break; 454*1da177e4SLinus Torvalds case 3: 455*1da177e4SLinus Torvalds case 4: 456*1da177e4SLinus Torvalds case 5: 457*1da177e4SLinus Torvalds case 6: if (psc_present) { 458*1da177e4SLinus Torvalds psc_irq_clear(irq); 459*1da177e4SLinus Torvalds } else if (oss_present) { 460*1da177e4SLinus Torvalds oss_irq_clear(irq); 461*1da177e4SLinus Torvalds } 462*1da177e4SLinus Torvalds break; 463*1da177e4SLinus Torvalds case 8: if (baboon_present) { 464*1da177e4SLinus Torvalds baboon_irq_clear(irq); 465*1da177e4SLinus Torvalds } 466*1da177e4SLinus Torvalds break; 467*1da177e4SLinus Torvalds } 468*1da177e4SLinus Torvalds } 469*1da177e4SLinus Torvalds 470*1da177e4SLinus Torvalds int mac_irq_pending( unsigned int irq ) 471*1da177e4SLinus Torvalds { 472*1da177e4SLinus Torvalds switch(IRQ_SRC(irq)) { 473*1da177e4SLinus Torvalds case 1: return via_irq_pending(irq); 474*1da177e4SLinus Torvalds case 2: 475*1da177e4SLinus Torvalds case 7: if (oss_present) { 476*1da177e4SLinus Torvalds return oss_irq_pending(irq); 477*1da177e4SLinus Torvalds } else { 478*1da177e4SLinus Torvalds return via_irq_pending(irq); 479*1da177e4SLinus Torvalds } 480*1da177e4SLinus Torvalds case 3: 481*1da177e4SLinus Torvalds case 4: 482*1da177e4SLinus Torvalds case 5: 483*1da177e4SLinus Torvalds case 6: if (psc_present) { 484*1da177e4SLinus Torvalds return psc_irq_pending(irq); 485*1da177e4SLinus Torvalds } else if (oss_present) { 486*1da177e4SLinus Torvalds return oss_irq_pending(irq); 487*1da177e4SLinus Torvalds } 488*1da177e4SLinus Torvalds } 489*1da177e4SLinus Torvalds return 0; 490*1da177e4SLinus Torvalds } 491*1da177e4SLinus Torvalds 492*1da177e4SLinus Torvalds /* 493*1da177e4SLinus Torvalds * Add an interrupt service routine to an interrupt source. 494*1da177e4SLinus Torvalds * Returns 0 on success. 495*1da177e4SLinus Torvalds * 496*1da177e4SLinus Torvalds * FIXME: You can register interrupts on nonexistent source (ie PSC4 on a 497*1da177e4SLinus Torvalds * non-PSC machine). We should return -EINVAL in those cases. 498*1da177e4SLinus Torvalds */ 499*1da177e4SLinus Torvalds 500*1da177e4SLinus Torvalds int mac_request_irq(unsigned int irq, 501*1da177e4SLinus Torvalds irqreturn_t (*handler)(int, void *, struct pt_regs *), 502*1da177e4SLinus Torvalds unsigned long flags, const char *devname, void *dev_id) 503*1da177e4SLinus Torvalds { 504*1da177e4SLinus Torvalds irq_node_t *node; 505*1da177e4SLinus Torvalds 506*1da177e4SLinus Torvalds #ifdef DEBUG_MACINTS 507*1da177e4SLinus Torvalds printk ("%s: irq %d requested for %s\n", __FUNCTION__, irq, devname); 508*1da177e4SLinus Torvalds #endif 509*1da177e4SLinus Torvalds 510*1da177e4SLinus Torvalds if (irq < VIA1_SOURCE_BASE) { 511*1da177e4SLinus Torvalds return cpu_request_irq(irq, handler, flags, devname, dev_id); 512*1da177e4SLinus Torvalds } 513*1da177e4SLinus Torvalds 514*1da177e4SLinus Torvalds if (irq >= NUM_MAC_SOURCES) { 515*1da177e4SLinus Torvalds printk ("%s: unknown irq %d requested by %s\n", 516*1da177e4SLinus Torvalds __FUNCTION__, irq, devname); 517*1da177e4SLinus Torvalds } 518*1da177e4SLinus Torvalds 519*1da177e4SLinus Torvalds /* Get a node and stick it onto the right list */ 520*1da177e4SLinus Torvalds 521*1da177e4SLinus Torvalds if (!(node = new_irq_node())) return -ENOMEM; 522*1da177e4SLinus Torvalds 523*1da177e4SLinus Torvalds node->handler = handler; 524*1da177e4SLinus Torvalds node->flags = flags; 525*1da177e4SLinus Torvalds node->dev_id = dev_id; 526*1da177e4SLinus Torvalds node->devname = devname; 527*1da177e4SLinus Torvalds node->next = NULL; 528*1da177e4SLinus Torvalds mac_insert_irq(&mac_irq_list[irq], node); 529*1da177e4SLinus Torvalds 530*1da177e4SLinus Torvalds /* Now enable the IRQ source */ 531*1da177e4SLinus Torvalds 532*1da177e4SLinus Torvalds mac_enable_irq(irq); 533*1da177e4SLinus Torvalds 534*1da177e4SLinus Torvalds return 0; 535*1da177e4SLinus Torvalds } 536*1da177e4SLinus Torvalds 537*1da177e4SLinus Torvalds /* 538*1da177e4SLinus Torvalds * Removes an interrupt service routine from an interrupt source. 539*1da177e4SLinus Torvalds */ 540*1da177e4SLinus Torvalds 541*1da177e4SLinus Torvalds void mac_free_irq(unsigned int irq, void *dev_id) 542*1da177e4SLinus Torvalds { 543*1da177e4SLinus Torvalds #ifdef DEBUG_MACINTS 544*1da177e4SLinus Torvalds printk ("%s: irq %d freed by %p\n", __FUNCTION__, irq, dev_id); 545*1da177e4SLinus Torvalds #endif 546*1da177e4SLinus Torvalds 547*1da177e4SLinus Torvalds if (irq < VIA1_SOURCE_BASE) { 548*1da177e4SLinus Torvalds cpu_free_irq(irq, dev_id); 549*1da177e4SLinus Torvalds return; 550*1da177e4SLinus Torvalds } 551*1da177e4SLinus Torvalds 552*1da177e4SLinus Torvalds if (irq >= NUM_MAC_SOURCES) { 553*1da177e4SLinus Torvalds printk ("%s: unknown irq %d freed\n", 554*1da177e4SLinus Torvalds __FUNCTION__, irq); 555*1da177e4SLinus Torvalds return; 556*1da177e4SLinus Torvalds } 557*1da177e4SLinus Torvalds 558*1da177e4SLinus Torvalds mac_delete_irq(&mac_irq_list[irq], dev_id); 559*1da177e4SLinus Torvalds 560*1da177e4SLinus Torvalds /* If the list for this interrupt is */ 561*1da177e4SLinus Torvalds /* empty then disable the source. */ 562*1da177e4SLinus Torvalds 563*1da177e4SLinus Torvalds if (!mac_irq_list[irq]) { 564*1da177e4SLinus Torvalds mac_disable_irq(irq); 565*1da177e4SLinus Torvalds } 566*1da177e4SLinus Torvalds } 567*1da177e4SLinus Torvalds 568*1da177e4SLinus Torvalds /* 569*1da177e4SLinus Torvalds * Generate a pretty listing for /proc/interrupts 570*1da177e4SLinus Torvalds * 571*1da177e4SLinus Torvalds * By the time we're called the autovector interrupt list has already been 572*1da177e4SLinus Torvalds * generated, so we just need to do the machspec interrupts. 573*1da177e4SLinus Torvalds * 574*1da177e4SLinus Torvalds * 990506 (jmt) - rewritten to handle chained machspec interrupt handlers. 575*1da177e4SLinus Torvalds * Also removed display of num_spurious it is already 576*1da177e4SLinus Torvalds * displayed for us as autovector irq 0. 577*1da177e4SLinus Torvalds */ 578*1da177e4SLinus Torvalds 579*1da177e4SLinus Torvalds int show_mac_interrupts(struct seq_file *p, void *v) 580*1da177e4SLinus Torvalds { 581*1da177e4SLinus Torvalds int i; 582*1da177e4SLinus Torvalds irq_node_t *node; 583*1da177e4SLinus Torvalds char *base; 584*1da177e4SLinus Torvalds 585*1da177e4SLinus Torvalds /* Don't do Nubus interrupts in this loop; we do them separately */ 586*1da177e4SLinus Torvalds /* below so that we can print slot numbers instead of IRQ numbers */ 587*1da177e4SLinus Torvalds 588*1da177e4SLinus Torvalds for (i = VIA1_SOURCE_BASE ; i < NUM_MAC_SOURCES ; ++i) { 589*1da177e4SLinus Torvalds 590*1da177e4SLinus Torvalds /* Nonexistant interrupt or nothing registered; skip it. */ 591*1da177e4SLinus Torvalds 592*1da177e4SLinus Torvalds if ((node = mac_irq_list[i]) == NULL) continue; 593*1da177e4SLinus Torvalds if (node->flags & IRQ_FLG_STD) continue; 594*1da177e4SLinus Torvalds 595*1da177e4SLinus Torvalds base = ""; 596*1da177e4SLinus Torvalds switch(IRQ_SRC(i)) { 597*1da177e4SLinus Torvalds case 1: base = "via1"; 598*1da177e4SLinus Torvalds break; 599*1da177e4SLinus Torvalds case 2: if (oss_present) { 600*1da177e4SLinus Torvalds base = "oss"; 601*1da177e4SLinus Torvalds } else { 602*1da177e4SLinus Torvalds base = "via2"; 603*1da177e4SLinus Torvalds } 604*1da177e4SLinus Torvalds break; 605*1da177e4SLinus Torvalds case 3: 606*1da177e4SLinus Torvalds case 4: 607*1da177e4SLinus Torvalds case 5: 608*1da177e4SLinus Torvalds case 6: if (psc_present) { 609*1da177e4SLinus Torvalds base = "psc"; 610*1da177e4SLinus Torvalds } else if (oss_present) { 611*1da177e4SLinus Torvalds base = "oss"; 612*1da177e4SLinus Torvalds } else { 613*1da177e4SLinus Torvalds if (IRQ_SRC(i) == 4) base = "scc"; 614*1da177e4SLinus Torvalds } 615*1da177e4SLinus Torvalds break; 616*1da177e4SLinus Torvalds case 7: base = "nbus"; 617*1da177e4SLinus Torvalds break; 618*1da177e4SLinus Torvalds case 8: base = "bbn"; 619*1da177e4SLinus Torvalds break; 620*1da177e4SLinus Torvalds } 621*1da177e4SLinus Torvalds seq_printf(p, "%4s %2d: %10u ", base, i, kstat_cpu(0).irqs[i]); 622*1da177e4SLinus Torvalds 623*1da177e4SLinus Torvalds do { 624*1da177e4SLinus Torvalds if (node->flags & IRQ_FLG_FAST) { 625*1da177e4SLinus Torvalds seq_puts(p, "F "); 626*1da177e4SLinus Torvalds } else if (node->flags & IRQ_FLG_SLOW) { 627*1da177e4SLinus Torvalds seq_puts(p, "S "); 628*1da177e4SLinus Torvalds } else { 629*1da177e4SLinus Torvalds seq_puts(p, " "); 630*1da177e4SLinus Torvalds } 631*1da177e4SLinus Torvalds seq_printf(p, "%s\n", node->devname); 632*1da177e4SLinus Torvalds if ((node = node->next)) { 633*1da177e4SLinus Torvalds seq_puts(p, " "); 634*1da177e4SLinus Torvalds } 635*1da177e4SLinus Torvalds } while(node); 636*1da177e4SLinus Torvalds 637*1da177e4SLinus Torvalds } 638*1da177e4SLinus Torvalds return 0; 639*1da177e4SLinus Torvalds } 640*1da177e4SLinus Torvalds 641*1da177e4SLinus Torvalds void mac_default_handler(int irq, void *dev_id, struct pt_regs *regs) 642*1da177e4SLinus Torvalds { 643*1da177e4SLinus Torvalds #ifdef DEBUG_SPURIOUS 644*1da177e4SLinus Torvalds printk("Unexpected IRQ %d on device %p\n", irq, dev_id); 645*1da177e4SLinus Torvalds #endif 646*1da177e4SLinus Torvalds } 647*1da177e4SLinus Torvalds 648*1da177e4SLinus Torvalds static int num_debug[8]; 649*1da177e4SLinus Torvalds 650*1da177e4SLinus Torvalds irqreturn_t mac_debug_handler(int irq, void *dev_id, struct pt_regs *regs) 651*1da177e4SLinus Torvalds { 652*1da177e4SLinus Torvalds if (num_debug[irq] < 10) { 653*1da177e4SLinus Torvalds printk("DEBUG: Unexpected IRQ %d\n", irq); 654*1da177e4SLinus Torvalds num_debug[irq]++; 655*1da177e4SLinus Torvalds } 656*1da177e4SLinus Torvalds return IRQ_HANDLED; 657*1da177e4SLinus Torvalds } 658*1da177e4SLinus Torvalds 659*1da177e4SLinus Torvalds static int in_nmi; 660*1da177e4SLinus Torvalds static volatile int nmi_hold; 661*1da177e4SLinus Torvalds 662*1da177e4SLinus Torvalds irqreturn_t mac_nmi_handler(int irq, void *dev_id, struct pt_regs *fp) 663*1da177e4SLinus Torvalds { 664*1da177e4SLinus Torvalds int i; 665*1da177e4SLinus Torvalds /* 666*1da177e4SLinus Torvalds * generate debug output on NMI switch if 'debug' kernel option given 667*1da177e4SLinus Torvalds * (only works with Penguin!) 668*1da177e4SLinus Torvalds */ 669*1da177e4SLinus Torvalds 670*1da177e4SLinus Torvalds in_nmi++; 671*1da177e4SLinus Torvalds for (i=0; i<100; i++) 672*1da177e4SLinus Torvalds udelay(1000); 673*1da177e4SLinus Torvalds 674*1da177e4SLinus Torvalds if (in_nmi == 1) { 675*1da177e4SLinus Torvalds nmi_hold = 1; 676*1da177e4SLinus Torvalds printk("... pausing, press NMI to resume ..."); 677*1da177e4SLinus Torvalds } else { 678*1da177e4SLinus Torvalds printk(" ok!\n"); 679*1da177e4SLinus Torvalds nmi_hold = 0; 680*1da177e4SLinus Torvalds } 681*1da177e4SLinus Torvalds 682*1da177e4SLinus Torvalds barrier(); 683*1da177e4SLinus Torvalds 684*1da177e4SLinus Torvalds while (nmi_hold == 1) 685*1da177e4SLinus Torvalds udelay(1000); 686*1da177e4SLinus Torvalds 687*1da177e4SLinus Torvalds if ( console_loglevel >= 8 ) { 688*1da177e4SLinus Torvalds #if 0 689*1da177e4SLinus Torvalds show_state(); 690*1da177e4SLinus Torvalds printk("PC: %08lx\nSR: %04x SP: %p\n", fp->pc, fp->sr, fp); 691*1da177e4SLinus Torvalds printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", 692*1da177e4SLinus Torvalds fp->d0, fp->d1, fp->d2, fp->d3); 693*1da177e4SLinus Torvalds printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", 694*1da177e4SLinus Torvalds fp->d4, fp->d5, fp->a0, fp->a1); 695*1da177e4SLinus Torvalds 696*1da177e4SLinus Torvalds if (STACK_MAGIC != *(unsigned long *)current->kernel_stack_page) 697*1da177e4SLinus Torvalds printk("Corrupted stack page\n"); 698*1da177e4SLinus Torvalds printk("Process %s (pid: %d, stackpage=%08lx)\n", 699*1da177e4SLinus Torvalds current->comm, current->pid, current->kernel_stack_page); 700*1da177e4SLinus Torvalds if (intr_count == 1) 701*1da177e4SLinus Torvalds dump_stack((struct frame *)fp); 702*1da177e4SLinus Torvalds #else 703*1da177e4SLinus Torvalds /* printk("NMI "); */ 704*1da177e4SLinus Torvalds #endif 705*1da177e4SLinus Torvalds } 706*1da177e4SLinus Torvalds in_nmi--; 707*1da177e4SLinus Torvalds return IRQ_HANDLED; 708*1da177e4SLinus Torvalds } 709*1da177e4SLinus Torvalds 710*1da177e4SLinus Torvalds /* 711*1da177e4SLinus Torvalds * Simple routines for masking and unmasking 712*1da177e4SLinus Torvalds * SCC interrupts in cases where this can't be 713*1da177e4SLinus Torvalds * done in hardware (only the PSC can do that.) 714*1da177e4SLinus Torvalds */ 715*1da177e4SLinus Torvalds 716*1da177e4SLinus Torvalds static void scc_irq_enable(int irq) { 717*1da177e4SLinus Torvalds int irq_idx = IRQ_IDX(irq); 718*1da177e4SLinus Torvalds 719*1da177e4SLinus Torvalds scc_mask |= (1 << irq_idx); 720*1da177e4SLinus Torvalds } 721*1da177e4SLinus Torvalds 722*1da177e4SLinus Torvalds static void scc_irq_disable(int irq) { 723*1da177e4SLinus Torvalds int irq_idx = IRQ_IDX(irq); 724*1da177e4SLinus Torvalds 725*1da177e4SLinus Torvalds scc_mask &= ~(1 << irq_idx); 726*1da177e4SLinus Torvalds } 727*1da177e4SLinus Torvalds 728*1da177e4SLinus Torvalds /* 729*1da177e4SLinus Torvalds * SCC master interrupt handler. We have to do a bit of magic here 730*1da177e4SLinus Torvalds * to figure out what channel gave us the interrupt; putting this 731*1da177e4SLinus Torvalds * here is cleaner than hacking it into drivers/char/macserial.c. 732*1da177e4SLinus Torvalds */ 733*1da177e4SLinus Torvalds 734*1da177e4SLinus Torvalds void mac_scc_dispatch(int irq, void *dev_id, struct pt_regs *regs) 735*1da177e4SLinus Torvalds { 736*1da177e4SLinus Torvalds volatile unsigned char *scc = (unsigned char *) mac_bi_data.sccbase + 2; 737*1da177e4SLinus Torvalds unsigned char reg; 738*1da177e4SLinus Torvalds unsigned long flags; 739*1da177e4SLinus Torvalds 740*1da177e4SLinus Torvalds /* Read RR3 from the chip. Always do this on channel A */ 741*1da177e4SLinus Torvalds /* This must be an atomic operation so disable irqs. */ 742*1da177e4SLinus Torvalds 743*1da177e4SLinus Torvalds local_irq_save(flags); 744*1da177e4SLinus Torvalds *scc = 3; 745*1da177e4SLinus Torvalds reg = *scc; 746*1da177e4SLinus Torvalds local_irq_restore(flags); 747*1da177e4SLinus Torvalds 748*1da177e4SLinus Torvalds /* Now dispatch. Bits 0-2 are for channel B and */ 749*1da177e4SLinus Torvalds /* bits 3-5 are for channel A. We can safely */ 750*1da177e4SLinus Torvalds /* ignore the remaining bits here. */ 751*1da177e4SLinus Torvalds /* */ 752*1da177e4SLinus Torvalds /* Note that we're ignoring scc_mask for now. */ 753*1da177e4SLinus Torvalds /* If we actually mask the ints then we tend to */ 754*1da177e4SLinus Torvalds /* get hammered by very persistent SCC irqs, */ 755*1da177e4SLinus Torvalds /* and since they're autovector interrupts they */ 756*1da177e4SLinus Torvalds /* pretty much kill the system. */ 757*1da177e4SLinus Torvalds 758*1da177e4SLinus Torvalds if (reg & 0x38) mac_do_irq_list(IRQ_SCCA, regs); 759*1da177e4SLinus Torvalds if (reg & 0x07) mac_do_irq_list(IRQ_SCCB, regs); 760*1da177e4SLinus Torvalds } 761