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