kernel - Make filters able to be marked MPSAFE
[dragonfly.git] / sys / dev / sound / pcm / dsp.c
1 /*-
2  * Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/sys/dev/sound/pcm/dsp.c,v 1.80.2.6 2006/04/04 17:43:48 ariff Exp $
27  * $DragonFly: src/sys/dev/sound/pcm/dsp.c,v 1.17 2008/02/28 17:19:11 tgen Exp $
28  */
29
30 #include <sys/param.h>
31 #include <sys/queue.h>
32 #include <sys/event.h>
33
34 #include <dev/sound/pcm/dsp.h>
35 #include <dev/sound/pcm/sound.h>
36
37 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pcm/dsp.c,v 1.17 2008/02/28 17:19:11 tgen Exp $");
38
39 #define OLDPCM_IOCTL
40
41 static d_open_t dsp_open;
42 static d_close_t dsp_close;
43 static d_read_t dsp_read;
44 static d_write_t dsp_write;
45 static d_ioctl_t dsp_ioctl;
46 static d_kqfilter_t dsp_kqfilter;
47 static d_mmap_t dsp_mmap;
48
49 static void dsp_filter_detach(struct knote *);
50 static int dsp_filter_read(struct knote *, long);
51 static int dsp_filter_write(struct knote *, long);
52
53 struct dev_ops dsp_cdevsw = {
54         { "dsp", SND_CDEV_MAJOR, 0},
55         /*.d_flags =    D_NEEDGIANT,*/
56         .d_open =       dsp_open,
57         .d_close =      dsp_close,
58         .d_read =       dsp_read,
59         .d_write =      dsp_write,
60         .d_ioctl =      dsp_ioctl,
61         .d_kqfilter =   dsp_kqfilter,
62         .d_mmap =       dsp_mmap,
63 };
64
65 struct snddev_info *
66 dsp_get_info(struct cdev *dev)
67 {
68         struct snddev_info *d;
69         int unit;
70
71         unit = PCMUNIT(dev);
72         if (unit >= devclass_get_maxunit(pcm_devclass))
73                 return NULL;
74         d = devclass_get_softc(pcm_devclass, unit);
75
76         return d;
77 }
78
79 static u_int32_t
80 dsp_get_flags(struct cdev *dev)
81 {
82         device_t bdev;
83         int unit;
84
85         unit = PCMUNIT(dev);
86         if (unit >= devclass_get_maxunit(pcm_devclass))
87                 return 0xffffffff;
88         bdev = devclass_get_device(pcm_devclass, unit);
89
90         return pcm_getflags(bdev);
91 }
92
93 static void
94 dsp_set_flags(struct cdev *dev, u_int32_t flags)
95 {
96         device_t bdev;
97         int unit;
98
99         unit = PCMUNIT(dev);
100         if (unit >= devclass_get_maxunit(pcm_devclass))
101                 return;
102         bdev = devclass_get_device(pcm_devclass, unit);
103
104         pcm_setflags(bdev, flags);
105 }
106
107 /*
108  * return the channels associated with an open device instance.
109  * set the priority if the device is simplex and one direction (only) is
110  * specified.
111  * lock channels specified.
112  */
113 static int
114 getchns(struct cdev *dev, struct pcm_channel **rdch, struct pcm_channel **wrch, u_int32_t prio)
115 {
116         struct snddev_info *d;
117         u_int32_t flags;
118
119         flags = dsp_get_flags(dev);
120         d = dsp_get_info(dev);
121         pcm_inprog(d, 1);
122         pcm_lock(d);
123         KASSERT((flags & SD_F_PRIO_SET) != SD_F_PRIO_SET, \
124                 ("getchns: read and write both prioritised"));
125
126         if ((flags & SD_F_PRIO_SET) == 0 && (prio != (SD_F_PRIO_RD | SD_F_PRIO_WR))) {
127                 flags |= prio & (SD_F_PRIO_RD | SD_F_PRIO_WR);
128                 dsp_set_flags(dev, flags);
129         }
130
131         *rdch = dev->si_drv1;
132         *wrch = dev->si_drv2;
133         if ((flags & SD_F_SIMPLEX) && (flags & SD_F_PRIO_SET)) {
134                 if (prio) {
135                         if (*rdch && flags & SD_F_PRIO_WR) {
136                                 dev->si_drv1 = NULL;
137                                 *rdch = pcm_getfakechan(d);
138                         } else if (*wrch && flags & SD_F_PRIO_RD) {
139                                 dev->si_drv2 = NULL;
140                                 *wrch = pcm_getfakechan(d);
141                         }
142                 }
143
144                 pcm_getfakechan(d)->flags |= CHN_F_BUSY;
145         }
146         pcm_unlock(d);
147
148         if (*rdch && *rdch != pcm_getfakechan(d) && (prio & SD_F_PRIO_RD))
149                 CHN_LOCK(*rdch);
150         if (*wrch && *wrch != pcm_getfakechan(d) && (prio & SD_F_PRIO_WR))
151                 CHN_LOCK(*wrch);
152
153         return 0;
154 }
155
156 /* unlock specified channels */
157 static void
158 relchns(struct cdev *dev, struct pcm_channel *rdch, struct pcm_channel *wrch, u_int32_t prio)
159 {
160         struct snddev_info *d;
161
162         d = dsp_get_info(dev);
163         if (wrch && wrch != pcm_getfakechan(d) && (prio & SD_F_PRIO_WR))
164                 CHN_UNLOCK(wrch);
165         if (rdch && rdch != pcm_getfakechan(d) && (prio & SD_F_PRIO_RD))
166                 CHN_UNLOCK(rdch);
167         pcm_inprog(d, -1);
168 }
169
170 static int
171 dsp_open(struct dev_open_args *ap)
172 {
173         struct cdev *i_dev = ap->a_head.a_dev;
174         struct thread *td = curthread;
175         int flags = ap->a_oflags;
176         struct pcm_channel *rdch, *wrch;
177         struct snddev_info *d = NULL;
178         struct snddev_channel *sce = NULL;
179         u_int32_t fmt = AFMT_U8;
180         int error;
181         int chnum;
182
183         if (i_dev == NULL) {
184                 error = ENODEV;
185                 goto out;
186         }
187
188         d = dsp_get_info(i_dev);
189         SLIST_FOREACH(sce, &d->channels, link) {
190                 if (sce->dsp_dev == i_dev)
191                         break;
192         }
193
194         if (sce == NULL) {
195                 error = ENODEV;
196                 goto out;
197         }
198
199         if (td == NULL) {
200                 error = ENODEV;
201                 goto out;
202         }
203
204         if ((flags & (FREAD | FWRITE)) == 0) {
205                 error = EINVAL;
206                 goto out;
207         }
208
209         chnum = PCMCHAN(i_dev);
210
211         /* lock snddev so nobody else can monkey with it */
212         pcm_lock(d);
213
214         rdch = i_dev->si_drv1;
215         wrch = i_dev->si_drv2;
216
217         if (rdch || wrch || ((dsp_get_flags(i_dev) & SD_F_SIMPLEX) &&
218                     (flags & (FREAD | FWRITE)) == (FREAD | FWRITE))) {
219                 /* simplex or not, better safe than sorry. */
220                 pcm_unlock(d);
221                 error = EBUSY;
222                 goto out;
223         }
224
225         /*
226          * if we get here, the open request is valid- either:
227          *   * we were previously not open
228          *   * we were open for play xor record and the opener wants
229          *     the non-open direction
230          */
231         if (flags & FREAD) {
232                 /* open for read */
233                 pcm_unlock(d);
234                 error = pcm_chnalloc(d, &rdch, PCMDIR_REC, td->td_proc->p_pid, chnum);
235                 if (error != 0 && error != EBUSY && chnum != -1 && (flags & FWRITE))
236                         error = pcm_chnalloc(d, &rdch, PCMDIR_REC, td->td_proc->p_pid, -1);
237
238                 if (error == 0 && (chn_reset(rdch, fmt) ||
239                                 (fmt && chn_setspeed(rdch, DSP_DEFAULT_SPEED))))
240                         error = ENODEV;
241
242                 if (error != 0) {
243                         if (rdch)
244                                 pcm_chnrelease(rdch);
245                         goto out;
246                 }
247
248                 pcm_chnref(rdch, 1);
249                 CHN_UNLOCK(rdch);
250                 pcm_lock(d);
251         }
252
253         if (flags & FWRITE) {
254             /* open for write */
255             pcm_unlock(d);
256             error = pcm_chnalloc(d, &wrch, PCMDIR_PLAY, td->td_proc->p_pid, chnum);
257             if (error != 0 && error != EBUSY && chnum != -1 && (flags & FREAD))
258                 error = pcm_chnalloc(d, &wrch, PCMDIR_PLAY, td->td_proc->p_pid, -1);
259
260             if (error == 0 && (chn_reset(wrch, fmt) ||
261                         (fmt && chn_setspeed(wrch, DSP_DEFAULT_SPEED))))
262                 error = ENODEV;
263
264             if (error != 0) {
265                 if (wrch)
266                     pcm_chnrelease(wrch);
267                 if (rdch) {
268                     /*
269                      * Lock, deref and release previously created record channel
270                      */
271                     CHN_LOCK(rdch);
272                     pcm_chnref(rdch, -1);
273                     pcm_chnrelease(rdch);
274                 }
275
276                 goto out;
277             }
278
279             pcm_chnref(wrch, 1);
280             CHN_UNLOCK(wrch);
281             pcm_lock(d);
282         }
283
284         i_dev->si_drv1 = rdch;
285         i_dev->si_drv2 = wrch;
286
287         sce->open++;
288
289         pcm_unlock(d);
290         return 0;
291
292 out:
293         if (i_dev != NULL && sce != NULL && sce->open == 0) {
294                 pcm_lock(d);
295                 destroy_dev(i_dev);
296                 sce->dsp_dev = NULL;
297                 pcm_unlock(d);
298         }
299         return (error);
300 }
301
302 static int
303 dsp_close(struct dev_close_args *ap)
304 {
305         struct cdev *i_dev = ap->a_head.a_dev;
306         struct pcm_channel *rdch, *wrch;
307         struct snddev_info *d;
308         struct snddev_channel *sce = NULL;
309         int refs;
310
311         d = dsp_get_info(i_dev);
312         pcm_lock(d);
313         rdch = i_dev->si_drv1;
314         wrch = i_dev->si_drv2;
315         i_dev->si_drv1 = NULL;
316         i_dev->si_drv2 = NULL;
317
318         SLIST_FOREACH(sce, &d->channels, link) {
319                 if (sce->dsp_dev == i_dev)
320                         break;
321         }
322         sce->dsp_dev = NULL;
323         destroy_dev(i_dev);
324
325         pcm_unlock(d);
326
327         if (rdch || wrch) {
328                 refs = 0;
329                 if (rdch) {
330                         CHN_LOCK(rdch);
331                         refs += pcm_chnref(rdch, -1);
332                         chn_abort(rdch); /* won't sleep */
333                         rdch->flags &= ~(CHN_F_RUNNING | CHN_F_MAPPED | CHN_F_DEAD);
334                         chn_reset(rdch, 0);
335                         pcm_chnrelease(rdch);
336                 }
337                 if (wrch) {
338                         CHN_LOCK(wrch);
339                         refs += pcm_chnref(wrch, -1);
340                         /*
341                          * XXX: Maybe the right behaviour is to abort on non_block.
342                          * It seems that mplayer flushes the audio queue by quickly
343                          * closing and re-opening.  In FBSD, there's a long pause
344                          * while the audio queue flushes that I presume isn't there in
345                          * linux.
346                          */
347                         chn_flush(wrch); /* may sleep */
348                         wrch->flags &= ~(CHN_F_RUNNING | CHN_F_MAPPED | CHN_F_DEAD);
349                         chn_reset(wrch, 0);
350                         pcm_chnrelease(wrch);
351                 }
352
353                 pcm_lock(d);
354                 /*
355                  * If there are no more references, release the channels.
356                  */
357                 if (refs == 0) {
358                         if (pcm_getfakechan(d))
359                                 pcm_getfakechan(d)->flags = 0;
360                         /* What is this?!? */
361                         dsp_set_flags(i_dev, dsp_get_flags(i_dev) & ~SD_F_TRANSIENT);
362                 }
363                 pcm_unlock(d);
364         }
365         return 0;
366 }
367
368 static int
369 dsp_read(struct dev_read_args *ap)
370 {
371         struct cdev *i_dev = ap->a_head.a_dev;
372         struct uio *buf = ap->a_uio;
373         int flag = ap->a_ioflag;
374         struct pcm_channel *rdch, *wrch;
375         int ret;
376
377         getchns(i_dev, &rdch, &wrch, SD_F_PRIO_RD);
378
379         KASSERT(rdch, ("dsp_read: nonexistant channel"));
380         KASSERT(rdch->flags & CHN_F_BUSY, ("dsp_read: nonbusy channel"));
381
382         if (rdch->flags & (CHN_F_MAPPED | CHN_F_DEAD)) {
383                 relchns(i_dev, rdch, wrch, SD_F_PRIO_RD);
384                 return EINVAL;
385         }
386         if (!(rdch->flags & CHN_F_RUNNING))
387                 rdch->flags |= CHN_F_RUNNING;
388         ret = chn_read(rdch, buf, flag);
389         relchns(i_dev, rdch, wrch, SD_F_PRIO_RD);
390
391         return ret;
392 }
393
394 static int
395 dsp_write(struct dev_write_args *ap)
396 {
397         struct cdev *i_dev = ap->a_head.a_dev;
398         struct uio *buf = ap->a_uio;
399         int flag = ap->a_ioflag;
400         struct pcm_channel *rdch, *wrch;
401         int ret;
402
403         getchns(i_dev, &rdch, &wrch, SD_F_PRIO_WR);
404
405         KASSERT(wrch, ("dsp_write: nonexistant channel"));
406         KASSERT(wrch->flags & CHN_F_BUSY, ("dsp_write: nonbusy channel"));
407
408         if (wrch->flags & (CHN_F_MAPPED | CHN_F_DEAD)) {
409                 relchns(i_dev, rdch, wrch, SD_F_PRIO_WR);
410                 return EINVAL;
411         }
412         if (!(wrch->flags & CHN_F_RUNNING))
413                 wrch->flags |= CHN_F_RUNNING;
414         ret = chn_write(wrch, buf, flag);
415         relchns(i_dev, rdch, wrch, SD_F_PRIO_WR);
416
417         return ret;
418 }
419
420 static int
421 dsp_ioctl(struct dev_ioctl_args *ap)
422 {
423         struct cdev *i_dev = ap->a_head.a_dev;
424         u_long cmd = ap->a_cmd;
425         caddr_t arg = ap->a_data;
426         struct pcm_channel *chn, *rdch, *wrch;
427         struct snddev_info *d;
428         int kill;
429         int ret = 0, *arg_i = (int *)arg, tmp;
430
431         d = dsp_get_info(i_dev);
432         getchns(i_dev, &rdch, &wrch, 0);
433
434         kill = 0;
435         if (wrch && (wrch->flags & CHN_F_DEAD))
436                 kill |= 1;
437         if (rdch && (rdch->flags & CHN_F_DEAD))
438                 kill |= 2;
439         if (kill == 3) {
440                 relchns(i_dev, rdch, wrch, 0);
441                 return EINVAL;
442         }
443         if (kill & 1)
444                 wrch = NULL;
445         if (kill & 2)
446                 rdch = NULL;
447
448         /*
449          * 4Front OSS specifies that dsp devices allow mixer controls to
450          * control PCM == their volume.
451          */
452         if (IOCGROUP(cmd) == 'M') {
453                 /*
454                  * For now only set the channel volume for vchans, pass
455                  * all others to the mixer.
456                  */
457                 if (wrch != NULL && wrch->flags & CHN_F_VIRTUAL &&
458                     (cmd & 0xff) == SOUND_MIXER_PCM) {
459                         if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)) {
460                                 int vol_raw = *(int *)arg;
461                                 int vol_left, vol_right;
462
463                                 vol_left = min(vol_raw & 0x00ff, 100);
464                                 vol_right = min((vol_raw & 0xff00) >> 8, 100);
465                                 ret = chn_setvolume(wrch, vol_left, vol_right);
466                         } else {
467                                 *(int *)arg = wrch->volume;
468                         }
469                 } else {
470                         ap->a_head.a_dev = d->mixer_dev;
471                         ret = mixer_ioctl(ap);
472                 }
473
474                 relchns(i_dev, rdch, wrch, 0);
475                 return ret;
476         }
477         
478         switch(cmd) {
479 #ifdef OLDPCM_IOCTL
480         /*
481          * we start with the new ioctl interface.
482          */
483         case AIONWRITE: /* how many bytes can write ? */
484                 if (wrch) {
485                         CHN_LOCK(wrch);
486 /*
487                 if (wrch && wrch->bufhard.dl)
488                         while (chn_wrfeed(wrch) == 0);
489 */
490                         *arg_i = sndbuf_getfree(wrch->bufsoft);
491                         CHN_UNLOCK(wrch);
492                 } else {
493                         *arg_i = 0;
494                         ret = EINVAL;
495                 }
496                 break;
497
498         case AIOSSIZE:     /* set the current blocksize */
499                 {
500                         struct snd_size *p = (struct snd_size *)arg;
501
502                         p->play_size = 0;
503                         p->rec_size = 0;
504                         if (wrch) {
505                                 CHN_LOCK(wrch);
506                                 chn_setblocksize(wrch, 2, p->play_size);
507                                 p->play_size = sndbuf_getblksz(wrch->bufsoft);
508                                 CHN_UNLOCK(wrch);
509                         }
510                         if (rdch) {
511                                 CHN_LOCK(rdch);
512                                 chn_setblocksize(rdch, 2, p->rec_size);
513                                 p->rec_size = sndbuf_getblksz(rdch->bufsoft);
514                                 CHN_UNLOCK(rdch);
515                         }
516                 }
517                 break;
518         case AIOGSIZE:  /* get the current blocksize */
519                 {
520                         struct snd_size *p = (struct snd_size *)arg;
521
522                         if (wrch) {
523                                 CHN_LOCK(wrch);
524                                 p->play_size = sndbuf_getblksz(wrch->bufsoft);
525                                 CHN_UNLOCK(wrch);
526                         }
527                         if (rdch) {
528                                 CHN_LOCK(rdch);
529                                 p->rec_size = sndbuf_getblksz(rdch->bufsoft);
530                                 CHN_UNLOCK(rdch);
531                         }
532                 }
533                 break;
534
535         case AIOSFMT:
536         case AIOGFMT:
537                 {
538                         snd_chan_param *p = (snd_chan_param *)arg;
539
540                         if (cmd == AIOSFMT &&
541                             ((p->play_format != 0 && p->play_rate == 0) ||
542                             (p->rec_format != 0 && p->rec_rate == 0))) {
543                                 ret = EINVAL;
544                                 break;
545                         }
546                         if (wrch) {
547                                 CHN_LOCK(wrch);
548                                 if (cmd == AIOSFMT && p->play_format != 0) {
549                                         chn_setformat(wrch, p->play_format);
550                                         chn_setspeed(wrch, p->play_rate);
551                                 }
552                                 p->play_rate = wrch->speed;
553                                 p->play_format = wrch->format;
554                                 CHN_UNLOCK(wrch);
555                         } else {
556                                 p->play_rate = 0;
557                                 p->play_format = 0;
558                         }
559                         if (rdch) {
560                                 CHN_LOCK(rdch);
561                                 if (cmd == AIOSFMT && p->rec_format != 0) {
562                                         chn_setformat(rdch, p->rec_format);
563                                         chn_setspeed(rdch, p->rec_rate);
564                                 }
565                                 p->rec_rate = rdch->speed;
566                                 p->rec_format = rdch->format;
567                                 CHN_UNLOCK(rdch);
568                         } else {
569                                 p->rec_rate = 0;
570                                 p->rec_format = 0;
571                         }
572                 }
573                 break;
574
575         case AIOGCAP:     /* get capabilities */
576                 {
577                         snd_capabilities *p = (snd_capabilities *)arg;
578                         struct pcmchan_caps *pcaps = NULL, *rcaps = NULL;
579                         struct cdev *pdev;
580
581                         if (rdch) {
582                                 CHN_LOCK(rdch);
583                                 rcaps = chn_getcaps(rdch);
584                         }
585                         if (wrch) {
586                                 CHN_LOCK(wrch);
587                                 pcaps = chn_getcaps(wrch);
588                         }
589                         p->rate_min = max(rcaps? rcaps->minspeed : 0,
590                                           pcaps? pcaps->minspeed : 0);
591                         p->rate_max = min(rcaps? rcaps->maxspeed : 1000000,
592                                           pcaps? pcaps->maxspeed : 1000000);
593                         p->bufsize = min(rdch? sndbuf_getsize(rdch->bufsoft) : 1000000,
594                                          wrch? sndbuf_getsize(wrch->bufsoft) : 1000000);
595                         /* XXX bad on sb16 */
596                         p->formats = (rdch? chn_getformats(rdch) : 0xffffffff) &
597                                      (wrch? chn_getformats(wrch) : 0xffffffff);
598                         if (rdch && wrch)
599                                 p->formats |= (dsp_get_flags(i_dev) & SD_F_SIMPLEX)? 0 : AFMT_FULLDUPLEX;
600                         pdev = d->mixer_dev;
601                         p->mixers = 1; /* default: one mixer */
602                         p->inputs = pdev->si_drv1? mix_getdevs(pdev->si_drv1) : 0;
603                         p->left = p->right = 100;
604                         if (rdch)
605                                 CHN_UNLOCK(rdch);
606                         if (wrch)
607                                 CHN_UNLOCK(wrch);
608                 }
609                 break;
610
611         case AIOSTOP:
612                 if (*arg_i == AIOSYNC_PLAY && wrch) {
613                         CHN_LOCK(wrch);
614                         *arg_i = chn_abort(wrch);
615                         CHN_UNLOCK(wrch);
616                 } else if (*arg_i == AIOSYNC_CAPTURE && rdch) {
617                         CHN_LOCK(rdch);
618                         *arg_i = chn_abort(rdch);
619                         CHN_UNLOCK(rdch);
620                 } else {
621                         kprintf("AIOSTOP: bad channel 0x%x\n", *arg_i);
622                         *arg_i = 0;
623                 }
624                 break;
625
626         case AIOSYNC:
627                 kprintf("AIOSYNC chan 0x%03lx pos %lu unimplemented\n",
628                         ((snd_sync_parm *)arg)->chan, ((snd_sync_parm *)arg)->pos);
629                 break;
630 #endif
631         /*
632          * here follow the standard ioctls (filio.h etc.)
633          */
634         case FIONREAD: /* get # bytes to read */
635                 if (rdch) {
636                         CHN_LOCK(rdch);
637 /*                      if (rdch && rdch->bufhard.dl)
638                                 while (chn_rdfeed(rdch) == 0);
639 */
640                         *arg_i = sndbuf_getready(rdch->bufsoft);
641                         CHN_UNLOCK(rdch);
642                 } else {
643                         *arg_i = 0;
644                         ret = EINVAL;
645                 }
646                 break;
647
648         case FIOASYNC: /*set/clear async i/o */
649                 DEB( kprintf("FIOASYNC\n") ; )
650                 break;
651
652         case SNDCTL_DSP_NONBLOCK:
653         case FIONBIO: /* set/clear non-blocking i/o */
654                 if (rdch) {
655                         CHN_LOCK(rdch);
656                         if (*arg_i)
657                                 rdch->flags |= CHN_F_NBIO;
658                         else
659                                 rdch->flags &= ~CHN_F_NBIO;
660                         CHN_UNLOCK(rdch);
661                 }
662                 if (wrch) {
663                         CHN_LOCK(wrch);
664                         if (*arg_i)
665                                 wrch->flags |= CHN_F_NBIO;
666                         else
667                                 wrch->flags &= ~CHN_F_NBIO;
668                         CHN_UNLOCK(wrch);
669                 }
670                 break;
671
672         /*
673          * Finally, here is the linux-compatible ioctl interface
674          */
675 #define THE_REAL_SNDCTL_DSP_GETBLKSIZE _IOWR('P', 4, int)
676         case THE_REAL_SNDCTL_DSP_GETBLKSIZE:
677         case SNDCTL_DSP_GETBLKSIZE:
678                 chn = wrch ? wrch : rdch;
679                 if (chn) {
680                         CHN_LOCK(chn);
681                         *arg_i = sndbuf_getblksz(chn->bufsoft);
682                         CHN_UNLOCK(chn);
683                 } else {
684                         *arg_i = 0;
685                         ret = EINVAL;
686                 }
687                 break ;
688
689         case SNDCTL_DSP_SETBLKSIZE:
690                 RANGE(*arg_i, 16, 65536);
691                 if (wrch) {
692                         CHN_LOCK(wrch);
693                         chn_setblocksize(wrch, 2, *arg_i);
694                         CHN_UNLOCK(wrch);
695                 }
696                 if (rdch) {
697                         CHN_LOCK(rdch);
698                         chn_setblocksize(rdch, 2, *arg_i);
699                         CHN_UNLOCK(rdch);
700                 }
701                 break;
702
703         case SNDCTL_DSP_RESET:
704                 DEB(kprintf("dsp reset\n"));
705                 if (wrch) {
706                         CHN_LOCK(wrch);
707                         chn_abort(wrch);
708                         chn_resetbuf(wrch);
709                         CHN_UNLOCK(wrch);
710                 }
711                 if (rdch) {
712                         CHN_LOCK(rdch);
713                         chn_abort(rdch);
714                         chn_resetbuf(rdch);
715                         CHN_UNLOCK(rdch);
716                 }
717                 break;
718
719         case SNDCTL_DSP_SYNC:
720                 DEB(kprintf("dsp sync\n"));
721                 /* chn_sync may sleep */
722                 if (wrch) {
723                         CHN_LOCK(wrch);
724                         chn_sync(wrch, sndbuf_getsize(wrch->bufsoft) - 4);
725                         CHN_UNLOCK(wrch);
726                 }
727                 break;
728
729         case SNDCTL_DSP_SPEED:
730                 /* chn_setspeed may sleep */
731                 tmp = 0;
732                 if (wrch) {
733                         CHN_LOCK(wrch);
734                         ret = chn_setspeed(wrch, *arg_i);
735                         tmp = wrch->speed;
736                         CHN_UNLOCK(wrch);
737                 }
738                 if (rdch && ret == 0) {
739                         CHN_LOCK(rdch);
740                         ret = chn_setspeed(rdch, *arg_i);
741                         if (tmp == 0)
742                                 tmp = rdch->speed;
743                         CHN_UNLOCK(rdch);
744                 }
745                 *arg_i = tmp;
746                 break;
747
748         case SOUND_PCM_READ_RATE:
749                 chn = wrch ? wrch : rdch;
750                 if (chn) {
751                         CHN_LOCK(chn);
752                         *arg_i = chn->speed;
753                         CHN_UNLOCK(chn);
754                 } else {
755                         *arg_i = 0;
756                         ret = EINVAL;
757                 }
758                 break;
759
760         case SNDCTL_DSP_STEREO:
761                 tmp = -1;
762                 *arg_i = (*arg_i)? AFMT_STEREO : 0;
763                 if (wrch) {
764                         CHN_LOCK(wrch);
765                         ret = chn_setformat(wrch, (wrch->format & ~AFMT_STEREO) | *arg_i);
766                         tmp = (wrch->format & AFMT_STEREO)? 1 : 0;
767                         CHN_UNLOCK(wrch);
768                 }
769                 if (rdch && ret == 0) {
770                         CHN_LOCK(rdch);
771                         ret = chn_setformat(rdch, (rdch->format & ~AFMT_STEREO) | *arg_i);
772                         if (tmp == -1)
773                                 tmp = (rdch->format & AFMT_STEREO)? 1 : 0;
774                         CHN_UNLOCK(rdch);
775                 }
776                 *arg_i = tmp;
777                 break;
778
779         case SOUND_PCM_WRITE_CHANNELS:
780 /*      case SNDCTL_DSP_CHANNELS: ( == SOUND_PCM_WRITE_CHANNELS) */
781                 if (*arg_i != 0) {
782                         tmp = 0;
783                         *arg_i = (*arg_i != 1)? AFMT_STEREO : 0;
784                         if (wrch) {
785                                 CHN_LOCK(wrch);
786                                 ret = chn_setformat(wrch, (wrch->format & ~AFMT_STEREO) | *arg_i);
787                                 tmp = (wrch->format & AFMT_STEREO)? 2 : 1;
788                                 CHN_UNLOCK(wrch);
789                         }
790                         if (rdch && ret == 0) {
791                                 CHN_LOCK(rdch);
792                                 ret = chn_setformat(rdch, (rdch->format & ~AFMT_STEREO) | *arg_i);
793                                 if (tmp == 0)
794                                         tmp = (rdch->format & AFMT_STEREO)? 2 : 1;
795                                 CHN_UNLOCK(rdch);
796                         }
797                         *arg_i = tmp;
798                 } else {
799                         chn = wrch ? wrch : rdch;
800                         CHN_LOCK(chn);
801                         *arg_i = (chn->format & AFMT_STEREO) ? 2 : 1;
802                         CHN_UNLOCK(chn);
803                 }
804                 break;
805
806         case SOUND_PCM_READ_CHANNELS:
807                 chn = wrch ? wrch : rdch;
808                 if (chn) {
809                         CHN_LOCK(chn);
810                         *arg_i = (chn->format & AFMT_STEREO) ? 2 : 1;
811                         CHN_UNLOCK(chn);
812                 } else {
813                         *arg_i = 0;
814                         ret = EINVAL;
815                 }
816                 break;
817
818         case SNDCTL_DSP_GETFMTS:        /* returns a mask of supported fmts */
819                 chn = wrch ? wrch : rdch;
820                 if (chn) {
821                         CHN_LOCK(chn);
822                         *arg_i = chn_getformats(chn);
823                         CHN_UNLOCK(chn);
824                 } else {
825                         *arg_i = 0;
826                         ret = EINVAL;
827                 }
828                 break ;
829
830         case SNDCTL_DSP_SETFMT: /* sets _one_ format */
831                 if ((*arg_i != AFMT_QUERY)) {
832                         tmp = 0;
833                         if (wrch) {
834                                 CHN_LOCK(wrch);
835                                 ret = chn_setformat(wrch, (*arg_i) | (wrch->format & AFMT_STEREO));
836                                 tmp = wrch->format & ~AFMT_STEREO;
837                                 CHN_UNLOCK(wrch);
838                         }
839                         if (rdch && ret == 0) {
840                                 CHN_LOCK(rdch);
841                                 ret = chn_setformat(rdch, (*arg_i) | (rdch->format & AFMT_STEREO));
842                                 if (tmp == 0)
843                                         tmp = rdch->format & ~AFMT_STEREO;
844                                 CHN_UNLOCK(rdch);
845                         }
846                         *arg_i = tmp;
847                 } else {
848                         chn = wrch ? wrch : rdch;
849                         CHN_LOCK(chn);
850                         *arg_i = chn->format & ~AFMT_STEREO;
851                         CHN_UNLOCK(chn);
852                 }
853                 break;
854
855         case SNDCTL_DSP_SETFRAGMENT:
856                 DEB(kprintf("SNDCTL_DSP_SETFRAGMENT 0x%08x\n", *(int *)arg));
857                 {
858                         u_int32_t fragln = (*arg_i) & 0x0000ffff;
859                         u_int32_t maxfrags = ((*arg_i) & 0xffff0000) >> 16;
860                         u_int32_t fragsz;
861                         u_int32_t r_maxfrags, r_fragsz;
862
863                         RANGE(fragln, 4, 16);
864                         fragsz = 1 << fragln;
865
866                         if (maxfrags == 0)
867                                 maxfrags = CHN_2NDBUFMAXSIZE / fragsz;
868                         if (maxfrags < 2)
869                                 maxfrags = 2;
870                         if (maxfrags * fragsz > CHN_2NDBUFMAXSIZE)
871                                 maxfrags = CHN_2NDBUFMAXSIZE / fragsz;
872
873                         DEB(kprintf("SNDCTL_DSP_SETFRAGMENT %d frags, %d sz\n", maxfrags, fragsz));
874                         if (rdch) {
875                                 CHN_LOCK(rdch);
876                                 ret = chn_setblocksize(rdch, maxfrags, fragsz);
877                                 r_maxfrags = sndbuf_getblkcnt(rdch->bufsoft);
878                                 r_fragsz = sndbuf_getblksz(rdch->bufsoft);
879                                 CHN_UNLOCK(rdch);
880                         } else {
881                                 r_maxfrags = maxfrags;
882                                 r_fragsz = fragsz;
883                         }
884                         if (wrch && ret == 0) {
885                                 CHN_LOCK(wrch);
886                                 ret = chn_setblocksize(wrch, maxfrags, fragsz);
887                                 maxfrags = sndbuf_getblkcnt(wrch->bufsoft);
888                                 fragsz = sndbuf_getblksz(wrch->bufsoft);
889                                 CHN_UNLOCK(wrch);
890                         } else { /* use whatever came from the read channel */
891                                 maxfrags = r_maxfrags;
892                                 fragsz = r_fragsz;
893                         }
894
895                         fragln = 0;
896                         while (fragsz > 1) {
897                                 fragln++;
898                                 fragsz >>= 1;
899                         }
900                         *arg_i = (maxfrags << 16) | fragln;
901                 }
902                 break;
903
904         case SNDCTL_DSP_GETISPACE:
905                 /* return the size of data available in the input queue */
906                 {
907                         audio_buf_info *a = (audio_buf_info *)arg;
908                         if (rdch) {
909                                 struct snd_dbuf *bs = rdch->bufsoft;
910
911                                 CHN_LOCK(rdch);
912                                 a->bytes = sndbuf_getready(bs);
913                                 a->fragments = a->bytes / sndbuf_getblksz(bs);
914                                 a->fragstotal = sndbuf_getblkcnt(bs);
915                                 a->fragsize = sndbuf_getblksz(bs);
916                                 CHN_UNLOCK(rdch);
917                         }
918                 }
919                 break;
920
921         case SNDCTL_DSP_GETOSPACE:
922                 /* return space available in the output queue */
923                 {
924                         audio_buf_info *a = (audio_buf_info *)arg;
925                         if (wrch) {
926                                 struct snd_dbuf *bs = wrch->bufsoft;
927
928                                 CHN_LOCK(wrch);
929                                 /* XXX abusive DMA update: chn_wrupdate(wrch); */
930                                 a->bytes = sndbuf_getfree(bs);
931                                 a->fragments = a->bytes / sndbuf_getblksz(bs);
932                                 a->fragstotal = sndbuf_getblkcnt(bs);
933                                 a->fragsize = sndbuf_getblksz(bs);
934                                 CHN_UNLOCK(wrch);
935                         }
936                 }
937                 break;
938
939         case SNDCTL_DSP_GETIPTR:
940                 {
941                         count_info *a = (count_info *)arg;
942                         if (rdch) {
943                                 struct snd_dbuf *bs = rdch->bufsoft;
944
945                                 CHN_LOCK(rdch);
946                                 /* XXX abusive DMA update: chn_rdupdate(rdch); */
947                                 a->bytes = sndbuf_gettotal(bs);
948                                 a->blocks = sndbuf_getblocks(bs) - rdch->blocks;
949                                 a->ptr = sndbuf_getreadyptr(bs);
950                                 rdch->blocks = sndbuf_getblocks(bs);
951                                 CHN_UNLOCK(rdch);
952                         } else
953                                 ret = EINVAL;
954                 }
955                 break;
956
957         case SNDCTL_DSP_GETOPTR:
958                 {
959                         count_info *a = (count_info *)arg;
960                         if (wrch) {
961                                 struct snd_dbuf *bs = wrch->bufsoft;
962
963                                 CHN_LOCK(wrch);
964                                 /* XXX abusive DMA update: chn_wrupdate(wrch); */
965                                 a->bytes = sndbuf_gettotal(bs);
966                                 a->blocks = sndbuf_getblocks(bs) - wrch->blocks;
967                                 a->ptr = sndbuf_getreadyptr(bs);
968                                 wrch->blocks = sndbuf_getblocks(bs);
969                                 CHN_UNLOCK(wrch);
970                         } else
971                                 ret = EINVAL;
972                 }
973                 break;
974
975         case SNDCTL_DSP_GETCAPS:
976                 *arg_i = DSP_CAP_REALTIME | DSP_CAP_MMAP | DSP_CAP_TRIGGER;
977                 if (rdch && wrch && !(dsp_get_flags(i_dev) & SD_F_SIMPLEX))
978                         *arg_i |= DSP_CAP_DUPLEX;
979                 break;
980
981         case SOUND_PCM_READ_BITS:
982                 chn = wrch ? wrch : rdch;
983                 if (chn) {
984                         CHN_LOCK(chn);
985                         if (chn->format & AFMT_8BIT)
986                                 *arg_i = 8;
987                         else if (chn->format & AFMT_16BIT)
988                                 *arg_i = 16;
989                         else if (chn->format & AFMT_24BIT)
990                                 *arg_i = 24;
991                         else if (chn->format & AFMT_32BIT)
992                                 *arg_i = 32;
993                         else
994                                 ret = EINVAL;
995                         CHN_UNLOCK(chn);
996                 } else {
997                         *arg_i = 0;
998                         ret = EINVAL;
999                 }
1000                 break;
1001
1002         case SNDCTL_DSP_SETTRIGGER:
1003                 if (rdch) {
1004                         CHN_LOCK(rdch);
1005                         rdch->flags &= ~(CHN_F_TRIGGERED | CHN_F_NOTRIGGER);
1006                         if (*arg_i & PCM_ENABLE_INPUT)
1007                                 chn_start(rdch, 1);
1008                         else
1009                                 rdch->flags |= CHN_F_NOTRIGGER;
1010                         CHN_UNLOCK(rdch);
1011                 }
1012                 if (wrch) {
1013                         CHN_LOCK(wrch);
1014                         wrch->flags &= ~(CHN_F_TRIGGERED | CHN_F_NOTRIGGER);
1015                         if (*arg_i & PCM_ENABLE_OUTPUT)
1016                                 chn_start(wrch, 1);
1017                         else
1018                                 wrch->flags |= CHN_F_NOTRIGGER;
1019                         CHN_UNLOCK(wrch);
1020                 }
1021                 break;
1022
1023         case SNDCTL_DSP_GETTRIGGER:
1024                 *arg_i = 0;
1025                 if (wrch) {
1026                         CHN_LOCK(wrch);
1027                         if (wrch->flags & CHN_F_TRIGGERED)
1028                                 *arg_i |= PCM_ENABLE_OUTPUT;
1029                         CHN_UNLOCK(wrch);
1030                 }
1031                 if (rdch) {
1032                         CHN_LOCK(rdch);
1033                         if (rdch->flags & CHN_F_TRIGGERED)
1034                                 *arg_i |= PCM_ENABLE_INPUT;
1035                         CHN_UNLOCK(rdch);
1036                 }
1037                 break;
1038
1039         case SNDCTL_DSP_GETODELAY:
1040                 if (wrch) {
1041                         struct snd_dbuf *b = wrch->bufhard;
1042                         struct snd_dbuf *bs = wrch->bufsoft;
1043
1044                         CHN_LOCK(wrch);
1045                         /* XXX abusive DMA update: chn_wrupdate(wrch); */
1046                         *arg_i = sndbuf_getready(b) + sndbuf_getready(bs);
1047                         CHN_UNLOCK(wrch);
1048                 } else
1049                         ret = EINVAL;
1050                 break;
1051
1052         case SNDCTL_DSP_POST:
1053                 if (wrch) {
1054                         CHN_LOCK(wrch);
1055                         wrch->flags &= ~CHN_F_NOTRIGGER;
1056                         chn_start(wrch, 1);
1057                         CHN_UNLOCK(wrch);
1058                 }
1059                 break;
1060
1061         case SNDCTL_DSP_SETDUPLEX:
1062                 /*
1063                  * switch to full-duplex mode if card is in half-duplex
1064                  * mode and is able to work in full-duplex mode
1065                  */
1066                 if (rdch && wrch && (dsp_get_flags(i_dev) & SD_F_SIMPLEX))
1067                         dsp_set_flags(i_dev, dsp_get_flags(i_dev)^SD_F_SIMPLEX);
1068                 break;
1069
1070         case SNDCTL_DSP_MAPINBUF:
1071         case SNDCTL_DSP_MAPOUTBUF:
1072         case SNDCTL_DSP_SETSYNCRO:
1073                 /* undocumented */
1074
1075         case SNDCTL_DSP_SUBDIVIDE:
1076         case SOUND_PCM_WRITE_FILTER:
1077         case SOUND_PCM_READ_FILTER:
1078                 /* dunno what these do, don't sound important */
1079
1080         default:
1081                 DEB(kprintf("default ioctl fn 0x%08lx fail\n", cmd));
1082                 ret = EINVAL;
1083                 break;
1084         }
1085         relchns(i_dev, rdch, wrch, 0);
1086         return ret;
1087 }
1088
1089 static struct filterops dsp_read_filtops =
1090         { FILTEROP_ISFD, NULL, dsp_filter_detach, dsp_filter_read };
1091 static struct filterops dsp_write_filtops =
1092         { FILTEROP_ISFD, NULL, dsp_filter_detach, dsp_filter_write };
1093
1094 static int
1095 dsp_kqfilter(struct dev_kqfilter_args *ap)
1096 {
1097         struct knote *kn = ap->a_kn;
1098         struct klist *klist;
1099         struct cdev *i_dev = ap->a_head.a_dev;
1100         struct pcm_channel *wrch = NULL, *rdch = NULL;
1101         struct snd_dbuf *bs = NULL;
1102
1103         getchns(i_dev, &rdch, &wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
1104
1105         switch (kn->kn_filter) {
1106         case EVFILT_READ:
1107                 if (rdch) {
1108                         kn->kn_fop = &dsp_read_filtops;
1109                         kn->kn_hook = (caddr_t)rdch;
1110                         bs = rdch->bufsoft;
1111                         ap->a_result = 0;
1112                 }
1113                 break;
1114         case EVFILT_WRITE:
1115                 if (wrch) {
1116                         kn->kn_fop = &dsp_write_filtops;
1117                         kn->kn_hook = (caddr_t)wrch;
1118                         bs = wrch->bufsoft;
1119                         ap->a_result = 0;
1120                 }
1121                 break;
1122         default:
1123                 ap->a_result = EOPNOTSUPP;
1124                 break;
1125         }
1126
1127         if (ap->a_result == 0) {
1128                 klist = &sndbuf_getkq(bs)->ki_note;
1129                 knote_insert(klist, kn);
1130         }
1131
1132         relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
1133
1134         return (0);
1135 }
1136
1137 static void
1138 dsp_filter_detach(struct knote *kn)
1139 {
1140         struct pcm_channel *ch = (struct pcm_channel *)kn->kn_hook;
1141         struct snd_dbuf *bs = ch->bufsoft;
1142         struct klist *klist;
1143
1144         CHN_LOCK(ch);
1145         klist = &sndbuf_getkq(bs)->ki_note;
1146         knote_remove(klist, kn);
1147         CHN_UNLOCK(ch);
1148 }
1149
1150 static int
1151 dsp_filter_read(struct knote *kn, long hint)
1152 {
1153         struct pcm_channel *rdch = (struct pcm_channel *)kn->kn_hook;
1154         struct thread *td = curthread;
1155         int ready;
1156
1157         CHN_LOCK(rdch);
1158         ready = chn_poll(rdch, 1, td);
1159         CHN_UNLOCK(rdch);
1160
1161         return (ready);
1162 }
1163
1164 static int
1165 dsp_filter_write(struct knote *kn, long hint)
1166 {
1167         struct pcm_channel *wrch = (struct pcm_channel *)kn->kn_hook;
1168         struct thread *td = curthread;
1169         int ready;
1170
1171         CHN_LOCK(wrch);
1172         ready = chn_poll(wrch, 1, td);
1173         CHN_UNLOCK(wrch);
1174
1175         return (ready);
1176 }
1177
1178 static int
1179 dsp_mmap(struct dev_mmap_args *ap)
1180 {
1181         struct cdev *i_dev = ap->a_head.a_dev;
1182         vm_offset_t offset = ap->a_offset;
1183         int nprot = ap->a_nprot;
1184         struct pcm_channel *wrch = NULL, *rdch = NULL, *c;
1185
1186         if (nprot & PROT_EXEC)
1187                 return -1;
1188
1189         getchns(i_dev, &rdch, &wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
1190 #if 0
1191         /*
1192          * XXX the linux api uses the nprot to select read/write buffer
1193          * our vm system doesn't allow this, so force write buffer
1194          */
1195
1196         if (wrch && (nprot & PROT_WRITE)) {
1197                 c = wrch;
1198         } else if (rdch && (nprot & PROT_READ)) {
1199                 c = rdch;
1200         } else {
1201                 return -1;
1202         }
1203 #else
1204         c = wrch;
1205 #endif
1206
1207         if (c == NULL) {
1208                 relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
1209                 return -1;
1210         }
1211
1212         if (offset >= sndbuf_getsize(c->bufsoft)) {
1213                 relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
1214                 return -1;
1215         }
1216
1217         if (!(c->flags & CHN_F_MAPPED))
1218                 c->flags |= CHN_F_MAPPED;
1219
1220         ap->a_result = atop(vtophys(sndbuf_getbufofs(c->bufsoft, offset)));
1221         relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR);
1222
1223         return (0);
1224 }
1225
1226 /*
1227  *    for i = 0 to channels of device N
1228  *      if dspN.i isn't busy and in the right dir, create a dev_t and return it
1229  */
1230 int
1231 dsp_clone(struct dev_clone_args *ap)
1232 {
1233         struct cdev *i_dev = ap->a_head.a_dev;
1234         struct cdev *pdev;
1235         struct snddev_info *pcm_dev;
1236         struct snddev_channel *pcm_chan;
1237         struct pcm_channel *c;
1238         int err = EBUSY;
1239         int dir;
1240
1241         pcm_dev = dsp_get_info(i_dev);
1242
1243         if (pcm_dev == NULL)
1244                 return (ENODEV);
1245
1246         dir = ap->a_mode & FWRITE ? PCMDIR_PLAY : PCMDIR_REC;
1247
1248 retry_chnalloc:
1249         SLIST_FOREACH(pcm_chan, &pcm_dev->channels, link) {
1250                 c = pcm_chan->channel;
1251                 CHN_LOCK(c);
1252                 pdev = pcm_chan->dsp_dev;
1253
1254                 /*
1255                  * Make sure that the channel has not been assigned
1256                  * to a device yet (and vice versa).
1257                  * The direction has to match and the channel may not
1258                  * be busy.
1259                  * dsp_open will use exactly this channel number to
1260                  * avoid (possible?) races between clone and open.
1261                  */
1262                 if (pdev == NULL && c->direction == dir &&
1263                     !(c->flags & CHN_F_BUSY)) {
1264                         CHN_UNLOCK(c);
1265                         pcm_lock(pcm_dev);
1266                         pcm_chan->dsp_dev = make_only_dev(&dsp_cdevsw,
1267                                 PCMMKMINOR(PCMUNIT(i_dev), pcm_chan->chan_num),
1268                                 UID_ROOT, GID_WHEEL,
1269                                 0666,
1270                                 "%s.%d",
1271                                 devtoname(i_dev),
1272                                 pcm_chan->chan_num);
1273                         pcm_unlock(pcm_dev);
1274
1275                         ap->a_dev = pcm_chan->dsp_dev;
1276                         return (0);
1277                 }
1278                 CHN_UNLOCK(c);
1279
1280 #if DEBUG
1281                 if ((pdev != NULL) && (pdev->si_drv1 == NULL) && (pdev->si_drv2 == NULL)) {
1282                         kprintf("%s: dangling device\n", devtoname(pdev));
1283                 }
1284 #endif
1285         }
1286
1287         /* no channel available, create vchannel */
1288         if (dir == PCMDIR_PLAY &&
1289             pcm_dev->vchancount > 0 &&
1290             pcm_dev->vchancount < snd_maxautovchans &&
1291             pcm_dev->devcount < PCMMAXCHAN) {
1292                 err = pcm_setvchans(pcm_dev, pcm_dev->vchancount + 1);
1293                 if (err == 0)
1294                         goto retry_chnalloc;
1295                 /*
1296                  * If we can't use vchans, because the main output is
1297                  * blocked for something else, we should not return
1298                  * any vchan create error, but the more descriptive
1299                  * EBUSY.
1300                  * After all, the user didn't ask us to clone, but
1301                  * only opened /dev/dsp.
1302                  */
1303                 err = EBUSY;
1304         }
1305
1306         return (err);
1307 }