Subject: [PATCH] indy_int clenaup

From: Ladislav Michl <[email-masked]>
Date: Fri, 16 Nov 2001 13:49:22 +0100 (CET)

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 ([email-masked])
  * Copyright (C) 1997, 98, 1999, 2000 Ralf Baechle
  * Copyright (C) 1999 Andrew R. Baker ([email-masked]) - INT2 corrections
+ * Copyright (C) 2001 Ladislav Michl ([email-masked])
  */
 #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 ([email-masked]) 
  *                    - Indigo2 changes
  *                    - Interrupt handling fixes
+ * Copyright (C) 2001 Ladislav Michl ([email-masked])
  */
-#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

---

From: Guido Guenther <[email-masked]>
Date: Fri, 16 Nov 2001 14:21:43 +0100

> this patch is HAL2 driver by-product...
I've done some work on porting Ulf's old ALSA HAL2 codebase to a more recent
(0.9) version of alsa, could that be of any use to you? 
 -- Guido

---

From: Ladislav Michl <[email-masked]>
Date: Fri, 16 Nov 2001 14:52:01 +0100 (CET)

> (0.9) version of alsa, could that be of any use to you? 

wow, so many people working on HAL2 :-) Klaus?

this is not useful for me, moreover i reworked HPC buffers handling (so
maybye, it will be usefull for you :-)). OSS kernel driver is working now.
it need some testing and cleanup, but it is mostly finished. i want to
listen music, so i implemented pcm playback and mixer only.

my plan is:
1. convience Ralf to include indy_int patch to cvs :-)
2. write and send CONFIG_NEW_TIME_C patch for Indy
3. once these will be included, send HAL2 driver.

btw, if anyone wants to look at vino driver here it is:
ftp://ftp.psi.cz/pub/ladis/vino/

regards,
ladis