summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-08-18 19:34:18 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-08-18 19:34:18 +0000
commit9a01ee2e8e0f86eba9a9f4027dee4a18ebc50664 (patch)
tree65ac981d577fb98abb08c55e4f88dd8d1bf8d313
parenta4b78b2607a328b161f44ec13bba1356993630cc (diff)
Blind partial support for IOC4 chip, found on IO8 and IO9 base I/O boards on
Origin 350 and Tezro systems. While this chip provides serial ports, an ATAPI interface and a PS/2 keyboard and mouse interface, this code currently only attempts to support the serial ports.
-rw-r--r--sys/arch/sgi/conf/GENERIC-IP277
-rw-r--r--sys/arch/sgi/conf/files.sgi12
-rw-r--r--sys/arch/sgi/dev/com_iof.c123
-rw-r--r--sys/arch/sgi/pci/iof.c343
-rw-r--r--sys/arch/sgi/pci/iofreg.h60
-rw-r--r--sys/arch/sgi/pci/iofvar.h30
6 files changed, 572 insertions, 3 deletions
diff --git a/sys/arch/sgi/conf/GENERIC-IP27 b/sys/arch/sgi/conf/GENERIC-IP27
index 38ce46db43b..acb88bad017 100644
--- a/sys/arch/sgi/conf/GENERIC-IP27
+++ b/sys/arch/sgi/conf/GENERIC-IP27
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC-IP27,v 1.13 2009/07/15 18:15:21 miod Exp $
+# $OpenBSD: GENERIC-IP27,v 1.14 2009/08/18 19:34:14 miod Exp $
#
# THIS KERNEL IS FOR Origin, Onyx, Fuel, Tezro (IP27, IP35) SYSTEMS ONLY.
#
@@ -59,6 +59,11 @@ option ONEWIREVERBOSE
owmac* at onewire?
owserial* at onewire?
+# IOC4
+iof* at pci?
+com0 at iof? base 0x380
+com* at iof?
+
#### SCSI
ahc* at pci?
isp* at pci?
diff --git a/sys/arch/sgi/conf/files.sgi b/sys/arch/sgi/conf/files.sgi
index 6137604eb2a..e869fceb9e5 100644
--- a/sys/arch/sgi/conf/files.sgi
+++ b/sys/arch/sgi/conf/files.sgi
@@ -1,4 +1,4 @@
-# $OpenBSD: files.sgi,v 1.31 2009/08/13 15:13:11 jasper Exp $
+# $OpenBSD: files.sgi,v 1.32 2009/08/18 19:34:14 miod Exp $
#
# maxpartitions must be first item in files.${ARCH}
#
@@ -103,9 +103,17 @@ device ioc: onewirebus
attach ioc at pci
file arch/sgi/pci/ioc.c ioc
-# IOC3 serial ports
+# IOC4
+define iof {[base = -1]}
+device iof
+attach iof at pci
+file arch/sgi/pci/iof.c iof
+
+# IOC3/4 serial ports
attach com at ioc with com_ioc
file arch/sgi/dev/com_ioc.c com_ioc
+attach com at iof with com_iof
+file arch/sgi/dev/com_iof.c com_iof
# DS1687 Time-Of-Day calendar device
device dsrtc
diff --git a/sys/arch/sgi/dev/com_iof.c b/sys/arch/sgi/dev/com_iof.c
new file mode 100644
index 00000000000..66e61bfc47a
--- /dev/null
+++ b/sys/arch/sgi/dev/com_iof.c
@@ -0,0 +1,123 @@
+/* $OpenBSD: com_iof.c,v 1.1 2009/08/18 19:34:15 miod Exp $ */
+
+/*
+ * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/tty.h>
+
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+
+#include <dev/ic/comreg.h>
+#include <dev/ic/comvar.h>
+#include <dev/ic/ns16550reg.h>
+
+#include <sgi/pci/iofvar.h>
+
+int com_iof_probe(struct device *, void *, void *);
+void com_iof_attach(struct device *, struct device *, void *);
+
+struct cfattach com_iof_ca = {
+ sizeof(struct com_softc), com_iof_probe, com_iof_attach
+};
+
+extern struct cfdriver com_cd;
+
+int
+com_iof_probe(struct device *parent, void *match, void *aux)
+{
+ struct iof_attach_args *iaa = aux;
+ bus_space_tag_t iot = iaa->iaa_memt;
+ bus_space_handle_t ioh;
+ int rv = 0, console;
+
+ if (strcmp(iaa->iaa_name, com_cd.cd_name) != 0)
+ return 0;
+
+ console = iaa->iaa_memh + iaa->iaa_base ==
+ comconsiot->bus_base + comconsaddr;
+
+ /* if it's in use as console, it's there. */
+ if (!(console && !comconsattached)) {
+ if (bus_space_subregion(iot, iaa->iaa_memh,
+ iaa->iaa_base, COM_NPORTS, &ioh) == 0)
+ rv = comprobe1(iot, ioh);
+ } else
+ rv = 1;
+
+ return rv;
+}
+
+void
+com_iof_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct com_softc *sc = (void *)self;
+ struct iof_attach_args *iaa = aux;
+ bus_space_handle_t ioh;
+ int console;
+
+ console = iaa->iaa_memh + iaa->iaa_base ==
+ comconsiot->bus_base + comconsaddr;
+
+ sc->sc_hwflags = 0;
+ sc->sc_swflags = 0;
+ sc->sc_frequency = 22000000 / 3;
+
+ /* if it's in use as console, it's there. */
+ if (!(console && !comconsattached)) {
+ sc->sc_iot = iaa->iaa_memt;
+ sc->sc_iobase = iaa->iaa_base;
+
+ if (bus_space_subregion(iaa->iaa_memt, iaa->iaa_memh,
+ iaa->iaa_base, COM_NPORTS, &ioh) != 0) {
+ printf(": can't map registers\n");
+ return;
+ }
+ } else {
+ /*
+ * If we are the console, reuse the existing bus_space
+ * information, so that comcnattach() invokes bus_space_map()
+ * with correct parameters.
+ */
+ sc->sc_iot = comconsiot;
+ sc->sc_iobase = comconsaddr;
+
+ if (comcnattach(sc->sc_iot, sc->sc_iobase, TTYDEF_SPEED,
+ sc->sc_frequency, (TTYDEF_CFLAG & ~(CSIZE | PARENB)) | CS8))
+ panic("can't setup serial console");
+ ioh = comconsioh;
+ }
+
+ sc->sc_ioh = ioh;
+
+ com_attach_subr(sc);
+
+ iof_intr_establish(parent, iaa->iaa_dev, IPL_TTY, comintr,
+ (void *)sc, sc->sc_dev.dv_xname);
+}
diff --git a/sys/arch/sgi/pci/iof.c b/sys/arch/sgi/pci/iof.c
new file mode 100644
index 00000000000..bc894f42cd1
--- /dev/null
+++ b/sys/arch/sgi/pci/iof.c
@@ -0,0 +1,343 @@
+/* $OpenBSD: iof.c,v 1.1 2009/08/18 19:34:17 miod Exp $ */
+
+/*
+ * Copyright (c) 2009 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * IOC4 device driver.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <sgi/pci/iofreg.h>
+#include <sgi/pci/iofvar.h>
+
+#include <sgi/xbow/xbow.h>
+
+int iof_match(struct device *, void *, void *);
+void iof_attach(struct device *, struct device *, void *);
+void iof_attach_child(struct device *, const char *, bus_addr_t, uint);
+int iof_search(struct device *, void *, void *);
+int iof_print(void *, const char *);
+
+struct iof_intr {
+ struct iof_softc *ii_iof;
+
+ int (*ii_func)(void *);
+ void *ii_arg;
+
+ struct evcount ii_count;
+ int ii_level;
+};
+
+struct iof_softc {
+ struct device sc_dev;
+
+ struct mips_bus_space *sc_mem_bus_space;
+
+ bus_space_tag_t sc_memt;
+ bus_space_handle_t sc_memh;
+ bus_dma_tag_t sc_dmat;
+ pci_chipset_tag_t sc_pc;
+
+ void *sc_ih;
+ struct iof_intr *sc_intr[IOC4_NDEVS];
+};
+
+struct cfattach iof_ca = {
+ sizeof(struct iof_softc), iof_match, iof_attach,
+};
+
+struct cfdriver iof_cd = {
+ NULL, "iof", DV_DULL,
+};
+
+int iof_intr_dispatch(struct iof_softc *, int);
+int iof_intr(void *);
+
+int
+iof_match(struct device *parent, void *match, void *aux)
+{
+ struct pci_attach_args *pa = aux;
+
+ if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SGI &&
+ PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SGI_IOC4)
+ return 1;
+
+ return 0;
+}
+
+int
+iof_print(void *aux, const char *iofname)
+{
+ struct iof_attach_args *iaa = aux;
+
+ if (iofname != NULL)
+ printf("%s at %s", iaa->iaa_name, iofname);
+
+ printf(" base 0x%x", iaa->iaa_base);
+
+ return UNCONF;
+}
+
+void
+iof_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct iof_softc *sc = (struct iof_softc *)self;
+ struct pci_attach_args *pa = aux;
+ pci_intr_handle_t ih;
+ bus_space_tag_t memt;
+ bus_space_handle_t memh;
+ bus_size_t memsize;
+ const char *intrstr;
+
+ if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM, 0,
+ &memt, &memh, NULL, &memsize, 0)) {
+ printf(": can't map mem space\n");
+ return;
+ }
+
+ sc->sc_pc = pa->pa_pc;
+ sc->sc_dmat = pa->pa_dmat;
+
+ /*
+ * Build a suitable bus_space_handle by restoring the original
+ * non-swapped subword access methods.
+ *
+ * XXX This is horrible and will need to be rethought if
+ * XXX IOC4 exist as real, removable PCI cards and
+ * XXX we ever support them cards not plugged to xbridges.
+ */
+
+ sc->sc_mem_bus_space = malloc(sizeof (*sc->sc_mem_bus_space),
+ M_DEVBUF, M_NOWAIT);
+ if (sc->sc_mem_bus_space == NULL) {
+ printf(": can't allocate bus_space\n");
+ goto unmap;
+ }
+
+ bcopy(memt, sc->sc_mem_bus_space, sizeof(*sc->sc_mem_bus_space));
+ sc->sc_mem_bus_space->_space_read_1 = xbow_read_1;
+ sc->sc_mem_bus_space->_space_read_2 = xbow_read_2;
+ sc->sc_mem_bus_space->_space_read_raw_2 = xbow_read_raw_2;
+ sc->sc_mem_bus_space->_space_write_1 = xbow_write_1;
+ sc->sc_mem_bus_space->_space_write_2 = xbow_write_2;
+ sc->sc_mem_bus_space->_space_write_raw_2 = xbow_write_raw_2;
+
+ sc->sc_memt = sc->sc_mem_bus_space;
+ sc->sc_memh = memh;
+
+ /*
+ * Acknowledge all pending interrupts, and disable them.
+ */
+
+ bus_space_write_4(sc->sc_memt, sc->sc_memh, IOC4_SIO_IEC, ~0x0);
+ bus_space_write_4(sc->sc_memt, sc->sc_memh, IOC4_SIO_IES, 0x0);
+ bus_space_write_4(sc->sc_memt, sc->sc_memh, IOC4_SIO_IR,
+ bus_space_read_4(sc->sc_memt, sc->sc_memh, IOC4_SIO_IR));
+
+ bus_space_write_4(sc->sc_memt, sc->sc_memh, IOC4_OTHER_IEC, ~0x0);
+ bus_space_write_4(sc->sc_memt, sc->sc_memh, IOC4_OTHER_IES, 0x0);
+ bus_space_write_4(sc->sc_memt, sc->sc_memh, IOC4_OTHER_IR,
+ bus_space_read_4(sc->sc_memt, sc->sc_memh, IOC4_OTHER_IR));
+
+ if (pci_intr_map(pa, &ih) != 0) {
+ printf(": failed to map interrupt!\n");
+ goto unmap;
+ }
+ intrstr = pci_intr_string(sc->sc_pc, ih);
+
+ sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_TTY, iof_intr,
+ sc, self->dv_xname);
+ if (sc->sc_ih == NULL) {
+ printf(": failed to establish interrupt at %s\n", intrstr);
+ goto unmap;
+ }
+ printf("%s\n", intrstr);
+
+ /*
+ * Attach other sub-devices.
+ */
+
+ iof_attach_child(self, "com", IOC4_UARTA_BASE, IOC4DEV_SERIAL_A);
+ iof_attach_child(self, "com", IOC4_UARTB_BASE, IOC4DEV_SERIAL_B);
+ iof_attach_child(self, "com", IOC4_UARTC_BASE, IOC4DEV_SERIAL_C);
+ iof_attach_child(self, "com", IOC4_UARTD_BASE, IOC4DEV_SERIAL_D);
+ iof_attach_child(self, "iockbc", IOC4_KBC_BASE, IOC4DEV_KBC);
+
+ return;
+
+unmap:
+ bus_space_unmap(memt, memh, memsize);
+}
+
+void
+iof_attach_child(struct device *iof, const char *name, bus_addr_t base,
+ uint dev)
+{
+ struct iof_softc *sc = (struct iof_softc *)iof;
+ struct iof_attach_args iaa;
+
+ iaa.iaa_name = name;
+ iaa.iaa_memt = sc->sc_memt;
+ iaa.iaa_memh = sc->sc_memh;
+ iaa.iaa_dmat = sc->sc_dmat;
+ iaa.iaa_base = base;
+ iaa.iaa_dev = dev;
+
+ config_found_sm(iof, &iaa, iof_print, iof_search);
+}
+
+int
+iof_search(struct device *parent, void *vcf, void *args)
+{
+ struct cfdata *cf = vcf;
+ struct iof_attach_args *iaa = (struct iof_attach_args *)args;
+
+ if (strcmp(cf->cf_driver->cd_name, iaa->iaa_name) != 0)
+ return 0;
+
+ if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != (int)iaa->iaa_base)
+ return 0;
+
+ return (*cf->cf_attach->ca_match)(parent, cf, iaa);
+}
+
+/*
+ * Interrupt handling.
+ */
+
+/*
+ * List of interrupt bits to enable for each device.
+ *
+ * For the serial ports, we only enable the passthrough interrupt and
+ * let com(4) tinker with the appropriate registers, instead of adding
+ * an unnecessary layer there.
+ */
+static const struct {
+ uint32_t sio;
+ uint32_t other;
+} ioc4_intrbits[IOC4_NDEVS] = {
+ { IOC4_SIRQ_UARTA, 0 },
+ { IOC4_SIRQ_UARTB, 0 },
+ { IOC4_SIRQ_UARTC, 0 },
+ { IOC4_SIRQ_UARTD, 0 },
+ { 0, IOC4_OIRQ_KBC },
+ { 0, IOC4_OIRQ_ATAPI }
+};
+
+void *
+iof_intr_establish(void *cookie, uint dev, int level, int (*func)(void *),
+ void *arg, char *name)
+{
+ struct iof_softc *sc = cookie;
+ struct iof_intr *ii;
+
+ if (dev < 0 || dev >= IOC4_NDEVS)
+ return NULL;
+
+ ii = (struct iof_intr *)malloc(sizeof(*ii), M_DEVBUF, M_NOWAIT);
+ if (ii == NULL)
+ return NULL;
+
+ ii->ii_iof = sc;
+ ii->ii_func = func;
+ ii->ii_arg = arg;
+ ii->ii_level = level;
+
+ evcount_attach(&ii->ii_count, name, &ii->ii_level, &evcount_intr);
+ sc->sc_intr[dev] = ii;
+
+ /* enable hardware source if necessary */
+ bus_space_write_4(sc->sc_memt, sc->sc_memh, IOC4_SIO_IES,
+ ioc4_intrbits[dev].sio);
+ bus_space_write_4(sc->sc_memt, sc->sc_memh, IOC4_OTHER_IES,
+ ioc4_intrbits[dev].other);
+
+ return (ii);
+}
+
+int
+iof_intr(void *v)
+{
+ struct iof_softc *sc = (struct iof_softc *)v;
+ uint32_t spending, opending, mask;
+ int dev;
+
+ spending = bus_space_read_4(sc->sc_memt, sc->sc_memh, IOC4_SIO_IR) &
+ bus_space_read_4(sc->sc_memt, sc->sc_memh, IOC4_SIO_IES);
+ opending = bus_space_read_4(sc->sc_memt, sc->sc_memh, IOC4_OTHER_IR) &
+ bus_space_read_4(sc->sc_memt, sc->sc_memh, IOC4_OTHER_IES);
+
+ if (spending == 0 && opending == 0)
+ return 0;
+
+ /* Disable pending interrupts */
+ bus_space_write_4(sc->sc_memt, sc->sc_memh, IOC4_SIO_IEC, spending);
+ bus_space_write_4(sc->sc_memt, sc->sc_memh, IOC4_OTHER_IEC, opending);
+
+ for (dev = 0; dev < IOC4_NDEVS; dev++) {
+ mask = spending & ioc4_intrbits[dev].sio;
+ if (mask != 0) {
+ (void)iof_intr_dispatch(sc, dev);
+
+ /* Ack, then reenable, pending interrupts */
+ bus_space_write_4(sc->sc_memt, sc->sc_memh,
+ IOC4_SIO_IR, mask);
+ bus_space_write_4(sc->sc_memt, sc->sc_memh,
+ IOC4_SIO_IES, mask);
+ }
+ mask = opending & ioc4_intrbits[dev].other;
+ if (mask != 0) {
+ (void)iof_intr_dispatch(sc, dev);
+
+ /* Ack, then reenable, pending interrupts */
+ bus_space_write_4(sc->sc_memt, sc->sc_memh,
+ IOC4_OTHER_IR, mask);
+ bus_space_write_4(sc->sc_memt, sc->sc_memh,
+ IOC4_OTHER_IES, mask);
+ }
+ }
+
+ return 1;
+}
+
+int
+iof_intr_dispatch(struct iof_softc *sc, int dev)
+{
+ struct iof_intr *ii;
+ int rc = 0;
+
+ /* Call registered interrupt function. */
+ if ((ii = sc->sc_intr[dev]) != NULL && ii->ii_func != NULL) {
+ rc = (*ii->ii_func)(ii->ii_arg);
+ if (rc != 0)
+ ii->ii_count.ec_count++;
+ }
+
+ return rc;
+}
diff --git a/sys/arch/sgi/pci/iofreg.h b/sys/arch/sgi/pci/iofreg.h
new file mode 100644
index 00000000000..753c6895b7f
--- /dev/null
+++ b/sys/arch/sgi/pci/iofreg.h
@@ -0,0 +1,60 @@
+/* $OpenBSD: iofreg.h,v 1.1 2009/08/18 19:34:17 miod Exp $ */
+
+/*
+ * Copyright (c) 2009 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Register definitions for SGI IOC4 ASIC.
+ */
+
+#define IOC4_NDEVS 7
+
+#define IOC4DEV_SERIAL_A 0
+#define IOC4DEV_SERIAL_B 1
+#define IOC4DEV_SERIAL_C 3
+#define IOC4DEV_SERIAL_D 4
+#define IOC4DEV_KBC 5
+#define IOC4DEV_ATAPI 6
+
+#define IOC4_SIO_IR 0x00000008
+#define IOC4_OTHER_IR 0x0000000c
+#define IOC4_SIO_IES 0x00000010
+#define IOC4_OTHER_IES 0x00000014
+#define IOC4_SIO_IEC 0x00000018
+#define IOC4_OTHER_IEC 0x0000001c
+#define IOC4_SIO_CR 0x00000020
+#define IOC4_MCR 0x00000024
+
+/* bits in the SIO interrupt register */
+#define IOC4_SIRQ_UARTA 0x00000040 /* UART A passthrough */
+#define IOC4_SIRQ_UARTB 0x00004000 /* UART B passthrough */
+#define IOC4_SIRQ_UARTC 0x00400000 /* UART C passthrough */
+#define IOC4_SIRQ_UARTD 0x40000000 /* UART D passthrough */
+
+/* bits in the OTHER interrupt register */
+#define IOC4_OIRQ_ATAPI 0x00000001 /* ATAPI passthrough */
+#define IOC4_OIRQ_KBC 0x00000040 /* keyboard controller */
+
+#define IOC4_ATAPI_BASE 0x00000100
+#define IOC4_ATAPI_SIZE 0x00000100
+
+#define IOC4_KBC_BASE 0x00000200
+#define IOC4_KBC_SIZE 0x00000014
+
+#define IOC4_UARTA_BASE 0x00000380
+#define IOC4_UARTB_BASE 0x00000388
+#define IOC4_UARTC_BASE 0x00000390
+#define IOC4_UARTD_BASE 0x00000398
diff --git a/sys/arch/sgi/pci/iofvar.h b/sys/arch/sgi/pci/iofvar.h
new file mode 100644
index 00000000000..1a5dc93a62d
--- /dev/null
+++ b/sys/arch/sgi/pci/iofvar.h
@@ -0,0 +1,30 @@
+/* $OpenBSD: iofvar.h,v 1.1 2009/08/18 19:34:17 miod Exp $ */
+
+/*
+ * Copyright (c) 2009 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+struct iof_attach_args {
+ const char *iaa_name;
+
+ bus_space_tag_t iaa_memt;
+ bus_space_handle_t iaa_memh;
+ bus_dma_tag_t iaa_dmat;
+
+ bus_addr_t iaa_base;
+ uint iaa_dev;
+};
+
+void *iof_intr_establish(void *, uint, int, int (*)(void *), void *, char *);