diff options
author | 2007-12-27 23:17:53 +0000 | |
---|---|---|
committer | 2007-12-27 23:17:53 +0000 | |
commit | 159450af1116f17a6ada2c1cf1efa869a21256f0 (patch) | |
tree | 7f712a838860106e5c8c649da44492094adf9a97 | |
parent | Undo previous commit after debating a few corner cases with gwk. This (diff) | |
download | wireguard-openbsd-159450af1116f17a6ada2c1cf1efa869a21256f0.tar.xz wireguard-openbsd-159450af1116f17a6ada2c1cf1efa869a21256f0.zip |
Make the mvme188 interrupt handling closer to the aviion interrupt handling:
non-VME syscon interrupt sources will now use their own intrhand array,
and interrupt sources will be enabled in the arbiter as interrupt handlers
are registered. This allows VME devices to use the whole 256 interrupts range.
-rw-r--r-- | sys/arch/mvme88k/dev/dart.c | 7 | ||||
-rw-r--r-- | sys/arch/mvme88k/dev/syscon.c | 227 | ||||
-rw-r--r-- | sys/arch/mvme88k/dev/sysconreg.h | 45 | ||||
-rw-r--r-- | sys/arch/mvme88k/dev/sysconvar.h | 38 | ||||
-rw-r--r-- | sys/arch/mvme88k/dev/vme.c | 9 | ||||
-rw-r--r-- | sys/arch/mvme88k/include/intr.h | 4 | ||||
-rw-r--r-- | sys/arch/mvme88k/include/mvme188.h | 43 | ||||
-rw-r--r-- | sys/arch/mvme88k/mvme88k/m188_machdep.c | 257 | ||||
-rw-r--r-- | sys/arch/mvme88k/mvme88k/machdep.c | 34 |
9 files changed, 353 insertions, 311 deletions
diff --git a/sys/arch/mvme88k/dev/dart.c b/sys/arch/mvme88k/dev/dart.c index b53df1e8f2e..c2d443aaf99 100644 --- a/sys/arch/mvme88k/dev/dart.c +++ b/sys/arch/mvme88k/dev/dart.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dart.c,v 1.49 2007/05/19 20:35:20 miod Exp $ */ +/* $OpenBSD: dart.c,v 1.50 2007/12/27 23:17:53 miod Exp $ */ /* * Mach Operating System @@ -40,7 +40,7 @@ #include <dev/cons.h> #include <machine/mvme188.h> -#include <mvme88k/dev/sysconreg.h> +#include <mvme88k/dev/sysconvar.h> #include <mvme88k/dev/dartreg.h> #ifdef DDB @@ -220,7 +220,6 @@ dartattach(struct device *parent, struct device *self, void *aux) dart_write(sc, DART_ACR, BDSET2 | CCLK16 | IPDCDIB | IPDCDIA); dart_write(sc, DART_IMR, sc->sc_sv_reg.sv_imr); dart_write(sc, DART_OPCR, OPSET); - dart_write(sc, DART_IVR, SYSCON_VECT + SYSCV_SCC); /* enable interrupts */ sc->sc_ih.ih_fn = dartintr; @@ -228,7 +227,7 @@ dartattach(struct device *parent, struct device *self, void *aux) sc->sc_ih.ih_wantframe = 0; sc->sc_ih.ih_ipl = ca->ca_ipl; - sysconintr_establish(SYSCV_SCC, &sc->sc_ih, self->dv_xname); + sysconintr_establish(INTSRC_DUART, &sc->sc_ih, self->dv_xname); printf("\n"); } diff --git a/sys/arch/mvme88k/dev/syscon.c b/sys/arch/mvme88k/dev/syscon.c index 29e6b8ed2be..10811cba4b1 100644 --- a/sys/arch/mvme88k/dev/syscon.c +++ b/sys/arch/mvme88k/dev/syscon.c @@ -1,4 +1,4 @@ -/* $OpenBSD: syscon.c,v 1.27 2006/11/18 12:04:57 miod Exp $ */ +/* $OpenBSD: syscon.c,v 1.28 2007/12/27 23:17:53 miod Exp $ */ /* * Copyright (c) 1999 Steve Murphree, Jr. * All rights reserved. @@ -38,7 +38,7 @@ #include <machine/cpu.h> #include <machine/mvme188.h> -#include <mvme88k/dev/sysconreg.h> +#include <mvme88k/dev/sysconvar.h> struct sysconsoftc { struct device sc_dev; @@ -46,9 +46,6 @@ struct sysconsoftc { struct intrhand sc_abih; /* `abort' switch */ struct intrhand sc_acih; /* `ac fail' */ struct intrhand sc_sfih; /* `sys fail' */ -#if 0 - struct intrhand sc_m188ih; /* `m188 interrupt' */ -#endif }; void sysconattach(struct device *, struct device *, void *); @@ -59,7 +56,6 @@ int syscon_scan(struct device *, void *, void *); int sysconabort(void *); int sysconacfail(void *); int sysconsysfail(void *); -int sysconm188(void *); struct cfattach syscon_ca = { sizeof(struct sysconsoftc), sysconmatch, sysconattach @@ -70,35 +66,58 @@ struct cfdriver syscon_cd = { }; int -sysconmatch(parent, vcf, args) - struct device *parent; - void *vcf, *args; +sysconmatch(struct device *parent, void *cf, void *args) { /* Don't match if wrong cpu */ if (brdtyp != BRD_188) return (0); - return (1); + return (syscon_cd.cd_ndevs == 0); } -int -syscon_print(args, bus) - void *args; - const char *bus; +void +sysconattach(struct device *parent, struct device *self, void *args) { - struct confargs *ca = args; + struct sysconsoftc *sc = (struct sysconsoftc *)self; + int i; - if (ca->ca_offset != -1) - printf(" offset 0x%x", ca->ca_offset); - if (ca->ca_ipl > 0) - printf(" ipl %d", ca->ca_ipl); - return (UNCONF); + printf("\n"); + + /* + * Set up interrupt handlers. + */ + for (i = 0; i < INTSRC_VME; i++) + SLIST_INIT(&sysconintr_handlers[i]); + + /* + * Clear SYSFAIL if lit. + */ + *(volatile u_int32_t *)MVME188_UCSR |= UCSR_DRVSFBIT; + + sc->sc_abih.ih_fn = sysconabort; + sc->sc_abih.ih_arg = 0; + sc->sc_abih.ih_wantframe = 1; + sc->sc_abih.ih_ipl = IPL_ABORT; + + sc->sc_acih.ih_fn = sysconacfail; + sc->sc_acih.ih_arg = 0; + sc->sc_acih.ih_wantframe = 1; + sc->sc_acih.ih_ipl = IPL_ABORT; + + sc->sc_sfih.ih_fn = sysconsysfail; + sc->sc_sfih.ih_arg = 0; + sc->sc_sfih.ih_wantframe = 1; + sc->sc_sfih.ih_ipl = IPL_ABORT; + + sysconintr_establish(INTSRC_ABORT, &sc->sc_abih, "abort"); + sysconintr_establish(INTSRC_ACFAIL, &sc->sc_acih, "acfail"); + sysconintr_establish(INTSRC_SYSFAIL, &sc->sc_sfih, "sysfail"); + + config_search(syscon_scan, self, args); } int -syscon_scan(parent, child, args) - struct device *parent; - void *child, *args; +syscon_scan(struct device *parent, void *child, void *args) { struct cfdata *cf = child; struct confargs oca, *ca = args; @@ -108,82 +127,129 @@ syscon_scan(parent, child, args) oca.ca_dmat = ca->ca_dmat; oca.ca_offset = cf->cf_loc[0]; oca.ca_ipl = cf->cf_loc[1]; - if (oca.ca_offset != -1) { + if (oca.ca_offset != -1) oca.ca_paddr = ca->ca_paddr + oca.ca_offset; - } else { + else oca.ca_paddr = -1; - } oca.ca_bustype = BUS_SYSCON; oca.ca_name = cf->cf_driver->cd_name; + if ((*cf->cf_attach->ca_match)(parent, cf, &oca) == 0) return (0); + config_attach(parent, cf, &oca, syscon_print); return (1); } +int +syscon_print(void *args, const char *bus) +{ + struct confargs *ca = args; + + if (ca->ca_offset != -1) + printf(" offset 0x%x", ca->ca_offset); + if (ca->ca_ipl > 0) + printf(" ipl %d", ca->ca_ipl); + return (UNCONF); +} + +/* + * Interrupt related code + */ + +intrhand_t sysconintr_handlers[INTSRC_VME]; + +int +sysconintr_establish(u_int intsrc, struct intrhand *ih, const char *name) +{ + intrhand_t *list; + + list = &sysconintr_handlers[intsrc]; + if (!SLIST_EMPTY(list)) { +#ifdef DIAGNOSTIC + printf("%s: interrupt source %u already registered\n", + __func__, intsrc); +#endif + return (EINVAL); + } + + evcount_attach(&ih->ih_count, name, (void *)&ih->ih_ipl, + &evcount_intr); + SLIST_INSERT_HEAD(list, ih, ih_link); + + syscon_intsrc_enable(intsrc, ih->ih_ipl); + + return (0); +} + void -sysconattach(parent, self, args) - struct device *parent, *self; - void *args; +sysconintr_disestablish(u_int intsrc, struct intrhand *ih) { - struct sysconsoftc *sc = (struct sysconsoftc *)self; + intrhand_t *list; - printf("\n"); + list = &sysconintr_handlers[intsrc]; + evcount_detach(&ih->ih_count); + SLIST_REMOVE(list, ih, intrhand, ih_link); - /* - * Clear SYSFAIL if lit. - */ - *(volatile u_int32_t *)MVME188_UCSR |= UCSR_DRVSFBIT; + syscon_intsrc_disable(intsrc); +} - /* - * pseudo driver, abort interrupt handler - */ - sc->sc_abih.ih_fn = sysconabort; - sc->sc_abih.ih_arg = 0; - sc->sc_abih.ih_wantframe = 1; - sc->sc_abih.ih_ipl = IPL_ABORT; +/* Interrupt masks per logical interrupt source */ +const u_int32_t syscon_intsrc[] = { + 0, + IRQ_ABORT, + IRQ_ACF, + IRQ_SF, + IRQ_CIOI, + IRQ_DTI, + IRQ_DI, + IRQ_VME1, + IRQ_VME2, + IRQ_VME3, + IRQ_VME4, + IRQ_VME5, + IRQ_VME6, + IRQ_VME7 +}; - sc->sc_acih.ih_fn = sysconacfail; - sc->sc_acih.ih_arg = 0; - sc->sc_acih.ih_wantframe = 1; - sc->sc_acih.ih_ipl = IPL_ABORT; +void +syscon_intsrc_enable(u_int intsrc, int ipl) +{ + u_int32_t psr; + u_int32_t intmask = syscon_intsrc[intsrc]; + int i; - sc->sc_sfih.ih_fn = sysconsysfail; - sc->sc_sfih.ih_arg = 0; - sc->sc_sfih.ih_wantframe = 1; - sc->sc_sfih.ih_ipl = IPL_ABORT; + psr = get_psr(); + set_psr(psr | PSR_IND); -#if 0 - sc->sc_m188ih.ih_fn = sysconm188; - sc->sc_m188ih.ih_arg = 0; - sc->sc_m188ih.ih_wantframe = 1; - sc->sc_m188ih.ih_ipl = IPL_ABORT; -#endif + for (i = IPL_NONE; i < ipl; i++) + int_mask_val[i] |= intmask; - sysconintr_establish(SYSCV_ABRT, &sc->sc_abih, "abort"); - sysconintr_establish(SYSCV_ACF, &sc->sc_acih, "acfail"); - sysconintr_establish(SYSCV_SYSF, &sc->sc_sfih, "sysfail"); -#if 0 - intr_establish(M188_IVEC, &sc->sc_m188ih, self->dv_xname); -#endif + setipl(getipl()); - config_search(syscon_scan, self, args); + set_psr(psr); } -int -sysconintr_establish(int vec, struct intrhand *ih, const char *name) +void +syscon_intsrc_disable(u_int intsrc) { -#ifdef DIAGNOSTIC - if (vec < 0 || vec >= SYSCON_NVEC) - panic("sysconintr_establish: illegal vector 0x%x", vec); -#endif + u_int32_t psr; + u_int32_t intmask = syscon_intsrc[intsrc]; + int i; + + psr = get_psr(); + set_psr(psr | PSR_IND); + + for (i = 0; i < NIPLS; i++) + int_mask_val[i] &= ~intmask; + + setipl(getipl()); - return intr_establish(SYSCON_VECT + vec, ih, name); + set_psr(psr); } int -sysconabort(eframe) - void *eframe; +sysconabort(void *eframe) { *(volatile u_int32_t *)MVME188_CLRINT = ISTATE_ABORT; nmihand(eframe); @@ -191,8 +257,7 @@ sysconabort(eframe) } int -sysconsysfail(eframe) - void *eframe; +sysconsysfail(void *eframe) { *(volatile u_int32_t *)MVME188_CLRINT = ISTATE_SYSFAIL; printf("WARNING: SYSFAIL* ASSERTED\n"); @@ -200,21 +265,9 @@ sysconsysfail(eframe) } int -sysconacfail(eframe) - void *eframe; +sysconacfail(void *eframe) { *(volatile u_int32_t *)MVME188_CLRINT = ISTATE_ACFAIL; printf("WARNING: ACFAIL* ASSERTED\n"); return (1); } - -#if 0 -int -sysconm188(eframe) - void *eframe; -{ - /* shouldn't happen! */ - printf("MVME188: self-inflicted interrupt\n"); - return (1); -} -#endif diff --git a/sys/arch/mvme88k/dev/sysconreg.h b/sys/arch/mvme88k/dev/sysconreg.h deleted file mode 100644 index b93f2d9d538..00000000000 --- a/sys/arch/mvme88k/dev/sysconreg.h +++ /dev/null @@ -1,45 +0,0 @@ -/* $OpenBSD: sysconreg.h,v 1.7 2004/07/30 19:02:06 miod Exp $ */ - -/* - * Copyright (c) 2004, Miodrag Vallat. - * Copyright (c) 1999 Steve Murphree, Jr. - * All rights reserved. - * - * 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. - */ - -/* - * Map syscon interrupts a la PCC2 - */ -#define SYSCON_VECT 0x50 -#define SYSCON_NVEC 0x10 - -#define SYSCV_ABRT 0x02 -#define SYSCV_SYSF 0x03 -#define SYSCV_ACF 0x04 -#define SYSCV_SCC 0x05 -#define SYSCV_TIMER4 0x06 -#define SYSCV_TIMER3 0x07 -#define SYSCV_TIMER2 0x08 -#define SYSCV_TIMER1 0x09 - -int sysconintr_establish(int, struct intrhand *, const char *); diff --git a/sys/arch/mvme88k/dev/sysconvar.h b/sys/arch/mvme88k/dev/sysconvar.h new file mode 100644 index 00000000000..8b8c04193f3 --- /dev/null +++ b/sys/arch/mvme88k/dev/sysconvar.h @@ -0,0 +1,38 @@ +/* $OpenBSD: sysconvar.h,v 1.1 2007/12/27 23:17:53 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. + */ + +/* + * Logical values for non-VME interrupt sources on 188. + */ + +#define INTSRC_ABORT 1 /* abort button */ +#define INTSRC_ACFAIL 2 /* AC failure */ +#define INTSRC_SYSFAIL 3 /* system failure */ +#define INTSRC_CIO 4 /* Z8536 */ +#define INTSRC_DTIMER 5 /* MC68692 timer interrupt */ +#define INTSRC_DUART 6 /* MC68692 serial interrupt */ +#define INTSRC_VME 7 /* seven VME interrupt levels */ + +extern intrhand_t sysconintr_handlers[INTSRC_VME]; + +int sysconintr_establish(u_int, struct intrhand *, const char *); +void sysconintr_disestablish(u_int, struct intrhand *); + +void syscon_intsrc_enable(u_int, int); +void syscon_intsrc_disable(u_int); diff --git a/sys/arch/mvme88k/dev/vme.c b/sys/arch/mvme88k/dev/vme.c index 59a5d7e6b04..7e1a07a13ad 100644 --- a/sys/arch/mvme88k/dev/vme.c +++ b/sys/arch/mvme88k/dev/vme.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vme.c,v 1.47 2007/11/17 05:33:38 miod Exp $ */ +/* $OpenBSD: vme.c,v 1.48 2007/12/27 23:17:53 miod Exp $ */ /* * Copyright (c) 2004, Miodrag Vallat. * Copyright (c) 1999 Steve Murphree, Jr. @@ -44,7 +44,7 @@ #include <mvme88k/dev/vme.h> #if NSYSCON > 0 #include <machine/mvme188.h> -#include <mvme88k/dev/sysconreg.h> +#include <mvme88k/dev/sysconvar.h> #endif int vmematch(struct device *, void *, void *); @@ -54,7 +54,6 @@ void vme2chip_init(struct vmesoftc *); void vmesyscon_init(struct vmesoftc *); u_long vme2chip_map(u_long, int); int vme2abort(void *); -int sysconabort(void *); int vmeprint(void *, const char *); int vmebustype; @@ -192,7 +191,7 @@ vmeprint(args, bus) printf(" addr 0x%x", ca->ca_paddr); if (ca->ca_ipl > 0) printf(" ipl %d", ca->ca_ipl); - if (ca->ca_vec > 0) + if (ca->ca_vec >= 0) printf(" vec 0x%x", ca->ca_vec); return (UNCONF); } @@ -275,7 +274,7 @@ vmeattach(parent, self, args) { u_int8_t sconc; - vmevecbase = 0x60; /* Hard coded for MVME188 */ + vmevecbase = 0; /* all vectors available */ sconc = *(volatile u_int8_t *)MVME188_GLOBAL1; if (ISSET(sconc, M188_SYSCON)) printf(": system controller"); diff --git a/sys/arch/mvme88k/include/intr.h b/sys/arch/mvme88k/include/intr.h index 38291e9c9d1..1df681e0826 100644 --- a/sys/arch/mvme88k/include/intr.h +++ b/sys/arch/mvme88k/include/intr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: intr.h,v 1.18 2006/03/13 19:43:21 brad Exp $ */ +/* $OpenBSD: intr.h,v 1.19 2007/12/27 23:17:55 miod Exp $ */ /* * Copyright (C) 2000 Steve Murphree, Jr. * All rights reserved. @@ -50,6 +50,8 @@ #define IPL_NMI 7 #define IPL_ABORT 7 +#define NIPLS 8 + #include <m88k/intr.h> #endif /* _MVME88K_INTR_H_ */ diff --git a/sys/arch/mvme88k/include/mvme188.h b/sys/arch/mvme88k/include/mvme188.h index b064c4c5cd1..6ef8921c8ae 100644 --- a/sys/arch/mvme88k/include/mvme188.h +++ b/sys/arch/mvme88k/include/mvme188.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mvme188.h,v 1.31 2007/11/11 13:06:57 miod Exp $ */ +/* $OpenBSD: mvme188.h,v 1.32 2007/12/27 23:17:55 miod Exp $ */ /* * Copyright (c) 1999 Steve Murphree, Jr. * All rights reserved. @@ -146,43 +146,10 @@ "\17IRQ5\15IRQ4\13IRQ3\11LMI" \ "\10SIGLPI\7IRQ2\5IRQ1\4SWI3\3SWI2\2SWI1\1SWI0" -/* groups by function */ - -/* hardware irq bits */ -#define HW_FAILURE_MASK (IRQ_ABORT | IRQ_ACF | IRQ_ARBTO | IRQ_SF) /* IPI bits (see below) */ -#define CLOCK_IPI_MASK (IRQ_SWI7 | IRQ_SWI6 | IRQ_SWI5 | IRQ_SWI4) -#define IPI_MASK (IRQ_SWI3 | IRQ_SWI2 | IRQ_SWI1 | IRQ_SWI0) -/* VME irq bits */ -#define VME_INTERRUPT_MASK (IRQ_VME7 | IRQ_VME6 | IRQ_VME5 | IRQ_VME4 | \ - IRQ_VME3 | IRQ_VME2 | IRQ_VME1) -/* on-board irq bits */ -#define OBIO_INTERRUPT_MASK (IRQ_DTI | IRQ_CIOI | IRQ_DI | IRQ_SIGHPI | \ - IRQ_LMI | IRQ_SIGLPI) - -/* groups by interrupt levels */ - -#define LVL7 (IRQ_ABORT | IRQ_ACF /* | IRQ_VME7 */ | IRQ_SF) -#define LVL6 (IRQ_VME6) -#define LVL5 (IRQ_VME5 | IRQ_DTI | IRQ_CIOI) -#define LVL4 (IRQ_VME4) -#define LVL3 (IRQ_VME3 | IRQ_DI) -#define LVL2 (IRQ_VME2) -#define LVL1 (IRQ_VME1) - -/* interrupts we want to process on the master CPU only */ -#define SLAVE_MASK (HW_FAILURE_MASK | OBIO_INTERRUPT_MASK | VME_INTERRUPT_MASK) - -#define MASK_LVL_0 (LVL7 | LVL6 | LVL5 | LVL4 | LVL3 | LVL2 | LVL1) -#define MASK_LVL_1 (LVL7 | LVL6 | LVL5 | LVL4 | LVL3 | LVL2) -#define MASK_LVL_2 (LVL7 | LVL6 | LVL5 | LVL4 | LVL3) -#define MASK_LVL_3 (LVL7 | LVL6 | LVL5 | LVL4) -#define MASK_LVL_4 (LVL7 | LVL6 | LVL5) -#define MASK_LVL_5 (LVL7 | LVL6) -#define MASK_LVL_6 (LVL7) -#define MASK_LVL_7 (IRQ_ABORT) - -#define INT_LEVEL 8 /* # of interrupt level + 1 */ +#define CLOCK_IPI_MASK (IRQ_SWI7 | IRQ_SWI6 | IRQ_SWI5 | IRQ_SWI4) +#define IPI_MASK (IRQ_SWI3 | IRQ_SWI2 | IRQ_SWI1 | IRQ_SWI0) + #define ISR_GET_CURRENT_MASK(cpu) \ (*(volatile u_int *)MVME188_IST & int_mask_reg[cpu]) @@ -304,6 +271,8 @@ extern u_int32_t pfsr_save_188_straight[]; extern u_int32_t pfsr_save_188_double[]; extern u_int32_t pfsr_save_188_quad[]; + +extern u_int32_t int_mask_val[NIPLS]; #endif #endif /* __MACHINE_MVME188_H__ */ diff --git a/sys/arch/mvme88k/mvme88k/m188_machdep.c b/sys/arch/mvme88k/mvme88k/m188_machdep.c index 11e7183a7b0..ded8d9a326e 100644 --- a/sys/arch/mvme88k/mvme88k/m188_machdep.c +++ b/sys/arch/mvme88k/mvme88k/m188_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: m188_machdep.c,v 1.43 2007/11/17 05:37:53 miod Exp $ */ +/* $OpenBSD: m188_machdep.c,v 1.44 2007/12/27 23:17:55 miod Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -126,7 +126,7 @@ #include <machine/m88100.h> #include <machine/mvme188.h> -#include <mvme88k/dev/sysconreg.h> +#include <mvme88k/dev/sysconvar.h> #include <mvme88k/mvme88k/clockvar.h> #ifdef MULTIPROCESSOR @@ -162,18 +162,16 @@ u_int32_t int_mask_reg[] = { 0, 0, 0, 0 }; u_int m188_curspl[] = { IPL_HIGH, IPL_HIGH, IPL_HIGH, IPL_HIGH }; /* - * external interrupt masks per spl. + * Interrupt masks, one per IPL level. */ -const u_int32_t int_mask_val[INT_LEVEL] = { - MASK_LVL_0, - MASK_LVL_1, - MASK_LVL_2, - MASK_LVL_3, - MASK_LVL_4, - MASK_LVL_5, - MASK_LVL_6, - MASK_LVL_7 -}; +u_int32_t int_mask_val[NIPLS]; + +#ifdef MULTIPROCESSOR +/* + * Interrupts allowed on secondary processors. + */ +#define SLAVE_MASK 0 +#endif /* * Figure out how much memory is available, by querying the MBus registers. @@ -226,9 +224,6 @@ m188_bootstrap() /* clear and disable all interrupts */ *(volatile u_int32_t *)MVME188_IENALL = 0; - - /* supply a vector base for m188ih */ - *(volatile u_int8_t *)MVME188_VIRQV = M188_IVEC; } void @@ -269,11 +264,11 @@ safe_level(u_int mask, u_int curlevel) curlevel = max(IPL_CLOCK, curlevel); mask &= ~(IPI_MASK | CLOCK_IPI_MASK); #endif - for (i = curlevel; i < INT_LEVEL; i++) + for (i = curlevel; i < NIPLS; i++) if ((int_mask_val[i] & mask) == 0) return (i); - return (INT_LEVEL - 1); + return (NIPLS - 1); } u_int @@ -301,7 +296,7 @@ m188_setipl(u_int level) mask = int_mask_val[level]; #ifdef MULTIPROCESSOR if (cpu != master_cpu) - mask &= ~SLAVE_MASK; + mask &= SLAVE_MASK; mask |= SWI_IPI_MASK(cpu); if (level < IPL_CLOCK) mask |= SWI_CLOCK_IPI_MASK(cpu); @@ -337,7 +332,7 @@ m188_raiseipl(u_int level) mask = int_mask_val[level]; #ifdef MULTIPROCESSOR if (cpu != master_cpu) - mask &= ~SLAVE_MASK; + mask &= SLAVE_MASK; mask |= SWI_IPI_MASK(cpu); if (level < IPL_CLOCK) mask |= SWI_CLOCK_IPI_MASK(cpu); @@ -436,48 +431,47 @@ m188_clock_ipi_handler(struct trapframe *eframe) #endif /* - * Device interrupt handler for MVME188 - */ - -/* - * Hard coded vector table for onboard devices and hardware failure - * interrupts. + * Provide the interrupt source for a give interrupt status bit. */ const u_int obio_vec[32] = { 0, /* SWI0 */ 0, /* SWI1 */ 0, /* SWI2 */ 0, /* SWI3 */ - 0, /* VME1 */ + INTSRC_VME, /* VME1 */ 0, - 0, /* VME2 */ - 0, /* SIGLPI */ /* no vector, but always masked */ - 0, /* LMI */ /* no vector, but always masked */ + INTSRC_VME, /* VME2 */ + 0, /* SIGLPI */ + 0, /* LMI */ 0, - 0, /* VME3 */ + INTSRC_VME, /* VME3 */ 0, - 0, /* VME4 */ + INTSRC_VME, /* VME4 */ 0, - 0, /* VME5 */ + INTSRC_VME, /* VME5 */ 0, - 0, /* SIGHPI */ /* no vector, but always masked */ - SYSCV_SCC, /* DI */ + 0, /* SIGHPI */ + INTSRC_DUART, /* DI */ 0, - 0, /* VME6 */ - SYSCV_SYSF, /* SF */ - SYSCV_TIMER2, /* CIOI */ + INTSRC_VME, /* VME6 */ + INTSRC_SYSFAIL, /* SF */ + INTSRC_CIO, /* CIOI */ 0, - 0, /* VME7 */ + INTSRC_VME, /* VME7 */ 0, /* SWI4 */ 0, /* SWI5 */ 0, /* SWI6 */ 0, /* SWI7 */ - SYSCV_TIMER1, /* DTI */ - 0, /* ARBTO */ /* no vector, but always masked */ - SYSCV_ACF, /* ACF */ - SYSCV_ABRT /* ABORT */ + INTSRC_DTIMER, /* DTI */ + 0, /* ARBTO */ + INTSRC_ACFAIL, /* ACF */ + INTSRC_ABORT /* ABORT */ }; +/* + * Device interrupt handler for MVME188 + */ + #define VME_VECTOR_MASK 0x1ff /* mask into VIACK register */ #define VME_BERR_MASK 0x100 /* timeout during VME IACK cycle */ @@ -496,8 +490,9 @@ m188_ext_int(u_int v, struct trapframe *eframe) intrhand_t *list; int ret, intbit; vaddr_t ivec; - u_int vec; + u_int intsrc, vec; int unmasked = 0; + int warn; #ifdef DIAGNOSTIC static int problems = 0; #endif @@ -574,76 +569,43 @@ m188_ext_int(u_int v, struct trapframe *eframe) } #endif - /* generate IACK and get the vector */ - + /* find the first bit set in the current mask */ + warn = 0; intbit = ff1(cur_mask); - if (OBIO_INTERRUPT_MASK & (1 << intbit)) { - vec = obio_vec[intbit]; - if (vec == 0) { - panic("unknown onboard interrupt: mask = 0x%b", - 1 << intbit, IST_STRING); - } - vec += SYSCON_VECT; - } else if (HW_FAILURE_MASK & (1 << intbit)) { - vec = obio_vec[intbit]; - if (vec == 0) { - panic("unknown hardware failure: mask = 0x%b", - 1 << intbit, IST_STRING); - } - vec += SYSCON_VECT; - } else if (VME_INTERRUPT_MASK & (1 << intbit)) { + intsrc = obio_vec[intbit]; + + if (intsrc == 0) + panic("%s: unexpected interrupt source (bit %d), " + "level %d, mask 0x%b", + __func__, intbit, level, cur_mask, IST_STRING); + + if (intsrc == INTSRC_VME) { ivec = MVME188_VIRQLV + (level << 2); vec = *(volatile u_int32_t *)ivec & VME_VECTOR_MASK; if (vec & VME_BERR_MASK) { /* - * This could be a self-inflicted interrupt. - * Except that we never write to VIRQV, so - * such things do not happen. - - u_int src = 0x07 & - *(volatile u_int32_t *)MVME188_VIRQLV; - if (src == 0) - vec = 0xff & - *(volatile u_int32_t *)MVME188_VIRQV; - else - + * If only one VME interrupt is registered + * with this IPL, we can reasonably safely + * assume that this is our vector. */ - { - /* - * If only one VME interrupt is - * registered with this IPL, - * we can reasonably safely - * assume that this is our vector. - */ - vec = vmevec_hints[level]; - if (vec == (u_int)-1) { - printf("%s: timeout getting VME" - " interrupt vector, " - "level %d, mask 0x%b\n", - __func__, level, - cur_mask, IST_STRING); - ign_mask |= 1 << intbit; - continue; - } + vec = vmevec_hints[level]; + if (vec == (u_int)-1) { + printf("%s: timeout getting VME " + "interrupt vector, " + "level %d, mask 0x%b\n", + __func__, level, + cur_mask, IST_STRING); + ign_mask |= 1 << intbit; + continue; } } - if (vec == 0) { - panic("%s: invalid VME interrupt vector, " - "level %d, mask 0x%b", - __func__, level, cur_mask, IST_STRING); - } + list = &intr_handlers[vec]; } else { - panic("%s: unexpected interrupt source, " - "level %d, mask 0x%b", - __func__, level, cur_mask, IST_STRING); + list = &sysconintr_handlers[intsrc]; } - list = &intr_handlers[vec]; if (SLIST_EMPTY(list)) { - printf("%s: spurious interrupt, " - "level %d, vec 0x%x, mask 0x%b\n", - __func__, level, vec, cur_mask, IST_STRING); - ign_mask |= 1 << intbit; + warn = 1; } else { /* * Walk through all interrupt handlers in the chain @@ -661,13 +623,25 @@ m188_ext_int(u_int v, struct trapframe *eframe) break; } } - if (ret == 0) { - printf("%s: unclaimed interrupt, " + if (ret == 0) + warn = 2; + } + + if (warn != 0) { + ign_mask |= 1 << intbit; + + if (intsrc == INTSRC_VME) + printf("%s: %s VME interrupt, " "level %d, vec 0x%x, mask 0x%b\n", - __func__, level, vec, cur_mask, IST_STRING); - ign_mask |= 1 << intbit; - continue; - } + __func__, + warn == 1 ? "spurious" : "unclaimed", + level, vec, cur_mask, IST_STRING); + else + printf("%s: %s interrupt, " + "level %d, bit %d, mask 0x%b\n", + __func__, + warn == 1 ? "spurious" : "unclaimed", + level, intbit, cur_mask, IST_STRING); } } while (((cur_mask = ISR_GET_CURRENT_MASK(cpu)) & ~ign_mask) != 0); @@ -708,8 +682,14 @@ u_int read_cio(int); void write_cio(int, u_int); int m188_clockintr(void *); +int m188_calibrateintr(void *); int m188_statintr(void *); +volatile int m188_calibrate_phase = 0; + +/* multiplication factor for delay() */ +u_int m188_delay_const = 25; /* no MVME188 is faster than 25MHz */ + #if defined(MULTIPROCESSOR) && 0 #include <machine/lock.h> __cpu_simple_lock_t m188_cio_lock; @@ -769,6 +749,11 @@ m188_init_clocks(void) { volatile u_int8_t imr; int statint, minint; + u_int iter, divisor; + u_int32_t psr; + + psr = get_psr(); + set_psr(psr | PSR_IND); CIO_LOCK_INIT(); @@ -803,8 +788,6 @@ m188_init_clocks(void) /* clear the counter/timer output OP3 while we program the DART */ *(volatile u_int8_t *)DART_OPCR = 0x00; - /* set interrupt vec */ - *(volatile u_int8_t *)DART_IVR = SYSCON_VECT + SYSCV_TIMER1; /* do the stop counter/timer command */ imr = *(volatile u_int8_t *)DART_STOPC; /* set counter/timer to counter mode, PCLK/16 */ @@ -816,17 +799,57 @@ m188_init_clocks(void) /* give the start counter/timer command */ imr = *(volatile u_int8_t *)DART_STARTC; - clock_ih.ih_fn = m188_clockintr; - clock_ih.ih_arg = 0; - clock_ih.ih_wantframe = 1; - clock_ih.ih_ipl = IPL_CLOCK; - sysconintr_establish(SYSCV_TIMER2, &clock_ih, "clock"); - statclock_ih.ih_fn = m188_statintr; statclock_ih.ih_arg = 0; statclock_ih.ih_wantframe = 1; statclock_ih.ih_ipl = IPL_STATCLOCK; - sysconintr_establish(SYSCV_TIMER1, &statclock_ih, "stat"); + sysconintr_establish(INTSRC_DTIMER, &statclock_ih, "stat"); + + /* + * Calibrate delay const. + */ + clock_ih.ih_fn = m188_calibrateintr; + clock_ih.ih_arg = 0; + clock_ih.ih_wantframe = 1; + clock_ih.ih_ipl = IPL_CLOCK; + sysconintr_establish(INTSRC_CIO, &clock_ih, "clock"); + + m188_delay_const = 1; + set_psr(psr); + while (m188_calibrate_phase == 0) + ; + + iter = 0; + while (m188_calibrate_phase == 1) { + delay(10000); + iter++; + } + + divisor = 1000000 / 10000; + m188_delay_const = (iter * hz + divisor - 1) / divisor; + + set_psr(psr | PSR_IND); + + sysconintr_disestablish(INTSRC_CIO, &clock_ih); + clock_ih.ih_fn = m188_clockintr; + sysconintr_establish(INTSRC_CIO, &clock_ih, "clock"); + + set_psr(psr); +} + +int +m188_calibrateintr(void *eframe) +{ + CIO_LOCK(); + write_cio(CIO_CSR1, CIO_GCB | CIO_CIP); /* Ack the interrupt */ + + /* restart counter */ + write_cio(CIO_CSR1, CIO_GCB | CIO_TCB | CIO_IE); + CIO_UNLOCK(); + + m188_calibrate_phase++; + + return (1); } int diff --git a/sys/arch/mvme88k/mvme88k/machdep.c b/sys/arch/mvme88k/mvme88k/machdep.c index 19359f15880..4aa9f800d52 100644 --- a/sys/arch/mvme88k/mvme88k/machdep.c +++ b/sys/arch/mvme88k/mvme88k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.205 2007/12/15 19:37:41 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.206 2007/12/27 23:17:55 miod Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -77,6 +77,9 @@ #ifdef M88100 #include <machine/m88100.h> #endif +#ifdef MVME188 +#include <mvme88k/dev/sysconvar.h> +#endif #include <dev/cons.h> @@ -768,38 +771,39 @@ intr_findvec(int start, int end, int skip) } /* - * Try to insert ihand in the list of handlers for vector vec. + * Try to insert ih in the list of handlers for vector vec. */ int -intr_establish(int vec, struct intrhand *ihand, const char *name) +intr_establish(int vec, struct intrhand *ih, const char *name) { struct intrhand *intr; intrhand_t *list; - if (vec < 0 || vec >= NVMEINTR) { -#ifdef DIAGNOSTIC - panic("intr_establish: vec (0x%x) not between 0x00 and 0xff", - vec); -#endif /* DIAGNOSTIC */ - return (EINVAL); - } - list = &intr_handlers[vec]; if (!SLIST_EMPTY(list)) { intr = SLIST_FIRST(list); - if (intr->ih_ipl != ihand->ih_ipl) { + if (intr->ih_ipl != ih->ih_ipl) { #ifdef DIAGNOSTIC panic("intr_establish: there are other handlers with " "vec (0x%x) at ipl %x, but you want it at %x", - vec, intr->ih_ipl, ihand->ih_ipl); + vec, intr->ih_ipl, ih->ih_ipl); #endif /* DIAGNOSTIC */ return (EINVAL); } } - evcount_attach(&ihand->ih_count, name, (void *)&ihand->ih_ipl, + evcount_attach(&ih->ih_count, name, (void *)&ih->ih_ipl, &evcount_intr); - SLIST_INSERT_HEAD(list, ihand, ih_link); + SLIST_INSERT_HEAD(list, ih, ih_link); + +#ifdef MVME188 + /* + * Enable VME interrupt source for this level. + */ + if (brdtyp == BRD_188) + syscon_intsrc_enable(INTSRC_VME + (ih->ih_ipl - 1), ih->ih_ipl); +#endif + return (0); } |