hi, this will bring you following: * Indy interrupt handling works now better. the only visible change is look of /proc/interrupts CPU0 2: 0 CPU_irq local0 cascade 3: 0 CPU_irq local1 cascade 6: 0 CPU_irq Bus Error 9: 2758 IP22 local 0 SGI WD93 11: 2197 IP22 local 0 SGI Seeq8003 15: 0 IP22 local 0 mappable0 cascade 17: 4 IP22 local 1 Front Panel 28: 6754 IP22 local 2 keyboard 29: 0 IP22 local 2 Zilog8530 ERR: 0 one question: should be cascade interrupts counted too? note, that timer irqs are not present. i'll do so once i'll implement CONFIG_NEW_TIME_C for Indy. * I removed irq 'space' for HPC and GIO interrupts. They weren't implemented and doing so will make interrupt routine _very_ slow. Driver should register HPC/MC/GIO interrupt as shareable and look to the proper register to see what happened (currently there is no such driver, except of HAL2 sitting on my hardisk) * Various definitions of IP22 interrups were added to sgint23.h * other minor fixes. note for those, who are waiting for VINO driver: at the beginning I was unable to start DMA transfer. now i'm unable to stop it... so to bring my ego from dust, i decided to write HAL2 driver, which needs HPC interupts. this patch is HAL2 driver by-product... any comments and/or suggestions are welcome, ladis Index: linux/include/asm-mips/sgi/sgint23.h =================================================================== RCS file: /cvs/linux/include/asm-mips/sgi/sgint23.h,v retrieving revision 1.4 diff -u -r1.4 sgint23.h --- linux/include/asm-mips/sgi/sgint23.h 2001/10/06 22:33:12 1.4 +++ linux/include/asm-mips/sgi/sgint23.h 2001/11/16 12:10:02 @@ -8,100 +8,123 @@ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1997, 98, 1999, 2000 Ralf Baechle * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - INT2 corrections + * Copyright (C) 2001 Ladislav Michl (ladis@psi.cz) */ #ifndef _ASM_SGI_SGINT23_H #define _ASM_SGI_SGINT23_H /* These are the virtual IRQ numbers, we divide all IRQ's into * 'spaces', the 'space' determines where and how to enable/disable - * that particular IRQ on an SGI machine. Add new 'spaces' as new - * IRQ hardware is supported. + * that particular IRQ on an SGI machine. HPC DMA and MC DMA interrups + * are not supported this way. Driver is supposed to allocate HPC/MC + * interrupt as shareable and then look to proper status bit (see + * HAL2 driver). This will prevent many complications, trust me ;-) + * --ladis */ -#define SGINT_LOCAL0 0 /* INDY has 8 local0 irq levels */ -#define SGINT_LOCAL1 8 /* INDY has 8 local1 irq levels */ -#define SGINT_LOCAL2 16 /* INDY has 8 local2 vectored irq levels */ -#define SGINT_LOCAL3 24 /* INDY has 8 local3 vectored irq levels */ -#define SGINT_GIO 32 /* INDY has 9 GIO irq levels */ -#define SGINT_HPCDMA 41 /* INDY has 11 HPCDMA irq _sources_ */ -#define SGINT_END 52 /* End of 'spaces' */ +#define SGINT_CPU 0 /* MIPS CPU define 8 interrupt sources */ +#define SGINT_LOCAL0 8 /* INDY has 8 local0 irq levels */ +#define SGINT_LOCAL1 16 /* INDY has 8 local1 irq levels */ +#define SGINT_LOCAL2 24 /* INDY has 8 local2 vectored irq levels */ +#define SGINT_LOCAL3 32 /* INDY has 8 local3 vectored irq levels */ +#define SGINT_END 40 /* End of 'spaces' */ /* * Individual interrupt definitions for the INDY and Indigo2 */ -#define SGI_WD93_0_IRQ SGINT_LOCAL0 + 1 /* 1st onboard WD93 */ -#define SGI_WD93_1_IRQ SGINT_LOCAL0 + 2 /* 2nd onboard WD93 */ -#define SGI_ENET_IRQ SGINT_LOCAL0 + 3 /* onboard ethernet */ - -#define SGI_PANEL_IRQ SGINT_LOCAL1 + 1 /* front panel */ -#define SGI_VINO_IRQ SGINT_LOCAL1 + 6 /* Indy VINO */ - -#define SGI_EISA_IRQ SGINT_LOCAL2 + 3 /* EISA interrupts */ +#define SGI_LOCAL_0_IRQ SGINT_CPU + 2 +#define SGI_LOCAL_1_IRQ SGINT_CPU + 3 +#define SGI_BUSERR_IRQ SGINT_CPU + 6 +#define SGI_TIMER_IRQ SGINT_CPU + 7 + +#define SGI_FIFO_IRQ SGINT_LOCAL0 + 0 /* FIFO full */ +#define SGI_GIO_0_IRQ SGI_FIFO_IRQ /* GIO-0 */ +#define SGI_WD93_0_IRQ SGINT_LOCAL0 + 1 /* 1st onboard WD93 */ +#define SGI_WD93_1_IRQ SGINT_LOCAL0 + 2 /* 2nd onboard WD93 */ +#define SGI_ENET_IRQ SGINT_LOCAL0 + 3 /* onboard ethernet */ +#define SGI_MCDMA_IRQ SGINT_LOCAL0 + 4 /* MC DMA done */ +#define SGI_PARPORT_IRQ SGINT_LOCAL0 + 5 /* Parallel port */ +#define SGI_GIO_1_IRQ SGINT_LOCAL0 + 6 /* GE / GIO-1 / 2nd-HPC */ +#define SGI_MAP_0_IRQ SGINT_LOCAL0 + 7 /* Mappable interrupt 0 */ + +#define SGI_GPL0_IRQ SGINT_LOCAL1 + 0 /* General Purpose LOCAL1_N<0> */ +#define SGI_PANEL_IRQ SGINT_LOCAL1 + 1 /* front panel */ +#define SGI_GPL2_IRQ SGINT_LOCAL1 + 2 /* General Purpose LOCAL1_N<2> */ +#define SGI_MAP_1_IRQ SGINT_LOCAL1 + 3 /* Mappable interrupt 1 */ +#define SGI_HPCDMA_IRQ SGINT_LOCAL1 + 4 /* HPC DMA done */ +#define SGI_ACFAIL_IRQ SGINT_LOCAL1 + 5 /* AC fail */ +#define SGI_VINO_IRQ SGINT_LOCAL1 + 6 /* Indy VINO */ +#define SGI_GIO_2_IRQ SGINT_LOCAL1 + 7 /* Vert retrace / GIO-2 */ + +/* Mapped interrupts. These interrupts may be mapped to either 0, or 1 + * We map them to 0 */ +#define SGI_VERT_IRQ SGINT_LOCAL2 + 0 /* INT3: newport vertical status */ +#define SGI_EISA_IRQ SGINT_LOCAL2 + 3 /* EISA interrupts */ #define SGI_KEYBOARD_IRQ SGINT_LOCAL2 + 4 /* keyboard */ -#define SGI_SERIAL_IRQ SGINT_LOCAL2 + 5 /* onboard serial */ +#define SGI_SERIAL_IRQ SGINT_LOCAL2 + 5 /* onboard serial */ /* INT2 occupies HPC PBUS slot 4, INT3 uses slot 6. */ -#define SGI_INT2_BASE 0x1fbd9000 /* physical */ -#define SGI_INT3_BASE 0x1fbd9880 /* physical */ +#define SGI_INT2_BASE 0x1fbd9000 /* physical */ +#define SGI_INT3_BASE 0x1fbd9880 /* physical */ struct sgi_ioc_ints { #ifdef __MIPSEB__ unsigned char _unused0[3]; - volatile unsigned char istat0; /* Interrupt status zero */ + volatile unsigned char istat0; /* Interrupt status zero */ #else - volatile unsigned char istat0; /* Interrupt status zero */ + volatile unsigned char istat0; /* Interrupt status zero */ unsigned char _unused0[3]; #endif -#define ISTAT0_FFULL 0x01 -#define ISTAT0_SCSI0 0x02 -#define ISTAT0_SCSI1 0x04 -#define ISTAT0_ENET 0x08 -#define ISTAT0_GFXDMA 0x10 -#define ISTAT0_LPR 0x20 -#define ISTAT0_HPC2 0x40 -#define ISTAT0_LIO2 0x80 - +#define ISTAT0_FFULL 0x01 +#define ISTAT0_SCSI0 0x02 +#define ISTAT0_SCSI1 0x04 +#define ISTAT0_ENET 0x08 +#define ISTAT0_GFXDMA 0x10 +#define ISTAT0_LPR 0x20 +#define ISTAT0_HPC2 0x40 +#define ISTAT0_LIO2 0x80 + #ifdef __MIPSEB__ unsigned char _unused1[3]; - volatile unsigned char imask0; /* Interrupt mask zero */ + volatile unsigned char imask0; /* Interrupt mask zero */ unsigned char _unused2[3]; - volatile unsigned char istat1; /* Interrupt status one */ + volatile unsigned char istat1; /* Interrupt status one */ #else - volatile unsigned char imask0; /* Interrupt mask zero */ + volatile unsigned char imask0; /* Interrupt mask zero */ unsigned char _unused1[3]; - volatile unsigned char istat1; /* Interrupt status one */ + volatile unsigned char istat1; /* Interrupt status one */ unsigned char _unused2[3]; #endif -#define ISTAT1_ISDNI 0x01 -#define ISTAT1_PWR 0x02 -#define ISTAT1_ISDNH 0x04 -#define ISTAT1_LIO3 0x08 -#define ISTAT1_HPC3 0x10 -#define ISTAT1_AFAIL 0x20 -#define ISTAT1_VIDEO 0x40 -#define ISTAT1_GIO2 0x80 - +#define ISTAT1_ISDNI 0x01 +#define ISTAT1_PWR 0x02 +#define ISTAT1_ISDNH 0x04 +#define ISTAT1_LIO3 0x08 +#define ISTAT1_HPC3 0x10 +#define ISTAT1_AFAIL 0x20 +#define ISTAT1_VIDEO 0x40 +#define ISTAT1_GIO2 0x80 + #ifdef __MIPSEB__ unsigned char _unused3[3]; - volatile unsigned char imask1; /* Interrupt mask one */ + volatile unsigned char imask1; /* Interrupt mask one */ unsigned char _unused4[3]; - volatile unsigned char vmeistat; /* VME interrupt status */ + volatile unsigned char vmeistat; /* VME interrupt status */ unsigned char _unused5[3]; - volatile unsigned char cmeimask0; /* VME interrupt mask zero */ + volatile unsigned char cmeimask0; /* VME interrupt mask zero */ unsigned char _unused6[3]; - volatile unsigned char cmeimask1; /* VME interrupt mask one */ + volatile unsigned char cmeimask1; /* VME interrupt mask one */ unsigned char _unused7[3]; - volatile unsigned char cmepol; /* VME polarity */ + volatile unsigned char cmepol; /* VME polarity */ #else - volatile unsigned char imask1; /* Interrupt mask one */ + volatile unsigned char imask1; /* Interrupt mask one */ unsigned char _unused3[3]; - volatile unsigned char vmeistat; /* VME interrupt status */ + volatile unsigned char vmeistat; /* VME interrupt status */ unsigned char _unused4[3]; - volatile unsigned char cmeimask0; /* VME interrupt mask zero */ + volatile unsigned char cmeimask0; /* VME interrupt mask zero */ unsigned char _unused5[3]; - volatile unsigned char cmeimask1; /* VME interrupt mask one */ + volatile unsigned char cmeimask1; /* VME interrupt mask one */ unsigned char _unused6[3]; - volatile unsigned char cmepol; /* VME polarity */ + volatile unsigned char cmepol; /* VME polarity */ unsigned char _unused7[3]; #endif }; @@ -109,21 +132,21 @@ struct sgi_ioc_timers { #ifdef __MIPSEB__ unsigned char _unused0[3]; - volatile unsigned char tcnt0; /* counter 0 */ + volatile unsigned char tcnt0; /* counter 0 */ unsigned char _unused1[3]; - volatile unsigned char tcnt1; /* counter 1 */ + volatile unsigned char tcnt1; /* counter 1 */ unsigned char _unused2[3]; - volatile unsigned char tcnt2; /* counter 2 */ + volatile unsigned char tcnt2; /* counter 2 */ unsigned char _unused3[3]; - volatile unsigned char tcword; /* control word */ + volatile unsigned char tcword; /* control word */ #else - volatile unsigned char tcnt0; /* counter 0 */ + volatile unsigned char tcnt0; /* counter 0 */ unsigned char _unused0[3]; - volatile unsigned char tcnt1; /* counter 1 */ + volatile unsigned char tcnt1; /* counter 1 */ unsigned char _unused1[3]; - volatile unsigned char tcnt2; /* counter 2 */ + volatile unsigned char tcnt2; /* counter 2 */ unsigned char _unused2[3]; - volatile unsigned char tcword; /* control word */ + volatile unsigned char tcword; /* control word */ unsigned char _unused3[3]; #endif }; @@ -156,22 +179,22 @@ struct sgi_int2_regs { struct sgi_ioc_ints ints; - volatile u32 ledbits; /* LED control bits */ -#define INT2_LED_TXCLK 0x01 /* GPI to TXCLK enable */ -#define INT2_LED_SERSLCT0 0x02 /* serial port0: 0=apple 1=pc */ -#define INT2_LED_SERSLCT1 0x04 /* serial port1: 0=apple 1=pc */ -#define INT2_LED_CHEAPER 0x08 /* 0=cheapernet 1=ethernet */ -#define INT2_LED_POWEROFF 0x10 /* Power-off request, active high */ + volatile u32 ledbits; /* LED control bits */ +#define INT2_LED_TXCLK 0x01 /* GPI to TXCLK enable */ +#define INT2_LED_SERSLCT0 0x02 /* serial port0: 0=apple 1=pc */ +#define INT2_LED_SERSLCT1 0x04 /* serial port1: 0=apple 1=pc */ +#define INT2_LED_CHEAPER 0x08 /* 0=cheapernet 1=ethernet */ +#define INT2_LED_POWEROFF 0x10 /* Power-off request, active high */ #ifdef __MIPSEB__ unsigned char _unused0[3]; - volatile unsigned char tclear; /* Timer clear strobe address */ + volatile unsigned char tclear; /* Timer clear strobe address */ #else - volatile unsigned char tclear; /* Timer clear strobe address */ + volatile unsigned char tclear; /* Timer clear strobe address */ unsigned char _unused0[3]; #endif -#define INT2_TCLEAR_T0CLR 0x1 /* Clear timer0 IRQ */ -#define INT2_TCLEAR_T1CLR 0x2 /* Clear timer1 IRQ */ +#define INT2_TCLEAR_T0CLR 0x1 /* Clear timer0 IRQ */ +#define INT2_TCLEAR_T1CLR 0x2 /* Clear timer1 IRQ */ /* I am guesing there are only two unused registers here * but I could be wrong... - andrewb */ @@ -185,12 +208,12 @@ #ifdef __MIPSEB__ unsigned char _unused0[3]; - volatile unsigned char tclear; /* Timer clear strobe address */ + volatile unsigned char tclear; /* Timer clear strobe address */ #else - volatile unsigned char tclear; /* Timer clear strobe address */ + volatile unsigned char tclear; /* Timer clear strobe address */ unsigned char _unused0[3]; #endif - volatile u32 estatus; /* Error status reg */ + volatile u32 estatus; /* Error status reg */ u32 _unused1[2]; struct sgi_ioc_timers timers; }; Index: linux/arch/mips/sgi/kernel/indy_int.c =================================================================== RCS file: /cvs/linux/arch/mips/sgi/kernel/indy_int.c,v retrieving revision 1.30 diff -u -r1.30 indy_int.c --- linux/arch/mips/sgi/kernel/indy_int.c 2001/11/14 02:40:09 1.30 +++ linux/arch/mips/sgi/kernel/indy_int.c 2001/11/16 12:10:03 @@ -7,54 +7,26 @@ * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) * - Indigo2 changes * - Interrupt handling fixes + * Copyright (C) 2001 Ladislav Michl (ladis@psi.cz) */ -#include <linux/init.h> -#include <linux/errno.h> +#include <linux/types.h> +#include <linux/init.h> #include <linux/kernel_stat.h> #include <linux/signal.h> #include <linux/sched.h> -#include <linux/types.h> #include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/timex.h> -#include <linux/slab.h> -#include <linux/random.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> - -#include <asm/bitops.h> -#include <asm/bootinfo.h> -#include <asm/io.h> + #include <asm/irq.h> #include <asm/mipsregs.h> -#include <asm/system.h> - -#include <asm/ptrace.h> -#include <asm/processor.h> -#include <asm/sgi/sgi.h> -#include <asm/sgi/sgihpc.h> -#include <asm/sgi/sgint23.h> -#include <asm/sgialib.h> +#include <asm/addrspace.h> #include <asm/gdb-stub.h> -/* - * Linux has a controller-independent x86 interrupt architecture. - * every controller has a 'controller-template', that is used - * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the apropriate - * controller. Thus drivers need not be aware of the - * interrupt-controller. - * - * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, - * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. - * (IO-APICs assumed to be messaging to Pentium local-APICs) - * - * the code is designed to be easily extended with new/different - * interrupt controllers, without having to do assembly magic. - */ +#include <asm/sgi/sgint23.h> +#include <asm/sgi/sgihpc.h> /* #define DEBUG_SGINT */ +#undef I_REALLY_NEED_THIS_IRQ struct sgi_int2_regs *sgi_i2regs; struct sgi_int3_regs *sgi_i3regs; @@ -68,30 +40,23 @@ static char lc3msk_to_irqnr[256]; extern asmlinkage void indyIRQ(void); +extern void do_IRQ(int irq, struct pt_regs *regs); -/* Local IRQ's are layed out logically like this: - * - * 0 --> 7 == local 0 interrupts - * 8 --> 15 == local 1 interrupts - * 16 --> 23 == vectored level 2 interrupts - * 24 --> 31 == vectored level 3 interrupts (not used) - * 32 --> 40 == vectored GIO interrupts - * 41 --> 52 == vectored HPCDMA interrupts - */ - static void enable_local0_irq(unsigned int irq) { unsigned long flags; save_and_cli(flags); - ioc_icontrol->imask0 |= (1 << (irq - SGINT_LOCAL0)); + /* don't allow mappable interrupt to be enabled from setup_irq, + * we have our own way to do so */ + if (irq != SGI_MAP_0_IRQ) + ioc_icontrol->imask0 |= (1 << (irq - SGINT_LOCAL0)); restore_flags(flags); } static unsigned int startup_local0_irq(unsigned int irq) { enable_local0_irq(irq); - return 0; /* Never anything pending */ } @@ -129,14 +94,16 @@ unsigned long flags; save_and_cli(flags); - ioc_icontrol->imask1 |= (1 << (irq - SGINT_LOCAL1)); + /* don't allow mappable interrupt to be enabled from setup_irq, + * we have our own way to do so */ + if (irq != SGI_MAP_1_IRQ) + ioc_icontrol->imask1 |= (1 << (irq - SGINT_LOCAL1)); restore_flags(flags); } static unsigned int startup_local1_irq(unsigned int irq) { enable_local1_irq(irq); - return 0; /* Never anything pending */ } @@ -145,7 +112,7 @@ unsigned long flags; save_and_cli(flags); - ioc_icontrol->imask1 &= ~(1 << (irq- SGINT_LOCAL1)); + ioc_icontrol->imask1 &= ~(1 << (irq - SGINT_LOCAL1)); restore_flags(flags); } @@ -174,7 +141,7 @@ unsigned long flags; save_and_cli(flags); - enable_local0_irq(7); + ioc_icontrol->imask0 |= (1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0)); ioc_icontrol->cmeimask0 |= (1 << (irq - SGINT_LOCAL2)); restore_flags(flags); } @@ -182,7 +149,6 @@ static unsigned int startup_local2_irq(unsigned int irq) { enable_local2_irq(irq); - return 0; /* Never anything pending */ } @@ -192,6 +158,8 @@ save_and_cli(flags); ioc_icontrol->cmeimask0 &= ~(1 << (irq - SGINT_LOCAL2)); + if (!ioc_icontrol->cmeimask0) + ioc_icontrol->imask0 &= ~(1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0)); restore_flags(flags); } @@ -217,18 +185,21 @@ static void enable_local3_irq(unsigned int irq) { +#ifdef I_REALLY_NEED_THIS_IRQ unsigned long flags; - + save_and_cli(flags); - printk("Yeeee, got passed irq_nr %d at enable_local3_irq\n", irq); - panic("Invalid IRQ level!"); + ioc_icontrol->imask1 |= (1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1)); + ioc_icontrol->cmeimask1 |= (1 << (irq - SGINT_LOCAL3)); restore_flags(flags); +#else + panic("Who need local 3 irq? see indy_int.c\n"); +#endif } static unsigned int startup_local3_irq(unsigned int irq) { enable_local3_irq(irq); - return 0; /* Never anything pending */ } @@ -237,12 +208,9 @@ unsigned long flags; save_and_cli(flags); - /* - * This way we'll see if anyone would ever want vectored level 3 - * interrupts. Highly unlikely. - */ - printk("Yeeee, got passed irq_nr %d at disable_local3_irq\n", irq); - panic("Invalid IRQ level!"); + ioc_icontrol->cmeimask1 &= ~(1 << (irq - SGINT_LOCAL3)); + if (!ioc_icontrol->cmeimask1) + ioc_icontrol->imask1 &= ~(1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1)); restore_flags(flags); } @@ -266,80 +234,6 @@ NULL }; -void enable_gio_irq(unsigned int irq) -{ - /* XXX TODO XXX */ -} - -static unsigned int startup_gio_irq(unsigned int irq) -{ - enable_gio_irq(irq); - - return 0; /* Never anything pending */ -} - -void disable_gio_irq(unsigned int irq) -{ - /* XXX TODO XXX */ -} - -#define shutdown_gio_irq disable_gio_irq -#define mask_and_ack_gio_irq disable_gio_irq - -static void end_gio_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_gio_irq(irq); -} - -static struct hw_interrupt_type ip22_gio_irq_type = { - "IP22 GIO", - startup_gio_irq, - shutdown_gio_irq, - enable_gio_irq, - disable_gio_irq, - mask_and_ack_gio_irq, - end_gio_irq, - NULL -}; - -void enable_hpcdma_irq(unsigned int irq) -{ - /* XXX TODO XXX */ -} - -static unsigned int startup_hpcdma_irq(unsigned int irq) -{ - enable_hpcdma_irq(irq); - - return 0; /* Never anything pending */ -} - -void disable_hpcdma_irq(unsigned int irq) -{ - /* XXX TODO XXX */ -} - -#define shutdown_hpcdma_irq disable_hpcdma_irq -#define mask_and_ack_hpcdma_irq disable_hpcdma_irq - -static void end_hpcdma_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_hpcdma_irq(irq); -} - -static struct hw_interrupt_type ip22_hpcdma_irq_type = { - "IP22 HPC DMA", - startup_hpcdma_irq, - shutdown_hpcdma_irq, - enable_hpcdma_irq, - disable_hpcdma_irq, - mask_and_ack_hpcdma_irq, - end_hpcdma_irq, - NULL -}; - void indy_local0_irqdispatch(struct pt_regs *regs) { unsigned char mask = ioc_icontrol->istat0; @@ -369,16 +263,17 @@ mask &= ioc_icontrol->imask1; if (mask & ISTAT1_LIO3) { - printk("WHee: Got an LIO3 irq, winging it...\n"); +#ifndef I_REALLY_NEED_THIS_IRQ + printk("Whee: Got an LIO3 irq, winging it...\n"); +#endif mask2 = ioc_icontrol->vmeistat; mask2 &= ioc_icontrol->cmeimask1; - irq = lc3msk_to_irqnr[ioc_icontrol->vmeistat]; + irq = lc3msk_to_irqnr[mask2]; } else { irq = lc1msk_to_irqnr[mask]; } /* if irq == 0, then the interrupt has already been cleared */ - /* not sure if it is needed here, but it is needed for local0 */ if (irq) do_IRQ(irq, regs); return; @@ -387,16 +282,35 @@ void indy_buserror_irq(struct pt_regs *regs) { int cpu = smp_processor_id(); - int irq = 6; + int irq = SGI_BUSERR_IRQ; irq_enter(cpu, irq); - kstat.irqs[0][irq]++; + kstat.irqs[cpu][irq]++; die("Got a bus error IRQ, shouldn't happen yet\n", regs); printk("Spinning...\n"); while(1); irq_exit(cpu, irq); } +static struct irqaction local0_cascade = + { no_action, SA_INTERRUPT, 0, "local0 cascade", NULL, NULL }; +static struct irqaction local1_cascade = + { no_action, SA_INTERRUPT, 0, "local1 cascade", NULL, NULL }; +static struct irqaction buserr = + { no_action, SA_INTERRUPT, 0, "Bus Error", NULL, NULL }; +static struct irqaction timer = + { no_action, SA_INTERRUPT, 0, "R4k Timer", NULL, NULL }; +static struct irqaction map0_cascade = + { no_action, SA_INTERRUPT, 0, "mappable0 cascade", NULL, NULL }; +#ifdef I_REALLY_NEED_THIS_IRQ +static struct irqaction map1_cascade = + { no_action, SA_INTERRUPT, 0, "mappable1 cascade", NULL, NULL }; +#endif + +extern int setup_irq(unsigned int irq, struct irqaction *irqaction); +extern void mips_cpu_irq_init(u32 irq_base); +extern void init_generic_irq(void); + void __init init_IRQ(void) { int i; @@ -407,45 +321,45 @@ /* Init local mask --> irq tables. */ for (i = 0; i < 256; i++) { if (i & 0x80) { - lc0msk_to_irqnr[i] = 7; - lc1msk_to_irqnr[i] = 15; - lc2msk_to_irqnr[i] = 23; - lc3msk_to_irqnr[i] = 31; + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 7; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 7; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 7; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 7; } else if (i & 0x40) { - lc0msk_to_irqnr[i] = 6; - lc1msk_to_irqnr[i] = 14; - lc2msk_to_irqnr[i] = 22; - lc3msk_to_irqnr[i] = 30; + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 6; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 6; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 6; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 6; } else if (i & 0x20) { - lc0msk_to_irqnr[i] = 5; - lc1msk_to_irqnr[i] = 13; - lc2msk_to_irqnr[i] = 21; - lc3msk_to_irqnr[i] = 29; + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 5; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 5; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 5; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 5; } else if (i & 0x10) { - lc0msk_to_irqnr[i] = 4; - lc1msk_to_irqnr[i] = 12; - lc2msk_to_irqnr[i] = 20; - lc3msk_to_irqnr[i] = 28; + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 4; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 4; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 4; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 4; } else if (i & 0x08) { - lc0msk_to_irqnr[i] = 3; - lc1msk_to_irqnr[i] = 11; - lc2msk_to_irqnr[i] = 19; - lc3msk_to_irqnr[i] = 27; + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 3; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 3; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 3; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 3; } else if (i & 0x04) { - lc0msk_to_irqnr[i] = 2; - lc1msk_to_irqnr[i] = 10; - lc2msk_to_irqnr[i] = 18; - lc3msk_to_irqnr[i] = 26; + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 2; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 2; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 2; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 2; } else if (i & 0x02) { - lc0msk_to_irqnr[i] = 1; - lc1msk_to_irqnr[i] = 9; - lc2msk_to_irqnr[i] = 17; - lc3msk_to_irqnr[i] = 25; + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 1; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 1; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 1; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 1; } else if (i & 0x01) { - lc0msk_to_irqnr[i] = 0; - lc1msk_to_irqnr[i] = 8; - lc2msk_to_irqnr[i] = 16; - lc3msk_to_irqnr[i] = 24; + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 0; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 0; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 0; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 0; } else { lc0msk_to_irqnr[i] = 0; lc1msk_to_irqnr[i] = 0; @@ -474,6 +388,8 @@ set_except_vector(0, indyIRQ); init_generic_irq(); + /* init CPU irqs */ + mips_cpu_irq_init(SGINT_CPU); for (i = SGINT_LOCAL0; i < SGINT_END; i++) { hw_irq_controller *handler; @@ -484,16 +400,27 @@ handler = &ip22_local1_irq_type; else if (i < SGINT_LOCAL3) handler = &ip22_local2_irq_type; - else if (i < SGINT_GIO) + else handler = &ip22_local3_irq_type; - else if (i < SGINT_HPCDMA) - handler = &ip22_gio_irq_type; - else if (i < SGINT_END) - handler = &ip22_hpcdma_irq_type; irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = 0; irq_desc[i].depth = 1; irq_desc[i].handler = handler; } + + /* vector handler. this register the IRQ as non-sharable */ + setup_irq(SGI_LOCAL_0_IRQ, &local0_cascade); + setup_irq(SGI_LOCAL_1_IRQ, &local1_cascade); + setup_irq(SGI_BUSERR_IRQ, &buserr); +/* This can't be enabled yet. we need to use CONFIG_NEW_TIME_C + * hopefully i'll rewrite it in couple of days. --ladis + setup_irq(SGI_TIMER_IRQ, &timer); +*/ + + /* cascade in cascade. i love Indy ;-) */ + setup_irq(SGI_MAP_0_IRQ, &map0_cascade); +#ifdef I_REALLY_NEED_THIS_IRQ + setup_irq(SGI_MAP_1_IRQ, &map1_cascade); +#endif } Index: linux/arch/mips/sgi/kernel/setup.c =================================================================== RCS file: /cvs/linux/arch/mips/sgi/kernel/setup.c,v retrieving revision 1.46 diff -u -r1.46 setup.c --- linux/arch/mips/sgi/kernel/setup.c 2001/08/23 22:24:24 1.46 +++ linux/arch/mips/sgi/kernel/setup.c 2001/11/16 12:10:08 @@ -302,7 +302,4 @@ #ifdef CONFIG_PSMOUSE aux_device_present = 0xaa; #endif -#ifdef CONFIG_VIDEO_VINO - init_vino(); -#endif } Index: linux/arch/mips/sgi/kernel/time.c =================================================================== RCS file: /cvs/linux/arch/mips/sgi/kernel/time.c,v retrieving revision 1.6 diff -u -r1.6 time.c --- linux/arch/mips/sgi/kernel/time.c 2001/03/18 04:20:23 1.6 +++ linux/arch/mips/sgi/kernel/time.c 2001/11/16 12:10:08 @@ -13,7 +13,7 @@ int irq = 4; irq_enter(cpu, irq); - kstat.irqs[0][irq]++; + kstat.irqs[cpu][irq]++; printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n"); prom_getchar(); ArcEnterInteractiveMode(); Index: linux/arch/mips/config.in =================================================================== RCS file: /cvs/linux/arch/mips/config.in,v retrieving revision 1.144 diff -u -r1.144 config.in --- linux/arch/mips/config.in 2001/11/13 05:40:00 1.144 +++ linux/arch/mips/config.in 2001/11/16 12:43:33 @@ -177,6 +177,7 @@ define_bool CONFIG_BOARD_SCACHE y define_bool CONFIG_PC_KEYB y define_bool CONFIG_SGI y + define_bool CONFIG_IRQ_CPU y define_bool CONFIG_NEW_IRQ y define_bool CONFIG_OLD_TIME_C y fi