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