summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-10-15 23:40:55 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-10-15 23:40:55 +0000
commit997d2ef5917da088bde3ab34e494968822818715 (patch)
tree1e6c7e1aeba09db86a7587d931b69e0196595bde
parent4c087c2e14db8c3d3b70b3cc0c345eb8c4de6fb8 (diff)
The Octane boot PROM is accessible through the PCI space of the on-board i/o
widget; make sure we reserve its address span so that no device risks having its resources overlap the PROM.
-rw-r--r--sys/arch/sgi/sgi/ip30.h17
-rw-r--r--sys/arch/sgi/xbow/xbridge.c100
2 files changed, 109 insertions, 8 deletions
diff --git a/sys/arch/sgi/sgi/ip30.h b/sys/arch/sgi/sgi/ip30.h
index ec49844d798..033e2b316b7 100644
--- a/sys/arch/sgi/sgi/ip30.h
+++ b/sys/arch/sgi/sgi/ip30.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip30.h,v 1.2 2009/10/14 20:21:16 miod Exp $ */
+/* $OpenBSD: ip30.h,v 1.3 2009/10/15 23:40:54 miod Exp $ */
/*
* Copyright (c) 2008, 2009 Miodrag Vallat.
@@ -28,6 +28,13 @@
#define IP30_MEMORY_ARCBIOS_LIMIT 0x40000000
/*
+ * Specific widget assignment
+ */
+
+#define IP30_HEART_WIDGET 8
+#define IP30_BRIDGE_WIDGET 15
+
+/*
* On-board IOC3 specific GPIO registers wiring
*/
@@ -36,3 +43,11 @@
#define IP30_GPIO_RED_LED 1
/* Classic Octane (1) vs Octane 2 (0), read only */
#define IP30_GPIO_CLASSIC 2
+
+/*
+ * Flash PROM physical address, within BRIDGE widget
+ */
+
+#define IP30_FLASH_BASE 0xc00000
+#define IP30_FLASH_SIZE 0x200000
+#define IP30_FLASH_ALT 0xe00000
diff --git a/sys/arch/sgi/xbow/xbridge.c b/sys/arch/sgi/xbow/xbridge.c
index d58fd19ff60..0b4e4627ac3 100644
--- a/sys/arch/sgi/xbow/xbridge.c
+++ b/sys/arch/sgi/xbow/xbridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xbridge.c,v 1.51 2009/10/10 19:59:28 miod Exp $ */
+/* $OpenBSD: xbridge.c,v 1.52 2009/10/15 23:40:49 miod Exp $ */
/*
* Copyright (c) 2008, 2009 Miodrag Vallat.
@@ -60,7 +60,10 @@
#include <sgi/xbow/xbridgereg.h>
+#ifdef TGT_OCTANE
#include <sgi/sgi/ip30.h>
+#include <sgi/xbow/xheartreg.h>
+#endif
#include "cardbus.h"
@@ -146,7 +149,7 @@ struct xbridge_softc {
#define XF_NO_DIRECT_IO 0x04 /* no direct I/O mapping */
int16_t sc_nasid;
int sc_widget;
- uint sc_devio_skew;
+ uint sc_devio_skew; /* upper bits of devio ARCS mappings */
uint sc_nbuses;
struct mips_bus_space sc_regt;
@@ -250,6 +253,7 @@ void xbridge_resource_manage(struct xbridge_bus *, pcitag_t,
void xbridge_ate_setup(struct xbridge_bus *);
void xbridge_device_setup(struct xbridge_bus *, int, int, uint32_t);
+int xbridge_extent_chomp(struct xbridge_bus *, struct extent *);
void xbridge_extent_setup(struct xbridge_bus *);
struct extent *
xbridge_mapping_setup(struct xbridge_bus *, int);
@@ -354,13 +358,30 @@ xbridge_attach(struct device *parent, struct device *self, void *aux)
SET(sc->sc_flags, XF_NO_DIRECT_IO);
/*
- * Figure out where the devio mappings will go.
- * On Octane, they are relative to the start of the widget.
- * On Origin, they are computed from the widget number.
+ * Figure out where the ARCS devio mappings will go.
+ * ARCS configures all the devio in a contiguous 16MB area
+ * (i.e. the upper 8 bits of the DEVIO_BASE field of the
+ * devio registers are the same).
+ *
+ * In order to make our life simpler, on widgets where we may
+ * want to keep some of the ARCS mappings (because that's where
+ * our console device lives), we will use the same 16MB area.
+ *
+ * Otherwise, we can use whatever values we want; to keep the
+ * code simpler, we will nevertheless use a 16MB area as well,
+ * making sure it does not start at zero so that pcmcia bridges
+ * can be used.
+ *
+ * On Octane, the upper bits of ARCS mappings are zero, and thus
+ * point to the start of the widget. On Origin, they match the
+ * widget number.
*/
- if (sys_config.system_type == SGI_OCTANE)
+#ifdef TGT_OCTANE
+ if (sys_config.system_type == SGI_OCTANE &&
+ sc->sc_widget == IP30_BRIDGE_WIDGET)
sc->sc_devio_skew = 0;
else
+#endif
sc->sc_devio_skew = sc->sc_widget;
sc->sc_nbuses =
@@ -1021,7 +1042,12 @@ xbridge_intr_handler(void *v)
switch (sys_config.system_type) {
#if defined(TGT_OCTANE)
case SGI_OCTANE:
- /* XXX what to do there? */
+ {
+ paddr_t heart;
+ heart = PHYS_TO_XKPHYS(HEART_PIU_BASE, CCA_NC);
+ *(volatile uint64_t *)(heart + HEART_ISR_SET) =
+ xi->xi_intrsrc;
+ }
break;
#endif
#if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
@@ -1248,9 +1274,11 @@ xbridge_space_map_mem(bus_space_tag_t t, bus_addr_t offs, bus_size_t size,
* mappings, because the large mapping is always available.
*/
+#if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
if (sys_config.system_type != SGI_OCTANE &&
(offs >> 24) == xb->xb_devio_skew)
return xbridge_space_map_devio(t, offs, size, flags, bshp);
+#endif
#ifdef DIAGNOSTIC
/* check that this does not overflow the mapping */
@@ -1346,6 +1374,8 @@ xbridge_space_region_mem(bus_space_tag_t t, bus_space_handle_t bsh,
* window. Except on Octane where we never setup devio memory
* mappings, because the large mapping is always available.
*/
+
+#if defined(TGT_ORIGIN200) || defined(TGT_ORIGIN2000)
if (sys_config.system_type != SGI_OCTANE) {
/*
* Note we can not use our own bus_base because it might not
@@ -1359,6 +1389,7 @@ xbridge_space_region_mem(bus_space_tag_t t, bus_space_handle_t bsh,
return xbridge_space_region_devio(t, bsh, offset, size,
nbshp);
}
+#endif
#ifdef DIAGNOSTIC
/* check that this does not overflow the mapping */
@@ -2335,6 +2366,43 @@ xbridge_resource_setup(struct xbridge_bus *xb)
}
/*
+ * Make the Octane flash area unavailable in the PCI space extents, so
+ * that we do not try to map devices in its area.
+ */
+int
+xbridge_extent_chomp(struct xbridge_bus *xb, struct extent *ex)
+{
+#ifdef TGT_OCTANE
+ /*
+ * On Octane, the boot PROM is part of the onboard IOC3
+ * device, and is accessible through the PCI memory space
+ * (and maybe through the PCI I/O space as well.
+ *
+ * To avoid undebuggable surprises, make sure we never use
+ * this space.
+ */
+ if (sys_config.system_type == SGI_OCTANE &&
+ xb->xb_widget == IP30_BRIDGE_WIDGET) {
+ u_long fmin, fmax;
+
+ /*
+ * This relies upon the knowledge that both flash bases
+ * are contiguous, to perform only one extent operation.
+ * I don't think we need to be pedantic to the point of
+ * doing this in two steps, really -- miod
+ */
+ fmin = max(IP30_FLASH_BASE, ex->ex_start);
+ fmax = min(IP30_FLASH_ALT + IP30_FLASH_SIZE - 1, ex->ex_end);
+ if (fmax >= fmin)
+ return extent_alloc_region(ex, fmin, fmax + 1 - fmin,
+ EX_NOWAIT | EX_MALLOCOK);
+ }
+#endif
+
+ return 0;
+}
+
+/*
* Build resource extents for the MI PCI code to play with.
* These extents cover the configured devio areas, and the large resource
* views, if applicable.
@@ -2390,6 +2458,9 @@ xbridge_extent_setup(struct xbridge_bus *xb)
errors++;
}
+ if (xbridge_extent_chomp(xb, xb->xb_ioex) != 0)
+ errors++;
+
if (errors != 0) {
extent_destroy(xb->xb_ioex);
xb->xb_ioex = NULL;
@@ -2437,6 +2508,9 @@ xbridge_extent_setup(struct xbridge_bus *xb)
errors++;
}
+ if (xbridge_extent_chomp(xb, xb->xb_memex) != 0)
+ errors++;
+
if (errors != 0) {
extent_destroy(xb->xb_memex);
xb->xb_memex = NULL;
@@ -2485,6 +2559,12 @@ xbridge_mapping_setup(struct xbridge_bus *xb, int io)
offs == 0 ? 1 : offs, offs + len - 1,
M_DEVBUF, NULL, 0, EX_NOWAIT);
+ /*
+ * Note that we do not need to invoke
+ * xbridge_extent_chomp() here since we will
+ * reserve the whole devio area.
+ */
+
if (ex != NULL) {
xb->xb_io_bus_space->bus_base = base - offs;
xb->xb_io_bus_space->_space_map =
@@ -2529,6 +2609,12 @@ xbridge_mapping_setup(struct xbridge_bus *xb, int io)
offs == 0 ? 1 : offs, offs + len - 1,
M_DEVBUF, NULL, 0, EX_NOWAIT);
+ /*
+ * Note that we do not need to invoke
+ * xbridge_extent_chomp() here since we will
+ * reserve the whole devio area.
+ */
+
if (ex != NULL) {
xb->xb_mem_bus_space->bus_base = base - offs;
xb->xb_mem_bus_space->_space_map =