aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMaxime Henrion <mux@FreeBSD.org>2004-06-04 16:42:33 +0000
committerMaxime Henrion <mux@FreeBSD.org>2004-06-04 16:42:33 +0000
commit05478063264e330f29e642d38b4f710f3bf28058 (patch)
treea60010977039484a8d6180ce6aa839375d5d46c2 /sys/dev
parent2140d01b277fa2ab698e66dda69e434f0be7bd13 (diff)
Notes
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/sound/pci/emu10k1.c74
1 files changed, 46 insertions, 28 deletions
diff --git a/sys/dev/sound/pci/emu10k1.c b/sys/dev/sound/pci/emu10k1.c
index e017335b3bf2..bf4c2984408b 100644
--- a/sys/dev/sound/pci/emu10k1.c
+++ b/sys/dev/sound/pci/emu10k1.c
@@ -1061,11 +1061,12 @@ CHANNEL_DECLARE(emurchan);
/* -------------------------------------------------------------------- */
/* The interrupt handler */
static void
-emu_intr(void *p)
+emu_intr(void *data)
{
- struct sc_info *sc = (struct sc_info *)p;
+ struct sc_info *sc = data;
u_int32_t stat, ack, i, x;
+ snd_mtxlock(sc->lock);
while (1) {
stat = emu_rd(sc, IPR, 4);
if (stat == 0)
@@ -1073,35 +1074,18 @@ emu_intr(void *p)
ack = 0;
/* process irq */
- if (stat & IPR_INTERVALTIMER) {
+ if (stat & IPR_INTERVALTIMER)
ack |= IPR_INTERVALTIMER;
- x = 0;
- for (i = 0; i < sc->nchans; i++) {
- if (sc->pch[i].run) {
- x = 1;
- chn_intr(sc->pch[i].channel);
- }
- }
- if (x == 0)
- emu_enatimer(sc, 0);
- }
-
- if (stat & (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL)) {
+ if (stat & (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL))
ack |= stat & (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL);
- if (sc->rch[0].channel)
- chn_intr(sc->rch[0].channel);
- }
- if (stat & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL)) {
+
+ if (stat & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL))
ack |= stat & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL);
- if (sc->rch[1].channel)
- chn_intr(sc->rch[1].channel);
- }
- if (stat & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL)) {
+
+ if (stat & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL))
ack |= stat & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL);
- if (sc->rch[2].channel)
- chn_intr(sc->rch[2].channel);
- }
+
if (stat & IPR_PCIERROR) {
ack |= IPR_PCIERROR;
device_printf(sc->dev, "pci error\n");
@@ -1116,10 +1100,44 @@ emu_intr(void *p)
}
if (stat & ~ack)
- device_printf(sc->dev, "dodgy irq: %x (harmless)\n", stat & ~ack);
+ device_printf(sc->dev, "dodgy irq: %x (harmless)\n",
+ stat & ~ack);
emu_wr(sc, IPR, stat, 4);
+
+ if (ack) {
+ snd_mtxunlock(sc->lock);
+
+ if (ack & IPR_INTERVALTIMER) {
+ x = 0;
+ for (i = 0; i < sc->nchans; i++) {
+ if (sc->pch[i].run) {
+ x = 1;
+ chn_intr(sc->pch[i].channel);
+ }
+ }
+ if (x == 0)
+ emu_enatimer(sc, 0);
+ }
+
+
+ if (ack & (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL)) {
+ if (sc->rch[0].channel)
+ chn_intr(sc->rch[0].channel);
+ }
+ if (ack & (IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL)) {
+ if (sc->rch[1].channel)
+ chn_intr(sc->rch[1].channel);
+ }
+ if (ack & (IPR_MICBUFFULL | IPR_MICBUFHALFFULL)) {
+ if (sc->rch[2].channel)
+ chn_intr(sc->rch[2].channel);
+ }
+
+ snd_mtxlock(sc->lock);
+ }
}
+ snd_mtxunlock(sc->lock);
}
/* -------------------------------------------------------------------- */
@@ -1944,7 +1962,7 @@ emu_pci_attach(device_t dev)
sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i,
RF_ACTIVE | RF_SHAREABLE);
if (!sc->irq ||
- snd_setup_intr(dev, sc->irq, 0, emu_intr, sc, &sc->ih)) {
+ snd_setup_intr(dev, sc->irq, INTR_MPSAFE, emu_intr, sc, &sc->ih)) {
device_printf(dev, "unable to map interrupt\n");
goto bad;
}