summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormiod <miod@openbsd.org>2012-05-17 19:46:52 +0000
committermiod <miod@openbsd.org>2012-05-17 19:46:52 +0000
commitb1650df9c5d1d61bfbe8a6d7b2ee202d819a73a0 (patch)
treebef2275c644c97f7075c7c8e01a0f1adddb3fc5a
parentBetter probes for sq and wdsc in gio-masqueraded-as-hpc expansion boards. (diff)
downloadwireguard-openbsd-b1650df9c5d1d61bfbe8a6d7b2ee202d819a73a0.tar.xz
wireguard-openbsd-b1650df9c5d1d61bfbe8a6d7b2ee202d819a73a0.zip
Yet another rework of the crucial gio_id() function responsible for correctly
recognizing a GIO device or an id-less frame buffer in a GIO slot. Turns out that GIO32 devices (at least those with a 32-bit ID register, but likely all of them) do NOT like accesses to the minimal GIO register area NOT done on 32-bit boundaries. While frame buffers won't mind, especially if their slots are pipelined. This makes it a lot easier to tell them apart. While there, split gio_intr_establish() into gio_intr_map(), which will return a logical interrupt number out of a GIO slot number, and gio_intr_establish(), which will now expect a logical interrupt number, instead of a logical slot number. These two functions are still unused, but upcoming changes depend on this work. (Yes, I'm too lazy to make two commits for this tonite)
-rw-r--r--sys/arch/sgi/gio/gio.c95
-rw-r--r--sys/arch/sgi/gio/giovar.h3
2 files changed, 33 insertions, 65 deletions
diff --git a/sys/arch/sgi/gio/gio.c b/sys/arch/sgi/gio/gio.c
index 3e6930ee9ac..214bdad8bd5 100644
--- a/sys/arch/sgi/gio/gio.c
+++ b/sys/arch/sgi/gio/gio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gio.c,v 1.9 2012/05/10 21:36:11 miod Exp $ */
+/* $OpenBSD: gio.c,v 1.10 2012/05/17 19:46:52 miod Exp $ */
/* $NetBSD: gio.c,v 1.32 2011/07/01 18:53:46 dyoung Exp $ */
/*
@@ -325,9 +325,12 @@ gio_id(vaddr_t va, paddr_t pa, int maybe_gfx)
/*
* First, attempt to read the address with various sizes.
- * If the slot is pipelined, and the address does not hit a
- * device register, we will not fault but read the transfer
- * width back.
+ *
+ * - GIO32 devices will only support reads from 32-bit aligned
+ * addresses, in all sizes (at least for the ID register).
+ * - frame buffers will support aligned reads from any size at
+ * any address, but will actually return the access width if
+ * the slot is pipelined.
*/
if (guarded_read_4(va, &id32) != 0)
@@ -354,52 +357,16 @@ gio_id(vaddr_t va, paddr_t pa, int maybe_gfx)
}
/*
- * 32-bit GIO devices may not like subword accesses to the
- * identification register. Don't bail out if any of these
- * access fails, it's probably one good sign of real GIO
- * hardware (as opposed to a non-Impact frame buffer) being
- * there.
- */
- if (GIO_PRODUCT_32BIT_ID(id32)) {
- if (guarded_read_2(va | 2, &id16) != 0 ||
- guarded_read_1(va | 3, &id8) != 0)
- return id32;
- } else {
- if (guarded_read_2(va | 2, &id16) != 0 ||
- guarded_read_1(va | 3, &id8) != 0)
- return 0;
- }
-
- /*
- * If there is a real GIO device at this address (as opposed to
- * a graphics card), then the low-order 8 bits of each read need
- * to be consistent...
+ * GIO32 devices will not answer to addresses not aligned on
+ * 32 bit boundaries.
*/
- if (id8 == (id16 & 0xff) && id8 == (id32 & 0xff)) {
- /*
- * If we are unlucky, this device will actually be a grtwo(4)
- * frame buffer, and we have read the first word of its
- * shared memory, which will satisfy the above test.
- *
- * Check its so-called mystery register to prevent matching
- * it as an unknown GIO device.
- */
- if (guarded_read_4(va + HQ2_MYSTERY, &mystery) == 0 &&
- mystery == HQ2_MYSTERY_VALUE)
- return maybe_gfx ? GIO_PRODUCT_FAKEID_GRTWO : 0;
-
- if (GIO_PRODUCT_32BIT_ID(id8)) {
- if (id16 == (id32 & 0xffff))
- return id32;
- } else {
- if (id8 != 0) {
- if (maybe_gfx)
- return id8;
- else
- return 0;
- }
- }
+ if (guarded_read_2(va | 2, &id16) != 0 ||
+ guarded_read_1(va | 3, &id8) != 0) {
+ if (GIO_PRODUCT_32BIT_ID(id32))
+ return id32;
+ else
+ return GIO_PRODUCT_PRODUCTID(id32);
}
/*
@@ -706,8 +673,8 @@ gio_arb_config(int slot, uint32_t flags)
}
/*
- * Establish an interrupt handler for expansion boards (not frame buffers!)
- * in the specified slot.
+ * Return the logical interrupt number for an expansion board (not a frame
+ * buffer!) in the specified slot.
*
* Indy and Challenge S have a single GIO interrupt per GIO slot, but
* distinct slot interrups. Indigo and Indigo2 have three GIO interrupts per
@@ -716,36 +683,36 @@ gio_arb_config(int slot, uint32_t flags)
*
* Expansion boards appear to always use the intermediate level.
*/
-void *
-gio_intr_establish(int slot, int level, int (*func)(void *), void *arg,
- const char *what)
+int
+gio_intr_map(int slot)
{
- int intr;
-
switch (sys_config.system_type) {
case SGI_IP20:
if (slot == GIO_SLOT_GFX)
- return NULL;
- intr = INT2_L0_INTR(INT2_L0_GIO_LVL1);
- break;
+ return -1;
+ return INT2_L0_INTR(INT2_L0_GIO_LVL1);
case SGI_IP22:
case SGI_IP26:
case SGI_IP28:
if (sys_config.system_subtype == IP22_INDIGO2) {
if (slot == GIO_SLOT_EXP1)
- return NULL;
- intr = INT2_L0_INTR(INT2_L0_GIO_LVL1);
+ return -1;
+ return INT2_L0_INTR(INT2_L0_GIO_LVL1);
} else {
if (slot == GIO_SLOT_GFX)
- return NULL;
- intr = INT2_MAP1_INTR(slot == GIO_SLOT_EXP0 ?
+ return -1;
+ return INT2_MAP1_INTR(slot == GIO_SLOT_EXP0 ?
INT2_MAP_GIO_SLOT0 : INT2_MAP_GIO_SLOT1);
}
- break;
default:
- return NULL;
+ return -1;
}
+}
+void *
+gio_intr_establish(int intr, int level, int (*func)(void *), void *arg,
+ const char *what)
+{
return int2_intr_establish(intr, level, func, arg, what);
}
diff --git a/sys/arch/sgi/gio/giovar.h b/sys/arch/sgi/gio/giovar.h
index 5bffeafdbaf..3b5b9ca62cf 100644
--- a/sys/arch/sgi/gio/giovar.h
+++ b/sys/arch/sgi/gio/giovar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: giovar.h,v 1.3 2012/04/24 20:11:26 miod Exp $ */
+/* $OpenBSD: giovar.h,v 1.4 2012/05/17 19:46:52 miod Exp $ */
/* $NetBSD: giovar.h,v 1.10 2011/07/01 18:53:46 dyoung Exp $ */
/*
@@ -76,6 +76,7 @@ struct gio_attach_args {
#define GIO_MAX_FB 3
int gio_arb_config(int, uint32_t);
+int gio_intr_map(int);
void *gio_intr_establish(int, int, int (*)(void *), void *,
const char *);
const char *gio_product_string(int);