diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2009-04-10 20:53:55 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2009-04-10 20:53:55 +0000 |
commit | b87d8aad6f1343a2b36ff29986060ba762a45fbb (patch) | |
tree | 21dd950980778036b5e89b97f8fd841b4ff956ae /sys | |
parent | 2d152c27f3b1a0ab189abf8353c05e196498d89e (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@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/sparc/dev/amd7930.c | 38 | ||||
-rw-r--r-- | sys/arch/sparc/dev/amd7930var.h | 3 | ||||
-rw-r--r-- | sys/arch/sparc/dev/fd.c | 48 | ||||
-rw-r--r-- | sys/arch/sparc/dev/magma.c | 41 | ||||
-rw-r--r-- | sys/arch/sparc/dev/magmareg.h | 6 | ||||
-rw-r--r-- | sys/arch/sparc/dev/spif.c | 38 | ||||
-rw-r--r-- | sys/arch/sparc/dev/spifvar.h | 4 | ||||
-rw-r--r-- | sys/arch/sparc/dev/zs.c | 64 | ||||
-rw-r--r-- | sys/arch/sparc/include/_types.h | 5 | ||||
-rw-r--r-- | sys/arch/sparc/include/cpu.h | 59 | ||||
-rw-r--r-- | sys/arch/sparc/include/intr.h | 102 | ||||
-rw-r--r-- | sys/arch/sparc/include/psl.h | 9 | ||||
-rw-r--r-- | sys/arch/sparc/include/z8530var.h | 3 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/amd7930intr.s | 9 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/bsd_fdintr.s | 9 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/genassym.cf | 8 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/intr.c | 249 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/intreg.h | 11 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/locore.s | 56 |
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 |