Subject: Re: EISA support

From: "William J. Earl" <[email-masked]>
Date: Mon, 2 Aug 1999 13:53:15 -0700 (PDT)

Andrew R. Baker writes:
 > 
 > While working in EISA support for the Indigo2 I have run across some
 > interesting design decisions and I would like to get some feedback.
 > 
 > First is interupt handling.  On the Indigo2 all the EISA interupts and
 > mapped down to a single INT2 interrupt.  In other words, an [E]ISA card
 > generates an interrupt, which in turn, generates an INT2 interrupt, which
 > generates a CPU interrupt.  This causes a problem because current device
 > drivers do a "request_irq" call to allocate an interrupt, on the Indy and
 > Indigo2, this procedure allocates an INT2/3 irq.  ASFAIK, this means that
 > to be supported on the Indigo2, the device driver needs to call something
 > else like "request_isa_irq", so that it can be allocated properly.  I see
 > two ways of implementing this.  The first is easier to implement, but
 > looks slightly grotesque and would involve lines like:
 > 
 > #ifndef CONFIG_SGI_EISA
 > request_irq(....);
 > #else
 > request_isa_irq(....);
 > #endif
 > 
 > the other would be to create a "request_isa_irq" procedure that defaults
 > to "request_irq" in most architectures.
 > 
 > Does anyone have any comments or suggestions on this?

      Suppose you define a range of request_irq() index values which
correspond to EISA interrupts.  The generic EISA interrupt would always
be enabled, and the selective masking would apply to various bits in the
EISA interrupt controller, in much the way that the cascading interrupts
in INT2 and INT3 are handled.

---

From: Ralf Baechle <[email-masked]>
Date: Tue, 3 Aug 1999 00:06:15 +0200

> Does anyone have any comments or suggestions on this?

The solution which we're using for other systems is to number the
interrupts such that 0 ... 15 are the (E)ISA interrupts; all other
system specific interrupts use higher numbers.  In such a scenario
request_irq() will essentially just be a demultiplexer which for
(E)ISA interrupt numbers calls request_isa_irq() etc.  You really
should try to leave the interrupt numbers unchanged as they are;
basically every (E)ISA interrupt driver has it's numbers hardwired.

  Ralf

---

From: Ralf Baechle <[email-masked]>
Date: Tue, 3 Aug 1999 00:26:24 +0200

On Tue, Aug 03, 1999 at 01:17:19AM -0500, Andrew R. Baker wrote:

> On Tue, 3 Aug 1999, Ralf Baechle wrote:
> That's basically what William Earl suggested.  I am going to change the
> SGINT_XXX defines in sgint23.h to leave space for the (E)ISA interrupts
> and get change any absolute references (like in the SCSI driver) to things
> like "SGINT_LOCAL0 + 1".   Is there anything else I should allocate some
> space for?

No, but I'd prefer symbolic names like SGINT_WD93_1 over SGINT_LOCAL0 + 1.

  Ralf

---

From: "William J. Earl" <[email-masked]>
Date: Mon, 2 Aug 1999 15:44:10 -0700 (PDT)

Andrew R. Baker writes:
 > 
 > 
 > On Mon, 2 Aug 1999, William J. Earl wrote:
...
 > I hadn't even thought about doing it that way, but after looking at the
 > existing interupt code, it shouldn't be much of a problem. My biggest
 > concern is maintaining compatability with the existing drivers. From what
 > I can tell, they all grab IRQs in the range of 1-15 (the available range
 > for EISA on x86 machines).  So the best course of action is to shift the
 > virtual IRQ numbers up to start at 16, and put the EISA irqs on the 0-15
 > range.  Are there any major things I should consider before doing this?
 > Are there any arguments against this? 

       I see that some drivers use NR_IRQS to form an IRQ_ports[] array,
to map from IRQ to board object, as in serial.c, whereas others, such as
riscom8.c, wire in 16 as the limit.   Still, you could make
probe_irq_on() and probe_irq_off() actually work for an Indy and Indigo2,
and simply declare broken any drives which do not use NR_IRQS and probe
using the probe_irq_* routines.  The biggest problem with that approach
is that NR_IRQS is 64 on mips, which means that probe_irq_on() and probe_irq_off()
would need a different interface (long long instead of int, to allow 64-bit
IRQ bit maps on 32-bit kernel).  

      Changing the MIPS symbolic IRQ mapping to put EISA in the bottom
16 slots is probably the course of least resistance.

---

From: "William J. Earl" <[email-masked]>
Date: Mon, 2 Aug 1999 16:00:46 -0700 (PDT)

Ralf Baechle writes:
...
 > basically every (E)ISA interrupt driver has it's numbers hardwired.

     That suggests that we need to renumber the levels in sgiint23.h,
moving all of them up by 16 to make room for the EISA interrupts, and
then increasing NR_IRQ to at least 68 from 64 to account for the extra
levels.

---

From: Ralf Baechle <[email-masked]>
Date: Tue, 3 Aug 1999 01:03:57 +0200

> then increasing NR_IRQ to at least 68 from 64 to account for the extra

Indeed, but I don't see a problem with that.

  Ralf

---

From: Ralf Baechle <[email-masked]>
Date: Tue, 3 Aug 1999 01:17:20 +0200

> IRQ bit maps on 32-bit kernel).  

probe_irq_{on,off} are being used for interrupt probing only and that's
an art only practiced for ISA.  So we don't even want to support these
functions for interupts >= 16, that is non (E)ISA interrupts.

  Ralf

---

From: "Andrew R. Baker" <[email-masked]>
Date: Mon, 2 Aug 1999 20:51:06 -0500 (CDT)

#ifndef CONFIG_SGI_EISA
request_irq(....);
#else
request_isa_irq(....);
#endif

The second is a request for comments on the advantages/disadvantages of
implementing EISA support as a loadable module?  There is nothing in the
running system that actually requires it to be available, and I think it
would be neat to have bus support as a module.

-Andrew

---

From: "Andrew R. Baker" <[email-masked]>
Date: Tue, 3 Aug 1999 00:41:46 -0500 (CDT)

-Andrew

---

From: "Andrew R. Baker" <[email-masked]>
Date: Tue, 3 Aug 1999 01:17:19 -0500 (CDT)

-Andrew

---

From: "Andrew R. Baker" <[email-masked]>
Date: Wed, 4 Aug 1999 23:19:27 -0500 (CDT)

Here is my first patch for moving around interrupts for future support of
EISA.  I want reassurance that I've done all of this step before I send
out the code that actually moves them around.  I have defined everything
in the form of "SGI_XXXX_IRQ" to match the definition for the keyboard irq
that used to be in sgihpc.h.  These patches go against the linux_2_2
branch but should apply to the 2.3 branch as well.  Let me know what you
think.

-Andrew 
--- linux/include/asm-mips/sgihpc.h.orig	Wed Aug  4 20:11:53 1999
+++ linux/include/asm-mips/sgihpc.h	Wed Aug  4 20:10:52 1999
@@ -330,8 +330,6 @@
 /* We need software copies of these because they are write only. */
 extern unsigned long sgi_hpc_write1, sgi_hpc_write2;
 
-#define SGI_KEYBOARD_IRQ 20
-
 struct hpc_keyb {
 #ifdef __MIPSEB__
 	unsigned char _unused0[3];
--- linux/include/asm-mips/sgint23.h.orig	Wed Aug  4 20:19:27 1999
+++ linux/include/asm-mips/sgint23.h	Wed Aug  4 22:54:39 1999
@@ -20,6 +20,19 @@
 #define SGINT_HPCDMA   41  /* INDY has 11 HPCDMA irq _sources_ */
 #define SGINT_END      52  /* 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_EISA_IRQ	SGINT_LOCAL2 + 3	/* EISA interrupts */
+#define SGI_KEYBOARD_IRQ	SGINT_LOCAL2 + 4	/* keyboard */
+#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 */
--- linux/drivers/net/sgiseeq.c.orig	Wed Aug  4 22:28:46 1999
+++ linux/drivers/net/sgiseeq.c	Wed Aug  4 21:59:15 1999
@@ -738,5 +738,5 @@
 	str2eaddr(onboard_eth_addr, ep);
 	return sgiseeq_init(dev,
 			    (struct sgiseeq_regs *) (KSEG1ADDR(0x1fbd4000)),
-			    &hpc3c0->ethregs, 3);
+			    &hpc3c0->ethregs, SGI_ENET_IRQ);
 }
--- linux/drivers/scsi/sgiwd93.c.orig	Wed Aug  4 21:59:51 1999
+++ linux/drivers/scsi/sgiwd93.c	Wed Aug  4 22:02:22 1999
@@ -281,7 +281,7 @@
 
 	sgiwd93_host = scsi_register(HPsUX, sizeof(struct WD33C93_hostdata));
 	sgiwd93_host->base = (unsigned char *) hregs;
-	sgiwd93_host->irq = 1;
+	sgiwd93_host->irq = SGI_WD93_0_IRQ;
 
 	buf = (uchar *) get_free_page(GFP_KERNEL);
 	init_hpc_chain(buf);
@@ -295,12 +295,12 @@
 	hdata->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf));
 	dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE);
 
-	request_irq(1, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host);
+	request_irq(SGI_WD93_0_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host);
         /* set up second controller on the Indigo2 */
 	if(!sgi_guiness) {
 		sgiwd93_host1 = scsi_register(HPsUX, sizeof(struct WD33C93_hostdata));
 		sgiwd93_host1->base = (unsigned char *) hregs1;
-		sgiwd93_host1->irq = 2;
+		sgiwd93_host1->irq = SGI_WD93_1_IRQ;
 
 		buf = (uchar *) get_free_page(GFP_KERNEL);
 		init_hpc_chain(buf);
@@ -314,7 +314,7 @@
 		hdata1->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf));
 		dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE);
 
-		request_irq(2, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host1);
+		request_irq(SGI_WD93_1_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host1);
 	}
 	
 	called = 1;
@@ -337,9 +337,14 @@
 int sgiwd93_release(struct Scsi_Host *instance)
 {
 #ifdef MODULE
-	free_irq(1, sgiwd93_intr);
+	free_irq(SGI_WD93_0_IRQ, sgiwd93_intr);
 	free_page(KSEG0ADDR(hdata->dma_bounce_buffer));
 	wd33c93_release();
+	if (!sgi_guiness) {
+		free_irq(SGI_WD93_1_IRQ, sgiwd93_intr);
+		free_page(KSEG0ADDR(hdata1->dma_bounce_buffer));
+		wd33c93_release();
+	}
 #endif
 	return 1;
 }
--- linux/arch/mips/sgi/kernel/reset.c.orig	Wed Aug  4 22:52:59 1999
+++ linux/arch/mips/sgi/kernel/reset.c	Wed Aug  4 21:45:59 1999
@@ -108,7 +108,7 @@
 	if (has_paniced)
 		prom_reboot();
 
-	enable_irq(9);
+	enable_irq(SGI_PANEL_IRQ);
 }
 
 static inline void power_button(void)
@@ -185,7 +185,7 @@
 	hpc3mregs->panel = 3; /* power_interrupt | power_supply_on */
 
 	if (ioc_icontrol->istat1 & 2) { /* Wait until interrupt goes away */
-		disable_irq(9);
+		disable_irq(SGI_PANEL_IRQ);
 		init_timer(&debounce_timer);
 		debounce_timer.function = debounce;
 		debounce_timer.expires = jiffies + 5;
@@ -239,7 +239,7 @@
 	_machine_halt = sgi_machine_halt;
 	_machine_power_off = sgi_machine_power_off;
 
-	request_irq(9, panel_int, 0, "Front Panel", NULL);
+	request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL);
 	init_timer(&blink_timer);
 	blink_timer.function = blink_timeout;
 	notifier_chain_register(&panic_notifier_list, &panic_block);