summaryrefslogtreecommitdiff
path: root/sys/arch/aviion/dev
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2007-12-19 22:05:07 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2007-12-19 22:05:07 +0000
commit0255bd8fe63cfd7bd3bf0506db8c29a1a9e02e66 (patch)
treee28de156abef3976ff7eb288c1b1b697a2e523a2 /sys/arch/aviion/dev
parentd746971c0c409e53e144c6c06e07d8594cd805ec (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')
-rw-r--r--sys/arch/aviion/dev/dart_syscon.c16
-rw-r--r--sys/arch/aviion/dev/if_le_syscon.c9
-rw-r--r--sys/arch/aviion/dev/if_le_vme.c9
-rw-r--r--sys/arch/aviion/dev/syscon.c82
-rw-r--r--sys/arch/aviion/dev/sysconreg.h45
-rw-r--r--sys/arch/aviion/dev/sysconvar.h23
-rw-r--r--sys/arch/aviion/dev/vme.c168
-rw-r--r--sys/arch/aviion/dev/vmevar.h29
8 files changed, 268 insertions, 113 deletions
diff --git a/sys/arch/aviion/dev/dart_syscon.c b/sys/arch/aviion/dev/dart_syscon.c
index d44fd619473..a237480a251 100644
--- a/sys/arch/aviion/dev/dart_syscon.c
+++ b/sys/arch/aviion/dev/dart_syscon.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dart_syscon.c,v 1.2 2007/12/19 21:52:46 miod Exp $ */
+/* $OpenBSD: dart_syscon.c,v 1.3 2007/12/19 22:05:06 miod Exp $ */
/*
* Copyright (c) 2006, Miodrag Vallat
*
@@ -29,11 +29,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>
#include <aviion/dev/dartvar.h>
int dart_syscon_match(struct device *parent, void *self, void *aux);
@@ -70,7 +70,7 @@ dart_syscon_attach(struct device *parent, struct device *self, void *aux)
struct dartsoftc *sc = (struct dartsoftc *)self;
struct confargs *ca = aux;
bus_space_handle_t ioh;
- u_int vec;
+ u_int intsrc;
if (ca->ca_ipl < 0)
ca->ca_ipl = IPL_TTY;
@@ -83,21 +83,21 @@ dart_syscon_attach(struct device *parent, struct device *self, void *aux)
sc->sc_ioh = ioh;
if (ca->ca_paddr == CONSOLE_DART_BASE) {
- vec = SYSCV_SCC;
+ intsrc = INTSRC_DUART1;
sc->sc_console = 1; /* XXX for now */
printf(": console");
} else {
- vec = SYSCV_SCC2;
+ intsrc = INTSRC_DUART2;
sc->sc_console = 0;
}
/* enable interrupts */
sc->sc_ih.ih_fn = dartintr;
sc->sc_ih.ih_arg = sc;
- sc->sc_ih.ih_wantframe = 0;
+ sc->sc_ih.ih_flags = 0;
sc->sc_ih.ih_ipl = ca->ca_ipl;
- sysconintr_establish(vec, &sc->sc_ih, self->dv_xname);
+ sysconintr_establish(intsrc, &sc->sc_ih, self->dv_xname);
dart_common_attach(sc);
}
diff --git a/sys/arch/aviion/dev/if_le_syscon.c b/sys/arch/aviion/dev/if_le_syscon.c
index e49f34bc1fe..78cfea22782 100644
--- a/sys/arch/aviion/dev/if_le_syscon.c
+++ b/sys/arch/aviion/dev/if_le_syscon.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_le_syscon.c,v 1.3 2007/12/19 21:51:29 miod Exp $ */
+/* $OpenBSD: if_le_syscon.c,v 1.4 2007/12/19 22:05:06 miod Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@@ -55,9 +55,10 @@
#include <net/if_media.h>
#include <machine/autoconf.h>
+#include <machine/board.h>
#include <machine/cpu.h>
-#include <aviion/dev/sysconreg.h>
+#include <aviion/dev/sysconvar.h>
#include <dev/ic/am7990reg.h>
#include <dev/ic/am7990var.h>
@@ -210,8 +211,8 @@ le_syscon_attach(parent, self, aux)
lesc->sc_ih.ih_fn = am7990_intr;
lesc->sc_ih.ih_arg = sc;
- lesc->sc_ih.ih_wantframe = 0;
+ lesc->sc_ih.ih_flags = 0;
lesc->sc_ih.ih_ipl = ca->ca_ipl;
- sysconintr_establish(SYSCV_LE, &lesc->sc_ih, self->dv_xname);
+ sysconintr_establish(INTSRC_ETHERNET1, &lesc->sc_ih, self->dv_xname);
}
diff --git a/sys/arch/aviion/dev/if_le_vme.c b/sys/arch/aviion/dev/if_le_vme.c
index 658ec2ddd16..ec1d710fce7 100644
--- a/sys/arch/aviion/dev/if_le_vme.c
+++ b/sys/arch/aviion/dev/if_le_vme.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_le_vme.c,v 1.1 2006/05/09 18:24:32 miod Exp $ */
+/* $OpenBSD: if_le_vme.c,v 1.2 2007/12/19 22:05:06 miod Exp $ */
/*-
* Copyright (c) 1982, 1992, 1993
@@ -305,11 +305,12 @@ le_vme_attach(parent, self, aux)
/*
* Allocate an interrupt vector.
*/
- if (vmeintr_allocate(1, VMEINTR_ANY, &lesc->sc_vec) != 0) {
+ lesc->sc_ipl = vaa->vaa_ipl == 0 ? IPL_NET : vaa->vaa_ipl;
+ if (vmeintr_allocate(1, VMEINTR_ANY | VMEINTR_SHARED, lesc->sc_ipl,
+ &lesc->sc_vec) != 0) {
printf(": no more interrupts!\n");
return;
}
- lesc->sc_ipl = vaa->vaa_ipl == 0 ? IPL_NET : vaa->vaa_ipl;
/*
* Map the dual-ported memory.
@@ -367,7 +368,7 @@ le_vme_attach(parent, self, aux)
/* connect the interrupt */
lesc->sc_ih.ih_fn = le_vme_intr;
lesc->sc_ih.ih_arg = sc;
- lesc->sc_ih.ih_wantframe = 0;
+ lesc->sc_ih.ih_flags = 0;
lesc->sc_ih.ih_ipl = lesc->sc_ipl;
vmeintr_establish(lesc->sc_vec, &lesc->sc_ih, self->dv_xname);
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
diff --git a/sys/arch/aviion/dev/sysconreg.h b/sys/arch/aviion/dev/sysconreg.h
deleted file mode 100644
index 56292778a12..00000000000
--- a/sys/arch/aviion/dev/sysconreg.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* $OpenBSD: sysconreg.h,v 1.1 2006/04/26 14:24:54 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.
- */
-
-/*
- * SYSCON interrupt vectors (reserved for non-VME interrupt sources)
- */
-#define SYSCON_VECT 0x50
-#define SYSCON_NVEC 0x10
-
-#define SYSCV_ABRT 0x02 /* abort button */
-#define SYSCV_SYSF 0x03 /* SYSFAIL */
-#define SYSCV_ACF 0x04 /* ACFAIL */
-#define SYSCV_SCC 0x05 /* dart(4) serial interrupts */
-#define SYSCV_TIMER2 0x06 /* profiling clock */
-#define SYSCV_SCC2 0x08 /* second dart(4) instance */
-#define SYSCV_LE 0x09 /* onboard ethernet */
-#define SYSCV_SCSI 0x0a /* onboard SCSI */
-
-int sysconintr_establish(u_int, struct intrhand *, const char *);
diff --git a/sys/arch/aviion/dev/sysconvar.h b/sys/arch/aviion/dev/sysconvar.h
new file mode 100644
index 00000000000..f9d09534d3a
--- /dev/null
+++ b/sys/arch/aviion/dev/sysconvar.h
@@ -0,0 +1,23 @@
+/* $OpenBSD: sysconvar.h,v 1.1 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.
+ */
+
+extern intrhand_t sysconintr_handlers[INTSRC_VME];
+
+int sysconintr_establish(u_int, struct intrhand *, const char *);
+void sysconintr_disestablish(u_int, struct intrhand *);
diff --git a/sys/arch/aviion/dev/vme.c b/sys/arch/aviion/dev/vme.c
index 6f73e319469..456e2e7b9cb 100644
--- a/sys/arch/aviion/dev/vme.c
+++ b/sys/arch/aviion/dev/vme.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: vme.c,v 1.3 2006/05/21 12:22:02 miod Exp $ */
+/* $OpenBSD: vme.c,v 1.4 2007/12/19 22:05:06 miod Exp $ */
/*
- * Copyright (c) 2006, Miodrag Vallat.
+ * Copyright (c) 2006, 2007, Miodrag Vallat.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,6 +37,7 @@
#include <sys/proc.h>
#include <sys/uio.h>
+#include <machine/board.h>
#include <machine/bus.h>
#include <machine/conf.h>
@@ -45,8 +46,7 @@
#include <aviion/dev/vmevar.h>
#include <machine/avcommon.h>
-#include <machine/av400.h>
-#include <aviion/dev/sysconreg.h>
+#include <machine/av400.h> /* XXX */
struct vmesoftc {
struct device sc_dev;
@@ -60,11 +60,11 @@ int vmematch(struct device *, void *, void *);
void vmeattach(struct device *, struct device *, void *);
struct cfattach vme_ca = {
- sizeof(struct vmesoftc), vmematch, vmeattach
+ sizeof(struct vmesoftc), vmematch, vmeattach
};
struct cfdriver vme_cd = {
- NULL, "vme", DV_DULL
+ NULL, "vme", DV_DULL
};
int vme16_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *);
@@ -83,13 +83,11 @@ void vme_unmap(struct extent *, vme_addr_t, vaddr_t, bus_size_t);
int vmeprint(void *, const char *);
int vmescan(struct device *, void *, void *);
-u_int vmevecbase;
-
int
vmematch(struct device *parent, void *vcf, void *aux)
{
/* XXX no VME on AV100/AV200/AV300, though */
- return (1);
+ return (vme_cd.cd_ndevs == 0);
}
void
@@ -97,10 +95,17 @@ vmeattach(struct device *parent, struct device *self, void *aux)
{
struct vmesoftc *sc = (struct vmesoftc *)self;
u_int32_t ucsr;
+ int i;
printf("\n");
/*
+ * Set up interrupt handlers.
+ */
+ for (i = 0; i < NVMEINTR; i++)
+ SLIST_INIT(&vmeintr_handlers[i]);
+
+ /*
* Initialize extents
*/
sc->sc_ext_a16 = extent_create("vme a16", 0, 1 << (16 - PAGE_SHIFT),
@@ -110,8 +115,6 @@ vmeattach(struct device *parent, struct device *self, void *aux)
sc->sc_ext_a32 = extent_create("vme a32", 0, 1 << (32 - PAGE_SHIFT),
M_DEVBUF, NULL, 0, EX_NOWAIT);
- vmevecbase = 0x80; /* Hard coded */
-
/*
* Force a reasonable timeout for VME data transfers.
* We can not disable this, this would cause autoconf to hang
@@ -188,46 +191,150 @@ vmeprint(void *aux, const char *pnp)
* Interrupt related code
*/
-/* allocate interrupt vectors */
+intrhand_t vmeintr_handlers[NVMEINTR];
+
int
-vmeintr_allocate(u_int count, int flags, u_int *array)
+vmeintr_allocate(u_int count, int flags, int ipl, u_int *array)
{
u_int vec, v;
+ struct intrhand *ih;
+
+ if (count > 1 && ISSET(flags, VMEINTR_CONTIGUOUS)) {
+ /*
+ * Try to find a range of count unused vectors first.
+ * If there isn't, it is not possible to provide exclusive
+ * contiguous vectors.
+ */
+ for (vec = 0; vec <= NVMEINTR - count; vec++) {
+ for (v = count; v != 0; v--)
+ if (!SLIST_EMPTY(&vmeintr_handlers[vec + v - 1]))
+ break;
- if ((flags & VMEINTR_CONTIGUOUS) == 0) {
- for (vec = vmevecbase; vec <= NVMEINTR - count; vec++) {
- if (SLIST_EMPTY(&intr_handlers[vec])) {
- *array++ = vec;
- if (--count == 0)
- return (0);
+ if (v == 0) {
+ for (v = 0; v < count; v++)
+ *array++ = vec++;
+ return (0);
}
}
- } else {
- for (vec = vmevecbase; vec <= NVMEINTR - count; vec++) {
- /* do we have count contiguous unassigned vectors? */
- for (v = count; v != 0; v--)
- if (!SLIST_EMPTY(&intr_handlers[vec + v - 1]))
+ if (ISSET(flags, VMEINTR_EXCLUSIVE))
+ return (EPERM);
+
+ /*
+ * Try to find a range of count contiguous vectors,
+ * sharing the level we intend to register at. If there
+ * isn't, it is not possible to provide shared contiguous
+ * vectors.
+ */
+ for (vec = 0; vec <= NVMEINTR - count; vec++) {
+ for (v = count; v != 0; v--) {
+ ih = SLIST_FIRST(&vmeintr_handlers[vec + v - 1]);
+ if (ih == NULL)
+ continue;
+ if (ih->ih_ipl != ipl ||
+ ISSET(ih->ih_flags, INTR_EXCLUSIVE))
break;
+ }
if (v == 0) {
- *array = vec;
+ for (v = 0; v < count; v++)
+ *array++ = vec++;
return (0);
}
}
+ return (EPERM);
}
+ /*
+ * Pick as many unused vectors as possible.
+ */
+ for (vec = 0; vec < NVMEINTR; vec++) {
+ if (SLIST_EMPTY(&vmeintr_handlers[vec])) {
+ *array++ = vec;
+ if (--count == 0)
+ return (0);
+ }
+ }
+
+ /*
+ * There are not enough free vectors, so we'll have to share.
+ */
+ for (vec = 0; vec < NVMEINTR; vec++) {
+ ih = SLIST_FIRST(&vmeintr_handlers[vec]);
+ if (ih->ih_ipl == ipl && !ISSET(ih->ih_flags, INTR_EXCLUSIVE)) {
+ *array++ = vec;
+ if (--count == 0)
+ return (0);
+ }
+ }
+
+ /*
+ * There are not enough vectors to share.
+ */
return (EPERM);
}
-/* enable and establish interrupt */
int
vmeintr_establish(u_int vec, struct intrhand *ih, const char *name)
{
+ struct intrhand *intr;
+ intrhand_t *list;
+
+ list = &vmeintr_handlers[vec];
+ intr = SLIST_FIRST(list);
+ if (intr != NULL) {
+ if (intr->ih_ipl != ih->ih_ipl) {
+#ifdef DIAGNOSTIC
+ printf("%s: can't use ipl %d for vector %x,"
+ " it uses ipl %d\n",
+ __func__, ih->ih_ipl, vec, intr->ih_ipl);
+#endif
+ return (EINVAL);
+ }
+ if (ISSET(intr->ih_flags, INTR_EXCLUSIVE) ||
+ ISSET(ih->ih_flags, INTR_EXCLUSIVE)) {
+#ifdef DIAGNOSTIC
+ printf("%s: can't share vector %x\n", __func__, vec);
+#endif
+ return (EINVAL);
+ }
+ }
+
+ evcount_attach(&ih->ih_count, name, (void *)&ih->ih_ipl,
+ &evcount_intr);
+ SLIST_INSERT_HEAD(list, ih, ih_link);
+
+ /*
+ * Enable VME interrupt source for this level.
+ */
+ intsrc_enable(INTSRC_VME + (ih->ih_ipl - 1), ih->ih_ipl);
+
+ return (0);
+}
+
+void
+vmeintr_disestablish(u_int vec, struct intrhand *ih)
+{
+ struct intrhand *intr;
+ intrhand_t *list;
+
+ list = &vmeintr_handlers[vec];
+ evcount_detach(&ih->ih_count);
+ SLIST_REMOVE(list, ih, intrhand, ih_link);
+
+ if (!SLIST_EMPTY(list))
+ return;
+
/*
- * No need to enable the VME interrupt source in the interrupt
- * controller, as they are enabled by default.
+ * Walk the interrupts table to check if this level needs
+ * to be disabled.
*/
- return intr_establish(vec, ih, name);
+ for (vec = 0; vec < NVMEINTR; vec++) {
+ intr = SLIST_FIRST(&vmeintr_handlers[vec]);
+ if (intr != NULL && intr->ih_ipl == ih->ih_ipl)
+ break;
+ }
+ if (vec == NVMEINTR)
+ intsrc_disable(INTSRC_VME + (ih->ih_ipl - 1));
}
/*
@@ -279,7 +386,6 @@ vme_map(struct extent *ext, paddr_t paddr, bus_addr_t addr, bus_size_t size,
psize_t len;
vaddr_t ova, va;
u_int pg;
- extern vaddr_t pmap_map(vaddr_t, paddr_t, paddr_t, vm_prot_t, u_int);
pa = trunc_page(paddr);
len = round_page(paddr + size) - pa;
@@ -299,7 +405,7 @@ vme_map(struct extent *ext, paddr_t paddr, bus_addr_t addr, bus_size_t size,
*ret = (bus_space_handle_t)va;
- for (pg = atop(len); pg !=0; pg--) {
+ for (pg = atop(len); pg != 0; pg--) {
pmap_kenter_pa(va, pa, UVM_PROT_RW);
va += PAGE_SIZE;
pa += PAGE_SIZE;
diff --git a/sys/arch/aviion/dev/vmevar.h b/sys/arch/aviion/dev/vmevar.h
index 207271ff9fe..9098585ce8c 100644
--- a/sys/arch/aviion/dev/vmevar.h
+++ b/sys/arch/aviion/dev/vmevar.h
@@ -1,6 +1,6 @@
-/* $OpenBSD: vmevar.h,v 1.2 2006/05/21 12:22:02 miod Exp $ */
+/* $OpenBSD: vmevar.h,v 1.3 2007/12/19 22:05:06 miod Exp $ */
/*
- * Copyright (c) 2006, Miodrag Vallat
+ * Copyright (c) 2006, 2007, Miodrag Vallat
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -44,11 +44,32 @@ struct vme_attach_args {
u_int vaa_ipl;
};
-int vmeintr_allocate(u_int, int, u_int *);
-#define VMEINTR_ANY 0x00
+/*
+ * There are 256 possible vectors for VME devices.
+ * One or more vectors may be allocated by vmeintr_allocate(), and then
+ * each vector is setup with vmeintr_establish(). Nothing is done to
+ * prevent the vector to be used in-between, so make sure no interrupt
+ * can occur between the vector allocation and the interrupt handler
+ * registration.
+ */
+#define NVMEINTR 256
+extern intrhand_t vmeintr_handlers[NVMEINTR];
+
+int vmeintr_allocate(u_int, int, int, u_int *);
+#define VMEINTR_ANY 0x00 /* any vector will do */
#define VMEINTR_CONTIGUOUS 0x01 /* allocate a contiguous range */
+#define VMEINTR_SHARED 0x00 /* sharing is ok */
+#define VMEINTR_EXCLUSIVE 0x02 /* do not share this vector */
+void vmeintr_disestablish(u_int, struct intrhand *);
int vmeintr_establish(u_int, struct intrhand *, const char *);
+/*
+ * VME device drivers need to obtain their bus_space_tag_t with
+ * vmebus_get_bst(), specifying the address and data width to use for
+ * bus accesses.
+ * Resources associated to the tag can be released with vmebus_release_bst()
+ * when bus accesses are no longer necessary.
+ */
int vmebus_get_bst(struct device *, u_int, u_int, bus_space_tag_t *);
#define VME_A32 0x04 /* 100..000 */
#define VME_A24 0x03 /* 011..000 */