Deleted Added
full compact
27,29d26
< #include <sys/param.h>
< #include <sys/queue.h>
<
30a28
> #include <sys/ctype.h>
32c30
< SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pcm/dsp.c 167647 2007-03-16 17:17:25Z ariff $");
---
> SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pcm/dsp.c 170161 2007-05-31 18:43:33Z ariff $");
33a32,48
> struct dsp_cdevinfo {
> struct pcm_channel *rdch, *wrch;
> };
>
> #define PCM_RDCH(x) (((struct dsp_cdevinfo *)(x)->si_drv1)->rdch)
> #define PCM_WRCH(x) (((struct dsp_cdevinfo *)(x)->si_drv1)->wrch)
>
> #define PCMDEV_ACQUIRE(x) do { \
> if ((x)->si_drv1 == NULL) \
> (x)->si_drv1 = x; \
> } while(0)
>
> #define PCMDEV_RELEASE(x) do { \
> if ((x)->si_drv1 == x) \
> (x)->si_drv1 = NULL; \
> } while(0)
>
58c73,75
< static eventhandler_tag dsp_ehtag;
---
> static eventhandler_tag dsp_ehtag = NULL;
> static int dsp_umax = -1;
> static int dsp_cmax = -1;
78,86c95
< struct snddev_info *d;
< int unit;
<
< unit = PCMUNIT(dev);
< if (unit >= devclass_get_maxunit(pcm_devclass))
< return NULL;
< d = devclass_get_softc(pcm_devclass, unit);
<
< return d;
---
> return (devclass_get_softc(pcm_devclass, PCMUNIT(dev)));
93d101
< int unit;
95,98c103
< unit = PCMUNIT(dev);
< if (unit >= devclass_get_maxunit(pcm_devclass))
< return 0xffffffff;
< bdev = devclass_get_device(pcm_devclass, unit);
---
> bdev = devclass_get_device(pcm_devclass, PCMUNIT(dev));
100c105
< return pcm_getflags(bdev);
---
> return ((bdev != NULL) ? pcm_getflags(bdev) : 0xffffffff);
107d111
< int unit;
109,112c113
< unit = PCMUNIT(dev);
< if (unit >= devclass_get_maxunit(pcm_devclass))
< return;
< bdev = devclass_get_device(pcm_devclass, unit);
---
> bdev = devclass_get_device(pcm_devclass, PCMUNIT(dev));
114c115,116
< pcm_setflags(bdev, flags);
---
> if (bdev != NULL)
> pcm_setflags(bdev, flags);
129d130
< flags = dsp_get_flags(dev);
130a132,133
> if (d == NULL)
> return -1;
132a136
> flags = dsp_get_flags(dev);
141,142c145,146
< *rdch = dev->si_drv1;
< *wrch = dev->si_drv2;
---
> *rdch = PCM_RDCH(dev);
> *wrch = PCM_WRCH(dev);
146c150
< dev->si_drv1 = NULL;
---
> PCM_RDCH(dev) = NULL;
149c153
< dev->si_drv2 = NULL;
---
> PCM_WRCH(dev) = NULL;
172a177,178
> if (d == NULL)
> return;
179a186,248
> static void
> dsp_cdevinfo_alloc(struct cdev *dev,
> struct pcm_channel *rdch, struct pcm_channel *wrch)
> {
> KASSERT(dev != NULL && dev->si_drv1 == dev && rdch != wrch,
> ("bogus %s(), what are you trying to accomplish here?", __func__));
>
> dev->si_drv1 = malloc(sizeof(struct dsp_cdevinfo), M_DEVBUF,
> M_WAITOK | M_ZERO);
> PCM_RDCH(dev) = rdch;
> PCM_WRCH(dev) = wrch;
> }
>
> static void
> dsp_cdevinfo_free(struct cdev *dev)
> {
> KASSERT(dev != NULL && dev->si_drv1 != NULL &&
> PCM_RDCH(dev) == NULL && PCM_WRCH(dev) == NULL,
> ("bogus %s(), what are you trying to accomplish here?", __func__));
>
> free(dev->si_drv1, M_DEVBUF);
> dev->si_drv1 = NULL;
> }
>
> /* duplex / simplex cdev type */
> enum {
> DSP_CDEV_TYPE_RDONLY, /* simplex read-only (record) */
> DSP_CDEV_TYPE_WRONLY, /* simplex write-only (play) */
> DSP_CDEV_TYPE_RDWR, /* duplex read, write, or both */
> };
>
> #define DSP_F_VALID(x) ((x) & (FREAD | FWRITE))
> #define DSP_F_DUPLEX(x) (((x) & (FREAD | FWRITE)) == (FREAD | FWRITE))
> #define DSP_F_SIMPLEX(x) (!DSP_F_DUPLEX(x))
> #define DSP_F_READ(x) ((x) & FREAD)
> #define DSP_F_WRITE(x) ((x) & FWRITE)
>
> static const struct {
> int type;
> char *name;
> char *sep;
> int use_sep;
> int hw;
> int max;
> uint32_t fmt, spd;
> int query;
> } dsp_cdevs[] = {
> { SND_DEV_DSP, "dsp", ".", 0, 0, 0,
> AFMT_U8, DSP_DEFAULT_SPEED, DSP_CDEV_TYPE_RDWR },
> { SND_DEV_AUDIO, "audio", ".", 0, 0, 0,
> AFMT_MU_LAW, DSP_DEFAULT_SPEED, DSP_CDEV_TYPE_RDWR },
> { SND_DEV_DSP16, "dspW", ".", 0, 0, 0,
> AFMT_S16_LE, DSP_DEFAULT_SPEED, DSP_CDEV_TYPE_RDWR },
> { SND_DEV_DSPHW_PLAY, "dsp", ".p", 1, 1, SND_MAXHWCHAN,
> AFMT_S16_LE | AFMT_STEREO, 48000, DSP_CDEV_TYPE_WRONLY },
> { SND_DEV_DSPHW_VPLAY, "dsp", ".vp", 1, 1, SND_MAXVCHANS,
> AFMT_S16_LE | AFMT_STEREO, 48000, DSP_CDEV_TYPE_WRONLY },
> { SND_DEV_DSPHW_REC, "dsp", ".r", 1, 1, SND_MAXHWCHAN,
> AFMT_S16_LE | AFMT_STEREO, 48000, DSP_CDEV_TYPE_RDONLY },
> { SND_DEV_DSPHW_VREC, "dsp", ".vr", 1, 1, SND_MAXVCHANS,
> AFMT_S16_LE | AFMT_STEREO, 48000, DSP_CDEV_TYPE_RDONLY },
> };
>
185,188c254,256
< u_int32_t fmt;
< int devtype;
< int error;
< int chnum;
---
> uint32_t fmt, spd;
> int i, error, devtype;
> int wdevunit, rdevunit;
189a258
> /* Kind of impossible.. */
193,195c262
< if ((flags & (FREAD | FWRITE)) == 0)
< return EINVAL;
<
---
> /* This too.. */
197,198c264,265
< devtype = PCMDEV(i_dev);
< chnum = -1;
---
> if (d == NULL)
> return EBADF;
200,204c267,268
< /* decide default format */
< switch (devtype) {
< case SND_DEV_DSP16:
< fmt = AFMT_S16_LE;
< break;
---
> /* Lock snddev so nobody else can monkey with it. */
> pcm_lock(d);
206,208c270,278
< case SND_DEV_DSP:
< fmt = AFMT_U8;
< break;
---
> /*
> * Try to acquire cloned device before someone else pick it.
> * ENODEV means this is not a cloned droids.
> */
> error = snd_clone_acquire(i_dev);
> if (!(error == 0 || error == ENODEV)) {
> pcm_unlock(d);
> return error;
> }
210,212c280,288
< case SND_DEV_AUDIO:
< fmt = AFMT_MU_LAW;
< break;
---
> if (!DSP_F_VALID(flags))
> error = EINVAL;
> else if (i_dev->si_drv1 != NULL)
> error = EBUSY;
> else if (DSP_F_DUPLEX(flags) &&
> (dsp_get_flags(i_dev) & SD_F_SIMPLEX))
> error = ENOTSUP;
> else
> error = 0;
214,228c290,293
< case SND_DEV_NORESET:
< fmt = 0;
< break;
<
< case SND_DEV_DSPHW:
< /*
< * HW *specific* access without channel numbering confusion
< * caused by "first come first served" by dsp_clone().
< */
< fmt = AFMT_U8;
< chnum = PCMCHAN(i_dev);
< break;
<
< default:
< panic("impossible devtype %d", devtype);
---
> if (error != 0) {
> (void)snd_clone_release(i_dev);
> pcm_unlock(d);
> return error;
231,232c296,300
< /* lock snddev so nobody else can monkey with it */
< pcm_lock(d);
---
> /*
> * Fake busy state by pointing si_drv1 to something else since
> * we have to give up locking somewhere during setup process.
> */
> PCMDEV_ACQUIRE(i_dev);
234,235c302,306
< rdch = i_dev->si_drv1;
< wrch = i_dev->si_drv2;
---
> devtype = PCMDEV(i_dev);
> wdevunit = -1;
> rdevunit = -1;
> fmt = 0;
> spd = 0;
237,241c308,330
< if (rdch || wrch || ((dsp_get_flags(i_dev) & SD_F_SIMPLEX) &&
< (flags & (FREAD | FWRITE)) == (FREAD | FWRITE))) {
< /* simplex or not, better safe than sorry. */
< pcm_unlock(d);
< return EBUSY;
---
> for (i = 0; i < (sizeof(dsp_cdevs) / sizeof(dsp_cdevs[0])); i++) {
> if (devtype != dsp_cdevs[i].type)
> continue;
> if (DSP_F_SIMPLEX(flags) &&
> ((dsp_cdevs[i].query == DSP_CDEV_TYPE_WRONLY &&
> DSP_F_READ(flags)) ||
> (dsp_cdevs[i].query == DSP_CDEV_TYPE_RDONLY &&
> DSP_F_WRITE(flags)))) {
> /*
> * simplex, opposite direction? Please be gone..
> */
> (void)snd_clone_release(i_dev);
> PCMDEV_RELEASE(i_dev);
> pcm_unlock(d);
> return ENOTSUP;
> }
> if (dsp_cdevs[i].query == DSP_CDEV_TYPE_WRONLY)
> wdevunit = dev2unit(i_dev);
> else if (dsp_cdevs[i].query == DSP_CDEV_TYPE_RDONLY)
> rdevunit = dev2unit(i_dev);
> fmt = dsp_cdevs[i].fmt;
> spd = dsp_cdevs[i].spd;
> break;
243a333,339
> /* No matching devtype? */
> if (fmt == 0 || spd == 0)
> panic("impossible devtype %d", devtype);
>
> rdch = NULL;
> wrch = NULL;
>
250c346
< if (flags & FREAD) {
---
> if (DSP_F_READ(flags)) {
253,255c349,350
< error = pcm_chnalloc(d, &rdch, PCMDIR_REC, td->td_proc->p_pid, chnum);
< if (error != 0 && error != EBUSY && chnum != -1 && (flags & FWRITE))
< error = pcm_chnalloc(d, &rdch, PCMDIR_REC, td->td_proc->p_pid, -1);
---
> error = pcm_chnalloc(d, &rdch, PCMDIR_REC, td->td_proc->p_pid,
> rdevunit);
257,258c352,353
< if (error == 0 && (chn_reset(rdch, fmt) ||
< (fmt && chn_setspeed(rdch, DSP_DEFAULT_SPEED))))
---
> if (error == 0 && (chn_reset(rdch, fmt) != 0 ||
> (chn_setspeed(rdch, spd) != 0)))
262c357
< if (rdch)
---
> if (rdch != NULL)
263a359,362
> pcm_lock(d);
> (void)snd_clone_release(i_dev);
> PCMDEV_RELEASE(i_dev);
> pcm_unlock(d);
274,279c373,377
< if (flags & FWRITE) {
< /* open for write */
< pcm_unlock(d);
< error = pcm_chnalloc(d, &wrch, PCMDIR_PLAY, td->td_proc->p_pid, chnum);
< if (error != 0 && error != EBUSY && chnum != -1 && (flags & FREAD))
< error = pcm_chnalloc(d, &wrch, PCMDIR_PLAY, td->td_proc->p_pid, -1);
---
> if (DSP_F_WRITE(flags)) {
> /* open for write */
> pcm_unlock(d);
> error = pcm_chnalloc(d, &wrch, PCMDIR_PLAY, td->td_proc->p_pid,
> wdevunit);
281,283c379,381
< if (error == 0 && (chn_reset(wrch, fmt) ||
< (fmt && chn_setspeed(wrch, DSP_DEFAULT_SPEED))))
< error = ENODEV;
---
> if (error == 0 && (chn_reset(wrch, fmt) != 0 ||
> (chn_setspeed(wrch, spd) != 0)))
> error = ENODEV;
285,294c383,399
< if (error != 0) {
< if (wrch)
< pcm_chnrelease(wrch);
< if (rdch) {
< /*
< * Lock, deref and release previously created record channel
< */
< CHN_LOCK(rdch);
< pcm_chnref(rdch, -1);
< pcm_chnrelease(rdch);
---
> if (error != 0) {
> if (wrch != NULL)
> pcm_chnrelease(wrch);
> if (rdch != NULL) {
> /*
> * Lock, deref and release previously
> * created record channel
> */
> CHN_LOCK(rdch);
> pcm_chnref(rdch, -1);
> pcm_chnrelease(rdch);
> }
> pcm_lock(d);
> (void)snd_clone_release(i_dev);
> PCMDEV_RELEASE(i_dev);
> pcm_unlock(d);
> return error;
297,304c402,406
< return error;
< }
<
< if (flags & O_NONBLOCK)
< wrch->flags |= CHN_F_NBIO;
< pcm_chnref(wrch, 1);
< CHN_UNLOCK(wrch);
< pcm_lock(d);
---
> if (flags & O_NONBLOCK)
> wrch->flags |= CHN_F_NBIO;
> pcm_chnref(wrch, 1);
> CHN_UNLOCK(wrch);
> pcm_lock(d);
307,308c409,412
< i_dev->si_drv1 = rdch;
< i_dev->si_drv2 = wrch;
---
> /*
> * Increase clone refcount for its automatic garbage collector.
> */
> (void)snd_clone_ref(i_dev);
310a415,421
>
> /*
> * We're done. Allocate and point si_drv1 to a real
> * allocated structure.
> */
> dsp_cdevinfo_alloc(i_dev, rdch, wrch);
>
321a433,434
> if (d == NULL)
> return EBADF;
323,325c436,437
< rdch = i_dev->si_drv1;
< wrch = i_dev->si_drv2;
< pcm_unlock(d);
---
> rdch = PCM_RDCH(i_dev);
> wrch = PCM_WRCH(i_dev);
334a447
> pcm_unlock(d);
374c487
< i_dev->si_drv1 = NULL;
---
> PCM_RDCH(i_dev) = NULL;
376c489
< i_dev->si_drv2 = NULL;
---
> PCM_WRCH(i_dev) = NULL;
380,381c493,494
< if (refs == 0 && i_dev->si_drv1 == NULL &&
< i_dev->si_drv2 == NULL) {
---
> if (refs == 0 && PCM_RDCH(i_dev) == NULL &&
> PCM_WRCH(i_dev) == NULL) {
385a499,507
> dsp_cdevinfo_free(i_dev);
> /*
> * Release clone busy state and unref it
> * so the automatic garbage collector will
> * get the hint and do the remaining cleanup
> * process.
> */
> (void)snd_clone_release(i_dev);
> (void)snd_clone_unref(i_dev);
387d508
< pcm_unlock(d);
389a511
> pcm_unlock(d);
407,408c529,530
< KASSERT(rdch, ("dsp_read: nonexistant channel"));
< KASSERT(rdch->flags & CHN_F_BUSY, ("dsp_read: nonbusy channel"));
---
> if (rdch == NULL || !(rdch->flags & CHN_F_BUSY))
> return EBADF;
430,431c552,553
< KASSERT(wrch, ("dsp_write: nonexistant channel"));
< KASSERT(wrch->flags & CHN_F_BUSY, ("dsp_write: nonbusy channel"));
---
> if (wrch == NULL || !(wrch->flags & CHN_F_BUSY))
> return EBADF;
471a594,595
> if (d == NULL)
> return EBADF;
519c643
<
---
>
1506,1513c1630,1681
< /*
< * Clone logic is this:
< * x E X = {dsp, dspW, audio}
< * x -> x${sysctl("hw.snd.unit")}
< * xN->
< * for i N = 1 to channels of device N
< * if xN.i isn't busy, return its dev_t
< */
---
> /* So much for dev_stdclone() */
> static int
> dsp_stdclone(char *name, char *namep, char *sep, int use_sep, int *u, int *c)
> {
> size_t len;
>
> len = strlen(namep);
>
> if (bcmp(name, namep, len) != 0)
> return (ENODEV);
>
> name += len;
>
> if (isdigit(*name) == 0)
> return (ENODEV);
>
> len = strlen(sep);
>
> if (*name == '0' && !(name[1] == '\0' || bcmp(name + 1, sep, len) == 0))
> return (ENODEV);
>
> for (*u = 0; isdigit(*name) != 0; name++) {
> *u *= 10;
> *u += *name - '0';
> if (*u > dsp_umax)
> return (ENODEV);
> }
>
> if (*name == '\0')
> return ((use_sep == 0) ? 0 : ENODEV);
>
> if (bcmp(name, sep, len) != 0 || isdigit(name[len]) == 0)
> return (ENODEV);
>
> name += len;
>
> if (*name == '0' && name[1] != '\0')
> return (ENODEV);
>
> for (*c = 0; isdigit(*name) != 0; name++) {
> *c *= 10;
> *c += *name - '0';
> if (*c > dsp_cmax)
> return (ENODEV);
> }
>
> if (*name != '\0')
> return (ENODEV);
>
> return (0);
> }
>
1515,1516c1683,1687
< dsp_clone(void *arg, struct ucred *cred, char *name, int namelen,
< struct cdev **dev)
---
> dsp_clone(void *arg,
> #if __FreeBSD_version >= 600034
> struct ucred *cred,
> #endif
> char *name, int namelen, struct cdev **dev)
1518,1523c1689,1693
< struct cdev *pdev;
< struct snddev_info *pcm_dev;
< struct snddev_channel *pcm_chan;
< int i, unit, devtype;
< static int devtypes[3] = {SND_DEV_DSP, SND_DEV_DSP16, SND_DEV_AUDIO};
< static char *devnames[3] = {"dsp", "dspW", "audio"};
---
> struct snddev_info *d;
> struct snd_clone_entry *ce;
> struct pcm_channel *c;
> int i, unit, udcmask, cunit, devtype, devhw, devcmax, tumax;
> char *devname, *devsep;
1524a1695,1696
> KASSERT(dsp_umax >= 0 && dsp_cmax >= 0, ("Uninitialized unit!"));
>
1527,1528d1698
< if (pcm_devclass == NULL)
< return;
1530d1699
< devtype = 0;
1532,1534c1701,1716
< for (i = 0; (i < 3) && (unit == -1); i++) {
< devtype = devtypes[i];
< if (strcmp(name, devnames[i]) == 0) {
---
> cunit = -1;
> devtype = -1;
> devhw = 0;
> devcmax = -1;
> tumax = -1;
> devname = NULL;
> devsep = NULL;
>
> for (i = 0; i < (sizeof(dsp_cdevs) / sizeof(dsp_cdevs[0])) &&
> unit == -1; i++) {
> devtype = dsp_cdevs[i].type;
> devname = dsp_cdevs[i].name;
> devsep = dsp_cdevs[i].sep;
> devhw = dsp_cdevs[i].hw;
> devcmax = dsp_cdevs[i].max - 1;
> if (strcmp(name, devname) == 0)
1536,1538c1718,1721
< } else {
< if (dev_stdclone(name, NULL, devnames[i], &unit) != 1)
< unit = -1;
---
> else if (dsp_stdclone(name, devname, devsep,
> dsp_cdevs[i].use_sep, &unit, &cunit) != 0) {
> unit = -1;
> cunit = -1;
1541c1724,1726
< if (unit == -1 || unit >= devclass_get_maxunit(pcm_devclass))
---
>
> d = devclass_get_softc(pcm_devclass, unit);
> if (d == NULL || d->clones == NULL)
1544,1546c1729,1731
< pcm_dev = devclass_get_softc(pcm_devclass, unit);
<
< if (pcm_dev == NULL)
---
> pcm_lock(d);
> if (snd_clone_disabled(d->clones)) {
> pcm_unlock(d);
1547a1733
> }
1549c1735
< SLIST_FOREACH(pcm_chan, &pcm_dev->channels, link) {
---
> udcmask = snd_u2unit(unit) | snd_d2unit(devtype);
1551,1567c1737,1741
< switch(devtype) {
< case SND_DEV_DSP:
< pdev = pcm_chan->dsp_devt;
< break;
< case SND_DEV_DSP16:
< pdev = pcm_chan->dspW_devt;
< break;
< case SND_DEV_AUDIO:
< pdev = pcm_chan->audio_devt;
< break;
< default:
< panic("Unknown devtype %d", devtype);
< }
<
< if ((pdev != NULL) && (pdev->si_drv1 == NULL) && (pdev->si_drv2 == NULL)) {
< *dev = pdev;
< dev_ref(*dev);
---
> if (devhw != 0) {
> KASSERT(devcmax <= dsp_cmax,
> ("overflow: devcmax=%d, dsp_cmax=%d", devcmax, dsp_cmax));
> if (cunit > devcmax) {
> pcm_unlock(d);
1569a1744,1792
> udcmask |= snd_c2unit(cunit);
> CHN_FOREACH(c, d, channels.pcm) {
> CHN_LOCK(c);
> if (c->unit != udcmask) {
> CHN_UNLOCK(c);
> continue;
> }
> CHN_UNLOCK(c);
> udcmask &= ~snd_c2unit(cunit);
> /*
> * Temporarily increase clone maxunit to overcome
> * vchan flexibility.
> *
> * # sysctl dev.pcm.0.play.vchans=256
> * dev.pcm.0.play.vchans: 1 -> 256
> * # cat /dev/zero > /dev/dsp0.vp255 &
> * [1] 17296
> * # sysctl dev.pcm.0.play.vchans=0
> * dev.pcm.0.play.vchans: 256 -> 1
> * # fg
> * [1] + running cat /dev/zero > /dev/dsp0.vp255
> * ^C
> * # cat /dev/zero > /dev/dsp0.vp255
> * zsh: operation not supported: /dev/dsp0.vp255
> */
> tumax = snd_clone_getmaxunit(d->clones);
> if (cunit > tumax)
> snd_clone_setmaxunit(d->clones, cunit);
> else
> tumax = -1;
> goto dsp_clone_alloc;
> }
> /*
> * Ok, so we're requesting unallocated vchan, but still
> * within maximum vchan limit.
> */
> if (((devtype == SND_DEV_DSPHW_VPLAY && d->pvchancount > 0) ||
> (devtype == SND_DEV_DSPHW_VREC && d->rvchancount > 0)) &&
> cunit < snd_maxautovchans) {
> udcmask &= ~snd_c2unit(cunit);
> tumax = snd_clone_getmaxunit(d->clones);
> if (cunit > tumax)
> snd_clone_setmaxunit(d->clones, cunit);
> else
> tumax = -1;
> goto dsp_clone_alloc;
> }
> pcm_unlock(d);
> return;
1570a1794,1811
>
> dsp_clone_alloc:
> ce = snd_clone_alloc(d->clones, dev, &cunit, udcmask);
> if (tumax != -1)
> snd_clone_setmaxunit(d->clones, tumax);
> if (ce != NULL) {
> udcmask |= snd_c2unit(cunit);
> pcm_unlock(d);
> *dev = make_dev(&dsp_cdevsw, unit2minor(udcmask),
> UID_ROOT, GID_WHEEL, 0666, "%s%d%s%d",
> devname, unit, devsep, cunit);
> pcm_lock(d);
> snd_clone_register(ce, *dev);
> }
> pcm_unlock(d);
>
> if (*dev != NULL)
> dev_ref(*dev);
1575a1817,1822
> if (dsp_ehtag != NULL)
> return;
> /* initialize unit numbering */
> snd_unit_init();
> dsp_umax = PCMMAXUNIT;
> dsp_cmax = PCMMAXCHAN;
1582,1583c1829,1832
< if (dsp_ehtag != NULL)
< EVENTHANDLER_DEREGISTER(dev_clone, dsp_ehtag);
---
> if (dsp_ehtag == NULL)
> return;
> EVENTHANDLER_DEREGISTER(dev_clone, dsp_ehtag);
> dsp_ehtag = NULL;
1589a1839,1858
> char *
> dsp_unit2name(char *buf, size_t len, int unit)
> {
> int i, dtype;
>
> KASSERT(buf != NULL && len != 0, ("bogus buf=%p len=%u", buf, len));
>
> dtype = snd_unit2d(unit);
>
> for (i = 0; i < (sizeof(dsp_cdevs) / sizeof(dsp_cdevs[0])); i++) {
> if (dtype != dsp_cdevs[i].type)
> continue;
> snprintf(buf, len, "%s%d%s%d", dsp_cdevs[i].name,
> snd_unit2u(unit), dsp_cdevs[i].sep, snd_unit2c(unit));
> return (buf);
> }
>
> return (NULL);
> }
>
1625d1893
< struct snddev_channel *sce;
1629d1896
< struct cdev *t_cdev;
1631a1899
> char *devname, buf[CHN_NAMELEN];
1642c1910
< t_cdev = NULL;
---
> devname = NULL;
1645c1913,1914
<
---
> bzero(buf, sizeof(buf));
>
1660,1661c1929
< SLIST_FOREACH(sce, &d->channels, link) {
< ch = sce->channel;
---
> CHN_FOREACH(ch, d, channels.pcm) {
1665,1667c1933,1935
< if ((ch == i_dev->si_drv1) || /* record ch */
< (ch == i_dev->si_drv2)) { /* playback ch */
< t_cdev = i_dev;
---
> if ((ch == PCM_RDCH(i_dev)) || /* record ch */
> (ch == PCM_WRCH(i_dev))) { /* playback ch */
> devname = i_dev->si_name;
1671c1939,1940
< t_cdev = sce->dsp_devt;
---
> devname = dsp_unit2name(buf, sizeof(buf),
> ch->unit);
1674a1944,1946
> /*
> * XXX I really doubt if this is correct.
> */
1687c1959
< if (t_cdev == NULL) {
---
> if (devname == NULL) {
1724c1996
<
---
>
1787c2059
< strlcpy(ai->devnode, t_cdev->si_name, sizeof(ai->devnode));
---
> strlcpy(ai->devnode, devname, sizeof(ai->devnode));
2011c2283
<
---
>