summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-06-27 22:23:18 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-06-27 22:23:18 +0000
commit82e7e176fbdb228b31b59105401cc58e53b30ad4 (patch)
treeea67f39791ef74c5ab325436af34ccfc6ca59bb8 /sys
parenta9ff1d7d42f9b99ba9ddbfc5ef2ea38ea28ff000 (diff)
Preliminary cleanup work in order to help the PCI resource management code.
As long as I can't figure out what endianness knobs I need to frob to make I/O and memory accesses through the large window work as intended, we are stuck to devio I/O mappings only...
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/sgi/xbow/xbridge.c222
1 files changed, 120 insertions, 102 deletions
diff --git a/sys/arch/sgi/xbow/xbridge.c b/sys/arch/sgi/xbow/xbridge.c
index de9a7da1dd3..fea82d15c1e 100644
--- a/sys/arch/sgi/xbow/xbridge.c
+++ b/sys/arch/sgi/xbow/xbridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: xbridge.c,v 1.28 2009/06/27 16:34:50 miod Exp $ */
+/* $OpenBSD: xbridge.c,v 1.29 2009/06/27 22:23:17 miod Exp $ */
/*
* Copyright (c) 2008, 2009 Miodrag Vallat.
@@ -122,16 +122,12 @@ void xbridge_read_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
uint8_t *, bus_size_t);
void xbridge_write_raw_2(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
const uint8_t *, bus_size_t);
-void xbridge_read_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
- uint8_t *, bus_size_t);
-void xbridge_write_raw_4(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
- const uint8_t *, bus_size_t);
-void xbridge_read_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
- uint8_t *, bus_size_t);
-void xbridge_write_raw_8(bus_space_tag_t, bus_space_handle_t, bus_addr_t,
- const uint8_t *, bus_size_t);
-int xbridge_space_map_short(bus_space_tag_t, bus_addr_t, bus_size_t, int,
+int xbridge_space_map_devio(bus_space_tag_t, bus_addr_t, bus_size_t, int,
+ bus_space_handle_t *);
+int xbridge_space_map_io(bus_space_tag_t, bus_addr_t, bus_size_t, int,
+ bus_space_handle_t *);
+int xbridge_space_map_mem(bus_space_tag_t, bus_addr_t, bus_size_t, int,
bus_space_handle_t *);
int xbridge_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
@@ -243,66 +239,56 @@ xbridge_attach(struct device *parent, struct device *self, void *aux)
if (sc->sc_io_bus_space == NULL)
goto fail2;
- if (sys_config.system_type == SGI_OCTANE) {
- /* Unrestricted memory mappings in the large window */
- bcopy(xaa->xaa_long_tag, sc->sc_mem_bus_space,
- sizeof(*sc->sc_mem_bus_space));
- sc->sc_mem_bus_space->bus_base += BRIDGE_PCI_MEM_SPACE_BASE;
- sc->sc_mem_ex = extent_create("pcimem",
- 0, BRIDGE_PCI_MEM_SPACE_LENGTH - 1,
- M_DEVBUF, NULL, 0, EX_NOWAIT);
+#ifdef notyet
+ /* Unrestricted memory mappings in the large window */
+ bcopy(xaa->xaa_long_tag, sc->sc_mem_bus_space,
+ sizeof(*sc->sc_mem_bus_space));
+ sc->sc_mem_ex = extent_create("pcimem",
+ 0, BRIDGE_PCI_MEM_SPACE_LENGTH - 1,
+ M_DEVBUF, NULL, 0, EX_NOWAIT);
+ sc->sc_mem_bus_space->_space_map = xbridge_space_map_mem;
+#else
+ /* Programmable memory mappings in the small window */
+ bcopy(xaa->xaa_short_tag, sc->sc_mem_bus_space,
+ sizeof(*sc->sc_mem_bus_space));
+ sc->sc_mem_bus_space->_space_map = xbridge_space_map_devio;
+#endif
- if (ISSET(sc->sc_flags, XBRIDGE_FLAGS_XBRIDGE) ||
- xaa->xaa_revision >= 4) {
- /* Unrestricted I/O mappings in the large window */
- bcopy(xaa->xaa_long_tag, sc->sc_io_bus_space,
- sizeof(*sc->sc_io_bus_space));
- sc->sc_io_bus_space->bus_base +=
- BRIDGE_PCI_IO_SPACE_BASE;
-
- sc->sc_io_ex = extent_create("pciio",
- 0, BRIDGE_PCI_IO_SPACE_LENGTH - 1,
- M_DEVBUF, NULL, 0, EX_NOWAIT);
- } else {
- /* Programmable I/O mappings in the small window */
- bcopy(xaa->xaa_short_tag, sc->sc_io_bus_space,
- sizeof(*sc->sc_io_bus_space));
- }
+#ifdef notyet
+ if (ISSET(sc->sc_flags, XBRIDGE_FLAGS_XBRIDGE) ||
+ xaa->xaa_revision >= 4) {
+#else
+ if (0) {
+#endif
+ /* Unrestricted I/O mappings in the large window */
+ bcopy(xaa->xaa_long_tag, sc->sc_io_bus_space,
+ sizeof(*sc->sc_io_bus_space));
+ sc->sc_io_ex = extent_create("pciio",
+ 0, BRIDGE_PCI_IO_SPACE_LENGTH - 1,
+ M_DEVBUF, NULL, 0, EX_NOWAIT);
+ sc->sc_io_bus_space->_space_map = xbridge_space_map_io;
} else {
- /* Limited memory mappings in the small window */
- bcopy(xaa->xaa_short_tag, sc->sc_mem_bus_space,
- sizeof(*sc->sc_mem_bus_space));
- sc->sc_mem_bus_space->bus_private = sc;
- sc->sc_mem_bus_space->_space_map = xbridge_space_map_short;
-
- /* Limited I/O mappings in the small window */
+ /* Programmable I/O mappings in the small window */
bcopy(xaa->xaa_short_tag, sc->sc_io_bus_space,
sizeof(*sc->sc_io_bus_space));
- sc->sc_io_bus_space->bus_private = sc;
- sc->sc_io_bus_space->_space_map = xbridge_space_map_short;
+ sc->sc_io_bus_space->_space_map = xbridge_space_map_devio;
}
+ sc->sc_io_bus_space->bus_private = sc;
sc->sc_io_bus_space->_space_read_1 = xbridge_read_1;
sc->sc_io_bus_space->_space_write_1 = xbridge_write_1;
sc->sc_io_bus_space->_space_read_2 = xbridge_read_2;
sc->sc_io_bus_space->_space_write_2 = xbridge_write_2;
sc->sc_io_bus_space->_space_read_raw_2 = xbridge_read_raw_2;
sc->sc_io_bus_space->_space_write_raw_2 = xbridge_write_raw_2;
- sc->sc_io_bus_space->_space_read_raw_4 = xbridge_read_raw_4;
- sc->sc_io_bus_space->_space_write_raw_4 = xbridge_write_raw_4;
- sc->sc_io_bus_space->_space_read_raw_8 = xbridge_read_raw_8;
- sc->sc_io_bus_space->_space_write_raw_8 = xbridge_write_raw_8;
+ sc->sc_mem_bus_space->bus_private = sc;
sc->sc_mem_bus_space->_space_read_1 = xbridge_read_1;
sc->sc_mem_bus_space->_space_write_1 = xbridge_write_1;
sc->sc_mem_bus_space->_space_read_2 = xbridge_read_2;
sc->sc_mem_bus_space->_space_write_2 = xbridge_write_2;
sc->sc_mem_bus_space->_space_read_raw_2 = xbridge_read_raw_2;
sc->sc_mem_bus_space->_space_write_raw_2 = xbridge_write_raw_2;
- sc->sc_mem_bus_space->_space_read_raw_4 = xbridge_read_raw_4;
- sc->sc_mem_bus_space->_space_write_raw_4 = xbridge_write_raw_4;
- sc->sc_mem_bus_space->_space_read_raw_8 = xbridge_read_raw_8;
- sc->sc_mem_bus_space->_space_write_raw_8 = xbridge_write_raw_8;
sc->sc_dmat = malloc(sizeof (*sc->sc_dmat), M_DEVBUF, M_NOWAIT);
if (sc->sc_dmat == NULL)
@@ -864,73 +850,85 @@ xbridge_write_raw_2(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
}
}
-void
-xbridge_read_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
- uint8_t *buf, bus_size_t len)
+int
+xbridge_space_map_devio(bus_space_tag_t t, bus_addr_t offs, bus_size_t size,
+ int cacheable, bus_space_handle_t *bshp)
{
- volatile uint32_t *addr = (volatile uint32_t *)(h + o);
- len >>= 2;
- while (len-- != 0) {
- *(uint32_t *)buf = *addr;
- buf += 4;
- }
-}
+ struct xbridge_softc *sc = (struct xbridge_softc *)t->bus_private;
+ bus_addr_t bpa, start, end;
+ uint d;
-void
-xbridge_write_raw_4(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
- const uint8_t *buf, bus_size_t len)
-{
- volatile uint32_t *addr = (volatile uint32_t *)(h + o);
- len >>= 2;
- while (len-- != 0) {
- *addr = *(uint32_t *)buf;
- buf += 4;
- }
-}
+ if ((offs >> 24) != sc->sc_widget)
+ return EINVAL; /* not a devio mapping */
-void
-xbridge_read_raw_8(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
- uint8_t *buf, bus_size_t len)
-{
- volatile uint64_t *addr = (volatile uint64_t *)(h + o);
- len >>= 3;
- while (len-- != 0) {
- *(uint64_t *)buf = *addr;
- buf += 8;
+ /*
+ * Figure out which devio `slot' we are using, and make sure
+ * we do not overrun it.
+ */
+ bpa = offs & ((1UL << 24) - 1);
+ for (d = 0; d < BRIDGE_NSLOTS; d++) {
+ start = BRIDGE_DEVIO_OFFS(d);
+ end = start + BRIDGE_DEVIO_SIZE(d);
+ if (bpa >= start && bpa < end) {
+ if (bpa + size > end)
+ return EINVAL;
+ else
+ break;
+ }
}
+ if (d == BRIDGE_NSLOTS)
+ return EINVAL;
+
+ /*
+ * Note we can not use our own bus_base because it might not point
+ * to our small window. Instead, use the one used by the xbridge
+ * driver itself, which _always_ points to the short window.
+ */
+ *bshp = sc->sc_iot->bus_base + bpa;
+ return 0;
}
-void
-xbridge_write_raw_8(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
- const uint8_t *buf, bus_size_t len)
+int
+xbridge_space_map_io(bus_space_tag_t t, bus_addr_t offs, bus_size_t size,
+ int cacheable, bus_space_handle_t *bshp)
{
- volatile uint64_t *addr = (volatile uint64_t *)(h + o);
- len >>= 3;
- while (len-- != 0) {
- *addr = *(uint64_t *)buf;
- buf += 8;
- }
+ struct xbridge_softc *sc = (struct xbridge_softc *)t->bus_private;
+
+ /*
+ * Base address is either within the devio area, or our direct
+ * window.
+ */
+
+ if ((offs >> 24) == sc->sc_widget)
+ return xbridge_space_map_devio(t, offs, size, cacheable, bshp);
+
+ /* check that this doesn't overflow the window */
+ if (offs + size > BRIDGE_PCI_IO_SPACE_LENGTH || offs + size < offs)
+ return EINVAL;
+
+ *bshp = t->bus_base + BRIDGE_PCI_IO_SPACE_BASE + offs;
+ return 0;
}
-/*
- * On IP27 and IP35, we can not use the default xbow space_map_short
- * because of the games we play with bus addresses.
- */
int
-xbridge_space_map_short(bus_space_tag_t t, bus_addr_t offs, bus_size_t size,
+xbridge_space_map_mem(bus_space_tag_t t, bus_addr_t offs, bus_size_t size,
int cacheable, bus_space_handle_t *bshp)
{
struct xbridge_softc *sc = (struct xbridge_softc *)t->bus_private;
- bus_addr_t bpa;
- bpa = t->bus_base - (sc->sc_widget << 24) + offs;
+ /*
+ * Base address is either within the devio area, or our direct
+ * window.
+ */
- /* check that this neither underflows nor overflows the window */
- if (((bpa + size - 1) >> 24) != (t->bus_base >> 24) ||
- (bpa >> 24) != (t->bus_base >> 24))
- return (EINVAL);
+ if ((offs >> 24) == sc->sc_widget)
+ return xbridge_space_map_devio(t, offs, size, cacheable, bshp);
- *bshp = bpa;
+ /* check that this doesn't overflow the window */
+ if (offs + size > BRIDGE_PCI_MEM_SPACE_LENGTH || offs + size < offs)
+ return EINVAL;
+
+ *bshp = t->bus_base + BRIDGE_PCI_MEM_SPACE_BASE + offs;
return 0;
}
@@ -1625,6 +1623,26 @@ xbridge_setup(struct xbridge_softc *sc)
xbridge_rrb_setup(sc, 0);
xbridge_rrb_setup(sc, 1);
+#ifdef notyet
+ /*
+ * Enable byteswapping on accesses through the large window,
+ * except on the main I/O widget on Octane, where the default
+ * mappings require them to be disabled (which doesn't matter,
+ * since the contents of the PCI bus are immutable and well-known).
+ */
+
+ if (sys_config.system_type != SGI_OCTANE ||
+ sc->sc_widget != WIDGET_MAX) {
+ uint32_t ctrl = bus_space_read_4(sc->sc_iot, sc->sc_regh,
+ WIDGET_CONTROL);
+ ctrl |= BRIDGE_WIDGET_CONTROL_IO_SWAP;
+ ctrl |= BRIDGE_WIDGET_CONTROL_MEM_SWAP;
+ bus_space_write_4(sc->sc_iot, sc->sc_regh, WIDGET_CONTROL,
+ ctrl);
+ (void)bus_space_read_4(sc->sc_iot, sc->sc_regh, WIDGET_TFLUSH);
+ }
+#endif
+
/*
* The PROM will only configure the onboard devices. Set up
* any other device we might encounter.