summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/hp300/conf/files.hp30014
-rw-r--r--sys/arch/hp300/dev/frodo.c104
-rw-r--r--sys/arch/hp300/dev/frodoreg.h12
-rw-r--r--sys/arch/hp300/dev/frodovar.h4
-rw-r--r--sys/arch/hp300/dev/isa_machdep.h40
-rw-r--r--sys/arch/hp300/dev/isabr.c1028
-rw-r--r--sys/arch/hp300/dev/isabrreg.h40
7 files changed, 1213 insertions, 29 deletions
diff --git a/sys/arch/hp300/conf/files.hp300 b/sys/arch/hp300/conf/files.hp300
index 706a27379b4..eeb8bda5f21 100644
--- a/sys/arch/hp300/conf/files.hp300
+++ b/sys/arch/hp300/conf/files.hp300
@@ -1,4 +1,4 @@
-# $OpenBSD: files.hp300,v 1.31 2006/04/14 21:05:43 miod Exp $
+# $OpenBSD: files.hp300,v 1.32 2007/01/06 20:17:41 miod Exp $
# $NetBSD: files.hp300,v 1.28 1997/05/12 08:23:28 thorpej Exp $
#
# hp300-specific configuration info
@@ -175,6 +175,18 @@ major {cd = 9}
attach sti at sgc with sti_sgc
file arch/hp300/dev/sti_sgc.c sti_sgc
+# ISA devices
+include "dev/isa/files.isa"
+include "dev/isa/files.isapnp"
+
+#
+# ISA bridge
+#
+
+device isabr: isabus
+attach isabr at frodo
+file arch/hp300/dev/isabr.c isabr needs-flag
+
#
# HIL Human Interface Loop devices
#
diff --git a/sys/arch/hp300/dev/frodo.c b/sys/arch/hp300/dev/frodo.c
index 6cae385aef2..e2ee8bfbb9c 100644
--- a/sys/arch/hp300/dev/frodo.c
+++ b/sys/arch/hp300/dev/frodo.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: frodo.c,v 1.9 2007/01/06 20:09:12 miod Exp $ */
+/* $OpenBSD: frodo.c,v 1.10 2007/01/06 20:17:43 miod Exp $ */
/* $NetBSD: frodo.c,v 1.5 1999/07/31 21:15:20 thorpej Exp $ */
/*-
@@ -83,12 +83,14 @@
#include <hp300/dev/frodoreg.h>
#include <hp300/dev/frodovar.h>
+#include "isabr.h"
+
struct frodo_softc {
struct device sc_dev; /* generic device glue */
volatile u_int8_t *sc_regs; /* register base */
struct isr *sc_intr[FRODO_NINTR]; /* interrupt handlers */
struct isr sc_isr; /* main interrupt handler */
- int sc_refcnt; /* number of interrupt refs */
+ u_int sc_refcnt; /* number of interrupt refs */
};
int frodomatch(struct device *, void *, void *);
@@ -98,6 +100,7 @@ int frodoprint(void *, const char *);
int frodosubmatch(struct device *, void *, void *);
int frodointr(void *);
+void frodo_state(struct frodo_softc *);
void frodo_imask(struct frodo_softc *, u_int16_t, u_int16_t);
@@ -114,6 +117,7 @@ struct frodo_attach_args frodo_subdevs[] = {
{ "apci", NULL, FRODO_APCI_OFFSET(1), FRODO_INTR_APCI1 },
{ "apci", NULL, FRODO_APCI_OFFSET(2), FRODO_INTR_APCI2 },
{ "apci", NULL, FRODO_APCI_OFFSET(3), FRODO_INTR_APCI3 },
+ { "isabr", NULL, 0, 0 },
{ NULL, NULL, 0, 0 },
};
@@ -184,11 +188,17 @@ frodoattach(parent, self, aux)
FRODO_WRITE(sc, FRODO_PIC_PU, 0xff);
FRODO_WRITE(sc, FRODO_PIC_PL, 0xff);
- /* Set interrupt polarities. */
+ /* Set interrupt polarities... */
FRODO_WRITE(sc, FRODO_PIO_IPR, 0x10);
- /* ...and configure for edge triggering. */
- FRODO_WRITE(sc, FRODO_PIO_IELR, 0xcf);
+ /* ...and configure 1-5 for edge triggering. */
+ FRODO_WRITE(sc, FRODO_PIO_IELR, 0xc1);
+
+ /* Initialize IVR high half to zero so we don't need to mask it later */
+ FRODO_WRITE(sc, FRODO_PIC_IVR, 0x00);
+
+ /* Mask ISA interrupts until an ISA interrupt handler is registered. */
+ FRODO_WRITE(sc, FRODO_PIO_ISA_CONTROL, 0x80);
/*
* We defer hooking up our interrupt handler until
@@ -240,7 +250,7 @@ frodoprint(aux, pnp)
return (UNCONF);
}
-void
+int
frodo_intr_establish(struct device *frdev, int line, struct isr *isr,
const char *name)
{
@@ -252,8 +262,11 @@ frodo_intr_establish(struct device *frdev, int line, struct isr *isr,
sc->sc_dev.dv_xname, line);
}
if (sc->sc_intr[line] != NULL) {
- panic("%s: interrupt line %d already used",
+#ifdef DEBUG
+ printf("%s: interrupt line %d already used\n",
sc->sc_dev.dv_xname, line);
+#endif
+ return (EPERM);
}
/*
@@ -279,7 +292,15 @@ frodo_intr_establish(struct device *frdev, int line, struct isr *isr,
sc->sc_intr[line] = isr;
/* Enable the interrupt line. */
- frodo_imask(sc, (1 << line), 0);
+ frodo_imask(sc, FRODO_INTR_BIT(line), 0);
+
+#if NISABR > 0
+ /* Unmask ISA interrupts if necessary. */
+ if (FRODO_INTR_ISA(line))
+ FRODO_WRITE(sc, FRODO_PIO_ISA_CONTROL, 0x00);
+#endif
+
+ return (0);
}
void
@@ -290,13 +311,26 @@ frodo_intr_disestablish(frdev, line)
struct frodo_softc *sc = (struct frodo_softc *)frdev;
int newpri;
+#ifdef DIAGNOSTIC
if (sc->sc_intr[line] == NULL) {
- panic("%s: no handler for line %d",
- sc->sc_dev.dv_xname, line);
+ printf("%s(%s): no handler for line %d",
+ sc->sc_dev.dv_xname, __func__, line);
+ return;
}
+#endif
sc->sc_intr[line] = NULL;
- frodo_imask(sc, 0, (1 << line));
+ frodo_imask(sc, 0, FRODO_INTR_BIT(line));
+
+#if NISABR > 0
+ /* Mask ISA interrupts if necessary. */
+ if (FRODO_INTR_ISA(line)) {
+ if (sc->sc_intr[FRODO_INTR_ILOW] == NULL &&
+ sc->sc_intr[FRODO_INTR_IMID] == NULL &&
+ sc->sc_intr[FRODO_INTR_IHIGH] == NULL)
+ FRODO_WRITE(sc, FRODO_PIO_ISA_CONTROL, 0x80);
+ }
+#endif
/* If this was the last, unhook ourselves. */
if (sc->sc_refcnt-- == 1) {
@@ -326,21 +360,29 @@ frodointr(arg)
{
struct frodo_softc *sc = arg;
struct isr *fisr;
- int line, taken = 0;
+ int pending, line, rc = 0;
+
+#ifdef DEBUG
+ frodo_state(sc);
+#endif
/* Any interrupts pending? */
- if (FRODO_GETPEND(sc) == 0)
- return (0);
+ while ((pending = FRODO_GETPEND(sc)) != 0) {
+ rc++;
- do {
/*
* Get pending interrupt; this also clears it for us.
*/
- line = FRODO_IPEND(sc);
+ line = FRODO_READ(sc, FRODO_PIC_ACK) /* & 0x0f */;
+
fisr = sc->sc_intr[line];
if (fisr == NULL) {
printf("%s: unhandled interrupt on line %d\n",
sc->sc_dev.dv_xname, line);
+#ifdef DEBUG
+ /* Disable interrupt source */
+ frodo_imask(sc, 0, FRODO_INTR_BIT(line));
+#endif
} else {
if ((*fisr->isr_func)(fisr->isr_arg) != 0) {
fisr->isr_count.ec_count++;
@@ -349,11 +391,17 @@ frodointr(arg)
sc->sc_dev.dv_xname, line);
}
}
- if (taken++ > 100)
- panic("frodointr: looping, line %d fisr %p", line, fisr);
- } while (FRODO_GETPEND(sc) != 0);
- return (1);
+ if (rc > 100)
+ panic("frodointr: looping, pending %x line %d fisr %p",
+ pending, line, fisr);
+
+#ifdef DEBUG
+ frodo_state(sc);
+#endif
+ }
+
+ return (rc);
}
void
@@ -370,3 +418,19 @@ frodo_imask(sc, set, clear)
FRODO_SETMASK(sc, imask);
}
+
+#ifdef DEBUG
+void
+frodo_state(struct frodo_softc *sc)
+{
+ int i;
+
+ printf("%s state:", sc->sc_dev.dv_xname);
+ for (i = 0xc0; i < 0x100; i += 4) {
+ printf(" %02x", FRODO_READ(sc, i));
+ if (i == 0xcc || i == 0xdc || i == 0xec)
+ printf(" /");
+ }
+ printf("\n");
+}
+#endif
diff --git a/sys/arch/hp300/dev/frodoreg.h b/sys/arch/hp300/dev/frodoreg.h
index c99c753b449..07b2280e4c3 100644
--- a/sys/arch/hp300/dev/frodoreg.h
+++ b/sys/arch/hp300/dev/frodoreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: frodoreg.h,v 1.1 1997/07/06 08:01:51 downsj Exp $ */
+/* $OpenBSD: frodoreg.h,v 1.2 2007/01/06 20:17:43 miod Exp $ */
/* $NetBSD: frodoreg.h,v 1.1 1997/05/12 08:03:49 thorpej Exp $ */
/*
@@ -57,9 +57,9 @@
#define FRODO_IISR 0xc0 /* ISA Interrupt Status Register
(also PIR) */
#define FRODO_IISR_SERVICE (1<<0) /* service switch "on" if 0 */
-#define FRODO_IISR_ILOW (1<<1) /* IRQ 3,4,5 or 6 on ISA if 1 */
-#define FRODO_IISR_IMID (1<<2) /* IRQ 7,9,10 or 11 on ISA if 1 */
-#define FRODO_IISR_IHI (1<<3) /* IRQ 12,13,14 or 15 on ISA if 1 */
+#define FRODO_IISR_ILOW (1<<1) /* IRQ 3,4,5 or 6 on ISA if 0 */
+#define FRODO_IISR_IMID (1<<2) /* IRQ 7,9,10 or 11 on ISA if 0 */
+#define FRODO_IISR_IHI (1<<3) /* IRQ 12,13,14 or 15 on ISA if 0 */
/* bits 4 and 5 are DN2500 SCSI interrupts */
/* bit 6 is unused */
#define FRODO_IISR_IOCHK (1<<7) /* ISA board asserted IOCHK if low */
@@ -68,6 +68,7 @@
(ints 7->0) */
#define FRODO_PIO_IELR 0xc8 /* input edge/level register */
+#define FRODO_PIO_ISA_CONTROL 0xcc /* ISA interrupts masking */
/* This is probably not used on the 4xx */
#define FRODO_DIAGCTL 0xd0 /* Diagnostic Control Register */
@@ -94,8 +95,6 @@
#define FRODO_GETPEND(sc) \
((FRODO_READ((sc), FRODO_PIC_PU) << 8) | \
FRODO_READ((sc), FRODO_PIC_PL))
-#define FRODO_IPEND(sc) \
- (FRODO_READ((sc), FRODO_PIC_ACK) & 0x0f)
/*
* Interrupt lines. Use FRODO_INTR_BIT() below to get a bit
@@ -120,4 +119,5 @@
#define FRODO_NINTR 16
+#define FRODO_INTR_ISA(l) ((l) != 0 && (l) <= FRODO_INTR_IHI)
#define FRODO_INTR_BIT(line) (1 << (line))
diff --git a/sys/arch/hp300/dev/frodovar.h b/sys/arch/hp300/dev/frodovar.h
index b5e56e0f8fd..3f78a022f4b 100644
--- a/sys/arch/hp300/dev/frodovar.h
+++ b/sys/arch/hp300/dev/frodovar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: frodovar.h,v 1.6 2007/01/06 20:09:12 miod Exp $ */
+/* $OpenBSD: frodovar.h,v 1.7 2007/01/06 20:17:43 miod Exp $ */
/* $NetBSD: frodovar.h,v 1.1 1997/05/12 08:03:50 thorpej Exp $ */
/*
@@ -45,5 +45,5 @@ struct frodo_attach_args {
#define frodocf_offset cf_loc[0]
#define FRODO_UNKNOWN_OFFSET -1
-void frodo_intr_establish(struct device *, int, struct isr *, const char *);
+int frodo_intr_establish(struct device *, int, struct isr *, const char *);
void frodo_intr_disestablish(struct device *, int);
diff --git a/sys/arch/hp300/dev/isa_machdep.h b/sys/arch/hp300/dev/isa_machdep.h
new file mode 100644
index 00000000000..f796298a580
--- /dev/null
+++ b/sys/arch/hp300/dev/isa_machdep.h
@@ -0,0 +1,40 @@
+/* $OpenBSD: isa_machdep.h,v 1.1 2007/01/06 20:17:43 miod Exp $ */
+
+/*
+ * Copyright (c) 2007 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, this permission notice, and the disclaimer below
+ * 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.
+ */
+
+#ifndef _HP300_ISA_MACHDEP_H_
+#define _HP300_ISA_MACHDEP_H_
+
+#include <machine/bus.h>
+
+#define __NO_ISA_INTR_CHECK
+
+typedef void * isa_chipset_tag_t;
+
+void isa_attach_hook(struct device *, struct device *,
+ struct isabus_attach_args *);
+void *isa_intr_establish(isa_chipset_tag_t, int, int, int,
+ int (*)(void *), void *, char *);
+void isa_intr_disestablish(isa_chipset_tag_t, void *);
+
+#define IST_NONE 0
+#define IST_PULSE 1
+#define IST_EDGE 2
+#define IST_LEVEL 3
+
+#endif /* _HP300_ISA_MACHDEP_H_ */
diff --git a/sys/arch/hp300/dev/isabr.c b/sys/arch/hp300/dev/isabr.c
new file mode 100644
index 00000000000..bd87f71378b
--- /dev/null
+++ b/sys/arch/hp300/dev/isabr.c
@@ -0,0 +1,1028 @@
+/* $OpenBSD: isabr.c,v 1.1 2007/01/06 20:17:43 miod Exp $ */
+
+/*
+ * Copyright (c) 2007 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, this permission notice, and the disclaimer below
+ * 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.
+ */
+
+/*
+ * HP 9000/4xx model `t' single ISA slot attachment
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/extent.h>
+#include <sys/malloc.h>
+
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/hp300spu.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <dev/isa/isareg.h>
+#include <dev/isa/isavar.h>
+
+#include <hp300/dev/frodoreg.h>
+#include <hp300/dev/frodovar.h>
+#include <hp300/dev/isabrreg.h>
+
+int isabr_match(struct device *, void *, void *);
+void isabr_attach(struct device *, struct device *, void *);
+int isabr_print(void *, const char *);
+
+struct isabr_softc {
+ struct device sc_dev;
+ struct extent *sc_io_extent;
+ struct extent *sc_mem_extent;
+};
+
+struct cfattach isabr_ca = {
+ sizeof(struct isabr_softc), isabr_match, isabr_attach
+};
+
+struct cfdriver isabr_cd = {
+ NULL, "isabr", DV_DULL
+};
+
+struct isabr_softc *isabr;
+
+int isabr_bus_space_setup(struct isabr_softc *, struct frodo_attach_args *,
+ struct isabus_attach_args *);
+
+int
+isabr_match(struct device *parent, void *match, void *aux)
+{
+ struct frodo_attach_args *fa = aux;
+ vaddr_t va;
+ int rv;
+ static int isa_matched = 0;
+
+ if (isa_matched != 0)
+ return (0);
+
+ if (strcmp(fa->fa_name, isabr_cd.cd_name) != 0)
+ return (0);
+
+ va = uvm_km_valloc(kernel_map, PAGE_SIZE);
+ if (va == NULL)
+ return (0);
+
+ /*
+ * Check that the iomem space answers probes
+ */
+ pmap_kenter_cache(va, ISABR_IOMEM_BASE, PG_RW | PG_CI);
+ pmap_update(pmap_kernel());
+ rv = badbaddr((caddr_t)va);
+ pmap_kremove(va, PAGE_SIZE);
+ pmap_update(pmap_kernel());
+
+ /*
+ * Check that the ioport space answers probes
+ */
+ pmap_kenter_cache(va, ISABR_IOPORT_BASE, PG_RW | PG_CI);
+ pmap_update(pmap_kernel());
+ rv |= badbaddr((caddr_t)va);
+ pmap_kremove(va, PAGE_SIZE);
+ pmap_update(pmap_kernel());
+
+ uvm_km_free(kernel_map, va, PAGE_SIZE);
+
+ if (rv != 0)
+ return (0);
+
+ return (isa_matched = 1);
+}
+
+void
+isabr_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct isabus_attach_args iba;
+ struct isabr_softc *sc = (struct isabr_softc *)self;
+ struct frodo_attach_args *faa = (struct frodo_attach_args *)aux;
+
+ bzero(&iba, sizeof(iba));
+
+ if (isabr_bus_space_setup(sc, faa, &iba) != 0) {
+ printf(": can not initialize bus_space\n");
+ return;
+ }
+ printf("\n");
+
+ iba.iba_busname = "isa";
+ config_found(self, &iba, isabr_print);
+}
+
+int
+isabr_print(void *aux, const char *pnp)
+{
+ if (pnp)
+ printf("isa at %s", pnp);
+ return (UNCONF);
+}
+
+/*
+ * ISA support functions
+ */
+
+void
+isa_attach_hook(struct device *parent, struct device *self,
+ struct isabus_attach_args *iba)
+{
+ iba->iba_ic = parent; /* isabr0 */
+}
+
+/*
+ * Interrupt handling.
+ *
+ * We are currently registering ISA interrupt handlers as Frodo interrupt
+ * handlers directly. We can because model `t' only have a single slot.
+ *
+ * Eventually this should be replaced with an isabr interrupt dispatcher,
+ * allowing multiple interrupts on the same Frodo line. This would also
+ * move the ISA-specific acknowledge out of non-ISA Frodo lines processing.
+ * And this would allow a real intr_disestablish function.
+ */
+void *
+isa_intr_establish(isa_chipset_tag_t ic, int irq, int type, int level,
+ int (*handler)(void *), void *arg, char *name)
+{
+ struct isabr_softc *sc = (struct isabr_softc *)ic;
+ struct isr *isr;
+ int fline;
+
+ /*
+ * Frodo is configured for edge interrupts.
+ */
+ if (type != IST_EDGE) {
+#ifdef DIAGNOSTIC
+ printf("%s: non-edge interrupt type not supported on hp300\n",
+ name);
+#endif
+ return (NULL);
+ }
+
+ switch (irq) {
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ fline = FRODO_INTR_ILOW;
+ break;
+ case 7:
+ case 9:
+ case 10:
+ case 11:
+ fline = FRODO_INTR_IMID;
+ break;
+ case 12:
+ case 14:
+ case 15:
+ fline = FRODO_INTR_IHI;
+ break;
+ default:
+#ifdef DIAGNOSTIC
+ printf("%s: ISA irq %d not available on " MACHINE "\n", name);
+#endif
+ return (NULL);
+ }
+
+ isr = (struct isr *)malloc(sizeof(struct isr), M_DEVBUF, M_NOWAIT);
+ if (isr == NULL)
+ return (NULL);
+
+ isr->isr_func = handler;
+ isr->isr_arg = arg;
+ isr->isr_priority = level;
+
+ if (frodo_intr_establish(sc->sc_dev.dv_parent, fline, isr, name) == 0)
+ return (isr);
+
+ free(isr, M_DEVBUF);
+ return (NULL);
+}
+
+void
+isa_intr_disestablish(isa_chipset_tag_t ic, void *cookie)
+{
+#if 0
+ struct isabr_softc *sc = (struct isabr_softc *)ic;
+ struct isr *isr = cookie;
+
+ /* XXX how to find fline back? */
+ frodo_intr_disestablish(sc->dv_parent, fline);
+ free(isr, M_DEVBUF);
+#else
+ panic("isa_intr_disestablish");
+#endif
+}
+
+/*
+ * Implementation of bus_space mapping for the hp300 isa slot.
+ *
+ * Everything is memory mapped, but the I/O space is scattered for better
+ * userland access control granularity, should we ever provide iopl
+ * facilities, thus i/o space accesses need their own routines set, while
+ * memory space simply reuse the ``canonical'' bus_space routines.
+ *
+ * For the I/O space, all bus_space_map allocations are extended to a 8 ports
+ * granularity, so that they span entire, contiguous pages; the handle value
+ * however needs to keep track of the in-page offset if the first port is
+ * not aligned to a ``line'' boundary.
+ *
+ * I.e, a bus_space_map(0x302, 0xe) call will map the 0x300-0x30f area,
+ * and return a pointer the 0x302 port. Access routines will then, from
+ * this pointer, construct a (0x300, 0x02) tuple, which they can use to
+ * access the remainder of the range.
+ */
+
+/*
+ * ISA I/O space
+ */
+
+int hp300_isa_io_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *);
+void hp300_isa_io_unmap(bus_space_handle_t, bus_size_t);
+int hp300_isa_io_subregion(bus_space_handle_t, bus_size_t, bus_size_t,
+ bus_space_handle_t *);
+void * hp300_isa_io_vaddr(bus_space_handle_t);
+
+u_int8_t hp300_isa_io_bsr1(bus_space_handle_t, bus_size_t);
+u_int16_t hp300_isa_io_bsr2(bus_space_handle_t, bus_size_t);
+u_int32_t hp300_isa_io_bsr4(bus_space_handle_t, bus_size_t);
+u_int16_t __hp300_isa_io_bsr2(bus_space_handle_t, bus_size_t);
+u_int32_t __hp300_isa_io_bsr4(bus_space_handle_t, bus_size_t);
+void hp300_isa_io_bsrm1(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
+void hp300_isa_io_bsrm2(bus_space_handle_t, bus_size_t, u_int16_t *, size_t);
+void hp300_isa_io_bsrm4(bus_space_handle_t, bus_size_t, u_int32_t *, size_t);
+void hp300_isa_io_bsrrm2(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
+void hp300_isa_io_bsrrm4(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
+void hp300_isa_io_bsrr1(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
+void hp300_isa_io_bsrr2(bus_space_handle_t, bus_size_t, u_int16_t *, size_t);
+void hp300_isa_io_bsrr4(bus_space_handle_t, bus_size_t, u_int32_t *, size_t);
+void hp300_isa_io_bsrrr2(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
+void hp300_isa_io_bsrrr4(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
+void hp300_isa_io_bsw1(bus_space_handle_t, bus_size_t, u_int8_t);
+void hp300_isa_io_bsw2(bus_space_handle_t, bus_size_t, u_int16_t);
+void hp300_isa_io_bsw4(bus_space_handle_t, bus_size_t, u_int32_t);
+void __hp300_isa_io_bsw2(bus_space_handle_t, bus_size_t, u_int16_t);
+void __hp300_isa_io_bsw4(bus_space_handle_t, bus_size_t, u_int32_t);
+void hp300_isa_io_bswm1(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
+void hp300_isa_io_bswm2(bus_space_handle_t, bus_size_t, const u_int16_t *, size_t);
+void hp300_isa_io_bswm4(bus_space_handle_t, bus_size_t, const u_int32_t *, size_t);
+void hp300_isa_io_bswrm2(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
+void hp300_isa_io_bswrm4(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
+void hp300_isa_io_bswr1(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
+void hp300_isa_io_bswr2(bus_space_handle_t, bus_size_t, const u_int16_t *, size_t);
+void hp300_isa_io_bswr4(bus_space_handle_t, bus_size_t, const u_int32_t *, size_t);
+void hp300_isa_io_bswrr2(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
+void hp300_isa_io_bswrr4(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
+void hp300_isa_io_bssm1(bus_space_handle_t, bus_size_t, u_int8_t, size_t);
+void hp300_isa_io_bssm2(bus_space_handle_t, bus_size_t, u_int16_t, size_t);
+void hp300_isa_io_bssm4(bus_space_handle_t, bus_size_t, u_int32_t, size_t);
+void hp300_isa_io_bssr1(bus_space_handle_t, bus_size_t, u_int8_t, size_t);
+void hp300_isa_io_bssr2(bus_space_handle_t, bus_size_t, u_int16_t, size_t);
+void hp300_isa_io_bssr4(bus_space_handle_t, bus_size_t, u_int32_t, size_t);
+
+struct hp300_bus_space_tag hp300_isa_io_tag = {
+ hp300_isa_io_map,
+ hp300_isa_io_unmap,
+ hp300_isa_io_subregion,
+ hp300_isa_io_vaddr,
+
+ hp300_isa_io_bsr1,
+ hp300_isa_io_bsr2,
+ hp300_isa_io_bsr4,
+
+ hp300_isa_io_bsrm1,
+ hp300_isa_io_bsrm2,
+ hp300_isa_io_bsrm4,
+
+ hp300_isa_io_bsrrm2,
+ hp300_isa_io_bsrrm4,
+
+ hp300_isa_io_bsrr1,
+ hp300_isa_io_bsrr2,
+ hp300_isa_io_bsrr4,
+
+ hp300_isa_io_bsrrr2,
+ hp300_isa_io_bsrrr4,
+
+ hp300_isa_io_bsw1,
+ hp300_isa_io_bsw2,
+ hp300_isa_io_bsw4,
+
+ hp300_isa_io_bswm1,
+ hp300_isa_io_bswm2,
+ hp300_isa_io_bswm4,
+
+ hp300_isa_io_bswrm2,
+ hp300_isa_io_bswrm4,
+
+ hp300_isa_io_bswr1,
+ hp300_isa_io_bswr2,
+ hp300_isa_io_bswr4,
+
+ hp300_isa_io_bswrr2,
+ hp300_isa_io_bswrr4,
+
+ hp300_isa_io_bssm1,
+ hp300_isa_io_bssm2,
+ hp300_isa_io_bssm4,
+
+ hp300_isa_io_bssr1,
+ hp300_isa_io_bssr2,
+ hp300_isa_io_bssr4
+};
+
+int
+hp300_isa_io_map(bus_addr_t bpa, bus_size_t size, int flags,
+ bus_space_handle_t *bshp)
+{
+ int error;
+ u_int iobase, iosize, npg;
+ vaddr_t va;
+ paddr_t pa;
+
+#ifdef DEBUG
+ printf("isa_io_map(%04x, %04x)", bpa, size);
+#endif
+
+ /*
+ * Reserve the range in the allocation extent.
+ */
+ if (bpa < IO_ISABEGIN || bpa + size > IO_ISAEND + 1) {
+#ifdef DEBUG
+ printf(" outside available range\n");
+#endif
+ return (ERANGE);
+ }
+ error = extent_alloc_region(isabr->sc_io_extent, bpa, size,
+ EX_MALLOCOK);
+ if (error != 0) {
+#ifdef DEBUG
+ printf(" overlaps extent\n");
+#endif
+ return (error);
+ }
+
+ /*
+ * Round the allocation to a multiple of 8 bytes, to end up
+ * with entire pages.
+ */
+ iobase = bpa & ~(ISABR_IOPORT_LINE - 1);
+ iosize = ((bpa + size + (ISABR_IOPORT_LINE - 1)) &
+ ~(ISABR_IOPORT_LINE - 1)) - iobase;
+
+ /*
+ * Compute how many pages will be necessary to map this range.
+ */
+ npg = iosize / ISABR_IOPORT_LINE;
+#ifdef DEBUG
+ printf("->(%04x, %04x)=%d@", iobase, iosize, npg);
+#endif
+
+ /*
+ * Allocate virtual address space to map this space in.
+ */
+ va = uvm_km_valloc(kernel_map, ptoa(npg));
+ if (va == 0) {
+#ifdef DEBUG
+ printf("NULL\n");
+#endif
+ extent_free(isabr->sc_io_extent, bpa, size, EX_MALLOCOK);
+ return (ENOMEM);
+ }
+
+ *bshp = (bus_space_handle_t)(va + (bpa - iobase));
+
+ pa = ISABR_IOPORT_BASE + ISAADDR(iobase);
+#ifdef DEBUG
+ printf("%08x (ret %08x) pa %08x\n", va, *bshp, pa);
+#endif
+
+ while (npg != 0) {
+ pmap_kenter_cache(va, pa, PG_RW | PG_CI);
+ npg--;
+ va += PAGE_SIZE;
+ pa += PAGE_SIZE;
+ }
+ pmap_update(pmap_kernel());
+
+ return (0);
+}
+
+void
+hp300_isa_io_unmap(bus_space_handle_t bsh, bus_size_t size)
+{
+ u_int iobase, iosize, npg;
+ vaddr_t va;
+ paddr_t pa;
+
+#ifdef DEBUG
+ printf("isa_io_unmap(%08x, %04x)", bsh, size);
+#endif
+
+ /*
+ * Find the pa matching this allocation, and the I/O port base
+ * from it.
+ */
+ va = (vaddr_t)bsh;
+ if (pmap_extract(pmap_kernel(), va, &pa) == FALSE) {
+#ifdef DEBUG
+ printf("-> no pa\n");
+#endif
+ return; /* XXX be vocal? */
+ }
+
+#ifdef DEBUG
+ printf("-> pa %08x ", pa);
+#endif
+ pa -= ISABR_IOPORT_BASE;
+ iobase = ISAPORT(pa);
+ if (iobase < IO_ISABEGIN || iobase > IO_ISAEND) {
+#ifdef DEBUG
+ printf("iobase %08x???\n", iobase);
+#endif
+ return; /* XXX be vocal? */
+ }
+
+ iosize = size + (iobase & (ISABR_IOPORT_LINE - 1)) +
+ (ISABR_IOPORT_LINE - 1);
+ npg = iosize / ISABR_IOPORT_LINE;
+#ifdef DEBUG
+ printf(" range %04x-%04x: %d\n", iobase, size, npg);
+#endif
+
+ pmap_kremove(va, ptoa(npg));
+ pmap_update(pmap_kernel());
+ uvm_km_free(kernel_map, va, ptoa(npg));
+
+ (void)extent_free(isabr->sc_io_extent, (u_long)iobase, size,
+ EX_MALLOCOK);
+}
+
+/*
+ * Round down an I/O space bus_space_handle, so that it points to the
+ * beginning of a page.
+ * This is gonna be hell when we support ports above 0x400.
+ */
+#define REALIGN_IO_HANDLE(h, o) \
+do { \
+ u_int tmp; \
+ tmp = (h) & (ISABR_IOPORT_LINE - 1); \
+ (h) -= tmp; \
+ (o) += tmp; \
+} while (0)
+
+/* ARGSUSED */
+int
+hp300_isa_io_subregion(bus_space_handle_t bsh, bus_size_t offset,
+ bus_size_t size, bus_space_handle_t *nbshp)
+{
+ REALIGN_IO_HANDLE(bsh, offset);
+ bsh += ISAADDR(offset);
+ *nbshp = bsh;
+ return (0);
+}
+
+void *
+hp300_isa_io_vaddr(bus_space_handle_t h)
+{
+ return (NULL);
+}
+
+/* bus_space_read_X */
+
+u_int8_t
+hp300_isa_io_bsr1(bus_space_handle_t bsh, bus_size_t offset)
+{
+ vaddr_t va;
+ u_int8_t rc;
+
+ REALIGN_IO_HANDLE(bsh, offset);
+ va = (vaddr_t)bsh + ISAADDR(offset);
+ rc = *(volatile u_int8_t *)va;
+#ifdef DEBUG
+ printf("R%03x(%x):%02x\t", offset, va, rc);
+#endif
+ return (rc);
+}
+
+u_int16_t
+__hp300_isa_io_bsr2(bus_space_handle_t bsh, bus_size_t offset)
+{
+ u_int16_t rc;
+ vaddr_t va;
+
+ if (offset & 1) {
+ rc = hp300_isa_io_bsr1(bsh, offset + 1) << 8;
+ rc |= hp300_isa_io_bsr1(bsh, offset);
+ } else {
+ REALIGN_IO_HANDLE(bsh, offset);
+ va = (vaddr_t)bsh + ISAADDR(offset);
+ rc = *(volatile u_int16_t *)va;
+ }
+#ifdef DEBUG
+ printf("R%03x:%04x\t", offset, rc);
+#endif
+ return (rc);
+}
+
+u_int16_t
+hp300_isa_io_bsr2(bus_space_handle_t bsh, bus_size_t offset)
+{
+ u_int16_t rc;
+
+ rc = __hp300_isa_io_bsr2(bsh, offset);
+ return (letoh16(rc));
+}
+
+u_int32_t
+__hp300_isa_io_bsr4(bus_space_handle_t bsh, bus_size_t offset)
+{
+ u_int32_t rc;
+ vaddr_t va;
+
+ if (offset & 3) {
+ rc = hp300_isa_io_bsr1(bsh, offset + 3) << 24;
+ rc |= hp300_isa_io_bsr1(bsh, offset + 2) << 16;
+ rc |= hp300_isa_io_bsr1(bsh, offset + 1) << 8;
+ rc |= hp300_isa_io_bsr1(bsh, offset);
+ } else {
+ REALIGN_IO_HANDLE(bsh, offset);
+ va = (vaddr_t)bsh + ISAADDR(offset);
+ rc = *(volatile u_int32_t *)va;
+ }
+#ifdef DEBUG
+ printf("R%03x:%08x\t", offset, rc);
+#endif
+ return (rc);
+}
+
+u_int32_t
+hp300_isa_io_bsr4(bus_space_handle_t bsh, bus_size_t offset)
+{
+ u_int32_t rc;
+
+ rc = __hp300_isa_io_bsr4(bsh, offset);
+ return (letoh32(rc));
+}
+
+/* bus_space_read_multi_X */
+
+void
+hp300_isa_io_bsrm1(bus_space_handle_t h, bus_size_t offset,
+ u_int8_t *a, size_t c)
+{
+ while ((int)--c >= 0)
+ *a++ = hp300_isa_io_bsr1(h, offset);
+}
+
+void
+hp300_isa_io_bsrm2(bus_space_handle_t h, bus_size_t offset,
+ u_int16_t *a, size_t c)
+{
+ while ((int)--c >= 0)
+ *a++ = hp300_isa_io_bsr2(h, offset);
+}
+
+void
+hp300_isa_io_bsrm4(bus_space_handle_t h, bus_size_t offset,
+ u_int32_t *a, size_t c)
+{
+ while ((int)--c >= 0)
+ *a++ = hp300_isa_io_bsr4(h, offset);
+}
+
+/* bus_space_read_raw_multi_X */
+
+void
+hp300_isa_io_bsrrm2(bus_space_handle_t h, bus_size_t offset,
+ u_int8_t *a, size_t c)
+{
+ while ((int)--c >= 0) {
+ *(u_int16_t *)a = __hp300_isa_io_bsr2(h, offset);
+ a += 2;
+ }
+}
+
+void
+hp300_isa_io_bsrrm4(bus_space_handle_t h, bus_size_t offset,
+ u_int8_t *a, size_t c)
+{
+ while ((int)--c >= 0) {
+ *(u_int32_t *)a = __hp300_isa_io_bsr4(h, offset);
+ a += 4;
+ }
+}
+
+/* bus_space_read_region_X */
+
+void
+hp300_isa_io_bsrr1(bus_space_handle_t h, bus_size_t offset,
+ u_int8_t *a, size_t c)
+{
+ while ((int)--c >= 0)
+ *a++ = hp300_isa_io_bsr1(h, offset++);
+}
+
+void
+hp300_isa_io_bsrr2(bus_space_handle_t h, bus_size_t offset,
+ u_int16_t *a, size_t c)
+{
+ while ((int)--c >= 0) {
+ *a++ = hp300_isa_io_bsr2(h, offset);
+ offset += 2;
+ }
+}
+
+void
+hp300_isa_io_bsrr4(bus_space_handle_t h, bus_size_t offset,
+ u_int32_t *a, size_t c)
+{
+ while ((int)--c >= 0) {
+ *a++ = hp300_isa_io_bsr4(h, offset);
+ offset += 4;
+ }
+}
+
+/* bus_space_read_raw_region_X */
+
+void
+hp300_isa_io_bsrrr2(bus_space_handle_t h, bus_size_t offset,
+ u_int8_t *a, size_t c)
+{
+ c >>= 1;
+ while ((int)--c >= 0) {
+ *(u_int16_t *)a = __hp300_isa_io_bsr2(h, offset);
+ offset += 2;
+ a += 2;
+ }
+}
+
+void
+hp300_isa_io_bsrrr4(bus_space_handle_t h, bus_size_t offset,
+ u_int8_t *a, size_t c)
+{
+ c >>= 2;
+ while ((int)--c >= 0) {
+ *(u_int32_t *)a = __hp300_isa_io_bsr4(h, offset);
+ offset += 4;
+ a += 4;
+ }
+}
+
+/* bus_space_write_X */
+
+void
+hp300_isa_io_bsw1(bus_space_handle_t h, bus_size_t offset, u_int8_t v)
+{
+ vaddr_t va;
+
+ REALIGN_IO_HANDLE(h, offset);
+ va = (vaddr_t)h + ISAADDR(offset);
+ *(volatile u_int8_t *)va = v;
+#ifdef DEBUG
+ printf("W%03x:%02x\t", offset, v);
+#endif
+}
+
+void
+__hp300_isa_io_bsw2(bus_space_handle_t h, bus_size_t offset, u_int16_t v)
+{
+ vaddr_t va;
+
+ if (offset & 1) {
+ hp300_isa_io_bsw1(h, offset + 1, v >> 8);
+ hp300_isa_io_bsw1(h, offset, v);
+ } else {
+ REALIGN_IO_HANDLE(h, offset);
+ va = (vaddr_t)h + ISAADDR(offset);
+ *(volatile u_int16_t *)va = v;
+ }
+#ifdef DEBUG
+ printf("W%03x:%04x\t", offset, v);
+#endif
+}
+
+void
+hp300_isa_io_bsw2(bus_space_handle_t h, bus_size_t offset, u_int16_t v)
+{
+ __hp300_isa_io_bsw2(h, offset, htole16(v));
+}
+
+void
+__hp300_isa_io_bsw4(bus_space_handle_t h, bus_size_t offset, u_int32_t v)
+{
+ vaddr_t va;
+
+ if (offset & 3) {
+ hp300_isa_io_bsw1(h, offset + 3, v >> 24);
+ hp300_isa_io_bsw1(h, offset + 2, v >> 16);
+ hp300_isa_io_bsw1(h, offset + 1, v >> 8);
+ hp300_isa_io_bsw1(h, offset, v);
+ } else {
+ REALIGN_IO_HANDLE(h, offset);
+ va = (vaddr_t)h + ISAADDR(offset);
+ *(volatile u_int32_t *)va = v;
+ }
+#ifdef DEBUG
+ printf("W%03x:%08x\t", offset, v);
+#endif
+}
+
+void
+hp300_isa_io_bsw4(bus_space_handle_t h, bus_size_t offset, u_int32_t v)
+{
+ __hp300_isa_io_bsw4(h, offset, htole32(v));
+}
+
+/* bus_space_write_multi_X */
+
+void
+hp300_isa_io_bswm1(bus_space_handle_t h, bus_size_t offset,
+ const u_int8_t *a, size_t c)
+{
+ while ((int)--c >= 0)
+ hp300_isa_io_bsw1(h, offset, *a++);
+}
+
+void
+hp300_isa_io_bswm2(bus_space_handle_t h, bus_size_t offset,
+ const u_int16_t *a, size_t c)
+{
+ while ((int)--c >= 0)
+ hp300_isa_io_bsw2(h, offset, *a++);
+}
+
+void
+hp300_isa_io_bswm4(bus_space_handle_t h, bus_size_t offset,
+ const u_int32_t *a, size_t c)
+{
+ while ((int)--c >= 0)
+ hp300_isa_io_bsw4(h, offset, *a++);
+}
+
+/* bus_space_write_raw_multi_X */
+
+void
+hp300_isa_io_bswrm2(bus_space_handle_t h, bus_size_t offset,
+ const u_int8_t *a, size_t c)
+{
+ while ((int)--c >= 0) {
+ __hp300_isa_io_bsw2(h, offset, *(u_int16_t *)a);
+ a += 2;
+ }
+}
+
+void
+hp300_isa_io_bswrm4(bus_space_handle_t h, bus_size_t offset,
+ const u_int8_t *a, size_t c)
+{
+ while ((int)--c >= 0) {
+ __hp300_isa_io_bsw4(h, offset, *(u_int32_t *)a);
+ a += 4;
+ }
+}
+
+/* bus_space_write_region_X */
+
+void
+hp300_isa_io_bswr1(bus_space_handle_t h, bus_size_t offset,
+ const u_int8_t *a, size_t c)
+{
+ while ((int)--c >= 0)
+ hp300_isa_io_bsw1(h, offset++, *a++);
+}
+
+void
+hp300_isa_io_bswr2(bus_space_handle_t h, bus_size_t offset,
+ const u_int16_t *a, size_t c)
+{
+ while ((int)--c >= 0) {
+ hp300_isa_io_bsw2(h, offset, *a++);
+ offset += 2;
+ }
+}
+
+void
+hp300_isa_io_bswr4(bus_space_handle_t h, bus_size_t offset,
+ const u_int32_t *a, size_t c)
+{
+ while ((int)--c >= 0) {
+ hp300_isa_io_bsw4(h, offset, *a++);
+ offset += 4;
+ }
+}
+
+/* bus_space_write_raw_region_X */
+
+void
+hp300_isa_io_bswrr2(bus_space_handle_t h, bus_size_t offset,
+ const u_int8_t *a, size_t c)
+{
+ c >>= 1;
+ while ((int)--c >= 0) {
+ __hp300_isa_io_bsw2(h, offset, *(u_int16_t *)a);
+ offset += 2;
+ a += 2;
+ }
+}
+
+void
+hp300_isa_io_bswrr4(bus_space_handle_t h, bus_size_t offset,
+ const u_int8_t *a, size_t c)
+{
+ c >>= 2;
+ while ((int)--c >= 0) {
+ __hp300_isa_io_bsw4(h, offset, *(u_int32_t *)a);
+ offset += 4;
+ a += 4;
+ }
+}
+
+/* bus_space_set_multi_X */
+
+void
+hp300_isa_io_bssm1(bus_space_handle_t h, bus_size_t offset,
+ u_int8_t v, size_t c)
+{
+ while ((int)--c >= 0)
+ hp300_isa_io_bsw1(h, offset, v);
+}
+
+void
+hp300_isa_io_bssm2(bus_space_handle_t h, bus_size_t offset,
+ u_int16_t v, size_t c)
+{
+ while ((int)--c >= 0)
+ hp300_isa_io_bsw2(h, offset, v);
+}
+
+void
+hp300_isa_io_bssm4(bus_space_handle_t h, bus_size_t offset,
+ u_int32_t v, size_t c)
+{
+ while ((int)--c >= 0)
+ hp300_isa_io_bsw4(h, offset, v);
+}
+
+/* bus_space_set_region_X */
+
+void
+hp300_isa_io_bssr1(bus_space_handle_t h, bus_size_t offset,
+ u_int8_t v, size_t c)
+{
+ while ((int)--c >= 0)
+ hp300_isa_io_bsw1(h, offset++, v);
+}
+
+void
+hp300_isa_io_bssr2(bus_space_handle_t h, bus_size_t offset,
+ u_int16_t v, size_t c)
+{
+ while ((int)--c >= 0) {
+ hp300_isa_io_bsw2(h, offset, v);
+ offset += 2;
+ }
+}
+
+void
+hp300_isa_io_bssr4(bus_space_handle_t h, bus_size_t offset,
+ u_int32_t v, size_t c)
+{
+ while ((int)--c >= 0) {
+ hp300_isa_io_bsw4(h, offset, v);
+ offset += 4;
+ }
+}
+
+/*
+ * ISA memory space
+ */
+
+int hp300_isa_mem_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *);
+void hp300_isa_mem_unmap(bus_space_handle_t, bus_size_t);
+
+int
+hp300_isa_mem_map(bus_addr_t bpa, bus_size_t size, int flags,
+ bus_space_handle_t *bshp)
+{
+ int error;
+ bus_addr_t membase;
+ bus_size_t rsize;
+ vaddr_t va;
+ paddr_t pa;
+ pt_entry_t template;
+
+ /*
+ * Reserve the range in the allocation extent.
+ */
+ if (bpa < IOM_BEGIN || bpa + size > IOM_END)
+ return (ERANGE);
+ error = extent_alloc_region(isabr->sc_mem_extent, bpa, size,
+ EX_MALLOCOK);
+ if (error != 0)
+ return (error);
+
+ /*
+ * Allocate virtual address space to map this space in.
+ */
+ membase = trunc_page(bpa);
+ rsize = round_page(bpa + size) - membase;
+ va = uvm_km_valloc(kernel_map, rsize);
+ if (va == 0) {
+ extent_free(isabr->sc_mem_extent, bpa, size, EX_MALLOCOK);
+ return (ENOMEM);
+ }
+
+ *bshp = (bus_space_handle_t)(va + (bpa - membase));
+
+ pa = membase + (ISABR_IOMEM_BASE - IOM_BEGIN);
+
+ if (flags & BUS_SPACE_MAP_CACHEABLE)
+ template = PG_RW;
+ else
+ template = PG_RW | PG_CI;
+
+ while (rsize != 0) {
+ pmap_kenter_cache(va, pa, template);
+ rsize -= PAGE_SIZE;
+ va += PAGE_SIZE;
+ pa += PAGE_SIZE;
+ }
+ pmap_update(pmap_kernel());
+
+ return (0);
+}
+
+void
+hp300_isa_mem_unmap(bus_space_handle_t bsh, bus_size_t size)
+{
+ vaddr_t va;
+ vsize_t rsize;
+
+ va = trunc_page((vaddr_t)bsh);
+ rsize = round_page((vaddr_t)bsh + size) - va;
+
+ pmap_kremove(va, rsize);
+ pmap_update(pmap_kernel());
+ uvm_km_free(kernel_map, va, rsize);
+
+ (void)extent_free(isabr->sc_mem_extent, (u_long)bsh, size, EX_MALLOCOK);
+}
+
+struct hp300_bus_space_tag hp300_isa_mem_tag; /* will be filled in */
+
+/*
+ * ISA bus_space initialization.
+ * This creates the necessary accounting elements and initializes the
+ * memory space bus_space_tag.
+ */
+
+int
+isabr_bus_space_setup(struct isabr_softc *sc, struct frodo_attach_args *faa,
+ struct isabus_attach_args *iba)
+{
+ /*
+ * Create the space extents.
+ * We only use them to prevent multiple allocations of the same areas.
+ */
+
+ sc->sc_io_extent = extent_create("isa_io", IO_ISABEGIN,
+ IO_ISAEND + 1, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_MALLOCOK);
+ if (sc->sc_io_extent == NULL)
+ return (ENOMEM);
+
+ sc->sc_mem_extent = extent_create("isa_mem", IOM_BEGIN,
+ IOM_END, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_MALLOCOK);
+ if (sc->sc_mem_extent == NULL) {
+ extent_destroy(sc->sc_io_extent);
+ return (ENOMEM);
+ }
+
+ iba->iba_iot = &hp300_isa_io_tag;
+ bcopy(faa->fa_tag, &hp300_isa_mem_tag,
+ sizeof(struct hp300_bus_space_tag));
+ hp300_isa_mem_tag.bs_map = hp300_isa_mem_map;
+ hp300_isa_mem_tag.bs_unmap = hp300_isa_mem_unmap;
+ iba->iba_memt = &hp300_isa_mem_tag;
+
+ isabr = sc;
+
+ return (0);
+}
diff --git a/sys/arch/hp300/dev/isabrreg.h b/sys/arch/hp300/dev/isabrreg.h
new file mode 100644
index 00000000000..6881e91a0bf
--- /dev/null
+++ b/sys/arch/hp300/dev/isabrreg.h
@@ -0,0 +1,40 @@
+/* $OpenBSD: isabrreg.h,v 1.1 2007/01/06 20:17:43 miod Exp $ */
+
+/*
+ * Copyright (c) 2007 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, this permission notice, and the disclaimer below
+ * 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.
+ */
+
+/*
+ * Models 4xx ISA slot memory spaces
+ */
+
+#define ISABR_IOMEM_BASE (0x30000000 + IOM_BEGIN)
+#define ISABR_IOMEM_END (0x30000000 + IOM_END)
+
+#define ISABR_IOPORT_BASE 0x30000000
+#define ISABR_IOPORT_END 0x30080000
+
+/*
+ * Ye mighty logic by which ports are interleaved.
+ * The actual scheme is more complex, to allow ports over 0x400 to be mapped
+ * in bits 3-11 of the address. But we don't support the multi-slot EISA
+ * bridges yet.
+ */
+#define ISABR_IOPORT_LINE 0x08
+#define ISAADDR(p) \
+ ((((p) & ~(ISABR_IOPORT_LINE - 1)) << 9) | ((p) & (ISABR_IOPORT_LINE - 1)))
+#define ISAPORT(a) \
+ ((((a) >> 9) & ~(ISABR_IOPORT_LINE - 1)) | ((a) & (ISABR_IOPORT_LINE - 1)))