1*d3ce0206Sthorpej /* $NetBSD: vme_two_isr.c,v 1.18 2024/01/19 03:59:47 thorpej Exp $ */
208bde987Sscw
308bde987Sscw /*-
408bde987Sscw * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
508bde987Sscw * All rights reserved.
608bde987Sscw *
708bde987Sscw * This code is derived from software contributed to The NetBSD Foundation
808bde987Sscw * by Steve C. Woodford.
908bde987Sscw *
1008bde987Sscw * Redistribution and use in source and binary forms, with or without
1108bde987Sscw * modification, are permitted provided that the following conditions
1208bde987Sscw * are met:
1308bde987Sscw * 1. Redistributions of source code must retain the above copyright
1408bde987Sscw * notice, this list of conditions and the following disclaimer.
1508bde987Sscw * 2. Redistributions in binary form must reproduce the above copyright
1608bde987Sscw * notice, this list of conditions and the following disclaimer in the
1708bde987Sscw * documentation and/or other materials provided with the distribution.
1808bde987Sscw *
1908bde987Sscw * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2008bde987Sscw * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2108bde987Sscw * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2208bde987Sscw * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2308bde987Sscw * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2408bde987Sscw * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2508bde987Sscw * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2608bde987Sscw * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2708bde987Sscw * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2808bde987Sscw * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2908bde987Sscw * POSSIBILITY OF SUCH DAMAGE.
3008bde987Sscw */
3108bde987Sscw
3208bde987Sscw /*
3308bde987Sscw * Split off from vme_two.c specifically to deal with hardware assisted
3408bde987Sscw * soft interrupts when the user hasn't specified `vmetwo0' in the
3508bde987Sscw * kernel config file (mvme1[67]2 only).
3608bde987Sscw */
3708bde987Sscw
38365cbd94Slukem #include <sys/cdefs.h>
39*d3ce0206Sthorpej __KERNEL_RCSID(0, "$NetBSD: vme_two_isr.c,v 1.18 2024/01/19 03:59:47 thorpej Exp $");
40365cbd94Slukem
4108bde987Sscw #include "vmetwo.h"
42*d3ce0206Sthorpej #include "opt_mvmeconf.h"
4308bde987Sscw
4408bde987Sscw #include <sys/param.h>
4508bde987Sscw #include <sys/kernel.h>
4608bde987Sscw #include <sys/systm.h>
4708bde987Sscw #include <sys/device.h>
4808bde987Sscw #include <sys/malloc.h>
49a2a38285Sad #include <sys/cpu.h>
50a2a38285Sad #include <sys/bus.h>
5108bde987Sscw
5208bde987Sscw #include <dev/vme/vmereg.h>
5308bde987Sscw #include <dev/vme/vmevar.h>
5408bde987Sscw
5508bde987Sscw #include <dev/mvme/mvmebus.h>
5608bde987Sscw #include <dev/mvme/vme_tworeg.h>
5708bde987Sscw #include <dev/mvme/vme_twovar.h>
5808bde987Sscw
5908bde987Sscw /*
6008bde987Sscw * Non-zero if there is no VMEChip2 on this board.
6108bde987Sscw */
6208bde987Sscw int vmetwo_not_present;
6308bde987Sscw
6408bde987Sscw /*
6508bde987Sscw * Array of interrupt handlers registered with us for the non-VMEbus
6608bde987Sscw * vectored interrupts. Eg. ABORT Switch, SYSFAIL etc.
6708bde987Sscw *
6808bde987Sscw * We can't just install a caller's handler directly, since these
6908bde987Sscw * interrupts have to be manually cleared, so we have a trampoline
7008bde987Sscw * which does the clearing automatically.
7108bde987Sscw */
7208bde987Sscw static struct vme_two_handler {
7318db93c7Sperry int (*isr_hand)(void *);
7408bde987Sscw void *isr_arg;
7508bde987Sscw } vme_two_handlers[(VME2_VECTOR_LOCAL_MAX - VME2_VECTOR_LOCAL_MIN) + 1];
7608bde987Sscw
7708bde987Sscw #define VMETWO_HANDLERS_SZ (sizeof(vme_two_handlers) / \
7808bde987Sscw sizeof(struct vme_two_handler))
7908bde987Sscw
8008bde987Sscw static int vmetwo_local_isr_trampoline(void *);
814b293a84Sad #ifdef notyet
8208bde987Sscw static void vmetwo_softintr_assert(void);
834b293a84Sad #endif
8408bde987Sscw
8508bde987Sscw static struct vmetwo_softc *vmetwo_sc;
8608bde987Sscw
8708bde987Sscw int
vmetwo_probe(bus_space_tag_t bt,bus_addr_t offset)8808bde987Sscw vmetwo_probe(bus_space_tag_t bt, bus_addr_t offset)
8908bde987Sscw {
9008bde987Sscw bus_space_handle_t bh;
9108bde987Sscw
9208bde987Sscw bus_space_map(bt, offset + VME2REG_LCSR_OFFSET, VME2LCSR_SIZE, 0, &bh);
9308bde987Sscw
9408bde987Sscw if (bus_space_peek_4(bt, bh, VME2LCSR_MISC_STATUS, NULL) != 0) {
9508bde987Sscw #if defined(MVME162) || defined(MVME172)
9608bde987Sscw #if defined(MVME167) || defined(MVME177)
9708bde987Sscw if (machineid == MVME_162 || machineid == MVME_172)
9808bde987Sscw #endif
9908bde987Sscw {
10008bde987Sscw /*
10108bde987Sscw * No VMEChip2 on mvme162/172 is not too big a
10208bde987Sscw * deal; we can fall back on timer4 in the
10308bde987Sscw * mcchip for h/w assisted soft interrupts...
10408bde987Sscw */
10508bde987Sscw extern void pcctwosoftintrinit(void);
10608bde987Sscw bus_space_unmap(bt, bh, VME2LCSR_SIZE);
10708bde987Sscw vmetwo_not_present = 1;
10808bde987Sscw pcctwosoftintrinit();
10908bde987Sscw return (0);
11008bde987Sscw }
11108bde987Sscw #endif
11208bde987Sscw #if defined(MVME167) || defined(MVME177) || defined(MVME88K)
11308bde987Sscw /*
11408bde987Sscw * No VMEChip2 on mvme167/177, however, is a Big Deal.
11508bde987Sscw * In fact, it means the hardware's shot since the
11608bde987Sscw * VMEChip2 is not a `build-option' on those boards.
11708bde987Sscw */
11808bde987Sscw panic("VMEChip2 not responding! Faulty board?");
11908bde987Sscw /* NOTREACHED */
12008bde987Sscw #endif
12108bde987Sscw #if defined(MVMEPPC)
12208bde987Sscw /*
12308bde987Sscw * No VMEChip2 on mvmeppc is no big deal.
12408bde987Sscw */
12508bde987Sscw bus_space_unmap(bt, bh, VME2LCSR_SIZE);
12608bde987Sscw vmetwo_not_present = 1;
12708bde987Sscw return (0);
12808bde987Sscw #endif
12908bde987Sscw }
13008bde987Sscw #if NVMETWO == 0
13108bde987Sscw else {
13208bde987Sscw /*
13308bde987Sscw * The kernel config file has no `vmetwo0' device, but
13408bde987Sscw * there is a VMEChip2 on the board. Fix up things
13508bde987Sscw * just enough to hook VMEChip2 local interrupts.
13608bde987Sscw */
13708bde987Sscw struct vmetwo_softc *sc;
13808bde987Sscw
139d47bcd29Schs sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK);
14008bde987Sscw sc->sc_mvmebus.sc_bust = bt;
14108bde987Sscw sc->sc_lcrh = bh;
14208bde987Sscw vmetwo_intr_init(sc);
14308bde987Sscw return 0;
14408bde987Sscw }
14508bde987Sscw #else
14608bde987Sscw bus_space_unmap(bt, bh, VME2LCSR_SIZE);
14708bde987Sscw return (1);
14808bde987Sscw #endif
14908bde987Sscw }
15008bde987Sscw
15108bde987Sscw void
vmetwo_intr_init(struct vmetwo_softc * sc)15208bde987Sscw vmetwo_intr_init(struct vmetwo_softc *sc)
15308bde987Sscw {
15408bde987Sscw u_int32_t reg;
15508bde987Sscw int i;
15608bde987Sscw
15708bde987Sscw vmetwo_sc = sc;
15808bde987Sscw
15908bde987Sscw /* Clear out the ISR handler array */
16008bde987Sscw for (i = 0; i < VMETWO_HANDLERS_SZ; i++)
16108bde987Sscw vme_two_handlers[i].isr_hand = NULL;
16208bde987Sscw
16308bde987Sscw /*
16408bde987Sscw * Initialize the chip.
16508bde987Sscw * Firstly, disable all VMEChip2 Interrupts
16608bde987Sscw */
16708bde987Sscw reg = vme2_lcsr_read(sc, VME2LCSR_MISC_STATUS) & ~VME2_MISC_STATUS_MIEN;
16808bde987Sscw vme2_lcsr_write(sc, VME2LCSR_MISC_STATUS, reg);
16908bde987Sscw vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_ENABLE, 0);
17008bde987Sscw vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_CLEAR,
17108bde987Sscw VME2_LOCAL_INTERRUPT_CLEAR_ALL);
17208bde987Sscw
17308bde987Sscw /* Zap all the IRQ level registers */
17408bde987Sscw for (i = 0; i < VME2_NUM_IL_REGS; i++)
17508bde987Sscw vme2_lcsr_write(sc, VME2LCSR_INTERRUPT_LEVEL_BASE + (i * 4), 0);
17608bde987Sscw
17708bde987Sscw /* Disable the tick timers */
17808bde987Sscw reg = vme2_lcsr_read(sc, VME2LCSR_TIMER_CONTROL);
17908bde987Sscw reg &= ~VME2_TIMER_CONTROL_EN(0);
18008bde987Sscw reg &= ~VME2_TIMER_CONTROL_EN(1);
18108bde987Sscw vme2_lcsr_write(sc, VME2LCSR_TIMER_CONTROL, reg);
18208bde987Sscw
18308bde987Sscw /* Set the VMEChip2's vector base register to the required value */
18408bde987Sscw reg = vme2_lcsr_read(sc, VME2LCSR_VECTOR_BASE);
18508bde987Sscw reg &= ~VME2_VECTOR_BASE_MASK;
18608bde987Sscw reg |= VME2_VECTOR_BASE_REG_VALUE;
18708bde987Sscw vme2_lcsr_write(sc, VME2LCSR_VECTOR_BASE, reg);
18808bde987Sscw
18908bde987Sscw /* Set the Master Interrupt Enable bit now */
19008bde987Sscw reg = vme2_lcsr_read(sc, VME2LCSR_MISC_STATUS) | VME2_MISC_STATUS_MIEN;
19108bde987Sscw vme2_lcsr_write(sc, VME2LCSR_MISC_STATUS, reg);
19208bde987Sscw
1937e69c325Sscw /* Allow the MD code the chance to do some initialising */
1947e69c325Sscw vmetwo_md_intr_init(sc);
1957e69c325Sscw
19608bde987Sscw #if defined(MVME167) || defined(MVME177)
19708bde987Sscw #if defined(MVME162) || defined(MVME172)
19808bde987Sscw if (machineid != MVME_162 && machineid != MVME_172)
19908bde987Sscw #endif
20008bde987Sscw {
20108bde987Sscw /*
20208bde987Sscw * Let the NMI handler deal with level 7 ABORT switch
20308bde987Sscw * interrupts
20408bde987Sscw */
20508bde987Sscw vmetwo_intr_establish(sc, 7, 7, VME2_VEC_ABORT, 1,
20608bde987Sscw nmihand, NULL, NULL);
20708bde987Sscw }
20808bde987Sscw #endif
20908bde987Sscw
21008bde987Sscw /* Setup hardware assisted soft interrupts */
2114b293a84Sad #ifdef notyet
21208bde987Sscw vmetwo_intr_establish(sc, 1, 1, VME2_VEC_SOFT0, 1,
21308bde987Sscw (int (*)(void *))softintr_dispatch, NULL, NULL);
21408bde987Sscw _softintr_chipset_assert = vmetwo_softintr_assert;
2154b293a84Sad #endif
21608bde987Sscw }
21708bde987Sscw
21808bde987Sscw static int
vmetwo_local_isr_trampoline(void * arg)219454af1c0Sdsl vmetwo_local_isr_trampoline(void *arg)
22008bde987Sscw {
22108bde987Sscw struct vme_two_handler *isr;
22208bde987Sscw int vec;
22308bde987Sscw
22408bde987Sscw vec = (int) arg; /* 0x08 <= vec <= 0x1f */
22508bde987Sscw
22608bde987Sscw /* Clear the interrupt source */
22708bde987Sscw vme2_lcsr_write(vmetwo_sc, VME2LCSR_LOCAL_INTERRUPT_CLEAR,
22808bde987Sscw VME2_LOCAL_INTERRUPT(vec));
22908bde987Sscw
23008bde987Sscw isr = &vme_two_handlers[vec - VME2_VECTOR_LOCAL_OFFSET];
23108bde987Sscw if (isr->isr_hand)
23208bde987Sscw (void) (*isr->isr_hand) (isr->isr_arg);
23308bde987Sscw else
23408bde987Sscw printf("vmetwo: Spurious local interrupt, vector 0x%x\n", vec);
23508bde987Sscw
23608bde987Sscw return (1);
23708bde987Sscw }
23808bde987Sscw
23908bde987Sscw void
vmetwo_local_intr_establish(int pri,int vec,int (* hand)(void *),void * arg,struct evcnt * evcnt)2407cc9af7dSdsl vmetwo_local_intr_establish(int pri, int vec, int (*hand)(void *), void *arg, struct evcnt *evcnt)
24108bde987Sscw {
24208bde987Sscw
24308bde987Sscw vmetwo_intr_establish(vmetwo_sc, pri, pri, vec, 1, hand, arg, evcnt);
24408bde987Sscw }
24508bde987Sscw
24608bde987Sscw /* ARGSUSED */
24708bde987Sscw void
vmetwo_intr_establish(void * csc,int prior,int lvl,int vec,int first,int (* hand)(void *),void * arg,struct evcnt * evcnt)2487cc9af7dSdsl vmetwo_intr_establish(void *csc, int prior, int lvl, int vec, int first, int (*hand)(void *), void *arg, struct evcnt *evcnt)
24908bde987Sscw {
25008bde987Sscw struct vmetwo_softc *sc = csc;
25108bde987Sscw u_int32_t reg;
25208bde987Sscw int bitoff;
25308bde987Sscw int iloffset, ilshift;
25408bde987Sscw int s;
25508bde987Sscw
25608bde987Sscw s = splhigh();
25708bde987Sscw
25808bde987Sscw #if NVMETWO > 0
25908bde987Sscw /*
26008bde987Sscw * Sort out interrupts generated locally by the VMEChip2 from
26108bde987Sscw * those generated by VMEbus devices...
26208bde987Sscw */
26308bde987Sscw if (vec >= VME2_VECTOR_LOCAL_MIN && vec <= VME2_VECTOR_LOCAL_MAX) {
26408bde987Sscw #endif
26508bde987Sscw /*
26608bde987Sscw * Local interrupts need to be bounced through some
26708bde987Sscw * trampoline code which acknowledges/clears them.
26808bde987Sscw */
26908bde987Sscw vme_two_handlers[vec - VME2_VECTOR_LOCAL_MIN].isr_hand = hand;
27008bde987Sscw vme_two_handlers[vec - VME2_VECTOR_LOCAL_MIN].isr_arg = arg;
27108bde987Sscw hand = vmetwo_local_isr_trampoline;
27208bde987Sscw arg = (void *) (vec - VME2_VECTOR_BASE);
27308bde987Sscw
27408bde987Sscw /*
27508bde987Sscw * Interrupt enable/clear bit offset is 0x08 - 0x1f
27608bde987Sscw */
27708bde987Sscw bitoff = vec - VME2_VECTOR_BASE;
27808bde987Sscw #if NVMETWO > 0
27908bde987Sscw first = 1; /* Force the interrupt to be enabled */
28008bde987Sscw } else {
28108bde987Sscw /*
28208bde987Sscw * Interrupts originating from the VMEbus are
28308bde987Sscw * controlled by an offset of 0x00 - 0x07
28408bde987Sscw */
28508bde987Sscw bitoff = lvl - 1;
28608bde987Sscw }
28708bde987Sscw #endif
28808bde987Sscw
28908bde987Sscw /* Hook the interrupt */
29008bde987Sscw (*sc->sc_isrlink)(sc->sc_isrcookie, hand, arg, prior, vec, evcnt);
29108bde987Sscw
29208bde987Sscw /*
29308bde987Sscw * Do we need to tell the VMEChip2 to let the interrupt through?
29408bde987Sscw * (This is always true for locally-generated interrupts, but only
29508bde987Sscw * needs doing once for each VMEbus interrupt level which is hooked)
29608bde987Sscw */
29708bde987Sscw #if NVMETWO > 0
29808bde987Sscw if (first) {
29908bde987Sscw if (evcnt)
30008bde987Sscw evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
30108bde987Sscw (*sc->sc_isrevcnt)(sc->sc_isrcookie, prior),
302cbab9cadSchs device_xname(sc->sc_mvmebus.sc_dev),
30308bde987Sscw mvmebus_irq_name[lvl]);
30408bde987Sscw #endif
30508bde987Sscw iloffset = VME2_ILOFFSET_FROM_VECTOR(bitoff) +
30608bde987Sscw VME2LCSR_INTERRUPT_LEVEL_BASE;
30708bde987Sscw ilshift = VME2_ILSHIFT_FROM_VECTOR(bitoff);
30808bde987Sscw
30908bde987Sscw /* Program the specified interrupt to signal at 'prior' */
31008bde987Sscw reg = vme2_lcsr_read(sc, iloffset);
31108bde987Sscw reg &= ~(VME2_INTERRUPT_LEVEL_MASK << ilshift);
31208bde987Sscw reg |= (prior << ilshift);
31308bde987Sscw vme2_lcsr_write(sc, iloffset, reg);
31408bde987Sscw
31508bde987Sscw /* Clear it */
31608bde987Sscw vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_CLEAR,
31708bde987Sscw VME2_LOCAL_INTERRUPT(bitoff));
31808bde987Sscw
31908bde987Sscw /* Enable it. */
32008bde987Sscw reg = vme2_lcsr_read(sc, VME2LCSR_LOCAL_INTERRUPT_ENABLE);
32108bde987Sscw reg |= VME2_LOCAL_INTERRUPT(bitoff);
32208bde987Sscw vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_ENABLE, reg);
32308bde987Sscw #if NVMETWO > 0
32408bde987Sscw }
32508bde987Sscw #ifdef DIAGNOSTIC
32608bde987Sscw else {
32708bde987Sscw /* Verify the interrupt priority is the same */
32808bde987Sscw iloffset = VME2_ILOFFSET_FROM_VECTOR(bitoff) +
32908bde987Sscw VME2LCSR_INTERRUPT_LEVEL_BASE;
33008bde987Sscw ilshift = VME2_ILSHIFT_FROM_VECTOR(bitoff);
33108bde987Sscw
33208bde987Sscw reg = vme2_lcsr_read(sc, iloffset);
33308bde987Sscw reg &= (VME2_INTERRUPT_LEVEL_MASK << ilshift);
33408bde987Sscw
33508bde987Sscw if ((prior << ilshift) != reg)
33608bde987Sscw panic("vmetwo_intr_establish: priority mismatch!");
33708bde987Sscw }
33808bde987Sscw #endif
33908bde987Sscw #endif
34008bde987Sscw splx(s);
34108bde987Sscw }
34208bde987Sscw
34308bde987Sscw void
vmetwo_intr_disestablish(void * csc,int lvl,int vec,int last,struct evcnt * evcnt)34482357f6dSdsl vmetwo_intr_disestablish(void *csc, int lvl, int vec, int last, struct evcnt *evcnt)
34508bde987Sscw {
34608bde987Sscw struct vmetwo_softc *sc = csc;
34708bde987Sscw u_int32_t reg;
34808bde987Sscw int iloffset, ilshift;
34908bde987Sscw int bitoff;
35008bde987Sscw int s;
35108bde987Sscw
35208bde987Sscw s = splhigh();
35308bde987Sscw
35408bde987Sscw #if NVMETWO > 0
35508bde987Sscw /*
35608bde987Sscw * Sort out interrupts generated locally by the VMEChip2 from
35708bde987Sscw * those generated by VMEbus devices...
35808bde987Sscw */
35908bde987Sscw if (vec >= VME2_VECTOR_LOCAL_MIN && vec <= VME2_VECTOR_LOCAL_MAX) {
36008bde987Sscw #endif
36108bde987Sscw /*
36208bde987Sscw * Interrupt enable/clear bit offset is 0x08 - 0x1f
36308bde987Sscw */
36408bde987Sscw bitoff = vec - VME2_VECTOR_BASE;
36508bde987Sscw vme_two_handlers[vec - VME2_VECTOR_LOCAL_MIN].isr_hand = NULL;
36608bde987Sscw last = 1; /* Force the interrupt to be cleared */
36708bde987Sscw #if NVMETWO > 0
36808bde987Sscw } else {
36908bde987Sscw /*
37008bde987Sscw * Interrupts originating from the VMEbus are
37108bde987Sscw * controlled by an offset of 0x00 - 0x07
37208bde987Sscw */
37308bde987Sscw bitoff = lvl - 1;
37408bde987Sscw }
37508bde987Sscw #endif
37608bde987Sscw
37708bde987Sscw /*
37808bde987Sscw * Do we need to tell the VMEChip2 to block the interrupt?
37908bde987Sscw * (This is always true for locally-generated interrupts, but only
38008bde987Sscw * needs doing once when the last VMEbus handler for any given level
38108bde987Sscw * has been unhooked.)
38208bde987Sscw */
38308bde987Sscw if (last) {
38408bde987Sscw iloffset = VME2_ILOFFSET_FROM_VECTOR(bitoff) +
38508bde987Sscw VME2LCSR_INTERRUPT_LEVEL_BASE;
38608bde987Sscw ilshift = VME2_ILSHIFT_FROM_VECTOR(bitoff);
38708bde987Sscw
38808bde987Sscw /* Disable it. */
38908bde987Sscw reg = vme2_lcsr_read(sc, VME2LCSR_LOCAL_INTERRUPT_ENABLE);
39008bde987Sscw reg &= ~VME2_LOCAL_INTERRUPT(bitoff);
39108bde987Sscw vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_ENABLE, reg);
39208bde987Sscw
39308bde987Sscw /* Set the interrupt's level to zero */
39408bde987Sscw reg = vme2_lcsr_read(sc, iloffset);
39508bde987Sscw reg &= ~(VME2_INTERRUPT_LEVEL_MASK << ilshift);
39608bde987Sscw vme2_lcsr_write(sc, iloffset, reg);
39708bde987Sscw
39808bde987Sscw /* Clear it */
39908bde987Sscw vme2_lcsr_write(sc, VME2LCSR_LOCAL_INTERRUPT_CLEAR,
40008bde987Sscw VME2_LOCAL_INTERRUPT(vec));
40108bde987Sscw
40208bde987Sscw if (evcnt)
40308bde987Sscw evcnt_detach(evcnt);
40408bde987Sscw }
40508bde987Sscw /* Un-hook it */
40608bde987Sscw (*sc->sc_isrunlink)(sc->sc_isrcookie, vec);
40708bde987Sscw
40808bde987Sscw splx(s);
40908bde987Sscw }
41008bde987Sscw
4114b293a84Sad #ifdef notyet
41208bde987Sscw static void
vmetwo_softintr_assert(void)41308bde987Sscw vmetwo_softintr_assert(void)
41408bde987Sscw {
41508bde987Sscw
41608bde987Sscw vme2_lcsr_write(vmetwo_sc, VME2LCSR_SOFTINT_SET, VME2_SOFTINT_SET(0));
41708bde987Sscw }
4184b293a84Sad #endif
419