diff options
-rw-r--r-- | sys/arch/sgi/gio/gio.c | 21 | ||||
-rw-r--r-- | sys/arch/sgi/localbus/int.c | 89 | ||||
-rw-r--r-- | sys/arch/sgi/localbus/intreg.h | 57 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/eisa_machdep.c | 6 |
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 * |