summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-04-10 20:53:55 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-04-10 20:53:55 +0000
commitb87d8aad6f1343a2b36ff29986060ba762a45fbb (patch)
tree21dd950980778036b5e89b97f8fd841b4ff956ae
parent2d152c27f3b1a0ab189abf8353c05e196498d89e (diff)
generic soft interrupts support for sparc. Soft interrupt handlers are now
kept in a separate intrhand array, with their own enable bits so that soft interrupts sharing the same level only get invoked if really triggered. Inspired by NetBSD with significant changes. ok kettenis@
-rw-r--r--sys/arch/sparc/dev/amd7930.c38
-rw-r--r--sys/arch/sparc/dev/amd7930var.h3
-rw-r--r--sys/arch/sparc/dev/fd.c48
-rw-r--r--sys/arch/sparc/dev/magma.c41
-rw-r--r--sys/arch/sparc/dev/magmareg.h6
-rw-r--r--sys/arch/sparc/dev/spif.c38
-rw-r--r--sys/arch/sparc/dev/spifvar.h4
-rw-r--r--sys/arch/sparc/dev/zs.c64
-rw-r--r--sys/arch/sparc/include/_types.h5
-rw-r--r--sys/arch/sparc/include/cpu.h59
-rw-r--r--sys/arch/sparc/include/intr.h102
-rw-r--r--sys/arch/sparc/include/psl.h9
-rw-r--r--sys/arch/sparc/include/z8530var.h3
-rw-r--r--sys/arch/sparc/sparc/amd7930intr.s9
-rw-r--r--sys/arch/sparc/sparc/bsd_fdintr.s9
-rw-r--r--sys/arch/sparc/sparc/genassym.cf8
-rw-r--r--sys/arch/sparc/sparc/intr.c249
-rw-r--r--sys/arch/sparc/sparc/intreg.h11
-rw-r--r--sys/arch/sparc/sparc/locore.s56
19 files changed, 410 insertions, 352 deletions
diff --git a/sys/arch/sparc/dev/amd7930.c b/sys/arch/sparc/dev/amd7930.c
index 5930c16a292..9c84d7fa035 100644
--- a/sys/arch/sparc/dev/amd7930.c
+++ b/sys/arch/sparc/dev/amd7930.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: amd7930.c,v 1.31 2008/04/21 00:32:42 jakemsr Exp $ */
+/* $OpenBSD: amd7930.c,v 1.32 2009/04/10 20:53:51 miod Exp $ */
/* $NetBSD: amd7930.c,v 1.37 1998/03/30 14:23:40 pk Exp $ */
/*
@@ -66,7 +66,6 @@ int amd7930debug = 0;
*/
struct amd7930_softc {
struct device sc_dev; /* base device */
- struct intrhand sc_swih; /* software interrupt vector */
int sc_open; /* single use device */
int sc_locked; /* true when transferring data */
@@ -86,25 +85,14 @@ struct amd7930_softc {
/* sc_au is special in that the hardware interrupt handler uses it */
struct auio sc_au; /* recv and xmit buffers, etc */
#define sc_hwih sc_au.au_ih /* hardware interrupt vector */
+#define sc_swih sc_au.au_swih /* software interrupt cookie */
};
-/* interrupt interfaces */
-#if defined(SUN4M)
-#define AUDIO_SET_SWINTR do { \
- if (CPU_ISSUN4M) \
- raise(0, 4); \
- else \
- ienab_bis(IE_L4); \
-} while(0);
-#else
-#define AUDIO_SET_SWINTR ienab_bis(IE_L4)
-#endif /* defined(SUN4M) */
-
#ifndef AUDIO_C_HANDLER
struct auio *auiop;
#endif /* AUDIO_C_HANDLER */
int amd7930hwintr(void *);
-int amd7930swintr(void *);
+void amd7930swintr(void *);
/* forward declarations */
void audio_setmap(volatile struct amd7930 *, struct mapreg *);
@@ -325,10 +313,7 @@ amd7930attach(parent, self, args)
intr_establish(pri, &sc->sc_hwih, IPL_AUHARD,
sc->sc_dev.dv_xname);
}
- sc->sc_swih.ih_fun = amd7930swintr;
- sc->sc_swih.ih_arg = sc;
- intr_establish(IPL_AUSOFT, &sc->sc_swih, IPL_AUSOFT,
- sc->sc_dev.dv_xname);
+ sc->sc_swih = softintr_establish(IPL_AUSOFT, amd7930swintr, sc);
audio_attach_mi(&sa_hw_if, sc, &sc->sc_dev);
amd7930_commit_settings(sc);
@@ -809,7 +794,7 @@ amd7930hwintr(au0)
if (amd7930debug > 1)
printf("amd7930hwintr: swintr(r) requested");
#endif
- AUDIO_SET_SWINTR;
+ softintr_schedule(au->au_swih);
}
}
@@ -824,20 +809,20 @@ amd7930hwintr(au0)
if (amd7930debug > 1)
printf("amd7930hwintr: swintr(p) requested");
#endif
- AUDIO_SET_SWINTR;
+ softintr_schedule(au->au_swih);
}
}
return (-1);
}
-int
+void
amd7930swintr(sc0)
void *sc0;
{
- register struct amd7930_softc *sc = sc0;
- register struct auio *au;
- register int s, ret = 0;
+ struct amd7930_softc *sc = sc0;
+ struct auio *au;
+ int s;
#ifdef AUDIO_DEBUG
if (amd7930debug > 1)
@@ -848,17 +833,14 @@ amd7930swintr(sc0)
s = splaudio();
if (au->au_rdata > au->au_rend && sc->sc_rintr != NULL) {
splx(s);
- ret = 1;
(*sc->sc_rintr)(sc->sc_rarg);
s = splaudio();
}
if (au->au_pdata > au->au_pend && sc->sc_pintr != NULL) {
splx(s);
- ret = 1;
(*sc->sc_pintr)(sc->sc_parg);
} else
splx(s);
- return (ret);
}
#ifndef AUDIO_C_HANDLER
diff --git a/sys/arch/sparc/dev/amd7930var.h b/sys/arch/sparc/dev/amd7930var.h
index ccc2bead247..91ce71c2122 100644
--- a/sys/arch/sparc/dev/amd7930var.h
+++ b/sys/arch/sparc/dev/amd7930var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: amd7930var.h,v 1.7 2004/09/29 07:35:11 miod Exp $ */
+/* $OpenBSD: amd7930var.h,v 1.8 2009/04/10 20:53:51 miod Exp $ */
/* $NetBSD: amd7930var.h,v 1.3 1996/02/01 22:32:25 mycroft Exp $ */
/*
@@ -64,6 +64,7 @@ struct auio {
u_char *au_pend; /* end of play data */
struct intrhand au_ih;
+ void *au_swih; /* software interrupt cookie */
};
/*
diff --git a/sys/arch/sparc/dev/fd.c b/sys/arch/sparc/dev/fd.c
index 1cb6a5c2e34..38cffc97355 100644
--- a/sys/arch/sparc/dev/fd.c
+++ b/sys/arch/sparc/dev/fd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fd.c,v 1.63 2008/10/15 19:12:19 blambert Exp $ */
+/* $OpenBSD: fd.c,v 1.64 2009/04/10 20:53:51 miod Exp $ */
/* $NetBSD: fd.c,v 1.51 1997/05/24 20:16:19 pk Exp $ */
/*-
@@ -138,7 +138,7 @@ enum fdc_state {
/* software state, per controller */
struct fdc_softc {
struct device sc_dev; /* boilerplate */
- struct intrhand sc_sih;
+ void *sc_sih; /* softintr cookie */
caddr_t sc_reg;
struct fd_softc *sc_fd[4]; /* pointers to children */
TAILQ_HEAD(drivehead, fd_softc) sc_drives;
@@ -261,7 +261,7 @@ int fdc_c_hwintr(struct fdc_softc *);
#else
void fdchwintr(void);
#endif
-int fdcswintr(struct fdc_softc *);
+void fdcswintr(void *);
int fdcstate(struct fdc_softc *);
void fdcretry(struct fdc_softc *fdc);
void fdfinish(struct fd_softc *fd, struct buf *bp);
@@ -269,25 +269,6 @@ int fdformat(dev_t, struct fd_formb *, struct proc *);
void fd_do_eject(struct fd_softc *);
static int fdconf(struct fdc_softc *);
-#if IPL_FDSOFT == 4
-#define IE_FDSOFT IE_L4
-#else
-#error 4
-#endif
-
-#ifdef FDC_C_HANDLER
-#if defined(SUN4M)
-#define FD_SET_SWINTR do { \
- if (CPU_ISSUN4M) \
- raise(0, IPL_FDSOFT); \
- else \
- ienab_bis(IE_FDSOFT); \
-} while(0)
-#else
-#define FD_SET_SWINTR ienab_bis(IE_FDSOFT)
-#endif /* defined(SUN4M) */
-#endif /* FDC_C_HANDLER */
-
#define OBP_FDNAME (CPU_ISSUN4M ? "SUNW,fdtwo" : "fd")
int
@@ -448,9 +429,7 @@ fdcattach(parent, self, aux)
evcount_attach(&fdc->sc_hih.ih_count, self->dv_xname,
&fdc->sc_hih.ih_vec, &evcount_intr);
#endif
- fdc->sc_sih.ih_fun = (void *)fdcswintr;
- fdc->sc_sih.ih_arg = fdc;
- intr_establish(IPL_FDSOFT, &fdc->sc_sih, IPL_BIO, self->dv_xname);
+ fdc->sc_sih = softintr_establish(IPL_FDSOFT, fdcswintr, fdc);
/* Assume a 82077 */
fdc->sc_reg_msr = &((struct fdreg_77 *)fdc->sc_reg)->fd_msr;
@@ -1168,14 +1147,14 @@ fdc_c_hwintr(fdc)
fdc->sc_istatus = FDC_ISTATUS_ERROR;
else
fdc->sc_istatus = FDC_ISTATUS_DONE;
- FD_SET_SWINTR;
+ softintr_schedule(fdc->sc_sih);
goto done;
case FDC_ITASK_RESULT:
if (fdcresult(fdc) == -1)
fdc->sc_istatus = FDC_ISTATUS_ERROR;
else
fdc->sc_istatus = FDC_ISTATUS_DONE;
- FD_SET_SWINTR;
+ softintr_schedule(fdc->sc_sih);
goto done;
case FDC_ITASK_DMA:
/* Proceed with pseudo-DMA below */
@@ -1183,7 +1162,7 @@ fdc_c_hwintr(fdc)
default:
printf("fdc: stray hard interrupt: itask=%d\n", fdc->sc_itask);
fdc->sc_istatus = FDC_ISTATUS_SPURIOUS;
- FD_SET_SWINTR;
+ softintr_schedule(fdc->sc_sih);
goto done;
}
@@ -1202,7 +1181,7 @@ fdc_c_hwintr(fdc)
if ((msr & NE7_NDM) == 0) {
fdcresult(fdc);
fdc->sc_istatus = FDC_ISTATUS_DONE;
- FD_SET_SWINTR;
+ softintr_schedule(fdc->sc_sih);
#ifdef FD_DEBUG
if (fdc_debug > 1)
printf("fdc: overrun: tc = %d\n", fdc->sc_tc);
@@ -1219,7 +1198,7 @@ fdc_c_hwintr(fdc)
fdc->sc_istatus = FDC_ISTATUS_DONE;
FTC_FLIP;
fdcresult(fdc);
- FD_SET_SWINTR;
+ softintr_schedule(fdc->sc_sih);
break;
}
}
@@ -1228,15 +1207,15 @@ done:
}
#endif
-int
-fdcswintr(fdc)
- struct fdc_softc *fdc;
+void
+fdcswintr(void *arg)
{
+ struct fdc_softc *fdc = (struct fdc_softc *)arg;
int s;
if (fdc->sc_istatus == FDC_ISTATUS_NONE)
/* This (software) interrupt is not for us */
- return (0);
+ return;
switch (fdc->sc_istatus) {
case FDC_ISTATUS_ERROR:
@@ -1250,7 +1229,6 @@ fdcswintr(fdc)
s = splbio();
fdcstate(fdc);
splx(s);
- return (1);
}
int
diff --git a/sys/arch/sparc/dev/magma.c b/sys/arch/sparc/dev/magma.c
index 2c4bedf3456..05b217a790f 100644
--- a/sys/arch/sparc/dev/magma.c
+++ b/sys/arch/sparc/dev/magma.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: magma.c,v 1.20 2008/11/29 01:55:06 ray Exp $ */
+/* $OpenBSD: magma.c,v 1.21 2009/04/10 20:53:51 miod Exp $ */
/*-
* Copyright (c) 1998 Iain Hibbert
@@ -59,19 +59,6 @@
#include <sparc/bppioctl.h>
#include <sparc/dev/magmareg.h>
-/*
- * Select tty soft interrupt bit based on TTY ipl. (stolen from zs.c)
- */
-#if IPL_TTY == 1
-# define IE_MSOFT IE_L1
-#elif IPL_TTY == 4
-# define IE_MSOFT IE_L4
-#elif IPL_TTY == 6
-# define IE_MSOFT IE_L6
-#else
-# error "no suitable software interrupt bit"
-#endif
-
#ifdef MAGMA_DEBUG
#define dprintf(x) printf x
#else
@@ -480,9 +467,7 @@ magma_attach(parent, dev, args)
intr_establish(ra->ra_intr[0].int_pri, &sc->ms_hardint, -1,
dev->dv_xname);
- sc->ms_softint.ih_fun = magma_soft;
- sc->ms_softint.ih_arg = sc;
- intr_establish(IPL_TTY, &sc->ms_softint, IPL_TTY, dev->dv_xname);
+ sc->ms_softint = softintr_establish(IPL_SOFTTTY, magma_soft, sc);
}
/*
@@ -715,14 +700,8 @@ magma_hard(arg)
}
*/
- if (needsoftint) { /* trigger the soft interrupt */
-#if defined(SUN4M)
- if (CPU_ISSUN4M)
- raise(0, IPL_TTY);
- else
-#endif
- ienab_bis(IE_MSOFT);
- }
+ if (needsoftint) /* trigger the soft interrupt */
+ softintr_schedule(sc->ms_softint);
return (serviced);
}
@@ -730,11 +709,9 @@ magma_hard(arg)
/*
* magma soft interrupt handler
*
- * returns 1 if it handled it, 0 otherwise
- *
* runs at spltty()
*/
-int
+void
magma_soft(arg)
void *arg;
{
@@ -742,7 +719,6 @@ magma_soft(arg)
struct mtty_softc *mtty = sc->ms_mtty;
struct mbpp_softc *mbpp = sc->ms_mbpp;
int port;
- int serviced = 0;
int s, flags;
/*
@@ -780,7 +756,6 @@ magma_soft(arg)
mtty->ms_dev.dv_xname, port);
(*linesw[tp->t_line].l_rint)(data, tp);
- serviced = 1;
}
s = splhigh(); /* block out hard interrupt routine */
@@ -795,14 +770,12 @@ magma_soft(arg)
mp->mp_carrier ? "on" : "off"));
(*linesw[tp->t_line].l_modem)(tp,
mp->mp_carrier);
- serviced = 1;
}
if (ISSET(flags, MTTYF_RING_OVERFLOW)) {
log(LOG_WARNING,
"%s%x: ring buffer overflow\n",
mtty->ms_dev.dv_xname, port);
- serviced = 1;
}
if (ISSET(flags, MTTYF_DONE)) {
@@ -811,7 +784,6 @@ magma_soft(arg)
CLR(tp->t_state, TS_BUSY);
/* might be some more */
(*linesw[tp->t_line].l_start)(tp);
- serviced = 1;
}
} /* for (each mtty...) */
}
@@ -833,12 +805,9 @@ magma_soft(arg)
if (ISSET(flags, MBPPF_WAKEUP)) {
wakeup(mp);
- serviced = 1;
}
} /* for (each mbpp...) */
}
-
- return (serviced);
}
/************************************************************************
diff --git a/sys/arch/sparc/dev/magmareg.h b/sys/arch/sparc/dev/magmareg.h
index 4bedc5cd6cc..95613b07901 100644
--- a/sys/arch/sparc/dev/magmareg.h
+++ b/sys/arch/sparc/dev/magmareg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: magmareg.h,v 1.10 2008/11/29 01:55:06 ray Exp $ */
+/* $OpenBSD: magmareg.h,v 1.11 2009/04/10 20:53:51 miod Exp $ */
/*-
* Copyright (c) 1998 Iain Hibbert
@@ -110,7 +110,7 @@ struct magma_softc {
struct mbpp_softc *ms_mbpp;
struct intrhand ms_hardint; /* hard interrupt handler */
- struct intrhand ms_softint; /* soft interrupt handler */
+ void *ms_softint; /* soft interrupt handler */
};
#define MTTY_RBUF_SIZE (2 * 512)
@@ -191,7 +191,7 @@ void cd1400_enable_transmitter(struct cd1400 *, int);
int magma_match(struct device *, void *, void *);
void magma_attach(struct device *, struct device *, void *);
int magma_hard(void *);
-int magma_soft(void *);
+void magma_soft(void *);
int mtty_match(struct device *, void *, void *);
void mtty_attach(struct device *, struct device *, void *);
diff --git a/sys/arch/sparc/dev/spif.c b/sys/arch/sparc/dev/spif.c
index 41acf0102f6..4102f97246b 100644
--- a/sys/arch/sparc/dev/spif.c
+++ b/sys/arch/sparc/dev/spif.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: spif.c,v 1.20 2006/06/02 20:00:54 miod Exp $ */
+/* $OpenBSD: spif.c,v 1.21 2009/04/10 20:53:51 miod Exp $ */
/*
* Copyright (c) 1999 Jason L. Wright (jason@thought.net)
@@ -53,16 +53,6 @@
#include <sparc/dev/spifreg.h>
#include <sparc/dev/spifvar.h>
-#if IPL_TTY == 1
-# define IE_MSOFT IE_L1
-#elif IPL_TTY == 4
-# define IE_MSOFT IE_L4
-#elif IPL_TTY == 6
-# define IE_MSOFT IE_L6
-#else
-# error "no suitable software interrupt bit"
-#endif
-
int spifmatch(struct device *, void *, void *);
void spifattach(struct device *, struct device *, void *);
@@ -80,7 +70,7 @@ int spifstcintr_mx(struct spif_softc *, int *);
int spifstcintr_tx(struct spif_softc *, int *);
int spifstcintr_rx(struct spif_softc *, int *);
int spifstcintr_rxexception(struct spif_softc *, int *);
-int spifsoftintr(void *);
+void spifsoftintr(void *);
int stty_param(struct tty *, struct termios *);
struct tty *sttytty(dev_t);
@@ -213,9 +203,7 @@ spifattach(parent, self, aux)
sc->sc_stcih.ih_arg = sc;
intr_establish(stcpri, &sc->sc_stcih, -1, self->dv_xname);
- sc->sc_softih.ih_fun = spifsoftintr;
- sc->sc_softih.ih_arg = sc;
- intr_establish(IPL_TTY, &sc->sc_softih, IPL_TTY, self->dv_xname);
+ sc->sc_softih = softintr_establish(IPL_SOFTTTY, spifsoftintr, sc);
}
int
@@ -869,24 +857,18 @@ spifstcintr(vsc)
r |= spifstcintr_mx(sc, &needsoft);
}
- if (needsoft) {
-#if defined(SUN4M)
- if (CPU_ISSUN4M)
- raise(0, IPL_TTY);
- else
-#endif
- ienab_bis(IE_MSOFT);
- }
+ if (needsoft)
+ softintr_schedule(sc->sc_softih);
return (r);
}
-int
+void
spifsoftintr(vsc)
void *vsc;
{
struct spif_softc *sc = (struct spif_softc *)vsc;
struct stty_softc *stc = sc->sc_ttys;
- int r = 0, i, data, s, flags;
+ int i, data, s, flags;
u_int8_t stat, msvr;
struct stty_port *sp;
struct tty *tp;
@@ -913,7 +895,6 @@ spifsoftintr(vsc)
data |= TTY_PE;
(*linesw[tp->t_line].l_rint)(data, tp);
- r = 1;
}
s = splhigh();
@@ -931,13 +912,11 @@ spifsoftintr(vsc)
sp->sp_carrier = msvr & CD180_MSVR_CD;
(*linesw[tp->t_line].l_modem)(tp,
sp->sp_carrier);
- r = 1;
}
if (ISSET(flags, STTYF_RING_OVERFLOW)) {
log(LOG_WARNING, "%s-%x: ring overflow\n",
stc->sc_dev.dv_xname, i);
- r = 1;
}
if (ISSET(flags, STTYF_DONE)) {
@@ -945,12 +924,9 @@ spifsoftintr(vsc)
sp->sp_txp - tp->t_outq.c_cf);
CLR(tp->t_state, TS_BUSY);
(*linesw[tp->t_line].l_start)(tp);
- r = 1;
}
}
}
-
- return (r);
}
static __inline void
diff --git a/sys/arch/sparc/dev/spifvar.h b/sys/arch/sparc/dev/spifvar.h
index 28076a5c095..42a80e31d90 100644
--- a/sys/arch/sparc/dev/spifvar.h
+++ b/sys/arch/sparc/dev/spifvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: spifvar.h,v 1.4 2006/06/02 20:00:54 miod Exp $ */
+/* $OpenBSD: spifvar.h,v 1.5 2009/04/10 20:53:51 miod Exp $ */
/*
* Copyright (c) 1999 Jason L. Wright (jason@thought.net)
@@ -61,7 +61,7 @@ struct spif_softc {
struct device sc_dev; /* base device */
struct intrhand sc_stcih; /* stc interrupt vectoring */
struct intrhand sc_ppcih; /* ppc interrupt vectoring */
- struct intrhand sc_softih; /* hard interrupt vectoring */
+ void *sc_softih; /* soft interrupt vectoring */
int sc_rev; /* revision level */
int sc_osc; /* oscillator speed (hz) */
int sc_node; /* which sbus node */
diff --git a/sys/arch/sparc/dev/zs.c b/sys/arch/sparc/dev/zs.c
index f7a93fefb35..d3751bc31a3 100644
--- a/sys/arch/sparc/dev/zs.c
+++ b/sys/arch/sparc/dev/zs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: zs.c,v 1.46 2008/06/26 05:42:13 ray Exp $ */
+/* $OpenBSD: zs.c,v 1.47 2009/04/10 20:53:51 miod Exp $ */
/* $NetBSD: zs.c,v 1.50 1997/10/18 00:00:40 gwr Exp $ */
/*-
@@ -96,19 +96,6 @@ int zs_major = 12;
*/
#define PCLK (9600 * 512) /* PCLK pin input clock rate */
-/*
- * Select software interrupt bit based on TTY ipl.
- */
-#if IPL_TTY == 1
-# define IE_ZSSOFT IE_L1
-#elif IPL_TTY == 4
-# define IE_ZSSOFT IE_L4
-#elif IPL_TTY == 6
-# define IE_ZSSOFT IE_L6
-#else
-# error "no suitable software interrupt bit"
-#endif
-
#define ZS_DELAY() (CPU_ISSUN4C ? (0) : delay(2))
/* The layout of this is hardware-dependent (padding, order). */
@@ -213,9 +200,8 @@ struct cfdriver zs_cd = {
/* Interrupt handlers. */
int zshard(void *);
-int zssoft(void *);
+void zssoft(void *);
struct intrhand levelhard = { zshard };
-struct intrhand levelsoft = { zssoft };
int zs_get_speed(struct zs_chanstate *);
@@ -360,10 +346,11 @@ zs_attach(parent, self, aux)
didintr = 1;
prevpri = pri;
intr_establish(pri, &levelhard, IPL_ZS, self->dv_xname);
- intr_establish(IPL_TTY, &levelsoft, IPL_TTY, self->dv_xname);
} else if (pri != prevpri)
panic("broken zs interrupt scheme");
+ zsc->zsc_softih = softintr_establish(IPL_SOFTTTY, zssoft, zsc);
+
/*
* Set the master interrupt enable and interrupt vector.
* (common to both channels, do it on A)
@@ -419,8 +406,6 @@ zs_print(aux, name)
return UNCONF;
}
-volatile int zssoftpending;
-
/*
* Our ZS chips all share a common, autovectored interrupt,
* so we have to look at all of them on each interrupt.
@@ -442,56 +427,27 @@ zshard(arg)
if (rr3) {
rval |= rr3;
}
- softreq |= zsc->zsc_cs[0].cs_softreq;
- softreq |= zsc->zsc_cs[1].cs_softreq;
+ if (zsc->zsc_cs[0].cs_softreq || zsc->zsc_cs[1].cs_softreq)
+ softintr_schedule(zsc->zsc_softih);
}
- /* We are at splzs here, so no need to lock. */
- if (softreq && (zssoftpending == 0)) {
- zssoftpending = IE_ZSSOFT;
-#if defined(SUN4M)
- if (CPU_ISSUN4M)
- raise(0, IPL_TTY);
- else
-#endif
- ienab_bis(IE_ZSSOFT);
- }
return (rval);
}
/*
* Similar scheme as for zshard (look at all of them)
*/
-int
+void
zssoft(arg)
void *arg;
{
- struct zsc_softc *zsc;
- int s, unit;
-
- /* This is not the only ISR on this IPL. */
- if (zssoftpending == 0)
- return (0);
-
- /*
- * The soft intr. bit will be set by zshard only if
- * the variable zssoftpending is zero. The order of
- * these next two statements prevents our clearing
- * the soft intr bit just after zshard has set it.
- */
- /* ienab_bic(IE_ZSSOFT); */
- zssoftpending = 0;
+ struct zsc_softc *zsc = (struct zsc_softc *)arg;
+ int s;
/* Make sure we call the tty layer at spltty. */
s = spltty();
- for (unit = 0; unit < zs_cd.cd_ndevs; unit++) {
- zsc = zs_cd.cd_devs[unit];
- if (zsc == NULL)
- continue;
- (void)zsc_intr_soft(zsc);
- }
+ (void)zsc_intr_soft(zsc);
splx(s);
- return (1);
}
diff --git a/sys/arch/sparc/include/_types.h b/sys/arch/sparc/include/_types.h
index 0353ef1e1ae..23331af88f9 100644
--- a/sys/arch/sparc/include/_types.h
+++ b/sys/arch/sparc/include/_types.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: _types.h,v 1.9 2008/07/21 20:50:55 martynas Exp $ */
+/* $OpenBSD: _types.h,v 1.10 2009/04/10 20:53:54 miod Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -116,4 +116,7 @@ typedef int __rune_t;
typedef void * __wctrans_t;
typedef void * __wctype_t;
+/* Feature test macros */
+#define __HAVE_GENERIC_SOFT_INTERRUPTS
+
#endif /* _SPARC__TYPES_H_ */
diff --git a/sys/arch/sparc/include/cpu.h b/sys/arch/sparc/include/cpu.h
index 27dbcc663df..2f68e5bb6aa 100644
--- a/sys/arch/sparc/include/cpu.h
+++ b/sys/arch/sparc/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.31 2009/03/26 17:24:33 oga Exp $ */
+/* $OpenBSD: cpu.h,v 1.32 2009/04/10 20:53:54 miod Exp $ */
/* $NetBSD: cpu.h,v 1.24 1997/03/15 22:25:15 pk Exp $ */
/*
@@ -66,9 +66,9 @@
* Exported definitions unique to SPARC cpu support.
*/
-#include <sys/evcount.h>
#include <machine/psl.h>
#include <machine/reg.h>
+#include <machine/intr.h>
#include <sparc/sparc/intreg.h>
#include <sparc/sparc/cpuvar.h>
@@ -94,32 +94,6 @@ extern int eintstack[];
#define CLKF_INTR(framep) ((framep)->fp < (u_int)eintstack)
/*
- * Software interrupt request `register'.
- */
-union sir {
- int sir_any;
- char sir_which[4];
-};
-extern union sir sir;
-
-#define SIR_NET 0
-#define SIR_CLOCK 1
-
-#if defined(SUN4M)
-extern void raise(int, int);
-#if !(defined(SUN4) || defined(SUN4C))
-#define setsoftint() raise(0,1)
-#else /* both defined */
-#define setsoftint() (cputyp == CPU_SUN4M ? raise(0,1) : ienab_bis(IE_L1))
-#endif /* !4,!4c */
-#else /* 4m not defined */
-#define setsoftint() ienab_bis(IE_L1)
-#endif /* SUN4M */
-
-#define setsoftnet() (sir.sir_which[SIR_NET] = 1, setsoftint())
-#define setsoftclock() (sir.sir_which[SIR_CLOCK] = 1, setsoftint())
-
-/*
* Preempt the current process if in interrupt from user mode,
* or after the current trap/syscall if in system mode.
*/
@@ -148,34 +122,6 @@ extern int want_ast;
extern int foundfpu; /* true => we have an FPU */
-/*
- * Interrupt handler chains. Interrupt handlers should return 0 for
- * ``not me'' or 1 (``I took care of it''). intr_establish() inserts a
- * handler into the list. The handler is called with its (single)
- * argument, or with a pointer to a clockframe if ih_arg is NULL.
- * ih_ipl specifies the interrupt level that should be blocked when
- * executing this handler.
- */
-struct intrhand {
- int (*ih_fun)(void *);
- void *ih_arg;
- int ih_ipl;
- int ih_vec; /* human readable ipl for vmstat */
- struct evcount ih_count;
- struct intrhand *ih_next;
-};
-extern struct intrhand *intrhand[15];
-void intr_establish(int level, struct intrhand *, int, const char *);
-void vmeintr_establish(int vec, int level, struct intrhand *, int, const char *);
-
-/*
- * intr_fasttrap() is a lot like intr_establish, but is used for ``fast''
- * interrupt vectors (vectors that are not shared and are handled in the
- * trap window). Such functions must be written in assembly.
- */
-int intr_fasttrap(int, void (*)(void), int (*)(void *), void *);
-void intr_fastuntrap(int);
-
/* auxreg.c */
void led_blink(void *);
/* scf.c */
@@ -186,7 +132,6 @@ int isbad(struct dkbad *bt, int, int, int);
/* machdep.c */
int ldcontrolb(caddr_t);
void dumpconf(void);
-void intr_init(void);
caddr_t reserve_dumppages(caddr_t);
/* clock.c */
struct timeval;
diff --git a/sys/arch/sparc/include/intr.h b/sys/arch/sparc/include/intr.h
new file mode 100644
index 00000000000..b4fff3a96ac
--- /dev/null
+++ b/sys/arch/sparc/include/intr.h
@@ -0,0 +1,102 @@
+/* $OpenBSD: intr.h,v 1.1 2009/04/10 20:53:54 miod Exp $ */
+/* $NetBSD: cpu.h,v 1.24 1997/03/15 22:25:15 pk Exp $ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ * @(#)cpu.h 8.4 (Berkeley) 1/5/94
+ */
+
+#ifndef _SPARC_INTR_H_
+#define _SPARC_INTR_H_
+
+#ifdef _KERNEL
+#include <sys/evcount.h>
+
+/*
+ * Interrupt handler chains. Interrupt handlers should return 0 for
+ * ``not me'' or 1 (``I took care of it''). intr_establish() inserts a
+ * handler into the list. The handler is called with its (single)
+ * argument, or with a pointer to a clockframe if ih_arg is NULL.
+ * ih_ipl specifies the interrupt level that should be blocked when
+ * executing this handler.
+ */
+struct intrhand {
+ int (*ih_fun)(void *);
+ void *ih_arg;
+ int ih_ipl;
+ int ih_vec; /* ipl for vmstat */
+ struct evcount ih_count;
+ struct intrhand *ih_next; /* global list */
+};
+extern struct intrhand *intrhand[15]; /* XXX obio.c */
+
+void intr_establish(int, struct intrhand *, int, const char *);
+void vmeintr_establish(int, int, struct intrhand *, int, const char *);
+
+/*
+ * intr_fasttrap() is a lot like intr_establish, but is used for ``fast''
+ * interrupt vectors (vectors that are not shared and are handled in the
+ * trap window). Such functions must be written in assembly.
+ */
+int intr_fasttrap(int, void (*)(void), int (*)(void *), void *);
+void intr_fastuntrap(int);
+
+void intr_init(void);
+
+/*
+ * Soft interrupt handler chains. In addition to a struct intrhand for
+ * proper dispatching, we also remember a pending state as well as the
+ * bits to frob in the software interrupt register.
+ */
+struct sintrhand {
+ struct intrhand sih_ih;
+ int sih_pending; /* nonzero if triggered */
+ int sih_hw; /* hw dependent */
+ int sih_ipl; /* ipl it's registered at */
+};
+
+void softintr_disestablish(void *);
+void *softintr_establish(int, void (*)(void *), void *);
+void softintr_schedule(void *);
+
+/* XXX legacy software interrupts */
+extern void *softnet_ih;
+#define setsoftnet() softintr_schedule(softnet_ih)
+
+#endif /* _KERNEL */
+#endif /* _SPARC_INTR_H_ */
diff --git a/sys/arch/sparc/include/psl.h b/sys/arch/sparc/include/psl.h
index cb9fc9022f4..b8afe55177f 100644
--- a/sys/arch/sparc/include/psl.h
+++ b/sys/arch/sparc/include/psl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: psl.h,v 1.24 2009/03/15 19:40:40 miod Exp $ */
+/* $OpenBSD: psl.h,v 1.25 2009/04/10 20:53:54 miod Exp $ */
/* $NetBSD: psl.h,v 1.12 1997/03/10 21:49:11 pk Exp $ */
/*
@@ -77,12 +77,13 @@
*/
#define IPL_NONE 0
#define IPL_SOFTINT 1
-#define IPL_SOFTCLOCK IPL_SOFTINT /* softclock() interrupts */
-#define IPL_SOFTNET IPL_SOFTINT /* soft network interrupts */
+#define IPL_SOFTCLOCK 1 /* softclock() interrupts */
+#define IPL_SOFTNET 1 /* soft network interrupts */
#define IPL_AUSOFT 4 /* audio soft interrupts */
#define IPL_FDSOFT 4 /* floppy soft interrupts */
#define IPL_BIO 5 /* block devices are at 5 and below */
-#define IPL_TTY 6 /* tty soft interrupts */
+#define IPL_TTY 6 /* MD tty soft interrupts */
+#define IPL_SOFTTTY IPL_TTY
#define IPL_NET 7 /* network hardware at 7 or below */
#define IPL_VM 7 /* max(BIO, NET, TTY) */
#define IPL_FB 9 /* framebuffer interrupts */
diff --git a/sys/arch/sparc/include/z8530var.h b/sys/arch/sparc/include/z8530var.h
index 387c49a5e40..05469563496 100644
--- a/sys/arch/sparc/include/z8530var.h
+++ b/sys/arch/sparc/include/z8530var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: z8530var.h,v 1.3 2004/09/29 07:35:13 miod Exp $ */
+/* $OpenBSD: z8530var.h,v 1.4 2009/04/10 20:53:54 miod Exp $ */
/* $NetBSD: z8530var.h,v 1.1 1997/10/18 00:01:30 gwr Exp $ */
/*
@@ -45,6 +45,7 @@
struct zsc_softc {
struct device zsc_dev; /* required first: base device */
+ void *zsc_softih; /* softintr cookie */
struct zs_chanstate zsc_cs[2]; /* channel A and B soft state */
};
diff --git a/sys/arch/sparc/sparc/amd7930intr.s b/sys/arch/sparc/sparc/amd7930intr.s
index 9f72e0151dd..89d2f1c858c 100644
--- a/sys/arch/sparc/sparc/amd7930intr.s
+++ b/sys/arch/sparc/sparc/amd7930intr.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: amd7930intr.s,v 1.9 2004/09/29 07:35:13 miod Exp $ */
+/* $OpenBSD: amd7930intr.s,v 1.10 2009/04/10 20:53:54 miod Exp $ */
/* $NetBSD: amd7930intr.s,v 1.10 1997/03/11 01:03:07 pk Exp $ */
/*
* Copyright (c) 1995 Rolf Grossmann.
@@ -48,6 +48,13 @@
#include <machine/psl.h>
#include <machine/asm.h>
+/*
+ * Note the following code hardcodes soft interrupt level 4, instead of
+ * picking the actual bits from the softintr cookie. We don't have enough
+ * free registers to be able to pick it easily, anyway; it's just not
+ * worth doing.
+ */
+
#define AUDIO_SET_SWINTR_4C \
sethi %hi(INTRREG_VA), %l5; \
ldub [%l5 + %lo(INTRREG_VA)], %l6; \
diff --git a/sys/arch/sparc/sparc/bsd_fdintr.s b/sys/arch/sparc/sparc/bsd_fdintr.s
index 4e75c341eea..18ceb7f52bf 100644
--- a/sys/arch/sparc/sparc/bsd_fdintr.s
+++ b/sys/arch/sparc/sparc/bsd_fdintr.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: bsd_fdintr.s,v 1.11 2004/09/29 07:35:13 miod Exp $ */
+/* $OpenBSD: bsd_fdintr.s,v 1.12 2009/04/10 20:53:54 miod Exp $ */
/* $NetBSD: bsd_fdintr.s,v 1.11 1997/04/07 21:00:36 pk Exp $ */
/*
@@ -43,6 +43,13 @@
#include <sparc/dev/fdreg.h>
#include <sparc/dev/fdvar.h>
+/*
+ * Note the following code hardcodes soft interrupt level 4, instead of
+ * picking the actual bits from the softintr cookie. We don't have enough
+ * free registers to be able to pick it easily, anyway; it's just not
+ * worth doing.
+ */
+
#define FD_SET_SWINTR_4C \
sethi %hi(INTRREG_VA), %l5; \
ldub [%l5 + %lo(INTRREG_VA)], %l6; \
diff --git a/sys/arch/sparc/sparc/genassym.cf b/sys/arch/sparc/sparc/genassym.cf
index 8b2286e5ebf..d5a934d5459 100644
--- a/sys/arch/sparc/sparc/genassym.cf
+++ b/sys/arch/sparc/sparc/genassym.cf
@@ -1,4 +1,4 @@
-# $OpenBSD: genassym.cf,v 1.20 2007/05/08 07:23:18 art Exp $
+# $OpenBSD: genassym.cf,v 1.21 2009/04/10 20:53:54 miod Exp $
# $NetBSD: genassym.cf,v 1.2 1997/06/28 19:59:04 pk Exp $
#
@@ -57,6 +57,7 @@ include <uvm/uvm_extern.h>
include <machine/pmap.h>
include <machine/cpu.h>
+include <machine/intr.h>
include <machine/oldmon.h>
include <machine/bsd_openprom.h>
@@ -97,6 +98,7 @@ struct uvmexp V_
member swtch
member INTR intrs
member faults
+member softs
# CPU info structure
struct cpu_softc
@@ -162,6 +164,10 @@ member ih_ipl
member ih_next
member IH_COUNT ih_count.ec_count
+# sintrhand fields.
+struct sintrhand
+member sih_pending
+
ifdef notyet
# ZSCC interrupt fields
struct zs_softc Z
diff --git a/sys/arch/sparc/sparc/intr.c b/sys/arch/sparc/sparc/intr.c
index 917f71766e0..d13183cd2a9 100644
--- a/sys/arch/sparc/sparc/intr.c
+++ b/sys/arch/sparc/sparc/intr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.c,v 1.31 2007/05/29 18:10:43 miod Exp $ */
+/* $OpenBSD: intr.c,v 1.32 2009/04/10 20:53:54 miod Exp $ */
/* $NetBSD: intr.c,v 1.20 1997/07/29 09:42:03 fair Exp $ */
/*
@@ -45,6 +45,7 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
+#include <sys/malloc.h>
#include <uvm/uvm_extern.h>
@@ -75,8 +76,13 @@
#include <netinet6/ip6_var.h>
#endif
+extern void raise(int, int);
+
+void ih_insert(struct intrhand **, struct intrhand *);
+void ih_remove(struct intrhand **, struct intrhand *);
+
+void softnet(void *);
void strayintr(struct clockframe *);
-int soft01intr(void *);
/*
* Stray interrupt handler. Clear it if possible.
@@ -103,46 +109,6 @@ strayintr(fp)
static struct intrhand level10 = { clockintr, NULL, (IPL_CLOCK << 8) };
static struct intrhand level14 = { statintr, NULL, (IPL_STATCLOCK << 8) };
-union sir sir;
-int netisr;
-
-/*
- * Level 1 software interrupt (could also be SBus level 1 interrupt).
- * Three possible reasons:
- * ROM console input needed
- * Network software interrupt
- * Soft clock interrupt
- */
-int
-soft01intr(fp)
- void *fp;
-{
- if (sir.sir_any) {
- if (sir.sir_which[SIR_NET]) {
- int n;
-
- sir.sir_which[SIR_NET] = 0;
- while ((n = netisr) != 0) {
- atomic_clearbits_int(&netisr, n);
-
-#define DONETISR(bit, fn) \
- do { \
- if (n & (1 << bit)) \
- fn(); \
- } while (0)
-
-#include <net/netisr_dispatch.h>
-
-#undef DONETISR
- }
- }
- if (sir.sir_which[SIR_CLOCK]) {
- sir.sir_which[SIR_CLOCK] = 0;
- softclock();
- }
- }
- return (1);
-}
#if defined(SUN4M)
void nmi_hard(void);
@@ -207,20 +173,17 @@ nmi_hard()
}
#endif
-static struct intrhand level01 = { soft01intr, NULL, (IPL_SOFTINT << 8) };
-
void
intr_init()
{
- level01.ih_vec = level01.ih_ipl >> 8;
- evcount_attach(&level01.ih_count, "softintr", &level01.ih_vec,
- &evcount_intr);
level10.ih_vec = level10.ih_ipl >> 8;
evcount_attach(&level10.ih_count, "clock", &level10.ih_vec,
&evcount_intr);
level14.ih_vec = level14.ih_ipl >> 8;
evcount_attach(&level14.ih_count, "prof", &level14.ih_vec,
&evcount_intr);
+
+ softnet_ih = softintr_establish(IPL_SOFTNET, softnet, NULL);
}
/*
@@ -230,7 +193,7 @@ intr_init()
*/
struct intrhand *intrhand[15] = {
NULL, /* 0 = error */
- &level01, /* 1 = software level 1 + SBus */
+ NULL, /* 1 = software level 1 + SBus */
NULL, /* 2 = SBus level 2 (4m: SBus L1) */
NULL, /* 3 = SCSI + DMA + SBus level 3 (4m: L2,lpt)*/
NULL, /* 4 = software level 4 (tty softint) (scsi) */
@@ -246,6 +209,44 @@ struct intrhand *intrhand[15] = {
&level14, /* 14 = counter 1 = profiling timer */
};
+/*
+ * Soft interrupts use a separate set of handler chains.
+ * This is necessary since soft interrupt handlers do not return a value
+ * and therefore can not be mixed with hardware interrupt handlers on a
+ * shared handler chain.
+ */
+struct intrhand *sintrhand[15];
+
+void
+ih_insert(struct intrhand **head, struct intrhand *ih)
+{
+ struct intrhand **p, *q;
+
+ /*
+ * This is O(N^2) for long chains, but chains are never long
+ * and we do want to preserve order.
+ */
+ for (p = head; (q = *p) != NULL; p = &q->ih_next)
+ continue;
+ *p = ih;
+ ih->ih_next = NULL;
+}
+
+void
+ih_remove(struct intrhand **head, struct intrhand *ih)
+{
+ struct intrhand **p, *q;
+
+ for (p = head; (q = *p) != ih; p = &q->ih_next)
+ continue;
+ if (q == NULL)
+ panic("ih_remove: intrhand %p (fn %p arg %p) not found from %p",
+ ih, ih->ih_fun, ih->ih_arg, head);
+
+ *p = q->ih_next;
+ q->ih_next = NULL;
+}
+
static int fastvec; /* marks fast vectors (see below) */
static struct {
int (*cb)(void *);
@@ -266,7 +267,6 @@ intr_establish(level, ih, ipl_block, name)
int ipl_block;
const char *name;
{
- struct intrhand **p, *q;
#ifdef DIAGNOSTIC
struct trapvec *tv;
int displ;
@@ -309,8 +309,8 @@ intr_establish(level, ih, ipl_block, name)
if (fastvec & (1 << level)) {
if (fastvec_share[level].cb == NULL ||
(*fastvec_share[level].cb)(fastvec_share[level].data) != 0)
- panic("intr_establish: level %d interrupt tied to fast vector",
- level);
+ panic("intr_establish: level %d interrupt tied to"
+ " unremovable fast vector", level);
}
#ifdef DIAGNOSTIC
@@ -331,14 +331,7 @@ intr_establish(level, ih, ipl_block, name)
I_MOVi(I_L3, level), I_BA(0, displ), I_RDPSR(I_L0));
}
#endif
- /*
- * This is O(N^2) for long chains, but chains are never long
- * and we do want to preserve order.
- */
- for (p = &intrhand[level]; (q = *p) != NULL; p = &q->ih_next)
- continue;
- *p = ih;
- ih->ih_next = NULL;
+ ih_insert(&intrhand[level], ih);
splx(s);
}
@@ -369,10 +362,12 @@ intr_fasttrap(int level, void (*vec)(void), int (*share)(void *), void *cbdata)
s = splhigh();
/*
- * If this interrupt is already being handled, fail; the caller will
- * either panic or try to register a slow (shareable) trap.
+ * If this interrupt is already being handled, or if it is also used
+ * for software interrupts, we fail; the caller will either panic or
+ * try to register a slow (shareable) trap.
*/
- if ((fastvec & (1 << level)) != 0 || intrhand[level] != NULL) {
+ if ((fastvec & (1 << level)) != 0 ||
+ intrhand[level] != NULL || sintrhand[level] != NULL) {
splx(s);
return (EBUSY);
}
@@ -448,6 +443,135 @@ intr_fastuntrap(int level)
splx(s);
}
+void
+softintr_disestablish(void *arg)
+{
+ struct sintrhand *sih = (struct sintrhand *)arg;
+
+ ih_remove(&sintrhand[sih->sih_ipl], &sih->sih_ih);
+ free(sih, M_DEVBUF);
+}
+
+void *
+softintr_establish(int level, void (*fn)(void *), void *arg)
+{
+ struct sintrhand *sih;
+ struct intrhand *ih;
+ int ipl, hw;
+ int s;
+
+ /*
+ * On a sun4m, the interrupt level is stored unmodified
+ * to be passed to raise().
+ * On a sun4 or sun4c, the appropriate bit to set
+ * in the interrupt enable register is stored, to be
+ * passed to ienab_bis().
+ */
+ ipl = hw = level;
+#if defined(SUN4) || defined(SUN4C)
+ if (CPU_ISSUN4OR4C) {
+ /*
+ * Select the most suitable of the three available
+ * softintr levels.
+ */
+ if (level < 4) {
+ ipl = 1;
+ hw = IE_L1;
+ } else if (level < 6) {
+ ipl = 4;
+ hw = IE_L4;
+ } else {
+ ipl = 6;
+ hw = IE_L6;
+ }
+ }
+#endif
+
+ sih = (struct sintrhand *)malloc(sizeof *sih, M_DEVBUF, M_ZERO);
+ if (sih == NULL)
+ return NULL;
+
+ sih->sih_ipl = ipl;
+ sih->sih_hw = hw;
+
+ ih = &sih->sih_ih;
+ ih->ih_fun = (int (*)(void *))fn;
+ ih->ih_arg = arg;
+ /*
+ * We store the ipl pre-shifted so that we can avoid one instruction
+ * in the interrupt handlers.
+ */
+ ih->ih_ipl = level << 8;
+
+ s = splhigh();
+
+ /*
+ * Check if this interrupt is already being handled by a fast trap.
+ * If so, attempt to change it back to a regular (thus) shareable
+ * trap.
+ */
+ if (fastvec & (1 << ipl)) {
+ if (fastvec_share[ipl].cb == NULL ||
+ (*fastvec_share[ipl].cb)(fastvec_share[ipl].data) != 0)
+ panic("softintr_establish: level %d interrupt tied to"
+ " unremovable fast vector", ipl);
+ }
+
+ ih_insert(&sintrhand[ipl], ih);
+ splx(s);
+
+ return sih;
+}
+
+void
+softintr_schedule(void *arg)
+{
+ struct sintrhand *sih = (struct sintrhand *)arg;
+ int s;
+
+ s = splhigh();
+ if (sih->sih_pending == 0) {
+ sih->sih_pending++;
+
+#if defined(SUN4M)
+ if (CPU_ISSUN4M)
+ raise(0, sih->sih_hw);
+#endif
+#if defined(SUN4) || defined(SUN4C)
+ if (CPU_ISSUN4OR4C)
+ ienab_bis(sih->sih_hw);
+#endif
+#if defined(solbourne)
+ if (CPU_ISKAP)
+ ienab_bis(sih->sih_hw);
+#endif
+ }
+ splx(s);
+}
+
+void *softnet_ih;
+int netisr;
+
+void
+softnet(void *arg)
+{
+ int n;
+
+ while ((n = netisr) != 0) {
+ atomic_clearbits_int(&netisr, n);
+
+#define DONETISR(bit, fn) \
+ do { \
+ if (n & (1 << bit)) \
+ fn(); \
+ } while (0)
+
+#include <net/netisr_dispatch.h>
+
+#undef DONETISR
+ }
+}
+
#ifdef DIAGNOSTIC
void
splassert_check(int wantipl, const char *func)
@@ -464,4 +588,3 @@ splassert_check(int wantipl, const char *func)
}
}
#endif
-
diff --git a/sys/arch/sparc/sparc/intreg.h b/sys/arch/sparc/sparc/intreg.h
index f6709559a14..436977f41e4 100644
--- a/sys/arch/sparc/sparc/intreg.h
+++ b/sys/arch/sparc/sparc/intreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: intreg.h,v 1.8 2006/05/29 20:40:01 miod Exp $ */
+/* $OpenBSD: intreg.h,v 1.9 2009/04/10 20:53:54 miod Exp $ */
/* $NetBSD: intreg.h,v 1.6 1997/07/22 20:19:10 pk Exp $ */
/*
@@ -60,14 +60,6 @@
* be cleared in software. This is done in locore.s. The ALLIE bit must
* be cleared to clear asynchronous memory error (level 15) interrupts.
*/
-#ifdef solbourne
-#define IE_L14 14
-#define IE_L10 10
-#define IE_L8 8
-#define IE_L6 6
-#define IE_L4 4
-#define IE_L1 1
-#else
#define IE_L14 0x80 /* enable level 14 (counter 1) interrupts */
#define IE_L10 0x20 /* enable level 10 (counter 0) interrupts */
#define IE_L8 0x10 /* enable level 8 interrupts */
@@ -75,7 +67,6 @@
#define IE_L4 0x04 /* request software level 4 interrupt */
#define IE_L1 0x02 /* request software level 1 interrupt */
#define IE_ALLIE 0x01 /* enable interrupts */
-#endif
#ifndef _LOCORE
void ienab_bis(int bis); /* set given bits */
diff --git a/sys/arch/sparc/sparc/locore.s b/sys/arch/sparc/sparc/locore.s
index 7b757b773db..9106f791769 100644
--- a/sys/arch/sparc/sparc/locore.s
+++ b/sys/arch/sparc/sparc/locore.s
@@ -1,4 +1,4 @@
-/* $OpenBSD: locore.s,v 1.83 2009/03/27 23:21:18 miod Exp $ */
+/* $OpenBSD: locore.s,v 1.84 2009/04/10 20:53:54 miod Exp $ */
/* $NetBSD: locore.s,v 1.73 1997/09/13 20:36:48 pk Exp $ */
/*
@@ -2330,15 +2330,23 @@ return_from_syscall:
* this contains the psr, pc, npc, and interrupt level.
*/
softintr_sun44c:
+ /*
+ * Entry point for level 1, 4 or 6 interrupts on sun4/sun4c
+ * which may be software interrupts. Check the interrupt
+ * register to see whether we're dealing software or hardware
+ * interrupt.
+ */
sethi %hi(INTRREG_VA), %l6
ldub [%l6 + %lo(INTRREG_VA)], %l5
- andn %l5, %l4, %l5
+ btst %l5, %l4 ! is IE_L{1,4,6} set?
+ bz sparc_interrupt_common ! if not, must be a hw intr
+ andn %l5, %l4, %l5 ! clear soft intr bit
stb %l5, [%l6 + %lo(INTRREG_VA)]
softintr_common:
INTR_SETUP(-CCFSZ-80)
std %g2, [%sp + CCFSZ + 24] ! save registers
- INCR(_C_LABEL(uvmexp)+V_INTR) ! cnt.v_intr++; (clobbers %o0,%o1)
+ INCR(_C_LABEL(uvmexp)+V_SOFTS) ! uvmexp.softs++; (clobbers %o0,%o1)
mov %g1, %l7
rd %y, %l6
std %g4, [%sp + CCFSZ + 32]
@@ -2351,28 +2359,29 @@ softintr_common:
std %l0, [%sp + CCFSZ + 0] ! set up intrframe/clockframe
sll %l3, 2, %l5
std %l2, [%sp + CCFSZ + 8]
- set _C_LABEL(intrhand), %l4 ! %l4 = intrhand[intlev];
+ set _C_LABEL(sintrhand), %l4 ! %l4 = sintrhand[intlev];
ld [%l4 + %l5], %l4
b 3f
st %fp, [%sp + CCFSZ + 16]
-1: rd %psr, %o1
+1: ld [%l4 + SIH_PENDING], %o0
+ tst %o0
+ bz 2f ! if (ih->sih_pending != 0)
+ st %g0, [%l4 + SIH_PENDING]
+ rd %psr, %o1
ld [%l4 + IH_IPL], %o0
and %o1, ~PSR_PIL, %o1
wr %o1, %o0, %psr
- ld [%l4 + IH_ARG], %o0
ld [%l4 + IH_FUN], %o1
- tst %o0
- bz,a 2f
- add %sp, CCFSZ, %o0
-2: jmpl %o1, %o7 ! (void)(*ih->ih_fun)(...)
- nop
+ jmpl %o1, %o7 ! (void)(*ih->ih_fun)(...)
+ ld [%l4 + IH_ARG], %o0
mov %l4, %l3
ldd [%l3 + IH_COUNT], %l4
inccc %l5
addx %l4, 0, %l4
std %l4, [%l3 + IH_COUNT]
- ld [%l3 + IH_NEXT], %l4 ! and ih = ih->ih_next
+ mov %l3, %l4
+2: ld [%l4 + IH_NEXT], %l4 ! and ih = ih->ih_next
3: tst %l4 ! while ih != NULL
bnz 1b
nop
@@ -2393,17 +2402,19 @@ softintr_common:
_C_LABEL(sparc_interrupt4m):
mov 1, %l4
sethi %hi(ICR_PI_PEND), %l5
- ld [%l5 + %lo(ICR_PI_PEND)], %l5
- sll %l4, %l3, %l4
- andcc %l5, %l4, %g0
- bne _C_LABEL(sparc_interrupt_common)
+ ld [%l5 + %lo(ICR_PI_PEND)], %l5 ! get pending interrupts
+ sll %l4, %l3, %l4 ! hw intr bits are in the lower halfword
+
+ btst %l4, %l5 ! has pending hw intr at this level?
+ bnz sparc_interrupt_common
nop
- ! a soft interrupt; clear bit in interrupt-pending register
- ! XXX - this is CPU0's register set.
+ ! both softint pending and clear bits are in upper halfwords of
+ ! their respective registers so shift the test bit in %l4 up there
+ sll %l4, 16, %l4
+
sethi %hi(ICR_PI_CLR), %l6
- sll %l4, 16, %l5
- st %l5, [%l6 + %lo(ICR_PI_CLR)]
+ st %l4, [%l6 + %lo(ICR_PI_CLR)] ! ack soft intr
/* Drain hw reg; might be necessary for Ross CPUs */
sethi %hi(ICR_PI_PEND), %l6
ld [%l6 + %lo(ICR_PI_PEND)], %g0
@@ -2415,7 +2426,7 @@ _C_LABEL(sparc_interrupt4m):
.globl _C_LABEL(sparc_interrupt44c)
_C_LABEL(sparc_interrupt44c):
#endif
-_C_LABEL(sparc_interrupt_common):
+sparc_interrupt_common:
INTR_SETUP(-CCFSZ-80)
std %g2, [%sp + CCFSZ + 24] ! save registers
INCR(_C_LABEL(uvmexp)+V_INTR) ! cnt.v_intr++; (clobbers %o0,%o1)
@@ -3850,8 +3861,7 @@ Lgandul: nop
nop
/*
- * Call main. This returns to us after loading /sbin/init into
- * user space. (If the exec fails, main() does not return.)
+ * Call main.
*/
call _C_LABEL(main)
clr %o0 ! our frame arg is ignored