summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/isa/sbc.c
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2001-03-24 23:10:29 +0000
committercg <cg@FreeBSD.org>2001-03-24 23:10:29 +0000
commit11442775804b9679c2c761846072b171d2507840 (patch)
tree2c8e61a99c9323312c5656a92269f975ac6b0c12 /sys/dev/sound/isa/sbc.c
parentfb291ae7e5515cf63d4544d3eeff0a4c791e3cad (diff)
downloadFreeBSD-src-11442775804b9679c2c761846072b171d2507840.zip
FreeBSD-src-11442775804b9679c2c761846072b171d2507840.tar.gz
mega-commit.
this introduces a new buffering mechanism which results in dramatic simplification of the channel manager. as several structures have changed, we take the opportunity to move their definitions into the source files where they are used, make them private and de-typedef them. the sound drivers are updated to use snd_setup_intr instead of bus_setup_intr, and to comply with the de-typedefed structures. the ac97, mixer and channel layers have been updated with finegrained locking, as have some drivers- not all though. the rest will follow soon.
Diffstat (limited to 'sys/dev/sound/isa/sbc.c')
-rw-r--r--sys/dev/sound/isa/sbc.c61
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 *
OpenPOWER on IntegriCloud