summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/sgi/gio/gio.c21
-rw-r--r--sys/arch/sgi/localbus/int.c89
-rw-r--r--sys/arch/sgi/localbus/intreg.h57
-rw-r--r--sys/arch/sgi/sgi/eisa_machdep.c6
4 files changed, 120 insertions, 53 deletions
diff --git a/sys/arch/sgi/gio/gio.c b/sys/arch/sgi/gio/gio.c
index b201adab5b9..b8b31b6be2b 100644
--- a/sys/arch/sgi/gio/gio.c
+++ b/sys/arch/sgi/gio/gio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gio.c,v 1.1 2012/03/28 20:44:23 miod Exp $ */
+/* $OpenBSD: gio.c,v 1.2 2012/04/15 20:44:51 miod Exp $ */
/* $NetBSD: gio.c,v 1.32 2011/07/01 18:53:46 dyoung Exp $ */
/*
@@ -47,6 +47,7 @@
#include <sgi/gio/giodevs_data.h>
#include <sgi/localbus/imcvar.h>
+#include <sgi/localbus/intreg.h>
#include <sgi/localbus/intvar.h>
#include <sgi/sgi/ip22.h>
@@ -468,10 +469,15 @@ gio_arb_config(int slot, uint32_t flags)
}
/*
- * Establish an interrupt handler for the specified slot.
+ * Establish an interrupt handler for expansion boards (not frame buffers!)
+ * in the specified slot.
*
- * Indy and Challenge S have an interrupt per GIO slot. Indigo and Indigo2
- * share a single interrupt, however.
+ * Indy and Challenge S have a single GIO interrupt per GIO slot, but
+ * distinct slot interrups. Indigo and Indigo2 have three GIO interrupts per
+ * slot, but at a given GIO interrupt level, all slots share the same
+ * interrupt on the interrupt controller.
+ *
+ * Expansion boards appear to always use the intermediate level.
*/
void *
gio_intr_establish(int slot, int level, int (*func)(void *), void *arg,
@@ -483,7 +489,7 @@ gio_intr_establish(int slot, int level, int (*func)(void *), void *arg,
case SGI_IP20:
if (slot == GIO_SLOT_GFX)
return NULL;
- intr = 6;
+ intr = INT2_L0_INTR(INT2_L0_GIO_LVL1);
break;
case SGI_IP22:
case SGI_IP26:
@@ -491,11 +497,12 @@ gio_intr_establish(int slot, int level, int (*func)(void *), void *arg,
if (sys_config.system_subtype == IP22_INDIGO2) {
if (slot == GIO_SLOT_EXP1)
return NULL;
- intr = 6;
+ intr = INT2_L0_INTR(INT2_L0_GIO_LVL1);
} else {
if (slot == GIO_SLOT_GFX)
return NULL;
- intr = (slot == GIO_SLOT_EXP0) ? 22 : 23;
+ intr = INT2_MAP1_INTR(slot == GIO_SLOT_EXP0 ?
+ INT2_MAP_GIO_SLOT0 : INT2_MAP_GIO_SLOT1);
}
break;
default:
diff --git a/sys/arch/sgi/localbus/int.c b/sys/arch/sgi/localbus/int.c
index 01e8b2a5dde..e521bce3c69 100644
--- a/sys/arch/sgi/localbus/int.c
+++ b/sys/arch/sgi/localbus/int.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: int.c,v 1.1 2012/03/28 20:44:23 miod Exp $ */
+/* $OpenBSD: int.c,v 1.2 2012/04/15 20:44:52 miod Exp $ */
/* $NetBSD: int.c,v 1.24 2011/07/01 18:53:46 dyoung Exp $ */
/*
@@ -30,7 +30,7 @@
*/
/*
- * INT2 (IP20, IP22) /INT3 (IP24) interrupt controllers
+ * INT2 (IP20, IP22) / INT3 (IP24) interrupt controllers
*/
#include <sys/param.h>
@@ -66,6 +66,7 @@ struct cfdriver int_cd = {
};
paddr_t int2_base;
+paddr_t int2_get_base(void);
#define int2_read(r) *(volatile uint8_t *)(int2_base + (r))
#define int2_write(r, v) *(volatile uint8_t *)(int2_base + (r)) = (v)
@@ -167,6 +168,9 @@ int2_intr_establish(int irq, int level, int (*ih_fun) (void *),
#ifdef DIAGNOSTIC
if (irq < 0 || irq >= INT2_NINTS)
panic("int2_intr_establish: illegal irq %d", irq);
+ /* Mappable interrupts can't be above IPL_TTY */
+ if ((irq >> 3) >= 2 && level > IPL_TTY)
+ return NULL;
#endif
ih = malloc(sizeof *ih, M_DEVBUF, M_NOWAIT);
@@ -200,12 +204,12 @@ int2_intr_establish(int irq, int level, int (*ih_fun) (void *),
* masked as a whole, by the level 0 or 1 interrupt they cascade to.
*/
case 2:
- int2_write(INT2_MAP_MASK0,
- int2_read(INT2_MAP_MASK0) | (1 << (irq & 7)));
+ int2_write(INT2_IP22_MAP_MASK0,
+ int2_read(INT2_IP22_MAP_MASK0) | (1 << (irq & 7)));
break;
case 3:
- int2_write(INT2_MAP_MASK1,
- int2_read(INT2_MAP_MASK1) | (1 << (irq & 7)));
+ int2_write(INT2_IP22_MAP_MASK1,
+ int2_read(INT2_IP22_MAP_MASK1) | (1 << (irq & 7)));
break;
}
@@ -241,13 +245,15 @@ int
int2_mappable_intr(void *arg)
{
uint which = (unsigned long)arg;
+ vaddr_t imrreg;
uint64_t imr, isr;
uint i, intnum;
struct intrhand *ih;
int rc, ret;
- isr = int2_read(INT2_MAP_STATUS);
- imr = int2_read(INT2_MAP_MASK0 + (which << 2));
+ imrreg = which == 0 ? INT2_IP22_MAP_MASK0 : INT2_IP22_MAP_MASK1;
+ isr = int2_read(INT2_IP22_MAP_STATUS);
+ imr = int2_read(imrreg);
isr &= imr;
if (isr == 0)
@@ -259,7 +265,6 @@ int2_mappable_intr(void *arg)
* is registered at IPL_TTY, so we can safely assume we are running
* at IPL_TTY now.
*/
-
for (i = 0; i < 8; i++) {
intnum = i + 16 + (which << 3);
if (isr & (1 << i)) {
@@ -305,31 +310,16 @@ int2_match(struct device *parent, void *match, void *aux)
void
int2_attach(struct device *parent, struct device *self, void *aux)
{
- uint32_t address;
-
- switch (sys_config.system_type) {
- case SGI_IP20:
- address = INT2_IP20;
- break;
- default:
- case SGI_IP22:
- case SGI_IP26:
- case SGI_IP28:
- if (sys_config.system_subtype == IP22_INDIGO2)
- address = INT2_IP22;
- else
- address = INT2_IP24;
- break;
- }
+ if (int2_base == 0)
+ int2_base = int2_get_base();
- printf(" addr 0x%x\n", address);
- int2_base = PHYS_TO_XKPHYS((uint64_t)address, CCA_NC);
+ printf(" addr 0x%x\n", XKPHYS_TO_PHYS(int2_base));
/* Clean out interrupt masks */
int2_write(INT2_LOCAL0_MASK, 0);
int2_write(INT2_LOCAL1_MASK, 0);
- int2_write(INT2_MAP_MASK0, 0);
- int2_write(INT2_MAP_MASK1, 0);
+ int2_write(INT2_IP22_MAP_MASK0, 0);
+ int2_write(INT2_IP22_MAP_MASK1, 0);
/* Reset timer interrupts */
int2_write(INT2_TIMER_CONTROL,
@@ -347,12 +337,35 @@ int2_attach(struct device *parent, struct device *self, void *aux)
register_splx_handler(int2_splx);
if (sys_config.system_type != SGI_IP20) {
- /* Wire interrupts 7, 11 to mappable interrupt 0,1 handlers */
- int2_intr_establish(7, IPL_TTY, int2_mappable_intr,
- (void *)0, NULL);
- int2_intr_establish(8 + 3, IPL_TTY, int2_mappable_intr,
- (void *)1, NULL);
+ /* Wire mappable interrupt handlers */
+ int2_intr_establish(INT2_L0_INTR(INT2_L0_IP22_MAP0), IPL_TTY,
+ int2_mappable_intr, (void *)0, NULL);
+ int2_intr_establish(INT2_L1_INTR(INT2_L1_IP22_MAP1), IPL_TTY,
+ int2_mappable_intr, (void *)1, NULL);
+ }
+}
+
+paddr_t
+int2_get_base(void)
+{
+ uint32_t address;
+
+ switch (sys_config.system_type) {
+ case SGI_IP20:
+ address = INT2_IP20;
+ break;
+ default:
+ case SGI_IP22:
+ case SGI_IP26:
+ case SGI_IP28:
+ if (sys_config.system_subtype == IP22_INDIGO2)
+ address = INT2_IP22;
+ else
+ address = INT2_IP24;
+ break;
}
+
+ return PHYS_TO_XKPHYS((uint64_t)address, CCA_NC);
}
/*
@@ -362,8 +375,8 @@ void
int2_wait_fifo(uint32_t flag)
{
if (int2_base == 0)
- delay(5000); /* XXX */
- else
- while (int2_read(INT2_LOCAL0_STATUS) & flag)
- ;
+ int2_base = int2_get_base();
+
+ while (int2_read(INT2_LOCAL0_STATUS) & flag)
+ ;
}
diff --git a/sys/arch/sgi/localbus/intreg.h b/sys/arch/sgi/localbus/intreg.h
index c6deca4e933..c06b4df8c02 100644
--- a/sys/arch/sgi/localbus/intreg.h
+++ b/sys/arch/sgi/localbus/intreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: intreg.h,v 1.1 2012/03/28 20:44:23 miod Exp $ */
+/* $OpenBSD: intreg.h,v 1.2 2012/04/15 20:44:52 miod Exp $ */
/* $NetBSD: int2reg.h,v 1.5 2009/02/12 06:33:57 rumble Exp $ */
/*
@@ -39,13 +39,60 @@
#define INT2_LOCAL0_MASK 0x07
#define INT2_LOCAL1_STATUS 0x0b
#define INT2_LOCAL1_MASK 0x0f
-#define INT2_MAP_STATUS 0x13
-#define INT2_MAP_MASK0 0x17
-#define INT2_MAP_MASK1 0x1b
-#define INT2_MAP_POL 0x1f
+#define INT2_IP22_MAP_STATUS 0x13
+#define INT2_IP22_MAP_MASK0 0x17
+#define INT2_IP22_MAP_MASK1 0x1b
+#define INT2_IP22_MAP_POL 0x1f
+#define INT2_IP20_LED 0x1f
#define INT2_TIMER_CLEAR 0x23
#define INT2_ERROR_STATUS 0x27
#define INT2_TIMER_0 0x33
#define INT2_TIMER_1 0x37
#define INT2_TIMER_2 0x3b
#define INT2_TIMER_CONTROL 0x3f
+
+/* LOCAL0 bits */
+#define INT2_L0_FIFO 0
+#define INT2_L0_GIO_SLOT0 0 /* IP24 */
+#define INT2_L0_GIO_LVL0 0 /* IP20/IP22 */
+#define INT2_L0_IP20_PARALLEL 1
+#define INT2_L0_IP22_SCSI0 1
+#define INT2_L0_SCSI1 2
+#define INT2_L0_ENET 3
+#define INT2_L0_GFX_DMA 4
+#define INT2_L0_IP20_SERIAL 5
+#define INT2_L0_IP22_PARALLEL 5
+#define INT2_L0_GIO_LVL1 6 /* IP20/IP22 */
+#define INT2_L0_IP20_VME0 7
+#define INT2_L0_IP22_MAP0 7
+
+/* LOCAL1 bits */
+#define INT2_L1_IP24_ISDN_ISAC 0
+#define INT2_L1_IP20_GR1MODE 1 /* not an interrupt but a status bit */
+#define INT2_L1_IP22_PANEL 1
+#define INT2_L1_IP24_ISDN_HSCX 2
+#define INT2_L1_IP20_VME1 3
+#define INT2_L1_IP22_MAP1 3
+#define INT2_L1_IP20_DSP 4
+#define INT2_L1_IP22_HPC_DMA 4
+#define INT2_L1_ACFAIL 5
+#define INT2_L1_VIDEO 6
+#define INT2_L1_RETRACE 7
+#define INT2_L1_GIO_LVL2 7 /* IP20/IP22 */
+
+/* MAP bits */
+#define INT2_MAP_NEWPORT 0 /* IP24 */
+#define INT2_MAP_PASSWD 1
+#define INT2_MAP_ISDN_POWER 2 /* IP24 */
+#define INT2_MAP_EISA 3 /* IP22 */
+#define INT2_MAP_PCKBC 4
+#define INT2_MAP_SERIAL 5
+#define INT2_MAP_GFX0_DRAIN 6 /* IP22 */
+#define INT2_MAP_GIO_SLOT0 6 /* IP24 */
+#define INT2_MAP_GFX1_DRAIN 7 /* IP22 */
+#define INT2_MAP_GIO_SLOT1 7 /* IP24 */
+
+#define INT2_L0_INTR(x) ((x) + 0)
+#define INT2_L1_INTR(x) ((x) + 8)
+#define INT2_MAP0_INTR(x) ((x) + 16)
+#define INT2_MAP1_INTR(x) ((x) + 24)
diff --git a/sys/arch/sgi/sgi/eisa_machdep.c b/sys/arch/sgi/sgi/eisa_machdep.c
index d7286ee268c..4da23e87680 100644
--- a/sys/arch/sgi/sgi/eisa_machdep.c
+++ b/sys/arch/sgi/sgi/eisa_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: eisa_machdep.c,v 1.1 2012/04/02 20:40:52 miod Exp $ */
+/* $OpenBSD: eisa_machdep.c,v 1.2 2012/04/15 20:44:52 miod Exp $ */
/*
* Copyright (c) 2012 Miodrag Vallat.
@@ -23,6 +23,7 @@
#include <sys/queue.h>
#include <machine/bus.h>
+#include <sgi/localbus/intreg.h>
#include <sgi/localbus/intvar.h>
#include <dev/ic/i8259reg.h>
@@ -57,7 +58,7 @@ int eisa_intr(void *);
#define eisa_io_write(o,v) \
*(volatile uint8_t *)PHYS_TO_XKPHYS(EISA_IO_BASE | (o), CCA_NC) = (v)
-#define EISA_INT2_IRQNO (24 + 3) /* Mapped interrupt #3 */
+#define EISA_INT2_IRQNO INT2_MAP1_INTR(INT2_MAP_EISA)
/*
* EISA interrupt handlers.
@@ -99,7 +100,6 @@ eisa_intr_string(eisa_chipset_tag_t ec, eisa_intr_handle_t ih)
snprintf(irqstr, sizeof irqstr, "eisa irq %d", ih);
return irqstr;
-
}
void *