diff options
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/hp300/conf/files.hp300 | 14 | ||||
-rw-r--r-- | sys/arch/hp300/dev/frodo.c | 104 | ||||
-rw-r--r-- | sys/arch/hp300/dev/frodoreg.h | 12 | ||||
-rw-r--r-- | sys/arch/hp300/dev/frodovar.h | 4 | ||||
-rw-r--r-- | sys/arch/hp300/dev/isa_machdep.h | 40 | ||||
-rw-r--r-- | sys/arch/hp300/dev/isabr.c | 1028 | ||||
-rw-r--r-- | sys/arch/hp300/dev/isabrreg.h | 40 |
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))) |