summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/pcm/dsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/sound/pcm/dsp.c')
-rw-r--r--sys/dev/sound/pcm/dsp.c112
1 files changed, 70 insertions, 42 deletions
diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c
index 94b1274..d1ae32f 100644
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -22,8 +22,6 @@
* 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.
- *
- * $FreeBSD$
*/
#include <sys/param.h>
@@ -31,6 +29,8 @@
#include <dev/sound/pcm/sound.h>
+SND_DECLARE_FILE("$FreeBSD$");
+
#define OLDPCM_IOCTL
static d_open_t dsp_open;
@@ -75,6 +75,34 @@ dsp_get_info(dev_t dev)
return d;
}
+static u_int32_t
+dsp_get_flags(dev_t dev)
+{
+ device_t bdev;
+ int unit;
+
+ unit = PCMUNIT(dev);
+ if (unit >= devclass_get_maxunit(pcm_devclass))
+ return 0xffffffff;
+ bdev = devclass_get_device(pcm_devclass, unit);
+
+ return pcm_getflags(bdev);
+}
+
+static void
+dsp_set_flags(dev_t dev, u_int32_t flags)
+{
+ device_t bdev;
+ int unit;
+
+ unit = PCMUNIT(dev);
+ if (unit >= devclass_get_maxunit(pcm_devclass))
+ return;
+ bdev = devclass_get_device(pcm_devclass, unit);
+
+ pcm_setflags(bdev, flags);
+}
+
/*
* return the channels channels associated with an open device instance.
* set the priority if the device is simplex and one direction (only) is
@@ -85,37 +113,41 @@ static int
getchns(dev_t dev, struct pcm_channel **rdch, struct pcm_channel **wrch, u_int32_t prio)
{
struct snddev_info *d;
+ u_int32_t flags;
+ flags = dsp_get_flags(dev);
d = dsp_get_info(dev);
- snd_mtxlock(d->lock);
- d->inprog++;
- KASSERT((d->flags & SD_F_PRIO_SET) != SD_F_PRIO_SET, \
+ pcm_lock(d);
+ pcm_inprog(d, 1);
+ KASSERT((flags & SD_F_PRIO_SET) != SD_F_PRIO_SET, \
("getchns: read and write both prioritised"));
- if ((d->flags & SD_F_PRIO_SET) == 0 && (prio != (SD_F_PRIO_RD | SD_F_PRIO_WR)))
- d->flags |= prio & (SD_F_PRIO_RD | SD_F_PRIO_WR);
+ if ((flags & SD_F_PRIO_SET) == 0 && (prio != (SD_F_PRIO_RD | SD_F_PRIO_WR))) {
+ flags |= prio & (SD_F_PRIO_RD | SD_F_PRIO_WR);
+ dsp_set_flags(dev, flags);
+ }
*rdch = dev->si_drv1;
*wrch = dev->si_drv2;
- if ((d->flags & SD_F_SIMPLEX) && (d->flags & SD_F_PRIO_SET)) {
+ if ((flags & SD_F_SIMPLEX) && (flags & SD_F_PRIO_SET)) {
if (prio) {
- if (*rdch && d->flags & SD_F_PRIO_WR) {
+ if (*rdch && flags & SD_F_PRIO_WR) {
dev->si_drv1 = NULL;
- *rdch = d->fakechan;
- } else if (*wrch && d->flags & SD_F_PRIO_RD) {
+ *rdch = pcm_getfakechan(d);
+ } else if (*wrch && flags & SD_F_PRIO_RD) {
dev->si_drv2 = NULL;
- *wrch = d->fakechan;
+ *wrch = pcm_getfakechan(d);
}
}
- d->fakechan->flags |= CHN_F_BUSY;
+ pcm_getfakechan(d)->flags |= CHN_F_BUSY;
}
+ pcm_unlock(d);
- if (*rdch && *rdch != d->fakechan && (prio & SD_F_PRIO_RD))
+ if (*rdch && *rdch != pcm_getfakechan(d) && (prio & SD_F_PRIO_RD))
CHN_LOCK(*rdch);
- if (*wrch && *wrch != d->fakechan && (prio & SD_F_PRIO_WR))
+ if (*wrch && *wrch != pcm_getfakechan(d) && (prio & SD_F_PRIO_WR))
CHN_LOCK(*wrch);
- snd_mtxunlock(d->lock);
return 0;
}
@@ -127,13 +159,13 @@ relchns(dev_t dev, struct pcm_channel *rdch, struct pcm_channel *wrch, u_int32_t
struct snddev_info *d;
d = dsp_get_info(dev);
- if (wrch && wrch != d->fakechan && (prio & SD_F_PRIO_WR))
+ if (wrch && wrch != pcm_getfakechan(d) && (prio & SD_F_PRIO_WR))
CHN_UNLOCK(wrch);
- if (rdch && rdch != d->fakechan && (prio & SD_F_PRIO_RD))
+ if (rdch && rdch != pcm_getfakechan(d) && (prio & SD_F_PRIO_RD))
CHN_UNLOCK(rdch);
- snd_mtxlock(d->lock);
- d->inprog--;
- snd_mtxunlock(d->lock);
+ pcm_lock(d);
+ pcm_inprog(d, -1);
+ pcm_unlock(d);
}
static int
@@ -172,10 +204,10 @@ dsp_open(dev_t i_dev, int flags, int mode, struct proc *p)
}
/* lock snddev so nobody else can monkey with it */
- snd_mtxlock(d->lock);
- if ((d->flags & SD_F_SIMPLEX) && (i_dev->si_drv1 || i_dev->si_drv2)) {
+ pcm_lock(d);
+ if ((dsp_get_flags(i_dev) & SD_F_SIMPLEX) && (i_dev->si_drv1 || i_dev->si_drv2)) {
/* simplex device, already open, exit */
- snd_mtxunlock(d->lock);
+ pcm_unlock(d);
splx(s);
return EBUSY;
}
@@ -191,14 +223,14 @@ dsp_open(dev_t i_dev, int flags, int mode, struct proc *p)
rdch = pcm_chnalloc(d, PCMDIR_REC, p->p_pid);
if (!rdch) {
/* no channel available, exit */
- snd_mtxunlock(d->lock);
+ pcm_unlock(d);
splx(s);
return EBUSY;
}
/* got a channel, already locked for us */
} else {
/* already open for read, exit */
- snd_mtxunlock(d->lock);
+ pcm_unlock(d);
splx(s);
return EBUSY;
}
@@ -216,7 +248,7 @@ dsp_open(dev_t i_dev, int flags, int mode, struct proc *p)
pcm_chnrelease(rdch);
}
/* exit */
- snd_mtxunlock(d->lock);
+ pcm_unlock(d);
splx(s);
return EBUSY;
}
@@ -228,7 +260,7 @@ dsp_open(dev_t i_dev, int flags, int mode, struct proc *p)
pcm_chnrelease(rdch);
}
/* exit */
- snd_mtxunlock(d->lock);
+ pcm_unlock(d);
splx(s);
return EBUSY;
}
@@ -236,7 +268,7 @@ dsp_open(dev_t i_dev, int flags, int mode, struct proc *p)
i_dev->si_drv1 = rdch;
i_dev->si_drv2 = wrch;
- snd_mtxunlock(d->lock);
+ pcm_unlock(d);
/* finished with snddev, new channels still locked */
/* bump refcounts, reset and unlock any channels that we just opened */
@@ -276,7 +308,7 @@ dsp_close(dev_t i_dev, int flags, int mode, struct proc *p)
s = spltty();
d = dsp_get_info(i_dev);
- snd_mtxlock(d->lock);
+ pcm_lock(d);
rdch = i_dev->si_drv1;
wrch = i_dev->si_drv2;
@@ -298,21 +330,21 @@ dsp_close(dev_t i_dev, int flags, int mode, struct proc *p)
}
}
if (exit) {
- snd_mtxunlock(d->lock);
+ pcm_unlock(d);
splx(s);
return 0;
}
/* both refcounts are zero, abort and release */
- if (d->fakechan)
- d->fakechan->flags = 0;
+ if (pcm_getfakechan(d))
+ pcm_getfakechan(d)->flags = 0;
i_dev->si_drv1 = NULL;
i_dev->si_drv2 = NULL;
- d->flags &= ~SD_F_TRANSIENT;
- snd_mtxunlock(d->lock);
+ dsp_set_flags(i_dev, dsp_get_flags(i_dev) & ~SD_F_TRANSIENT);
+ pcm_unlock(d);
if (rdch) {
chn_abort(rdch); /* won't sleep */
@@ -425,10 +457,6 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc *p)
if (kill & 2)
rdch = NULL;
- /*
- * all routines are called with int. blocked. Make sure that
- * ints are re-enabled when calling slow or blocking functions!
- */
switch(cmd) {
#ifdef OLDPCM_IOCTL
/*
@@ -527,8 +555,8 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc *p)
p->formats = (rdch? chn_getformats(rdch) : 0xffffffff) &
(wrch? chn_getformats(wrch) : 0xffffffff);
if (rdch && wrch)
- p->formats |= (d->flags & SD_F_SIMPLEX)? 0 : AFMT_FULLDUPLEX;
- pdev = makedev(SND_CDEV_MAJOR, PCMMKMINOR(device_get_unit(d->dev), SND_DEV_CTL, 0));
+ p->formats |= (dsp_get_flags(i_dev) & SD_F_SIMPLEX)? 0 : AFMT_FULLDUPLEX;
+ pdev = makedev(SND_CDEV_MAJOR, PCMMKMINOR(PCMUNIT(i_dev), SND_DEV_CTL, 0));
p->mixers = 1; /* default: one mixer */
p->inputs = pdev->si_drv1? mix_getdevs(pdev->si_drv1) : 0;
p->left = p->right = 100;
@@ -842,7 +870,7 @@ dsp_ioctl(dev_t i_dev, u_long cmd, caddr_t arg, int mode, struct proc *p)
case SNDCTL_DSP_GETCAPS:
*arg_i = DSP_CAP_REALTIME | DSP_CAP_MMAP | DSP_CAP_TRIGGER;
- if (rdch && wrch && !(d->flags & SD_F_SIMPLEX))
+ if (rdch && wrch && !(dsp_get_flags(i_dev) & SD_F_SIMPLEX))
*arg_i |= DSP_CAP_DUPLEX;
break;
OpenPOWER on IntegriCloud