diff options
Diffstat (limited to 'sys/dev/sound/isa/sbc.c')
-rw-r--r-- | sys/dev/sound/isa/sbc.c | 61 |
1 files changed, 51 insertions, 10 deletions
diff --git a/sys/dev/sound/isa/sbc.c b/sys/dev/sound/isa/sbc.c index 8629554..2129161 100644 --- a/sys/dev/sound/isa/sbc.c +++ b/sys/dev/sound/isa/sbc.c @@ -35,9 +35,12 @@ #define DRQ_MAX 2 #define INTR_MAX 2 +struct sbc_softc; + struct sbc_ihl { driver_intr_t *intr[INTR_MAX]; void *intr_arg[INTR_MAX]; + struct sbc_softc *parent; }; /* Here is the parameter structure per a device. */ @@ -61,6 +64,8 @@ struct sbc_softc { void *ih[IRQ_MAX]; + void *lock; + u_int32_t bd_ver; }; @@ -106,6 +111,30 @@ static int sb_cmd(struct resource *io, u_char val); static u_int sb_get_byte(struct resource *io); static void sb_setmixer(struct resource *io, u_int port, u_int value); +static void +sbc_lockinit(struct sbc_softc *scp) +{ + scp->lock = snd_mtxcreate(device_get_nameunit(scp->dev)); +} + +static void +sbc_lockdestroy(struct sbc_softc *scp) +{ + snd_mtxfree(scp->lock); +} + +void +sbc_lock(struct sbc_softc *scp) +{ + snd_mtxlock(scp->lock); +} + +void +sbc_unlock(struct sbc_softc *scp) +{ + snd_mtxunlock(scp->lock); +} + static int sb_rd(struct resource *io, int reg) { @@ -311,6 +340,7 @@ sbc_attach(device_t dev) scp = device_get_softc(dev); bzero(scp, sizeof(*scp)); scp->dev = dev; + sbc_lockinit(scp); err = "alloc_resource"; if (alloc_resource(scp)) goto bad; @@ -396,7 +426,8 @@ sbc_attach(device_t dev) err = "setup_intr"; for (i = 0; i < IRQ_MAX; i++) { - if (bus_setup_intr(dev, scp->irq[i], INTR_TYPE_TTY, sbc_intr, &scp->ihl[i], &scp->ih[i])) + scp->ihl[i].parent = scp; + if (snd_setup_intr(dev, scp->irq[i], INTR_MPSAFE, sbc_intr, &scp->ihl[i], &scp->ih[i])) goto bad; } @@ -439,10 +470,12 @@ sbc_detach(device_t dev) { struct sbc_softc *scp = device_get_softc(dev); + sbc_lock(scp); device_delete_child(dev, scp->child_midi2); device_delete_child(dev, scp->child_midi1); device_delete_child(dev, scp->child_pcm); release_resource(scp); + sbc_lockdestroy(scp); return bus_generic_detach(dev); } @@ -452,11 +485,13 @@ sbc_intr(void *p) struct sbc_ihl *ihl = p; int i; + /* sbc_lock(ihl->parent); */ i = 0; while (i < INTR_MAX) { if (ihl->intr[i] != NULL) ihl->intr[i](ihl->intr_arg[i]); i++; } + /* sbc_unlock(ihl->parent); */ } static int @@ -466,24 +501,27 @@ sbc_setup_intr(device_t dev, device_t child, struct resource *irq, { struct sbc_softc *scp = device_get_softc(dev); struct sbc_ihl *ihl = NULL; - int i; + int i, ret; + sbc_lock(scp); i = 0; while (i < IRQ_MAX) { if (irq == scp->irq[i]) ihl = &scp->ihl[i]; i++; } - if (ihl == NULL) return (EINVAL); + ret = 0; + if (ihl == NULL) ret = EINVAL; i = 0; - while (i < INTR_MAX) { + while ((ret == 0) && (i < INTR_MAX)) { if (ihl->intr[i] == NULL) { ihl->intr[i] = intr; ihl->intr_arg[i] = arg; *cookiep = &ihl->intr[i]; - return 0; + ret = -1; } else i++; } - return (EINVAL); + sbc_unlock(scp); + return (ret > 0)? EINVAL : 0; } static int @@ -492,23 +530,26 @@ sbc_teardown_intr(device_t dev, device_t child, struct resource *irq, { struct sbc_softc *scp = device_get_softc(dev); struct sbc_ihl *ihl = NULL; - int i; + int i, ret; + sbc_lock(scp); i = 0; while (i < IRQ_MAX) { if (irq == scp->irq[i]) ihl = &scp->ihl[i]; i++; } - if (ihl == NULL) return (EINVAL); + ret = 0; + if (ihl == NULL) ret = EINVAL; i = 0; - while (i < INTR_MAX) { + while ((ret == 0) && (i < INTR_MAX)) { if (cookie == &ihl->intr[i]) { ihl->intr[i] = NULL; ihl->intr_arg[i] = NULL; return 0; } else i++; } - return (EINVAL); + sbc_unlock(scp); + return (ret > 0)? EINVAL : 0; } static struct resource * |