2 * indy_int.c: Routines for generic manipulation of the INT[23] ASIC
3 * found on INDY workstations..
5 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
6 * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org)
7 * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - Indigo2 changes
9 #include <linux/config.h>
10 #include <linux/init.h>
12 #include <linux/errno.h>
13 #include <linux/kernel_stat.h>
14 #include <linux/signal.h>
15 #include <linux/sched.h>
16 #include <linux/types.h>
17 #include <linux/interrupt.h>
18 #include <linux/ioport.h>
19 #include <linux/timex.h>
20 #include <linux/malloc.h>
21 #include <linux/random.h>
22 #include <linux/smp.h>
23 #include <linux/smp_lock.h>
25 #include <asm/bitops.h>
26 #include <asm/bootinfo.h>
29 #include <asm/mipsregs.h>
30 #include <asm/system.h>
32 #include <asm/ptrace.h>
33 #include <asm/processor.h>
34 #include <asm/sgi/sgi.h>
35 #include <asm/sgi/sgihpc.h>
36 #include <asm/sgi/sgint23.h>
37 #include <asm/sgialib.h>
40 * Linux has a controller-independent x86 interrupt architecture.
41 * every controller has a 'controller-template', that is used
42 * by the main code to do the right thing. Each driver-visible
43 * interrupt source is transparently wired to the apropriate
44 * controller. Thus drivers need not be aware of the
45 * interrupt-controller.
47 * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC,
48 * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC.
49 * (IO-APICs assumed to be messaging to Pentium local-APICs)
51 * the code is designed to be easily extended with new/different
52 * interrupt controllers, without having to do assembly magic.
55 struct sgi_int2_regs
*sgi_i2regs
;
56 struct sgi_int3_regs
*sgi_i3regs
;
57 struct sgi_ioc_ints
*ioc_icontrol
;
58 struct sgi_ioc_timers
*ioc_timers
;
59 volatile unsigned char *ioc_tclear
;
61 static char lc0msk_to_irqnr
[256];
62 static char lc1msk_to_irqnr
[256];
63 static char lc2msk_to_irqnr
[256];
64 static char lc3msk_to_irqnr
[256];
66 extern asmlinkage
void indyIRQ(void);
68 #ifdef CONFIG_REMOTE_DEBUG
69 extern void rs_kgdb_hook(int);
72 unsigned long spurious_count
= 0;
74 /* Local IRQ's are layed out logically like this:
76 * 0 --> 7 == local 0 interrupts
77 * 8 --> 15 == local 1 interrupts
78 * 16 --> 23 == vectored level 2 interrupts
79 * 24 --> 31 == vectored level 3 interrupts (not used)
81 void disable_local_irq(unsigned int irq_nr
)
87 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
88 ioc_icontrol
->imask0
&= ~(1 << irq_nr
);
91 case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
92 ioc_icontrol
->imask1
&= ~(1 << (irq_nr
- 8));
95 case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23:
96 ioc_icontrol
->cmeimask0
&= ~(1 << (irq_nr
- 16));
100 /* This way we'll see if anyone would ever want vectored
101 * level 3 interrupts. Highly unlikely.
103 printk("Yeeee, got passed irq_nr %d at disable_irq\n", irq_nr
);
104 panic("INVALID IRQ level!");
106 restore_flags(flags
);
109 void enable_local_irq(unsigned int irq_nr
)
114 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
115 ioc_icontrol
->imask0
|= (1 << irq_nr
);
118 case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
119 ioc_icontrol
->imask1
|= (1 << (irq_nr
- 8));
122 case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23:
124 ioc_icontrol
->cmeimask0
|= (1 << (irq_nr
- 16));
128 printk("Yeeee, got passed irq_nr %d at disable_irq\n", irq_nr
);
129 panic("INVALID IRQ level!");
131 restore_flags(flags
);
134 void disable_gio_irq(unsigned int irq_nr
)
139 void enable_gio_irq(unsigned int irq_nr
)
144 void disable_hpcdma_irq(unsigned int irq_nr
)
149 void enable_hpcdma_irq(unsigned int irq_nr
)
154 void disable_irq(unsigned int irq_nr
)
156 unsigned int n
= irq_nr
;
158 printk("whee, invalid irq_nr %d\n", irq_nr
);
159 panic("IRQ, you lose...");
161 if(n
>= SGINT_LOCAL0
&& n
< SGINT_GIO
) {
162 disable_local_irq(n
- SGINT_LOCAL0
);
163 } else if(n
>= SGINT_GIO
&& n
< SGINT_HPCDMA
) {
164 disable_gio_irq(n
- SGINT_GIO
);
165 } else if(n
>= SGINT_HPCDMA
&& n
< SGINT_END
) {
166 disable_hpcdma_irq(n
- SGINT_HPCDMA
);
168 panic("how did I get here?");
172 void enable_irq(unsigned int irq_nr
)
174 unsigned int n
= irq_nr
;
176 printk("whee, invalid irq_nr %d\n", irq_nr
);
177 panic("IRQ, you lose...");
179 if(n
>= SGINT_LOCAL0
&& n
< SGINT_GIO
) {
180 enable_local_irq(n
- SGINT_LOCAL0
);
181 } else if(n
>= SGINT_GIO
&& n
< SGINT_HPCDMA
) {
182 enable_gio_irq(n
- SGINT_GIO
);
183 } else if(n
>= SGINT_HPCDMA
&& n
< SGINT_END
) {
184 enable_hpcdma_irq(n
- SGINT_HPCDMA
);
186 panic("how did I get here?");
194 static void local_unex(int irq
, void *data
, struct pt_regs
*regs
)
196 printk("Whee: unexpected local IRQ at %08lx\n",
197 (unsigned long) regs
->cp0_epc
);
198 printk("DUMP: stat0<%x> stat1<%x> vmeistat<%x>\n",
199 ioc_icontrol
->istat0
, ioc_icontrol
->istat1
,
200 ioc_icontrol
->vmeistat
);
204 static struct irqaction
*local_irq_action
[24] = {
205 NULL
, NULL
, NULL
, NULL
,
206 NULL
, NULL
, NULL
, NULL
,
207 NULL
, NULL
, NULL
, NULL
,
208 NULL
, NULL
, NULL
, NULL
,
209 NULL
, NULL
, NULL
, NULL
,
210 NULL
, NULL
, NULL
, NULL
213 int setup_indy_irq(int irq
, struct irqaction
* new)
215 printk("setup_indy_irq: Yeee, don't know how to setup irq<%d> for %s %p\n",
216 irq
, new->name
, new->handler
);
220 static struct irqaction r4ktimer_action
= {
221 NULL
, 0, 0, "R4000 timer/counter", NULL
, NULL
,
224 static struct irqaction indy_berr_action
= {
225 NULL
, 0, 0, "IP22 Bus Error", NULL
, NULL
,
228 static struct irqaction
*irq_action
[16] = {
229 NULL
, NULL
, NULL
, NULL
,
230 NULL
, NULL
, &indy_berr_action
, &r4ktimer_action
,
231 NULL
, NULL
, NULL
, NULL
,
232 NULL
, NULL
, NULL
, NULL
235 int get_irq_list(char *buf
)
239 struct irqaction
* action
;
241 for (i
= 0 ; i
< 16 ; i
++, num
++) {
242 action
= irq_action
[i
];
245 len
+= sprintf(buf
+len
, "%2d: %8d %c %s",
246 num
, kstat
.irqs
[0][num
],
247 (action
->flags
& SA_INTERRUPT
) ? '+' : ' ',
249 for (action
=action
->next
; action
; action
= action
->next
) {
250 len
+= sprintf(buf
+len
, ",%s %s",
251 (action
->flags
& SA_INTERRUPT
) ? " +" : "",
254 len
+= sprintf(buf
+len
, " [on-chip]\n");
256 for (i
= 0 ; i
< 24 ; i
++, num
++) {
257 action
= local_irq_action
[i
];
260 len
+= sprintf(buf
+len
, "%2d: %8d %c %s",
261 num
, kstat
.irqs
[0][num
],
262 (action
->flags
& SA_INTERRUPT
) ? '+' : ' ',
264 for (action
=action
->next
; action
; action
= action
->next
) {
265 len
+= sprintf(buf
+len
, ",%s %s",
266 (action
->flags
& SA_INTERRUPT
) ? " +" : "",
269 len
+= sprintf(buf
+len
, " [local]\n");
275 * do_IRQ handles IRQ's that have been installed without the
276 * SA_INTERRUPT flag: it uses the full signal-handling return
277 * and runs with other interrupts enabled. All relatively slow
278 * IRQ's should use this format: notably the keyboard/timer
281 asmlinkage
void do_IRQ(int irq
, struct pt_regs
* regs
)
283 struct irqaction
*action
;
286 cpu
= smp_processor_id();
288 kstat
.irqs
[0][irq
]++;
290 printk("Got irq %d, press a key.", irq
);
292 ArcEnterInteractiveMode();
295 * mask and ack quickly, we don't want the irq controller
296 * thinking we're snobs just because some other CPU has
297 * disabled global interrupts (we have already done the
298 * INT_ACK cycles, it's too late to try to pretend to the
299 * controller that we aren't taking the interrupt).
301 * Commented out because we've already done this in the
302 * machinespecific part of the handler. It's reasonable to
303 * do this here in a highlevel language though because that way
304 * we could get rid of a good part of duplicated code ...
306 /* mask_and_ack_irq(irq); */
308 action
= *(irq
+ irq_action
);
310 if (!(action
->flags
& SA_INTERRUPT
))
312 action
= *(irq
+ irq_action
);
315 do_random
|= action
->flags
;
316 action
->handler(irq
, action
->dev_id
, regs
);
317 action
= action
->next
;
319 if (do_random
& SA_SAMPLE_RANDOM
)
320 add_interrupt_randomness(irq
);
325 /* unmasking and bottom half handling is done magically for us. */
328 int request_local_irq(unsigned int lirq
, void (*func
)(int, void *, struct pt_regs
*),
329 unsigned long iflags
, const char *dname
, void *devid
)
331 struct irqaction
*action
;
333 lirq
-= SGINT_LOCAL0
;
334 if(lirq
>= 24 || !func
)
337 action
= (struct irqaction
*)kmalloc(sizeof(struct irqaction
), GFP_KERNEL
);
341 action
->handler
= func
;
342 action
->flags
= iflags
;
344 action
->name
= dname
;
345 action
->dev_id
= devid
;
347 local_irq_action
[lirq
] = action
;
348 enable_irq(lirq
+ SGINT_LOCAL0
);
352 void free_local_irq(unsigned int lirq
, void *dev_id
)
354 struct irqaction
*action
;
356 lirq
-= SGINT_LOCAL0
;
358 printk("Aieee: trying to free bogus local irq %d\n",
359 lirq
+ SGINT_LOCAL0
);
362 action
= local_irq_action
[lirq
];
363 local_irq_action
[lirq
] = NULL
;
364 disable_irq(lirq
+ SGINT_LOCAL0
);
368 int request_irq(unsigned int irq
,
369 void (*handler
)(int, void *, struct pt_regs
*),
370 unsigned long irqflags
,
371 const char * devname
,
375 struct irqaction
* action
;
377 if (irq
>= SGINT_END
)
382 if((irq
>= SGINT_LOCAL0
) && (irq
< SGINT_GIO
))
383 return request_local_irq(irq
, handler
, irqflags
, devname
, dev_id
);
385 action
= (struct irqaction
*)kmalloc(sizeof(struct irqaction
), GFP_KERNEL
);
389 action
->handler
= handler
;
390 action
->flags
= irqflags
;
392 action
->name
= devname
;
394 action
->dev_id
= dev_id
;
396 retval
= setup_indy_irq(irq
, action
);
403 void free_irq(unsigned int irq
, void *dev_id
)
405 struct irqaction
* action
, **p
;
408 if (irq
>= SGINT_END
) {
409 printk("Trying to free IRQ%d\n",irq
);
412 if((irq
>= SGINT_LOCAL0
) && (irq
< SGINT_GIO
)) {
413 free_local_irq(irq
, dev_id
);
416 for (p
= irq
+ irq_action
; (action
= *p
) != NULL
; p
= &action
->next
) {
417 if (action
->dev_id
!= dev_id
)
420 /* Found it - now free it */
423 restore_flags(flags
);
427 printk("Trying to free free IRQ%d\n",irq
);
430 void indy_local0_irqdispatch(struct pt_regs
*regs
)
432 struct irqaction
*action
;
433 unsigned char mask
= ioc_icontrol
->istat0
;
434 unsigned char mask2
= 0;
435 int irq
, cpu
= smp_processor_id();;
437 mask
&= ioc_icontrol
->imask0
;
438 if(mask
& ISTAT0_LIO2
) {
439 mask2
= ioc_icontrol
->vmeistat
;
440 mask2
&= ioc_icontrol
->cmeimask0
;
441 irq
= lc2msk_to_irqnr
[mask2
];
442 action
= local_irq_action
[irq
];
444 irq
= lc0msk_to_irqnr
[mask
];
445 action
= local_irq_action
[irq
];
449 kstat
.irqs
[0][irq
+ 16]++;
450 action
->handler(irq
, action
->dev_id
, regs
);
454 void indy_local1_irqdispatch(struct pt_regs
*regs
)
456 struct irqaction
*action
;
457 unsigned char mask
= ioc_icontrol
->istat1
;
458 unsigned char mask2
= 0;
459 int irq
, cpu
= smp_processor_id();;
461 mask
&= ioc_icontrol
->imask1
;
462 if(mask
& ISTAT1_LIO3
) {
463 printk("WHee: Got an LIO3 irq, winging it...\n");
464 mask2
= ioc_icontrol
->vmeistat
;
465 mask2
&= ioc_icontrol
->cmeimask1
;
466 irq
= lc3msk_to_irqnr
[ioc_icontrol
->vmeistat
];
467 action
= local_irq_action
[irq
];
469 irq
= lc1msk_to_irqnr
[mask
];
470 action
= local_irq_action
[irq
];
473 kstat
.irqs
[0][irq
+ 24]++;
474 action
->handler(irq
, action
->dev_id
, regs
);
478 void indy_buserror_irq(struct pt_regs
*regs
)
480 int cpu
= smp_processor_id();
484 kstat
.irqs
[0][irq
]++;
485 printk("Got a bus error IRQ, shouldn't happen yet\n");
487 printk("Spinning...\n");
492 /* Misc. crap just to keep the kernel linking... */
493 unsigned long probe_irq_on (void)
498 int probe_irq_off (unsigned long irqs
)
503 static inline void sgint_init(void)
506 #ifdef CONFIG_REMOTE_DEBUG
510 sgi_i2regs
= (struct sgi_int2_regs
*) (KSEG1
+ SGI_INT2_BASE
);
511 sgi_i3regs
= (struct sgi_int3_regs
*) (KSEG1
+ SGI_INT3_BASE
);
513 /* Init local mask --> irq tables. */
514 for(i
= 0; i
< 256; i
++) {
516 lc0msk_to_irqnr
[i
] = 7;
517 lc1msk_to_irqnr
[i
] = 15;
518 lc2msk_to_irqnr
[i
] = 23;
519 lc3msk_to_irqnr
[i
] = 31;
520 } else if(i
& 0x40) {
521 lc0msk_to_irqnr
[i
] = 6;
522 lc1msk_to_irqnr
[i
] = 14;
523 lc2msk_to_irqnr
[i
] = 22;
524 lc3msk_to_irqnr
[i
] = 30;
525 } else if(i
& 0x20) {
526 lc0msk_to_irqnr
[i
] = 5;
527 lc1msk_to_irqnr
[i
] = 13;
528 lc2msk_to_irqnr
[i
] = 21;
529 lc3msk_to_irqnr
[i
] = 29;
530 } else if(i
& 0x10) {
531 lc0msk_to_irqnr
[i
] = 4;
532 lc1msk_to_irqnr
[i
] = 12;
533 lc2msk_to_irqnr
[i
] = 20;
534 lc3msk_to_irqnr
[i
] = 28;
535 } else if(i
& 0x08) {
536 lc0msk_to_irqnr
[i
] = 3;
537 lc1msk_to_irqnr
[i
] = 11;
538 lc2msk_to_irqnr
[i
] = 19;
539 lc3msk_to_irqnr
[i
] = 27;
540 } else if(i
& 0x04) {
541 lc0msk_to_irqnr
[i
] = 2;
542 lc1msk_to_irqnr
[i
] = 10;
543 lc2msk_to_irqnr
[i
] = 18;
544 lc3msk_to_irqnr
[i
] = 26;
545 } else if(i
& 0x02) {
546 lc0msk_to_irqnr
[i
] = 1;
547 lc1msk_to_irqnr
[i
] = 9;
548 lc2msk_to_irqnr
[i
] = 17;
549 lc3msk_to_irqnr
[i
] = 25;
550 } else if(i
& 0x01) {
551 lc0msk_to_irqnr
[i
] = 0;
552 lc1msk_to_irqnr
[i
] = 8;
553 lc2msk_to_irqnr
[i
] = 16;
554 lc3msk_to_irqnr
[i
] = 24;
556 lc0msk_to_irqnr
[i
] = 0;
557 lc1msk_to_irqnr
[i
] = 0;
558 lc2msk_to_irqnr
[i
] = 0;
559 lc3msk_to_irqnr
[i
] = 0;
563 /* Indy uses an INT3, Indigo2 uses an INT2 */
565 ioc_icontrol
= &sgi_i3regs
->ints
;
566 ioc_timers
= &sgi_i3regs
->timers
;
567 ioc_tclear
= &sgi_i3regs
->tclear
;
569 ioc_icontrol
= &sgi_i2regs
->ints
;
570 ioc_timers
= &sgi_i2regs
->timers
;
571 ioc_tclear
= &sgi_i2regs
->tclear
;
574 /* Mask out all interrupts. */
575 ioc_icontrol
->imask0
= 0;
576 ioc_icontrol
->imask1
= 0;
577 ioc_icontrol
->cmeimask0
= 0;
578 ioc_icontrol
->cmeimask1
= 0;
580 /* Now safe to set the exception vector. */
581 set_except_vector(0, indyIRQ
);
583 #ifdef CONFIG_REMOTE_DEBUG
584 ctype
= prom_getcmdline();
585 for(i
= 0; i
< strlen(ctype
); i
++) {
586 if(ctype
[i
]=='k' && ctype
[i
+1]=='g' &&
587 ctype
[i
+2]=='d' && ctype
[i
+3]=='b' &&
588 ctype
[i
+4]=='=' && ctype
[i
+5]=='t' &&
589 ctype
[i
+6]=='t' && ctype
[i
+7]=='y' &&
591 (ctype
[i
+9] == '1' || ctype
[i
+9] == '2')) {
592 printk("KGDB: Using serial line /dev/ttyd%d for "
593 "session\n", (ctype
[i
+9] - '0'));
596 else if(ctype
[i
+9]=='2')
599 printk("KGDB: whoops bogon tty line "
600 "requested, disabling session\n");
608 void __init
init_IRQ(void)