diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2007-12-19 22:05:07 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2007-12-19 22:05:07 +0000 |
commit | 0255bd8fe63cfd7bd3bf0506db8c29a1a9e02e66 (patch) | |
tree | e28de156abef3976ff7eb288c1b1b697a2e523a2 /sys/arch/aviion/dev/syscon.c | |
parent | d746971c0c409e53e144c6c06e07d8594cd805ec (diff) |
Overhaul interrupt handling, in order to make it (arguably) simpler and
more board design-independent.
The main changes are:
- define logical interrupt sources, which match the on-board devices as
well as the seven VME interrupt sources. Use these whenever possible
when registering interrupts in the drivers, so that the actual interrupt
mask layouts are hidden.
- make the on-board and VME interrupt handlers separate. On-board interrupt
handlers are not really associated to an interrupt vector, only to a
given interrupt source, and only one handler can be registered for a
logical interrupt source. On the other hand, VME interrupts come with a
vector number, and can be shared. This allows VME devices to really use
the whole 256 vectors space, starting at vector zero.
- update the real interrupt masks upon interrupt handler registration and
removal, so that only interrupt sources for which a handler exists may
be enabled.
- update the VME interrupt allocation logic to allow exclusive vector
allocation.
- move the Z8536 clock routines to their own file, since they are not
AV400-specific; while there, calibrate the delay constant upon startup
for more accurate delay().
The vme driver is the only one left with AV400 tentacles left, to be fixed
very soon.
Diffstat (limited to 'sys/arch/aviion/dev/syscon.c')
-rw-r--r-- | sys/arch/aviion/dev/syscon.c | 82 |
1 files changed, 65 insertions, 17 deletions
diff --git a/sys/arch/aviion/dev/syscon.c b/sys/arch/aviion/dev/syscon.c index b52b4631ec1..85d0c0e9376 100644 --- a/sys/arch/aviion/dev/syscon.c +++ b/sys/arch/aviion/dev/syscon.c @@ -1,4 +1,20 @@ -/* $OpenBSD: syscon.c,v 1.3 2006/11/16 23:21:56 miod Exp $ */ +/* $OpenBSD: syscon.c,v 1.4 2007/12/19 22:05:06 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. + */ /* * Copyright (c) 1999 Steve Murphree, Jr. * All rights reserved. @@ -31,10 +47,11 @@ #include <sys/device.h> #include <machine/autoconf.h> +#include <machine/board.h> #include <machine/cpu.h> #include <machine/avcommon.h> -#include <aviion/dev/sysconreg.h> +#include <aviion/dev/sysconvar.h> struct sysconsoftc { struct device sc_dev; @@ -52,7 +69,6 @@ int syscon_scan(struct device *, void *, void *); int sysconabort(void *); int sysconacfail(void *); int sysconsysfail(void *); -int sysconav400(void *); struct cfattach syscon_ca = { sizeof(struct sysconsoftc), sysconmatch, sysconattach @@ -72,35 +88,39 @@ void sysconattach(struct device *parent, struct device *self, void *args) { struct sysconsoftc *sc = (struct sysconsoftc *)self; + int i; printf("\n"); /* - * Clear SYSFAIL if lit. + * Set up interrupt handlers. */ - *(volatile u_int32_t *)AV_UCSR |= UCSR_DRVSFBIT; + for (i = 0; i < INTSRC_VME; i++) + SLIST_INIT(&sysconintr_handlers[i]); /* - * pseudo driver, abort interrupt handler + * Clear SYSFAIL if lit. */ + *(volatile u_int32_t *)AV_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_flags = INTR_WANTFRAME; 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_flags = INTR_WANTFRAME; 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_flags = INTR_WANTFRAME; sc->sc_sfih.ih_ipl = IPL_ABORT; - sysconintr_establish(SYSCV_ABRT, &sc->sc_abih, "abort"); - sysconintr_establish(SYSCV_ACF, &sc->sc_acih, "acfail"); - sysconintr_establish(SYSCV_SYSF, &sc->sc_sfih, "sysfail"); + 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); } @@ -139,17 +159,45 @@ syscon_print(void *args, const char *pnp) return (UNCONF); } +/* + * Interrupt related code + */ + +intrhand_t sysconintr_handlers[INTSRC_VME]; + int -sysconintr_establish(u_int vec, struct intrhand *ih, const char *name) +sysconintr_establish(u_int intsrc, struct intrhand *ih, const char *name) { + intrhand_t *list; + + list = &sysconintr_handlers[intsrc]; + if (!SLIST_EMPTY(list)) { #ifdef DIAGNOSTIC - if (vec < 0 || vec >= SYSCON_NVEC) { - printf("sysconintr_establish: illegal vector 0x%x\n", vec); + printf("%s: interrupt source %u already registered\n", + __func__, intsrc); +#endif return (EINVAL); } -#endif - return (intr_establish(SYSCON_VECT + vec, ih, name)); + evcount_attach(&ih->ih_count, name, (void *)&ih->ih_ipl, + &evcount_intr); + SLIST_INSERT_HEAD(list, ih, ih_link); + + intsrc_enable(intsrc, ih->ih_ipl); + + return (0); +} + +void +sysconintr_disestablish(u_int intsrc, struct intrhand *ih) +{ + intrhand_t *list; + + list = &sysconintr_handlers[intsrc]; + evcount_detach(&ih->ih_count); + SLIST_REMOVE(list, ih, intrhand, ih_link); + + intsrc_disable(intsrc); } int |