xref: /freebsd/sys/dev/sound/pcm/dsp.c (revision 47efa8128268c35ac8f0a552d7a7ce43cd1c5925)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org>
5  * Portions Copyright (c) Ryan Beasley <ryan.beasley@gmail.com> - GSoC 2006
6  * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org>
7  * All rights reserved.
8  * Copyright (c) 2024-2025 The FreeBSD Foundation
9  *
10  * Portions of this software were developed by Christos Margiolis
11  * <christos@FreeBSD.org> under sponsorship from the FreeBSD Foundation.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #ifdef HAVE_KERNEL_OPTION_HEADERS
36 #include "opt_snd.h"
37 #endif
38 
39 #include <dev/sound/pcm/sound.h>
40 #include <dev/sound/pcm/vchan.h>
41 #include <sys/ctype.h>
42 #include <sys/lock.h>
43 #include <sys/rwlock.h>
44 #include <sys/sysent.h>
45 
46 #include <vm/vm.h>
47 #include <vm/vm_object.h>
48 #include <vm/vm_page.h>
49 #include <vm/vm_pager.h>
50 
51 struct dsp_cdevpriv {
52 	struct snddev_info *sc;
53 	struct pcm_channel *rdch;
54 	struct pcm_channel *wrch;
55 };
56 
57 static int dsp_mmap_allow_prot_exec = -1;
58 SYSCTL_INT(_hw_snd, OID_AUTO, compat_linux_mmap, CTLFLAG_RWTUN,
59     &dsp_mmap_allow_prot_exec, 0,
60     "linux mmap compatibility (-1=force-disable 0=auto)");
61 
62 static int dsp_basename_clone = 1;
63 SYSCTL_INT(_hw_snd, OID_AUTO, basename_clone, CTLFLAG_RWTUN,
64     &dsp_basename_clone, 0,
65     "DSP basename cloning (0: Disable; 1: Enabled)");
66 
67 #define DSP_REGISTERED(x)	(PCM_REGISTERED(x) && (x)->dsp_dev != NULL)
68 
69 #define DSP_F_VALID(x)		((x) & (FREAD | FWRITE))
70 #define DSP_F_DUPLEX(x)		(((x) & (FREAD | FWRITE)) == (FREAD | FWRITE))
71 #define DSP_F_SIMPLEX(x)	(!DSP_F_DUPLEX(x))
72 #define DSP_F_READ(x)		((x) & FREAD)
73 #define DSP_F_WRITE(x)		((x) & FWRITE)
74 
75 static d_open_t dsp_open;
76 static d_read_t dsp_read;
77 static d_write_t dsp_write;
78 static d_ioctl_t dsp_ioctl;
79 static d_poll_t dsp_poll;
80 static d_mmap_single_t dsp_mmap_single;
81 static d_kqfilter_t dsp_kqfilter;
82 
83 struct cdevsw dsp_cdevsw = {
84 	.d_version	= D_VERSION,
85 	.d_open		= dsp_open,
86 	.d_read		= dsp_read,
87 	.d_write	= dsp_write,
88 	.d_ioctl	= dsp_ioctl,
89 	.d_poll		= dsp_poll,
90 	.d_kqfilter	= dsp_kqfilter,
91 	.d_mmap_single	= dsp_mmap_single,
92 	.d_name		= "dsp",
93 };
94 
95 static eventhandler_tag dsp_ehtag = NULL;
96 
97 static int dsp_oss_syncgroup(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_syncgroup *group);
98 static int dsp_oss_syncstart(int sg_id);
99 static int dsp_oss_policy(struct pcm_channel *wrch, struct pcm_channel *rdch, int policy);
100 static int dsp_oss_cookedmode(struct pcm_channel *wrch, struct pcm_channel *rdch, int enabled);
101 static int dsp_oss_getchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map);
102 static int dsp_oss_setchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map);
103 static int dsp_oss_getchannelmask(struct pcm_channel *wrch, struct pcm_channel *rdch, int *mask);
104 #ifdef OSSV4_EXPERIMENT
105 static int dsp_oss_getlabel(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_label_t *label);
106 static int dsp_oss_setlabel(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_label_t *label);
107 static int dsp_oss_getsong(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *song);
108 static int dsp_oss_setsong(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *song);
109 static int dsp_oss_setname(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *name);
110 #endif
111 
112 int
113 dsp_make_dev(device_t dev)
114 {
115 	struct make_dev_args devargs;
116 	struct snddev_info *sc;
117 	int err, unit;
118 
119 	sc = device_get_softc(dev);
120 	unit = device_get_unit(dev);
121 
122 	make_dev_args_init(&devargs);
123 	devargs.mda_devsw = &dsp_cdevsw;
124 	devargs.mda_uid = UID_ROOT;
125 	devargs.mda_gid = GID_AUDIO;
126 	devargs.mda_mode = 0660;
127 	devargs.mda_si_drv1 = sc;
128 	err = make_dev_s(&devargs, &sc->dsp_dev, "dsp%d", unit);
129 	if (err != 0) {
130 		device_printf(dev, "failed to create dsp%d: error %d",
131 		    unit, err);
132 		return (ENXIO);
133 	}
134 
135 	return (0);
136 }
137 
138 void
139 dsp_destroy_dev(device_t dev)
140 {
141 	struct snddev_info *d;
142 
143 	d = device_get_softc(dev);
144 	destroy_dev(d->dsp_dev);
145 }
146 
147 static int
148 dsp_chn_alloc(struct snddev_info *d, struct pcm_channel **ch, int direction,
149     int flags, struct thread *td)
150 {
151 	struct pcm_channel *c;
152 	char *comm;
153 	pid_t pid;
154 	int err;
155 	bool vdir_enabled;
156 
157 	KASSERT(d != NULL && ch != NULL &&
158 	    (direction == PCMDIR_PLAY || direction == PCMDIR_REC),
159 	    ("%s(): invalid d=%p ch=%p direction=%d",
160 	    __func__, d, ch, direction));
161 	PCM_BUSYASSERT(d);
162 
163 	pid = td->td_proc->p_pid;
164 	comm = td->td_proc->p_comm;
165 
166 	vdir_enabled = (direction == PCMDIR_PLAY && d->flags & SD_F_PVCHANS) ||
167 	    (direction == PCMDIR_REC && d->flags & SD_F_RVCHANS);
168 
169 	*ch = NULL;
170 	CHN_FOREACH(c, d, channels.pcm.primary) {
171 		CHN_LOCK(c);
172 		if (c->direction != direction) {
173 			CHN_UNLOCK(c);
174 			continue;
175 		}
176 		/* Find an available primary channel to use. */
177 		if ((c->flags & CHN_F_BUSY) == 0 ||
178 		    (vdir_enabled && (c->flags & CHN_F_HAS_VCHAN)))
179 			break;
180 		CHN_UNLOCK(c);
181 	}
182 	if (c == NULL)
183 		return (EBUSY);
184 
185 	/*
186 	 * We can have the following cases:
187 	 * - vchans are enabled, add a new vchan to the primary channel.
188 	 * - vchans are disabled, use the primary channel directly.
189 	 */
190 	if (vdir_enabled && ((c->flags & CHN_F_BUSY) == 0 ||
191 	    c->flags & CHN_F_HAS_VCHAN)) {
192 		err = vchan_create(c, ch);
193 		CHN_UNLOCK(c);
194 		if (err != 0)
195 			return (err);
196 		CHN_LOCK(*ch);
197 	} else if ((c->flags & CHN_F_BUSY) == 0) {
198 		*ch = c;
199 	} else {
200 		CHN_UNLOCK(c);
201 		return (ENODEV);
202 	}
203 
204 	(*ch)->flags |= CHN_F_BUSY;
205 	if (flags & O_NONBLOCK)
206 		(*ch)->flags |= CHN_F_NBIO;
207 	if (flags & O_EXCL)
208 		(*ch)->flags |= CHN_F_EXCLUSIVE;
209 	(*ch)->pid = pid;
210 	strlcpy((*ch)->comm, (comm != NULL) ? comm : CHN_COMM_UNKNOWN,
211 	    sizeof((*ch)->comm));
212 
213 	if ((err = chn_reset(*ch, (*ch)->format, (*ch)->speed)) != 0)
214 		return (err);
215 	chn_vpc_reset(*ch, SND_VOL_C_PCM, 0);
216 
217 	CHN_UNLOCK(*ch);
218 
219 	return (0);
220 }
221 
222 static void
223 dsp_close(void *data)
224 {
225 	struct dsp_cdevpriv *priv = data;
226 	struct pcm_channel *rdch, *wrch, *parent;
227 	struct snddev_info *d;
228 	int sg_ids;
229 
230 	if (priv == NULL)
231 		return;
232 
233 	d = priv->sc;
234 	/* At this point pcm_unregister() will destroy all channels anyway. */
235 	if (!DSP_REGISTERED(d))
236 		goto skip;
237 
238 	PCM_GIANT_ENTER(d);
239 
240 	PCM_LOCK(d);
241 	PCM_WAIT(d);
242 	PCM_ACQUIRE(d);
243 
244 	rdch = priv->rdch;
245 	wrch = priv->wrch;
246 
247 	if (rdch != NULL)
248 		CHN_REMOVE(d, rdch, channels.pcm.opened);
249 	if (wrch != NULL)
250 		CHN_REMOVE(d, wrch, channels.pcm.opened);
251 
252 	if (rdch != NULL || wrch != NULL) {
253 		PCM_UNLOCK(d);
254 		if (rdch != NULL) {
255 			/*
256 			 * The channel itself need not be locked because:
257 			 *   a)  Adding a channel to a syncgroup happens only
258 			 *       in dsp_ioctl(), which cannot run concurrently
259 			 *       to dsp_close().
260 			 *   b)  The syncmember pointer (sm) is protected by
261 			 *       the global syncgroup list lock.
262 			 *   c)  A channel can't just disappear, invalidating
263 			 *       pointers, unless it's closed/dereferenced
264 			 *       first.
265 			 */
266 			PCM_SG_LOCK();
267 			sg_ids = chn_syncdestroy(rdch);
268 			PCM_SG_UNLOCK();
269 			if (sg_ids != 0)
270 				free_unr(pcmsg_unrhdr, sg_ids);
271 
272 			/*
273 			 * Go through the channel abort/flush path for both
274 			 * primary and virtual channels to ensure that, in the
275 			 * case of vchans, the stream is always properly
276 			 * stopped, and the primary channels do not keep being
277 			 * interrupted even if all vchans are gone.
278 			 */
279 			CHN_LOCK(rdch);
280 			chn_abort(rdch); /* won't sleep */
281 			rdch->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP |
282 			    CHN_F_DEAD | CHN_F_EXCLUSIVE | CHN_F_NBIO);
283 			chn_reset(rdch, 0, 0);
284 			chn_release(rdch);
285 			if (rdch->flags & CHN_F_VIRTUAL) {
286 				parent = rdch->parentchannel;
287 				CHN_LOCK(parent);
288 				CHN_LOCK(rdch);
289 				vchan_destroy(rdch);
290 				CHN_UNLOCK(parent);
291 			}
292 		}
293 		if (wrch != NULL) {
294 			/*
295 			 * Please see block above.
296 			 */
297 			PCM_SG_LOCK();
298 			sg_ids = chn_syncdestroy(wrch);
299 			PCM_SG_UNLOCK();
300 			if (sg_ids != 0)
301 				free_unr(pcmsg_unrhdr, sg_ids);
302 
303 			CHN_LOCK(wrch);
304 			chn_flush(wrch); /* may sleep */
305 			wrch->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP |
306 			    CHN_F_DEAD | CHN_F_EXCLUSIVE | CHN_F_NBIO);
307 			chn_reset(wrch, 0, 0);
308 			chn_release(wrch);
309 			if (wrch->flags & CHN_F_VIRTUAL) {
310 				parent = wrch->parentchannel;
311 				CHN_LOCK(parent);
312 				CHN_LOCK(wrch);
313 				vchan_destroy(wrch);
314 				CHN_UNLOCK(parent);
315 			}
316 		}
317 		PCM_LOCK(d);
318 	}
319 
320 	PCM_RELEASE(d);
321 	PCM_UNLOCK(d);
322 
323 	PCM_GIANT_LEAVE(d);
324 skip:
325 	free(priv, M_DEVBUF);
326 	priv = NULL;
327 }
328 
329 static int
330 dsp_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
331 {
332 	struct dsp_cdevpriv *priv;
333 	struct pcm_channel *ch;
334 	struct snddev_info *d;
335 	int error, dir;
336 
337 	/* Kind of impossible.. */
338 	if (i_dev == NULL || td == NULL)
339 		return (ENODEV);
340 
341 	d = i_dev->si_drv1;
342 	if (!DSP_REGISTERED(d))
343 		return (EBADF);
344 
345 	if (PCM_CHANCOUNT(d) >= PCM_MAXCHANS)
346 		return (ENOMEM);
347 
348 	priv = malloc(sizeof(*priv), M_DEVBUF, M_WAITOK | M_ZERO);
349 	priv->sc = d;
350 
351 	error = devfs_set_cdevpriv(priv, dsp_close);
352 	if (error != 0)
353 		return (error);
354 
355 	PCM_GIANT_ENTER(d);
356 
357 	/* Lock snddev so nobody else can monkey with it. */
358 	PCM_LOCK(d);
359 	PCM_WAIT(d);
360 
361 	error = 0;
362 	if (!DSP_F_VALID(flags))
363 		error = EINVAL;
364 	else if (!DSP_F_DUPLEX(flags) &&
365 	    ((DSP_F_READ(flags) && d->reccount == 0) ||
366 	    (DSP_F_WRITE(flags) && d->playcount == 0)))
367 		error = ENOTSUP;
368 	if (pcm_getflags(d->dev) & SD_F_SIMPLEX) {
369 		if (DSP_F_DUPLEX(flags)) {
370 			/*
371 			 * If no channels are opened yet, and we request
372 			 * DUPLEX, limit to playback only, otherwise open one
373 			 * channel in a direction that already exists.
374 			 */
375 			if (CHN_EMPTY(d, channels.pcm.opened)) {
376 				if (d->playcount > 0)
377 					flags &= ~FREAD;
378 				else if (d->reccount > 0)
379 					flags &= ~FWRITE;
380 			} else {
381 				ch = CHN_FIRST(d, channels.pcm.opened);
382 				if (ch->direction == PCMDIR_PLAY)
383 					flags &= ~FREAD;
384 				else if (ch->direction == PCMDIR_REC)
385 					flags &= ~FWRITE;
386 			}
387 		} else if (!CHN_EMPTY(d, channels.pcm.opened)) {
388 			/*
389 			 * If we requested SIMPLEX, make sure we do not open a
390 			 * channel in the opposite direction.
391 			 */
392 			ch = CHN_FIRST(d, channels.pcm.opened);
393 			dir = DSP_F_READ(flags) ? PCMDIR_REC : PCMDIR_PLAY;
394 			if (ch->direction != dir)
395 				error = ENOTSUP;
396 		}
397 	}
398 	if (error != 0) {
399 		PCM_UNLOCK(d);
400 		PCM_GIANT_EXIT(d);
401 		return (error);
402 	}
403 
404 	/*
405 	 * That is just enough. Acquire and unlock pcm lock so
406 	 * the other will just have to wait until we finish doing
407 	 * everything.
408 	 */
409 	PCM_ACQUIRE(d);
410 	PCM_UNLOCK(d);
411 
412 	if (DSP_F_WRITE(flags)) {
413 		error = dsp_chn_alloc(d, &priv->wrch, PCMDIR_PLAY, flags, td);
414 		if (error != 0) {
415 			PCM_RELEASE_QUICK(d);
416 			PCM_GIANT_EXIT(d);
417 			return (error);
418 		}
419 		PCM_LOCK(d);
420 		CHN_INSERT_HEAD(d, priv->wrch, channels.pcm.opened);
421 		PCM_UNLOCK(d);
422 	}
423 	if (DSP_F_READ(flags)) {
424 		error = dsp_chn_alloc(d, &priv->rdch, PCMDIR_REC, flags, td);
425 		if (error != 0) {
426 			PCM_RELEASE_QUICK(d);
427 			PCM_GIANT_EXIT(d);
428 			return (error);
429 		}
430 		PCM_LOCK(d);
431 		CHN_INSERT_HEAD(d, priv->rdch, channels.pcm.opened);
432 		PCM_UNLOCK(d);
433 	}
434 
435 	PCM_RELEASE_QUICK(d);
436 	PCM_GIANT_LEAVE(d);
437 
438 	return (0);
439 }
440 
441 static __inline int
442 dsp_io_ops(struct dsp_cdevpriv *priv, struct uio *buf)
443 {
444 	struct snddev_info *d;
445 	struct pcm_channel *ch;
446 	int (*chn_io)(struct pcm_channel *, struct uio *);
447 	int ret;
448 
449 	d = priv->sc;
450 	if (!DSP_REGISTERED(d))
451 		return (EBADF);
452 
453 	PCM_GIANT_ENTER(d);
454 
455 	switch (buf->uio_rw) {
456 	case UIO_READ:
457 		ch = priv->rdch;
458 		chn_io = chn_read;
459 		break;
460 	case UIO_WRITE:
461 		ch = priv->wrch;
462 		chn_io = chn_write;
463 		break;
464 	}
465 	if (ch == NULL) {
466 		PCM_GIANT_EXIT(d);
467 		return (ENXIO);
468 	}
469 	CHN_LOCK(ch);
470 
471 	if (!(ch->flags & CHN_F_BUSY) ||
472 	    (ch->flags & (CHN_F_MMAP | CHN_F_DEAD))) {
473 		CHN_UNLOCK(ch);
474 		PCM_GIANT_EXIT(d);
475 		return (ENXIO);
476 	} else if (!(ch->flags & CHN_F_RUNNING))
477 		ch->flags |= CHN_F_RUNNING;
478 
479 	/*
480 	 * chn_read/write must give up channel lock in order to copy bytes
481 	 * from/to userland, so up the "in progress" counter to make sure
482 	 * someone else doesn't come along and muss up the buffer.
483 	 */
484 	ch->inprog++;
485 	ret = chn_io(ch, buf);
486 	ch->inprog--;
487 
488 	CHN_BROADCAST(&ch->cv);
489 	CHN_UNLOCK(ch);
490 
491 	PCM_GIANT_LEAVE(d);
492 
493 	return (ret);
494 }
495 
496 static int
497 dsp_read(struct cdev *i_dev, struct uio *buf, int flag)
498 {
499 	struct dsp_cdevpriv *priv;
500 	int err;
501 
502 	if ((err = devfs_get_cdevpriv((void **)&priv)) != 0)
503 		return (err);
504 	return (dsp_io_ops(priv, buf));
505 }
506 
507 static int
508 dsp_write(struct cdev *i_dev, struct uio *buf, int flag)
509 {
510 	struct dsp_cdevpriv *priv;
511 	int err;
512 
513 	if ((err = devfs_get_cdevpriv((void **)&priv)) != 0)
514 		return (err);
515 	return (dsp_io_ops(priv, buf));
516 }
517 
518 static int
519 dsp_ioctl_channel(struct dsp_cdevpriv *priv, struct pcm_channel *ch,
520     u_long cmd, caddr_t arg)
521 {
522 	struct snddev_info *d;
523 	struct pcm_channel *rdch, *wrch;
524 	int j, left, right, center, mute;
525 
526 	d = priv->sc;
527 	if (!PCM_REGISTERED(d))
528 		return (-1);
529 
530 	PCM_UNLOCKASSERT(d);
531 
532 	j = cmd & 0xff;
533 
534 	rdch = priv->rdch;
535 	wrch = priv->wrch;
536 
537 	if (ch == NULL) {
538 		if (j == SOUND_MIXER_RECLEV && rdch != NULL)
539 			ch = rdch;
540 		else if (j == SOUND_MIXER_PCM && wrch != NULL)
541 			ch = wrch;
542 	}
543 
544 	if (ch == NULL)
545 		return (EINVAL);
546 
547 	CHN_LOCK(ch);
548 	if (!(ch->feederflags & (1 << FEEDER_VOLUME))) {
549 		CHN_UNLOCK(ch);
550 		return (EINVAL);
551 	}
552 
553 	switch (cmd & ~0xff) {
554 	case MIXER_WRITE(0):
555 		switch (j) {
556 		case SOUND_MIXER_MUTE:
557 			if (ch->direction == PCMDIR_REC) {
558 				chn_setmute_multi(ch, SND_VOL_C_PCM, (*(int *)arg & SOUND_MASK_RECLEV) != 0);
559 			} else {
560 				chn_setmute_multi(ch, SND_VOL_C_PCM, (*(int *)arg & SOUND_MASK_PCM) != 0);
561 			}
562 			break;
563 		case SOUND_MIXER_PCM:
564 			if (ch->direction != PCMDIR_PLAY)
565 				break;
566 			left = *(int *)arg & 0x7f;
567 			right = ((*(int *)arg) >> 8) & 0x7f;
568 			center = (left + right) >> 1;
569 			chn_setvolume_multi(ch, SND_VOL_C_PCM,
570 			    left, right, center);
571 			break;
572 		case SOUND_MIXER_RECLEV:
573 			if (ch->direction != PCMDIR_REC)
574 				break;
575 			left = *(int *)arg & 0x7f;
576 			right = ((*(int *)arg) >> 8) & 0x7f;
577 			center = (left + right) >> 1;
578 			chn_setvolume_multi(ch, SND_VOL_C_PCM,
579 			    left, right, center);
580 			break;
581 		default:
582 			/* ignore all other mixer writes */
583 			break;
584 		}
585 		break;
586 
587 	case MIXER_READ(0):
588 		switch (j) {
589 		case SOUND_MIXER_MUTE:
590 			mute = chn_getmute_matrix(ch,
591 			    SND_VOL_C_PCM, SND_CHN_T_FL) ||
592 			    chn_getmute_matrix(ch, SND_VOL_C_PCM, SND_CHN_T_FR);
593 			if (ch->direction == PCMDIR_REC) {
594 				*(int *)arg = mute << SOUND_MIXER_RECLEV;
595 			} else {
596 				*(int *)arg = mute << SOUND_MIXER_PCM;
597 			}
598 			break;
599 		case SOUND_MIXER_PCM:
600 			if (ch->direction != PCMDIR_PLAY)
601 				break;
602 			*(int *)arg = chn_getvolume_matrix(ch,
603 			    SND_VOL_C_PCM, SND_CHN_T_FL);
604 			*(int *)arg |= chn_getvolume_matrix(ch,
605 			    SND_VOL_C_PCM, SND_CHN_T_FR) << 8;
606 			break;
607 		case SOUND_MIXER_RECLEV:
608 			if (ch->direction != PCMDIR_REC)
609 				break;
610 			*(int *)arg = chn_getvolume_matrix(ch,
611 			    SND_VOL_C_PCM, SND_CHN_T_FL);
612 			*(int *)arg |= chn_getvolume_matrix(ch,
613 			    SND_VOL_C_PCM, SND_CHN_T_FR) << 8;
614 			break;
615 		case SOUND_MIXER_DEVMASK:
616 		case SOUND_MIXER_CAPS:
617 		case SOUND_MIXER_STEREODEVS:
618 			if (ch->direction == PCMDIR_REC)
619 				*(int *)arg = SOUND_MASK_RECLEV;
620 			else
621 				*(int *)arg = SOUND_MASK_PCM;
622 			break;
623 		default:
624 			*(int *)arg = 0;
625 			break;
626 		}
627 		break;
628 
629 	default:
630 		break;
631 	}
632 	CHN_UNLOCK(ch);
633 	return (0);
634 }
635 
636 #ifdef COMPAT_FREEBSD32
637 typedef struct _snd_chan_param32 {
638 	uint32_t	play_rate;
639 	uint32_t	rec_rate;
640 	uint32_t	play_format;
641 	uint32_t	rec_format;
642 } snd_chan_param32;
643 #define AIOGFMT32    _IOC_NEWTYPE(AIOGFMT, snd_chan_param32)
644 #define AIOSFMT32    _IOC_NEWTYPE(AIOSFMT, snd_chan_param32)
645 
646 typedef struct _snd_capabilities32 {
647 	uint32_t	rate_min, rate_max;
648 	uint32_t	formats;
649 	uint32_t	bufsize;
650 	uint32_t	mixers;
651 	uint32_t	inputs;
652 	uint16_t	left, right;
653 } snd_capabilities32;
654 #define AIOGCAP32 _IOC_NEWTYPE(AIOGCAP, snd_capabilities32)
655 
656 typedef struct audio_errinfo32
657 {
658 	int32_t		play_underruns;
659 	int32_t		rec_overruns;
660 	uint32_t	play_ptradjust;
661 	uint32_t	rec_ptradjust;
662 	int32_t		play_errorcount;
663 	int32_t		rec_errorcount;
664 	int32_t		play_lasterror;
665 	int32_t		rec_lasterror;
666 	int32_t		play_errorparm;
667 	int32_t		rec_errorparm;
668 	int32_t		filler[16];
669 } audio_errinfo32;
670 #define SNDCTL_DSP_GETERROR32 _IOC_NEWTYPE(SNDCTL_DSP_GETERROR, audio_errinfo32)
671 #endif
672 
673 static int
674 dsp_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
675     struct thread *td)
676 {
677 	struct dsp_cdevpriv *priv;
678     	struct pcm_channel *chn, *rdch, *wrch;
679 	struct snddev_info *d;
680 	u_long xcmd;
681 	int *arg_i, ret, tmp, err;
682 
683 	if ((err = devfs_get_cdevpriv((void **)&priv)) != 0)
684 		return (err);
685 
686 	d = priv->sc;
687 	if (!DSP_REGISTERED(d))
688 		return (EBADF);
689 
690 	PCM_GIANT_ENTER(d);
691 
692 	arg_i = (int *)arg;
693 	ret = 0;
694 	xcmd = 0;
695 	chn = NULL;
696 
697 	if (IOCGROUP(cmd) == 'M') {
698 		if (cmd == OSS_GETVERSION) {
699 			*arg_i = SOUND_VERSION;
700 			PCM_GIANT_EXIT(d);
701 			return (0);
702 		}
703 		ret = dsp_ioctl_channel(priv, NULL, cmd, arg);
704 		if (ret != -1) {
705 			PCM_GIANT_EXIT(d);
706 			return (ret);
707 		}
708 
709 		if (d->mixer_dev != NULL) {
710 			PCM_ACQUIRE_QUICK(d);
711 			ret = mixer_ioctl_cmd(d->mixer_dev, cmd, arg, -1, td);
712 			PCM_RELEASE_QUICK(d);
713 		} else
714 			ret = EBADF;
715 
716 		PCM_GIANT_EXIT(d);
717 
718 		return (ret);
719 	}
720 
721 	/*
722 	 * Certain ioctls may be made on any type of device (audio, mixer,
723 	 * and MIDI).  Handle those special cases here.
724 	 */
725 	if (IOCGROUP(cmd) == 'X') {
726 		PCM_ACQUIRE_QUICK(d);
727 		switch(cmd) {
728 		case SNDCTL_SYSINFO:
729 			sound_oss_sysinfo((oss_sysinfo *)arg);
730 			break;
731 		case SNDCTL_CARDINFO:
732 			ret = sound_oss_card_info((oss_card_info *)arg);
733 			break;
734 		case SNDCTL_AUDIOINFO:
735 			ret = dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg,
736 			    false);
737 			break;
738 		case SNDCTL_AUDIOINFO_EX:
739 			ret = dsp_oss_audioinfo(i_dev, (oss_audioinfo *)arg,
740 			    true);
741 			break;
742 		case SNDCTL_ENGINEINFO:
743 			ret = dsp_oss_engineinfo(i_dev, (oss_audioinfo *)arg);
744 			break;
745 		case SNDCTL_MIXERINFO:
746 			ret = mixer_oss_mixerinfo(i_dev, (oss_mixerinfo *)arg);
747 			break;
748 		default:
749 			ret = EINVAL;
750 		}
751 		PCM_RELEASE_QUICK(d);
752 		PCM_GIANT_EXIT(d);
753 		return (ret);
754 	}
755 
756 	rdch = priv->rdch;
757 	wrch = priv->wrch;
758 
759 	if (wrch != NULL && (wrch->flags & CHN_F_DEAD))
760 		wrch = NULL;
761 	if (rdch != NULL && (rdch->flags & CHN_F_DEAD))
762 		rdch = NULL;
763 
764 	if (wrch == NULL && rdch == NULL) {
765 		PCM_GIANT_EXIT(d);
766 		return (EINVAL);
767 	}
768 
769     	switch(cmd) {
770     	case AIONWRITE:	/* how many bytes can write ? */
771 		if (wrch) {
772 			CHN_LOCK(wrch);
773 /*
774 		if (wrch && wrch->bufhard.dl)
775 			while (chn_wrfeed(wrch) == 0);
776 */
777 			*arg_i = sndbuf_getfree(wrch->bufsoft);
778 			CHN_UNLOCK(wrch);
779 		} else {
780 			*arg_i = 0;
781 			ret = EINVAL;
782 		}
783 		break;
784 
785     	case AIOSSIZE:     /* set the current blocksize */
786 		{
787 	    		struct snd_size *p = (struct snd_size *)arg;
788 
789 			p->play_size = 0;
790 			p->rec_size = 0;
791 			PCM_ACQUIRE_QUICK(d);
792 	    		if (wrch) {
793 				CHN_LOCK(wrch);
794 				chn_setblocksize(wrch, 2, p->play_size);
795 				p->play_size = wrch->bufsoft->blksz;
796 				CHN_UNLOCK(wrch);
797 			}
798 	    		if (rdch) {
799 				CHN_LOCK(rdch);
800 				chn_setblocksize(rdch, 2, p->rec_size);
801 				p->rec_size = rdch->bufsoft->blksz;
802 				CHN_UNLOCK(rdch);
803 			}
804 			PCM_RELEASE_QUICK(d);
805 		}
806 		break;
807     	case AIOGSIZE:	/* get the current blocksize */
808 		{
809 	    		struct snd_size *p = (struct snd_size *)arg;
810 
811 	    		if (wrch) {
812 				CHN_LOCK(wrch);
813 				p->play_size = wrch->bufsoft->blksz;
814 				CHN_UNLOCK(wrch);
815 			}
816 	    		if (rdch) {
817 				CHN_LOCK(rdch);
818 				p->rec_size = rdch->bufsoft->blksz;
819 				CHN_UNLOCK(rdch);
820 			}
821 		}
822 		break;
823 
824     	case AIOSFMT:
825     	case AIOGFMT:
826 #ifdef COMPAT_FREEBSD32
827 	case AIOSFMT32:
828 	case AIOGFMT32:
829 #endif
830 		{
831 	    		snd_chan_param *p = (snd_chan_param *)arg;
832 
833 #ifdef COMPAT_FREEBSD32
834 			snd_chan_param32 *p32 = (snd_chan_param32 *)arg;
835 			snd_chan_param param;
836 
837 			if (cmd == AIOSFMT32) {
838 				p = &param;
839 				p->play_rate = p32->play_rate;
840 				p->rec_rate = p32->rec_rate;
841 				p->play_format = p32->play_format;
842 				p->rec_format = p32->rec_format;
843 			}
844 #endif
845 			if (cmd == AIOSFMT &&
846 			    ((p->play_format != 0 && p->play_rate == 0) ||
847 			    (p->rec_format != 0 && p->rec_rate == 0))) {
848 				ret = EINVAL;
849 				break;
850 			}
851 			PCM_ACQUIRE_QUICK(d);
852 	    		if (wrch) {
853 				CHN_LOCK(wrch);
854 				if (cmd == AIOSFMT && p->play_format != 0) {
855 					chn_setformat(wrch,
856 					    SND_FORMAT(p->play_format,
857 					    AFMT_CHANNEL(wrch->format),
858 					    AFMT_EXTCHANNEL(wrch->format)));
859 					chn_setspeed(wrch, p->play_rate);
860 				}
861 	    			p->play_rate = wrch->speed;
862 	    			p->play_format = AFMT_ENCODING(wrch->format);
863 				CHN_UNLOCK(wrch);
864 			} else {
865 	    			p->play_rate = 0;
866 	    			p->play_format = 0;
867 	    		}
868 	    		if (rdch) {
869 				CHN_LOCK(rdch);
870 				if (cmd == AIOSFMT && p->rec_format != 0) {
871 					chn_setformat(rdch,
872 					    SND_FORMAT(p->rec_format,
873 					    AFMT_CHANNEL(rdch->format),
874 					    AFMT_EXTCHANNEL(rdch->format)));
875 					chn_setspeed(rdch, p->rec_rate);
876 				}
877 				p->rec_rate = rdch->speed;
878 				p->rec_format = AFMT_ENCODING(rdch->format);
879 				CHN_UNLOCK(rdch);
880 			} else {
881 	    			p->rec_rate = 0;
882 	    			p->rec_format = 0;
883 	    		}
884 			PCM_RELEASE_QUICK(d);
885 #ifdef COMPAT_FREEBSD32
886 			if (cmd == AIOSFMT32 || cmd == AIOGFMT32) {
887 				p32->play_rate = p->play_rate;
888 				p32->rec_rate = p->rec_rate;
889 				p32->play_format = p->play_format;
890 				p32->rec_format = p->rec_format;
891 			}
892 #endif
893 		}
894 		break;
895 
896     	case AIOGCAP:     /* get capabilities */
897 #ifdef COMPAT_FREEBSD32
898 	case AIOGCAP32:
899 #endif
900 		{
901 	    		snd_capabilities *p = (snd_capabilities *)arg;
902 			struct pcmchan_caps *pcaps = NULL, *rcaps = NULL;
903 			struct cdev *pdev;
904 #ifdef COMPAT_FREEBSD32
905 			snd_capabilities32 *p32 = (snd_capabilities32 *)arg;
906 			snd_capabilities capabilities;
907 
908 			if (cmd == AIOGCAP32) {
909 				p = &capabilities;
910 				p->rate_min = p32->rate_min;
911 				p->rate_max = p32->rate_max;
912 				p->formats = p32->formats;
913 				p->bufsize = p32->bufsize;
914 				p->mixers = p32->mixers;
915 				p->inputs = p32->inputs;
916 				p->left = p32->left;
917 				p->right = p32->right;
918 			}
919 #endif
920 			PCM_LOCK(d);
921 			if (rdch) {
922 				CHN_LOCK(rdch);
923 				rcaps = chn_getcaps(rdch);
924 			}
925 			if (wrch) {
926 				CHN_LOCK(wrch);
927 				pcaps = chn_getcaps(wrch);
928 			}
929 	    		p->rate_min = max(rcaps? rcaps->minspeed : 0,
930 	                      		  pcaps? pcaps->minspeed : 0);
931 	    		p->rate_max = min(rcaps? rcaps->maxspeed : 1000000,
932 	                      		  pcaps? pcaps->maxspeed : 1000000);
933 			p->bufsize = min(rdch? rdch->bufsoft->bufsize : 1000000,
934 					 wrch? wrch->bufsoft->bufsize : 1000000);
935 			/* XXX bad on sb16 */
936 	    		p->formats = (rdch? chn_getformats(rdch) : 0xffffffff) &
937 			 	     (wrch? chn_getformats(wrch) : 0xffffffff);
938 			if (rdch && wrch) {
939 				p->formats |=
940 				    (pcm_getflags(d->dev) & SD_F_SIMPLEX) ? 0 :
941 				    AFMT_FULLDUPLEX;
942 			}
943 			pdev = d->mixer_dev;
944 	    		p->mixers = 1; /* default: one mixer */
945 	    		p->inputs = pdev->si_drv1? mix_getdevs(pdev->si_drv1) : 0;
946 	    		p->left = p->right = 100;
947 			if (wrch)
948 				CHN_UNLOCK(wrch);
949 			if (rdch)
950 				CHN_UNLOCK(rdch);
951 			PCM_UNLOCK(d);
952 #ifdef COMPAT_FREEBSD32
953 			if (cmd == AIOGCAP32) {
954 				p32->rate_min = p->rate_min;
955 				p32->rate_max = p->rate_max;
956 				p32->formats = p->formats;
957 				p32->bufsize = p->bufsize;
958 				p32->mixers = p->mixers;
959 				p32->inputs = p->inputs;
960 				p32->left = p->left;
961 				p32->right = p->right;
962 			}
963 #endif
964 		}
965 		break;
966 
967     	case AIOSTOP:
968 		if (*arg_i == AIOSYNC_PLAY && wrch) {
969 			CHN_LOCK(wrch);
970 			*arg_i = chn_abort(wrch);
971 			CHN_UNLOCK(wrch);
972 		} else if (*arg_i == AIOSYNC_CAPTURE && rdch) {
973 			CHN_LOCK(rdch);
974 			*arg_i = chn_abort(rdch);
975 			CHN_UNLOCK(rdch);
976 		} else {
977 	   	 	printf("AIOSTOP: bad channel 0x%x\n", *arg_i);
978 	    		*arg_i = 0;
979 		}
980 		break;
981 
982     	case AIOSYNC:
983 		printf("AIOSYNC chan 0x%03lx pos %lu unimplemented\n",
984 	    		((snd_sync_parm *)arg)->chan, ((snd_sync_parm *)arg)->pos);
985 		break;
986     	case FIONREAD: /* get # bytes to read */
987 		if (rdch) {
988 			CHN_LOCK(rdch);
989 /*			if (rdch && rdch->bufhard.dl)
990 				while (chn_rdfeed(rdch) == 0);
991 */
992 			*arg_i = sndbuf_getready(rdch->bufsoft);
993 			CHN_UNLOCK(rdch);
994 		} else {
995 			*arg_i = 0;
996 			ret = EINVAL;
997 		}
998 		break;
999 
1000     	case FIOASYNC: /*set/clear async i/o */
1001 		DEB( printf("FIOASYNC\n") ; )
1002 		break;
1003 
1004     	case SNDCTL_DSP_NONBLOCK: /* set non-blocking i/o */
1005     	case FIONBIO: /* set/clear non-blocking i/o */
1006 		if (rdch) {
1007 			CHN_LOCK(rdch);
1008 			if (cmd == SNDCTL_DSP_NONBLOCK || *arg_i)
1009 				rdch->flags |= CHN_F_NBIO;
1010 			else
1011 				rdch->flags &= ~CHN_F_NBIO;
1012 			CHN_UNLOCK(rdch);
1013 		}
1014 		if (wrch) {
1015 			CHN_LOCK(wrch);
1016 			if (cmd == SNDCTL_DSP_NONBLOCK || *arg_i)
1017 				wrch->flags |= CHN_F_NBIO;
1018 			else
1019 				wrch->flags &= ~CHN_F_NBIO;
1020 			CHN_UNLOCK(wrch);
1021 		}
1022 		break;
1023 
1024     	case SNDCTL_DSP_GETBLKSIZE:
1025 		chn = wrch ? wrch : rdch;
1026 		if (chn) {
1027 			CHN_LOCK(chn);
1028 			*arg_i = chn->bufsoft->blksz;
1029 			CHN_UNLOCK(chn);
1030 		} else {
1031 			*arg_i = 0;
1032 			ret = EINVAL;
1033 		}
1034 		break;
1035 
1036     	case SNDCTL_DSP_SETBLKSIZE:
1037 		RANGE(*arg_i, 16, 65536);
1038 		PCM_ACQUIRE_QUICK(d);
1039 		if (wrch) {
1040 			CHN_LOCK(wrch);
1041 			chn_setblocksize(wrch, 2, *arg_i);
1042 			CHN_UNLOCK(wrch);
1043 		}
1044 		if (rdch) {
1045 			CHN_LOCK(rdch);
1046 			chn_setblocksize(rdch, 2, *arg_i);
1047 			CHN_UNLOCK(rdch);
1048 		}
1049 		PCM_RELEASE_QUICK(d);
1050 		break;
1051 
1052     	case SNDCTL_DSP_RESET:
1053 		DEB(printf("dsp reset\n"));
1054 		if (wrch) {
1055 			CHN_LOCK(wrch);
1056 			chn_abort(wrch);
1057 			chn_resetbuf(wrch);
1058 			CHN_UNLOCK(wrch);
1059 		}
1060 		if (rdch) {
1061 			CHN_LOCK(rdch);
1062 			chn_abort(rdch);
1063 			chn_resetbuf(rdch);
1064 			CHN_UNLOCK(rdch);
1065 		}
1066 		break;
1067 
1068     	case SNDCTL_DSP_SYNC:
1069 		DEB(printf("dsp sync\n"));
1070 		/* chn_sync may sleep */
1071 		if (wrch) {
1072 			CHN_LOCK(wrch);
1073 			chn_sync(wrch, 0);
1074 			CHN_UNLOCK(wrch);
1075 		}
1076 		break;
1077 
1078     	case SNDCTL_DSP_SPEED:
1079 		/* chn_setspeed may sleep */
1080 		tmp = 0;
1081 		PCM_ACQUIRE_QUICK(d);
1082 		if (wrch) {
1083 			CHN_LOCK(wrch);
1084 			ret = chn_setspeed(wrch, *arg_i);
1085 			tmp = wrch->speed;
1086 			CHN_UNLOCK(wrch);
1087 		}
1088 		if (rdch && ret == 0) {
1089 			CHN_LOCK(rdch);
1090 			ret = chn_setspeed(rdch, *arg_i);
1091 			if (tmp == 0)
1092 				tmp = rdch->speed;
1093 			CHN_UNLOCK(rdch);
1094 		}
1095 		PCM_RELEASE_QUICK(d);
1096 		*arg_i = tmp;
1097 		break;
1098 
1099     	case SOUND_PCM_READ_RATE:
1100 		chn = wrch ? wrch : rdch;
1101 		if (chn) {
1102 			CHN_LOCK(chn);
1103 			*arg_i = chn->speed;
1104 			CHN_UNLOCK(chn);
1105 		} else {
1106 			*arg_i = 0;
1107 			ret = EINVAL;
1108 		}
1109 		break;
1110 
1111     	case SNDCTL_DSP_STEREO:
1112 		tmp = -1;
1113 		*arg_i = (*arg_i)? 2 : 1;
1114 		PCM_ACQUIRE_QUICK(d);
1115 		if (wrch) {
1116 			CHN_LOCK(wrch);
1117 			ret = chn_setformat(wrch,
1118 			    SND_FORMAT(wrch->format, *arg_i, 0));
1119 			tmp = (AFMT_CHANNEL(wrch->format) > 1)? 1 : 0;
1120 			CHN_UNLOCK(wrch);
1121 		}
1122 		if (rdch && ret == 0) {
1123 			CHN_LOCK(rdch);
1124 			ret = chn_setformat(rdch,
1125 			    SND_FORMAT(rdch->format, *arg_i, 0));
1126 			if (tmp == -1)
1127 				tmp = (AFMT_CHANNEL(rdch->format) > 1)? 1 : 0;
1128 			CHN_UNLOCK(rdch);
1129 		}
1130 		PCM_RELEASE_QUICK(d);
1131 		*arg_i = tmp;
1132 		break;
1133 
1134     	case SOUND_PCM_WRITE_CHANNELS:
1135 /*	case SNDCTL_DSP_CHANNELS: ( == SOUND_PCM_WRITE_CHANNELS) */
1136 		if (*arg_i < 0 || *arg_i > AFMT_CHANNEL_MAX) {
1137 			*arg_i = 0;
1138 			ret = EINVAL;
1139 			break;
1140 		}
1141 		if (*arg_i != 0) {
1142 			uint32_t ext = 0;
1143 
1144 			tmp = 0;
1145 			/*
1146 			 * Map channel number to surround sound formats.
1147 			 * Devices that need bitperfect mode to operate
1148 			 * (e.g. more than SND_CHN_MAX channels) are not
1149 			 * subject to any mapping.
1150 			 */
1151 			if (!(pcm_getflags(d->dev) & SD_F_BITPERFECT)) {
1152 				struct pcmchan_matrix *m;
1153 
1154 				if (*arg_i > SND_CHN_MAX)
1155 					*arg_i = SND_CHN_MAX;
1156 
1157 				m = feeder_matrix_default_channel_map(*arg_i);
1158 				if (m != NULL)
1159 					ext = m->ext;
1160 			}
1161 
1162 			PCM_ACQUIRE_QUICK(d);
1163 	  		if (wrch) {
1164 				CHN_LOCK(wrch);
1165 				ret = chn_setformat(wrch,
1166 				    SND_FORMAT(wrch->format, *arg_i, ext));
1167 				tmp = AFMT_CHANNEL(wrch->format);
1168 				CHN_UNLOCK(wrch);
1169 			}
1170 			if (rdch && ret == 0) {
1171 				CHN_LOCK(rdch);
1172 				ret = chn_setformat(rdch,
1173 				    SND_FORMAT(rdch->format, *arg_i, ext));
1174 				if (tmp == 0)
1175 					tmp = AFMT_CHANNEL(rdch->format);
1176 				CHN_UNLOCK(rdch);
1177 			}
1178 			PCM_RELEASE_QUICK(d);
1179 			*arg_i = tmp;
1180 		} else {
1181 			chn = wrch ? wrch : rdch;
1182 			CHN_LOCK(chn);
1183 			*arg_i = AFMT_CHANNEL(chn->format);
1184 			CHN_UNLOCK(chn);
1185 		}
1186 		break;
1187 
1188     	case SOUND_PCM_READ_CHANNELS:
1189 		chn = wrch ? wrch : rdch;
1190 		if (chn) {
1191 			CHN_LOCK(chn);
1192 			*arg_i = AFMT_CHANNEL(chn->format);
1193 			CHN_UNLOCK(chn);
1194 		} else {
1195 			*arg_i = 0;
1196 			ret = EINVAL;
1197 		}
1198 		break;
1199 
1200     	case SNDCTL_DSP_GETFMTS:	/* returns a mask of supported fmts */
1201 		chn = wrch ? wrch : rdch;
1202 		if (chn) {
1203 			CHN_LOCK(chn);
1204 			*arg_i = chn_getformats(chn);
1205 			CHN_UNLOCK(chn);
1206 		} else {
1207 			*arg_i = 0;
1208 			ret = EINVAL;
1209 		}
1210 		break;
1211 
1212     	case SNDCTL_DSP_SETFMT:	/* sets _one_ format */
1213 		if (*arg_i != AFMT_QUERY) {
1214 			tmp = 0;
1215 			PCM_ACQUIRE_QUICK(d);
1216 			if (wrch) {
1217 				CHN_LOCK(wrch);
1218 				ret = chn_setformat(wrch, SND_FORMAT(*arg_i,
1219 				    AFMT_CHANNEL(wrch->format),
1220 				    AFMT_EXTCHANNEL(wrch->format)));
1221 				tmp = wrch->format;
1222 				CHN_UNLOCK(wrch);
1223 			}
1224 			if (rdch && ret == 0) {
1225 				CHN_LOCK(rdch);
1226 				ret = chn_setformat(rdch, SND_FORMAT(*arg_i,
1227 				    AFMT_CHANNEL(rdch->format),
1228 				    AFMT_EXTCHANNEL(rdch->format)));
1229 				if (tmp == 0)
1230 					tmp = rdch->format;
1231 				CHN_UNLOCK(rdch);
1232 			}
1233 			PCM_RELEASE_QUICK(d);
1234 			*arg_i = AFMT_ENCODING(tmp);
1235 		} else {
1236 			chn = wrch ? wrch : rdch;
1237 			CHN_LOCK(chn);
1238 			*arg_i = AFMT_ENCODING(chn->format);
1239 			CHN_UNLOCK(chn);
1240 		}
1241 		break;
1242 
1243     	case SNDCTL_DSP_SETFRAGMENT:
1244 		DEB(printf("SNDCTL_DSP_SETFRAGMENT 0x%08x\n", *(int *)arg));
1245 		{
1246 			uint32_t fragln = (*arg_i) & 0x0000ffff;
1247 			uint32_t maxfrags = ((*arg_i) & 0xffff0000) >> 16;
1248 			uint32_t fragsz;
1249 			uint32_t r_maxfrags, r_fragsz;
1250 
1251 			RANGE(fragln, 4, 16);
1252 			fragsz = 1 << fragln;
1253 
1254 			if (maxfrags == 0)
1255 				maxfrags = CHN_2NDBUFMAXSIZE / fragsz;
1256 			if (maxfrags < 2)
1257 				maxfrags = 2;
1258 			if (maxfrags * fragsz > CHN_2NDBUFMAXSIZE)
1259 				maxfrags = CHN_2NDBUFMAXSIZE / fragsz;
1260 
1261 			DEB(printf("SNDCTL_DSP_SETFRAGMENT %d frags, %d sz\n", maxfrags, fragsz));
1262 			PCM_ACQUIRE_QUICK(d);
1263 		    	if (rdch) {
1264 				CHN_LOCK(rdch);
1265 				ret = chn_setblocksize(rdch, maxfrags, fragsz);
1266 				r_maxfrags = rdch->bufsoft->blkcnt;
1267 				r_fragsz = rdch->bufsoft->blksz;
1268 				CHN_UNLOCK(rdch);
1269 			} else {
1270 				r_maxfrags = maxfrags;
1271 				r_fragsz = fragsz;
1272 			}
1273 		    	if (wrch && ret == 0) {
1274 				CHN_LOCK(wrch);
1275 				ret = chn_setblocksize(wrch, maxfrags, fragsz);
1276 				maxfrags = wrch->bufsoft->blkcnt;
1277 				fragsz = wrch->bufsoft->blksz;
1278 				CHN_UNLOCK(wrch);
1279 			} else { /* use whatever came from the read channel */
1280 				maxfrags = r_maxfrags;
1281 				fragsz = r_fragsz;
1282 			}
1283 			PCM_RELEASE_QUICK(d);
1284 
1285 			fragln = 0;
1286 			while (fragsz > 1) {
1287 				fragln++;
1288 				fragsz >>= 1;
1289 			}
1290 	    		*arg_i = (maxfrags << 16) | fragln;
1291 		}
1292 		break;
1293 
1294     	case SNDCTL_DSP_GETISPACE:
1295 		/* return the size of data available in the input queue */
1296 		{
1297 	    		audio_buf_info *a = (audio_buf_info *)arg;
1298 	    		if (rdch) {
1299 	        		struct snd_dbuf *bs = rdch->bufsoft;
1300 
1301 				CHN_LOCK(rdch);
1302 				a->bytes = sndbuf_getready(bs);
1303 				a->fragments = a->bytes / bs->blksz;
1304 				a->fragstotal = bs->blkcnt;
1305 				a->fragsize = bs->blksz;
1306 				CHN_UNLOCK(rdch);
1307 	    		} else
1308 				ret = EINVAL;
1309 		}
1310 		break;
1311 
1312     	case SNDCTL_DSP_GETOSPACE:
1313 		/* return space available in the output queue */
1314 		{
1315 	    		audio_buf_info *a = (audio_buf_info *)arg;
1316 	    		if (wrch) {
1317 	        		struct snd_dbuf *bs = wrch->bufsoft;
1318 
1319 				CHN_LOCK(wrch);
1320 				a->bytes = sndbuf_getfree(bs);
1321 				a->fragments = a->bytes / bs->blksz;
1322 				a->fragstotal = bs->blkcnt;
1323 				a->fragsize = bs->blksz;
1324 				CHN_UNLOCK(wrch);
1325 	    		} else
1326 				ret = EINVAL;
1327 		}
1328 		break;
1329 
1330     	case SNDCTL_DSP_GETIPTR:
1331 		{
1332 	    		count_info *a = (count_info *)arg;
1333 	    		if (rdch) {
1334 	        		struct snd_dbuf *bs = rdch->bufsoft;
1335 
1336 				CHN_LOCK(rdch);
1337 				a->bytes = bs->total;
1338 	        		a->blocks = sndbuf_getblocks(bs) - rdch->blocks;
1339 	        		a->ptr = sndbuf_getfreeptr(bs);
1340 				rdch->blocks = sndbuf_getblocks(bs);
1341 				CHN_UNLOCK(rdch);
1342 	    		} else
1343 				ret = EINVAL;
1344 		}
1345 		break;
1346 
1347     	case SNDCTL_DSP_GETOPTR:
1348 		{
1349 	    		count_info *a = (count_info *)arg;
1350 	    		if (wrch) {
1351 	        		struct snd_dbuf *bs = wrch->bufsoft;
1352 
1353 				CHN_LOCK(wrch);
1354 				a->bytes = bs->total;
1355 	        		a->blocks = sndbuf_getblocks(bs) - wrch->blocks;
1356 	        		a->ptr = sndbuf_getreadyptr(bs);
1357 				wrch->blocks = sndbuf_getblocks(bs);
1358 				CHN_UNLOCK(wrch);
1359 	    		} else
1360 				ret = EINVAL;
1361 		}
1362 		break;
1363 
1364     	case SNDCTL_DSP_GETCAPS:
1365 		PCM_LOCK(d);
1366 		*arg_i = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER;
1367 		if (rdch && wrch && !(pcm_getflags(d->dev) & SD_F_SIMPLEX))
1368 			*arg_i |= PCM_CAP_DUPLEX;
1369 		if (rdch && (rdch->flags & CHN_F_VIRTUAL) != 0)
1370 			*arg_i |= PCM_CAP_VIRTUAL;
1371 		if (wrch && (wrch->flags & CHN_F_VIRTUAL) != 0)
1372 			*arg_i |= PCM_CAP_VIRTUAL;
1373 		PCM_UNLOCK(d);
1374 		break;
1375 
1376     	case SOUND_PCM_READ_BITS:
1377 		chn = wrch ? wrch : rdch;
1378 		if (chn) {
1379 			CHN_LOCK(chn);
1380 			if (chn->format & AFMT_8BIT)
1381 				*arg_i = 8;
1382 			else if (chn->format & AFMT_16BIT)
1383 				*arg_i = 16;
1384 			else if (chn->format & AFMT_24BIT)
1385 				*arg_i = 24;
1386 			else if (chn->format & AFMT_32BIT)
1387 				*arg_i = 32;
1388 			else
1389 				ret = EINVAL;
1390 			CHN_UNLOCK(chn);
1391 		} else {
1392 			*arg_i = 0;
1393 			ret = EINVAL;
1394 		}
1395 		break;
1396 
1397     	case SNDCTL_DSP_SETTRIGGER:
1398 		if (rdch) {
1399 			CHN_LOCK(rdch);
1400 			rdch->flags &= ~CHN_F_NOTRIGGER;
1401 		    	if (*arg_i & PCM_ENABLE_INPUT)
1402 				chn_start(rdch, 1);
1403 			else {
1404 				chn_abort(rdch);
1405 				chn_resetbuf(rdch);
1406 				rdch->flags |= CHN_F_NOTRIGGER;
1407 			}
1408 			CHN_UNLOCK(rdch);
1409 		}
1410 		if (wrch) {
1411 			CHN_LOCK(wrch);
1412 			wrch->flags &= ~CHN_F_NOTRIGGER;
1413 		    	if (*arg_i & PCM_ENABLE_OUTPUT)
1414 				chn_start(wrch, 1);
1415 			else {
1416 				chn_abort(wrch);
1417 				chn_resetbuf(wrch);
1418 				wrch->flags |= CHN_F_NOTRIGGER;
1419 			}
1420 			CHN_UNLOCK(wrch);
1421 		}
1422 		break;
1423 
1424     	case SNDCTL_DSP_GETTRIGGER:
1425 		*arg_i = 0;
1426 		if (wrch) {
1427 			CHN_LOCK(wrch);
1428 			if (wrch->flags & CHN_F_TRIGGERED)
1429 				*arg_i |= PCM_ENABLE_OUTPUT;
1430 			CHN_UNLOCK(wrch);
1431 		}
1432 		if (rdch) {
1433 			CHN_LOCK(rdch);
1434 			if (rdch->flags & CHN_F_TRIGGERED)
1435 				*arg_i |= PCM_ENABLE_INPUT;
1436 			CHN_UNLOCK(rdch);
1437 		}
1438 		break;
1439 
1440 	case SNDCTL_DSP_GETODELAY:
1441 		if (wrch) {
1442 	        	struct snd_dbuf *bs = wrch->bufsoft;
1443 
1444 			CHN_LOCK(wrch);
1445 			*arg_i = sndbuf_getready(bs);
1446 			CHN_UNLOCK(wrch);
1447 		} else
1448 			ret = EINVAL;
1449 		break;
1450 
1451     	case SNDCTL_DSP_POST:
1452 		if (wrch) {
1453 			CHN_LOCK(wrch);
1454 			wrch->flags &= ~CHN_F_NOTRIGGER;
1455 			chn_start(wrch, 1);
1456 			CHN_UNLOCK(wrch);
1457 		}
1458 		break;
1459 
1460 	case SNDCTL_DSP_SETDUPLEX:
1461 		/*
1462 		 * switch to full-duplex mode if card is in half-duplex
1463 		 * mode and is able to work in full-duplex mode
1464 		 */
1465 		PCM_LOCK(d);
1466 		if (rdch && wrch && (pcm_getflags(d->dev) & SD_F_SIMPLEX))
1467 			pcm_setflags(d->dev, pcm_getflags(d->dev)^SD_F_SIMPLEX);
1468 		PCM_UNLOCK(d);
1469 		break;
1470 
1471 	/*
1472 	 * The following four ioctls are simple wrappers around mixer_ioctl
1473 	 * with no further processing.  xcmd is short for "translated
1474 	 * command".
1475 	 */
1476 	case SNDCTL_DSP_GETRECVOL:
1477 		if (xcmd == 0) {
1478 			xcmd = SOUND_MIXER_READ_RECLEV;
1479 			chn = rdch;
1480 		}
1481 		/* FALLTHROUGH */
1482 	case SNDCTL_DSP_SETRECVOL:
1483 		if (xcmd == 0) {
1484 			xcmd = SOUND_MIXER_WRITE_RECLEV;
1485 			chn = rdch;
1486 		}
1487 		/* FALLTHROUGH */
1488 	case SNDCTL_DSP_GETPLAYVOL:
1489 		if (xcmd == 0) {
1490 			xcmd = SOUND_MIXER_READ_PCM;
1491 			chn = wrch;
1492 		}
1493 		/* FALLTHROUGH */
1494 	case SNDCTL_DSP_SETPLAYVOL:
1495 		if (xcmd == 0) {
1496 			xcmd = SOUND_MIXER_WRITE_PCM;
1497 			chn = wrch;
1498 		}
1499 
1500 		ret = dsp_ioctl_channel(priv, chn, xcmd, arg);
1501 		if (ret != -1) {
1502 			PCM_GIANT_EXIT(d);
1503 			return (ret);
1504 		}
1505 
1506 		if (d->mixer_dev != NULL) {
1507 			PCM_ACQUIRE_QUICK(d);
1508 			ret = mixer_ioctl_cmd(d->mixer_dev, xcmd, arg, -1, td);
1509 			PCM_RELEASE_QUICK(d);
1510 		} else
1511 			ret = ENOTSUP;
1512 
1513 		break;
1514 
1515 	case SNDCTL_DSP_GET_RECSRC_NAMES:
1516 	case SNDCTL_DSP_GET_RECSRC:
1517 	case SNDCTL_DSP_SET_RECSRC:
1518 		if (d->mixer_dev != NULL) {
1519 			PCM_ACQUIRE_QUICK(d);
1520 			ret = mixer_ioctl_cmd(d->mixer_dev, cmd, arg, -1, td);
1521 			PCM_RELEASE_QUICK(d);
1522 		} else
1523 			ret = ENOTSUP;
1524 		break;
1525 
1526 	/*
1527 	 * The following 3 ioctls aren't very useful at the moment.  For
1528 	 * now, only a single channel is associated with a cdev (/dev/dspN
1529 	 * instance), so there's only a single output routing to use (i.e.,
1530 	 * the wrch bound to this cdev).
1531 	 */
1532 	case SNDCTL_DSP_GET_PLAYTGT_NAMES:
1533 		{
1534 			oss_mixer_enuminfo *ei;
1535 			ei = (oss_mixer_enuminfo *)arg;
1536 			ei->dev = 0;
1537 			ei->ctrl = 0;
1538 			ei->version = 0; /* static for now */
1539 			ei->strindex[0] = 0;
1540 
1541 			if (wrch != NULL) {
1542 				ei->nvalues = 1;
1543 				strlcpy(ei->strings, wrch->name,
1544 					sizeof(ei->strings));
1545 			} else {
1546 				ei->nvalues = 0;
1547 				ei->strings[0] = '\0';
1548 			}
1549 		}
1550 		break;
1551 	case SNDCTL_DSP_GET_PLAYTGT:
1552 	case SNDCTL_DSP_SET_PLAYTGT:	/* yes, they are the same for now */
1553 		/*
1554 		 * Re: SET_PLAYTGT
1555 		 *   OSSv4: "The value that was accepted by the device will
1556 		 *   be returned back in the variable pointed by the
1557 		 *   argument."
1558 		 */
1559 		if (wrch != NULL)
1560 			*arg_i = 0;
1561 		else
1562 			ret = EINVAL;
1563 		break;
1564 
1565 	case SNDCTL_DSP_SILENCE:
1566 	/*
1567 	 * Flush the software (pre-feed) buffer, but try to minimize playback
1568 	 * interruption.  (I.e., record unplayed samples with intent to
1569 	 * restore by SNDCTL_DSP_SKIP.) Intended for application "pause"
1570 	 * functionality.
1571 	 */
1572 		if (wrch == NULL)
1573 			ret = EINVAL;
1574 		else {
1575 			struct snd_dbuf *bs;
1576 			CHN_LOCK(wrch);
1577 			while (wrch->inprog != 0)
1578 				cv_wait(&wrch->cv, &wrch->lock);
1579 			bs = wrch->bufsoft;
1580 			if ((bs->shadbuf != NULL) && (sndbuf_getready(bs) > 0)) {
1581 				bs->sl = sndbuf_getready(bs);
1582 				sndbuf_dispose(bs, bs->shadbuf, sndbuf_getready(bs));
1583 				sndbuf_fillsilence(bs);
1584 				chn_start(wrch, 0);
1585 			}
1586 			CHN_UNLOCK(wrch);
1587 		}
1588 		break;
1589 
1590 	case SNDCTL_DSP_SKIP:
1591 	/*
1592 	 * OSSv4 docs: "This ioctl call discards all unplayed samples in the
1593 	 * playback buffer by moving the current write position immediately
1594 	 * before the point where the device is currently reading the samples."
1595 	 */
1596 		if (wrch == NULL)
1597 			ret = EINVAL;
1598 		else {
1599 			struct snd_dbuf *bs;
1600 			CHN_LOCK(wrch);
1601 			while (wrch->inprog != 0)
1602 				cv_wait(&wrch->cv, &wrch->lock);
1603 			bs = wrch->bufsoft;
1604 			if ((bs->shadbuf != NULL) && (bs->sl > 0)) {
1605 				sndbuf_softreset(bs);
1606 				sndbuf_acquire(bs, bs->shadbuf, bs->sl);
1607 				bs->sl = 0;
1608 				chn_start(wrch, 0);
1609 			}
1610 			CHN_UNLOCK(wrch);
1611 		}
1612 		break;
1613 
1614 	case SNDCTL_DSP_CURRENT_OPTR:
1615 	case SNDCTL_DSP_CURRENT_IPTR:
1616 	/**
1617 	 * @note Changing formats resets the buffer counters, which differs
1618 	 * 	 from the 4Front drivers.  However, I don't expect this to be
1619 	 * 	 much of a problem.
1620 	 *
1621 	 * @note In a test where @c CURRENT_OPTR is called immediately after write
1622 	 * 	 returns, this driver is about 32K samples behind whereas
1623 	 * 	 4Front's is about 8K samples behind.  Should determine source
1624 	 * 	 of discrepancy, even if only out of curiosity.
1625 	 *
1626 	 * @todo Actually test SNDCTL_DSP_CURRENT_IPTR.
1627 	 */
1628 		chn = (cmd == SNDCTL_DSP_CURRENT_OPTR) ? wrch : rdch;
1629 		if (chn == NULL)
1630 			ret = EINVAL;
1631 		else {
1632 			struct snd_dbuf *bs;
1633 			/* int tmp; */
1634 
1635 			oss_count_t *oc = (oss_count_t *)arg;
1636 
1637 			CHN_LOCK(chn);
1638 			bs = chn->bufsoft;
1639 			oc->samples = bs->total / bs->align;
1640 			oc->fifo_samples = sndbuf_getready(bs) / bs->align;
1641 			CHN_UNLOCK(chn);
1642 		}
1643 		break;
1644 
1645 	case SNDCTL_DSP_HALT_OUTPUT:
1646 	case SNDCTL_DSP_HALT_INPUT:
1647 		chn = (cmd == SNDCTL_DSP_HALT_OUTPUT) ? wrch : rdch;
1648 		if (chn == NULL)
1649 			ret = EINVAL;
1650 		else {
1651 			CHN_LOCK(chn);
1652 			chn_abort(chn);
1653 			CHN_UNLOCK(chn);
1654 		}
1655 		break;
1656 
1657 	case SNDCTL_DSP_LOW_WATER:
1658 	/*
1659 	 * Set the number of bytes required to attract attention by
1660 	 * select/poll.
1661 	 */
1662 		if (wrch != NULL) {
1663 			CHN_LOCK(wrch);
1664 			wrch->lw = (*arg_i > 1) ? *arg_i : 1;
1665 			CHN_UNLOCK(wrch);
1666 		}
1667 		if (rdch != NULL) {
1668 			CHN_LOCK(rdch);
1669 			rdch->lw = (*arg_i > 1) ? *arg_i : 1;
1670 			CHN_UNLOCK(rdch);
1671 		}
1672 		break;
1673 
1674 	case SNDCTL_DSP_GETERROR:
1675 #ifdef COMPAT_FREEBSD32
1676 	case SNDCTL_DSP_GETERROR32:
1677 #endif
1678 	/*
1679 	 * OSSv4 docs:  "All errors and counters will automatically be
1680 	 * cleared to zeroes after the call so each call will return only
1681 	 * the errors that occurred after the previous invocation. ... The
1682 	 * play_underruns and rec_overrun fields are the only useful fields
1683 	 * returned by OSS 4.0."
1684 	 */
1685 		{
1686 			audio_errinfo *ei = (audio_errinfo *)arg;
1687 #ifdef COMPAT_FREEBSD32
1688 			audio_errinfo errinfo;
1689 			audio_errinfo32 *ei32 = (audio_errinfo32 *)arg;
1690 
1691 			if (cmd == SNDCTL_DSP_GETERROR32) {
1692 				ei = &errinfo;
1693 			}
1694 #endif
1695 
1696 			bzero((void *)ei, sizeof(*ei));
1697 
1698 			if (wrch != NULL) {
1699 				CHN_LOCK(wrch);
1700 				ei->play_underruns = wrch->xruns;
1701 				wrch->xruns = 0;
1702 				CHN_UNLOCK(wrch);
1703 			}
1704 			if (rdch != NULL) {
1705 				CHN_LOCK(rdch);
1706 				ei->rec_overruns = rdch->xruns;
1707 				rdch->xruns = 0;
1708 				CHN_UNLOCK(rdch);
1709 			}
1710 #ifdef COMPAT_FREEBSD32
1711 			if (cmd == SNDCTL_DSP_GETERROR32) {
1712 				bzero((void *)ei32, sizeof(*ei32));
1713 				ei32->play_underruns = ei->play_underruns;
1714 				ei32->rec_overruns = ei->rec_overruns;
1715 				ei32->play_ptradjust = ei->play_ptradjust;
1716 				ei32->rec_ptradjust = ei->rec_ptradjust;
1717 				ei32->play_errorcount = ei->play_errorcount;
1718 				ei32->rec_errorcount = ei->rec_errorcount;
1719 				ei32->play_lasterror = ei->play_lasterror;
1720 				ei32->rec_lasterror = ei->rec_lasterror;
1721 				ei32->play_errorparm = ei->play_errorparm;
1722 				ei32->rec_errorparm = ei->rec_errorparm;
1723 			}
1724 #endif
1725 		}
1726 		break;
1727 
1728 	case SNDCTL_DSP_SYNCGROUP:
1729 		PCM_ACQUIRE_QUICK(d);
1730 		ret = dsp_oss_syncgroup(wrch, rdch, (oss_syncgroup *)arg);
1731 		PCM_RELEASE_QUICK(d);
1732 		break;
1733 
1734 	case SNDCTL_DSP_SYNCSTART:
1735 		PCM_ACQUIRE_QUICK(d);
1736 		ret = dsp_oss_syncstart(*arg_i);
1737 		PCM_RELEASE_QUICK(d);
1738 		break;
1739 
1740 	case SNDCTL_DSP_POLICY:
1741 		PCM_ACQUIRE_QUICK(d);
1742 		ret = dsp_oss_policy(wrch, rdch, *arg_i);
1743 		PCM_RELEASE_QUICK(d);
1744 		break;
1745 
1746 	case SNDCTL_DSP_COOKEDMODE:
1747 		PCM_ACQUIRE_QUICK(d);
1748 		if (!(pcm_getflags(d->dev) & SD_F_BITPERFECT))
1749 			ret = dsp_oss_cookedmode(wrch, rdch, *arg_i);
1750 		PCM_RELEASE_QUICK(d);
1751 		break;
1752 	case SNDCTL_DSP_GET_CHNORDER:
1753 		PCM_ACQUIRE_QUICK(d);
1754 		ret = dsp_oss_getchnorder(wrch, rdch, (unsigned long long *)arg);
1755 		PCM_RELEASE_QUICK(d);
1756 		break;
1757 	case SNDCTL_DSP_SET_CHNORDER:
1758 		PCM_ACQUIRE_QUICK(d);
1759 		ret = dsp_oss_setchnorder(wrch, rdch, (unsigned long long *)arg);
1760 		PCM_RELEASE_QUICK(d);
1761 		break;
1762 	case SNDCTL_DSP_GETCHANNELMASK:		/* XXX vlc */
1763 		PCM_ACQUIRE_QUICK(d);
1764 		ret = dsp_oss_getchannelmask(wrch, rdch, (int *)arg);
1765 		PCM_RELEASE_QUICK(d);
1766 		break;
1767 	case SNDCTL_DSP_BIND_CHANNEL:		/* XXX what?!? */
1768 		ret = EINVAL;
1769 		break;
1770 #ifdef	OSSV4_EXPERIMENT
1771 	/*
1772 	 * XXX The following ioctls are not yet supported and just return
1773 	 * EINVAL.
1774 	 */
1775 	case SNDCTL_DSP_GETOPEAKS:
1776 	case SNDCTL_DSP_GETIPEAKS:
1777 		chn = (cmd == SNDCTL_DSP_GETOPEAKS) ? wrch : rdch;
1778 		if (chn == NULL)
1779 			ret = EINVAL;
1780 		else {
1781 			oss_peaks_t *op = (oss_peaks_t *)arg;
1782 			int lpeak, rpeak;
1783 
1784 			CHN_LOCK(chn);
1785 			ret = chn_getpeaks(chn, &lpeak, &rpeak);
1786 			if (ret == -1)
1787 				ret = EINVAL;
1788 			else {
1789 				(*op)[0] = lpeak;
1790 				(*op)[1] = rpeak;
1791 			}
1792 			CHN_UNLOCK(chn);
1793 		}
1794 		break;
1795 
1796 	/*
1797 	 * XXX Once implemented, revisit this for proper cv protection
1798 	 *     (if necessary).
1799 	 */
1800 	case SNDCTL_GETLABEL:
1801 		ret = dsp_oss_getlabel(wrch, rdch, (oss_label_t *)arg);
1802 		break;
1803 	case SNDCTL_SETLABEL:
1804 		ret = dsp_oss_setlabel(wrch, rdch, (oss_label_t *)arg);
1805 		break;
1806 	case SNDCTL_GETSONG:
1807 		ret = dsp_oss_getsong(wrch, rdch, (oss_longname_t *)arg);
1808 		break;
1809 	case SNDCTL_SETSONG:
1810 		ret = dsp_oss_setsong(wrch, rdch, (oss_longname_t *)arg);
1811 		break;
1812 	case SNDCTL_SETNAME:
1813 		ret = dsp_oss_setname(wrch, rdch, (oss_longname_t *)arg);
1814 		break;
1815 #endif	/* !OSSV4_EXPERIMENT */
1816     	case SNDCTL_DSP_MAPINBUF:
1817     	case SNDCTL_DSP_MAPOUTBUF:
1818     	case SNDCTL_DSP_SETSYNCRO:
1819 		/* undocumented */
1820 
1821     	case SNDCTL_DSP_SUBDIVIDE:
1822     	case SOUND_PCM_WRITE_FILTER:
1823     	case SOUND_PCM_READ_FILTER:
1824 		/* dunno what these do, don't sound important */
1825 
1826     	default:
1827 		DEB(printf("default ioctl fn 0x%08lx fail\n", cmd));
1828 		ret = EINVAL;
1829 		break;
1830     	}
1831 
1832 	PCM_GIANT_LEAVE(d);
1833 
1834     	return (ret);
1835 }
1836 
1837 static int
1838 dsp_poll(struct cdev *i_dev, int events, struct thread *td)
1839 {
1840 	struct dsp_cdevpriv *priv;
1841 	struct snddev_info *d;
1842 	struct pcm_channel *wrch, *rdch;
1843 	int ret, e, err;
1844 
1845 	if ((err = devfs_get_cdevpriv((void **)&priv)) != 0)
1846 		return (err);
1847 	d = priv->sc;
1848 	if (!DSP_REGISTERED(d)) {
1849 		/* XXX many clients don't understand POLLNVAL */
1850 		return (events & (POLLHUP | POLLPRI | POLLIN |
1851 		    POLLRDNORM | POLLOUT | POLLWRNORM));
1852 	}
1853 	PCM_GIANT_ENTER(d);
1854 
1855 	ret = 0;
1856 
1857 	wrch = priv->wrch;
1858 	rdch = priv->rdch;
1859 
1860 	if (wrch != NULL && !(wrch->flags & CHN_F_DEAD)) {
1861 		CHN_LOCK(wrch);
1862 		e = (events & (POLLOUT | POLLWRNORM));
1863 		if (e)
1864 			ret |= chn_poll(wrch, e, td);
1865 		CHN_UNLOCK(wrch);
1866 	}
1867 
1868 	if (rdch != NULL && !(rdch->flags & CHN_F_DEAD)) {
1869 		CHN_LOCK(rdch);
1870 		e = (events & (POLLIN | POLLRDNORM));
1871 		if (e)
1872 			ret |= chn_poll(rdch, e, td);
1873 		CHN_UNLOCK(rdch);
1874 	}
1875 
1876 	PCM_GIANT_LEAVE(d);
1877 
1878 	return (ret);
1879 }
1880 
1881 struct dsp_mmap_handle {
1882 	struct cdev *cdev;
1883 	struct snd_dbuf *buf;
1884 };
1885 
1886 static int
1887 dsp_dev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot,
1888     vm_ooffset_t foff, struct ucred *cred, u_short *color)
1889 {
1890 	struct dsp_mmap_handle *h = handle;
1891 
1892 	dev_ref(h->cdev);
1893 	sndbuf_ref(h->buf);
1894 	return (0);
1895 }
1896 
1897 static void
1898 dsp_dev_pager_dtor(void *handle)
1899 {
1900 	struct dsp_mmap_handle *h = handle;
1901 
1902 	sndbuf_rele(h->buf);
1903 	dev_rel(h->cdev);
1904 	free(h, M_DEVBUF);
1905 }
1906 
1907 static int
1908 dsp_dev_pager_fault(vm_object_t object, vm_ooffset_t offset, int prot,
1909     vm_page_t *mres)
1910 {
1911 	struct dsp_mmap_handle *h = object->handle;
1912 	vm_page_t m;
1913 	uintptr_t addr;
1914 	vm_paddr_t paddr;
1915 
1916 	addr = (uintptr_t)offset;
1917 	if (addr < (uintptr_t)h->buf->buf ||
1918 	    addr >= (uintptr_t)h->buf->buf + h->buf->allocsize)
1919 		return (VM_PAGER_ERROR);
1920 	paddr = vtophys((void *)addr);
1921 
1922 	if (((*mres)->flags & PG_FICTITIOUS) != 0) {
1923 		m = *mres;
1924 		vm_page_updatefake(m, paddr, object->memattr);
1925 	} else {
1926 		VM_OBJECT_WUNLOCK(object);
1927 		m = vm_page_getfake(paddr, object->memattr);
1928 		VM_OBJECT_WLOCK(object);
1929 		vm_page_replace(m, object, (*mres)->pindex, *mres);
1930 		*mres = m;
1931 	}
1932 	m->valid = VM_PAGE_BITS_ALL;
1933 	return (VM_PAGER_OK);
1934 }
1935 
1936 static void
1937 dsp_dev_pager_path(void *handle, char *path, size_t len)
1938 {
1939 	struct dsp_mmap_handle *h = handle;
1940 
1941 	dev_copyname(h->cdev, path, len);
1942 }
1943 
1944 static const struct cdev_pager_ops dsp_dev_pager_ops = {
1945 	.cdev_pg_ctor = dsp_dev_pager_ctor,
1946 	.cdev_pg_dtor = dsp_dev_pager_dtor,
1947 	.cdev_pg_fault = dsp_dev_pager_fault,
1948 	.cdev_pg_path = dsp_dev_pager_path,
1949 };
1950 
1951 static int
1952 dsp_mmap_single(struct cdev *cdev, vm_ooffset_t *offset,
1953     vm_size_t size, struct vm_object **object, int nprot)
1954 {
1955 	struct dsp_mmap_handle *handle;
1956 	struct dsp_cdevpriv *priv;
1957 	struct snddev_info *d;
1958 	struct pcm_channel *c;
1959 	int err;
1960 	bool dealloc;
1961 
1962 	if (*offset >= *offset + size)
1963 		return (EINVAL);
1964 
1965 	/*
1966 	 * https://lists.freebsd.org/pipermail/freebsd-emulation/2007-June/003698.html
1967 	 */
1968 	if ((nprot & PROT_EXEC) && (dsp_mmap_allow_prot_exec < 0 ||
1969 	    (dsp_mmap_allow_prot_exec == 0 &&
1970 	    SV_CURPROC_ABI() != SV_ABI_LINUX)))
1971 		return (EINVAL);
1972 
1973 	if ((nprot & (PROT_READ | PROT_WRITE)) == 0)
1974 		return (EINVAL);
1975 
1976 	if ((err = devfs_get_cdevpriv((void **)&priv)) != 0)
1977 		return (err);
1978 	d = priv->sc;
1979 	if (!DSP_REGISTERED(d))
1980 		return (EINVAL);
1981 
1982 	PCM_GIANT_ENTER(d);
1983 
1984 	/*
1985 	 * PROT_READ (alone) selects the input buffer.
1986 	 * PROT_WRITE (alone) selects the output buffer.
1987 	 * PROT_WRITE|PROT_READ together select the output buffer.
1988 	 */
1989 	c = ((nprot & PROT_WRITE) != 0) ? priv->wrch : priv->rdch;
1990 	if (c == NULL) {
1991 		PCM_GIANT_EXIT(d);
1992 		return (EINVAL);
1993 	}
1994 
1995 	CHN_LOCK(c);
1996 	if ((c->flags & CHN_F_MMAP_INVALID) ||
1997 	    c->bufsoft->allocsize < *offset + size) {
1998 		CHN_UNLOCK(c);
1999 		PCM_GIANT_EXIT(d);
2000 		return (EINVAL);
2001 	}
2002 	c->flags |= CHN_F_MMAP;
2003 	*offset = (uintptr_t)sndbuf_getbufofs(c->bufsoft, *offset);
2004 	CHN_UNLOCK(c);
2005 
2006 	handle = malloc(sizeof(*handle), M_DEVBUF, M_WAITOK);
2007 	handle->cdev = cdev;
2008 	handle->buf = c->bufsoft;
2009 	*object = cdev_pager_allocate(handle, OBJT_DEVICE, &dsp_dev_pager_ops,
2010 	    size, nprot, *offset, curthread->td_ucred);
2011 	PCM_GIANT_LEAVE(d);
2012 	if (*object != NULL) {
2013 		err = 0;
2014 		dealloc = false;
2015 		CHN_LOCK(c);
2016 		if (c->flags & CHN_F_MMAP_INVALID) {
2017 			c->flags &= ~CHN_F_MMAP;
2018 			err = EINVAL;
2019 			dealloc = true;
2020 		}
2021 		CHN_UNLOCK(c);
2022 		/* We use a helper bool to keep the channel locking simpler. */
2023 		if (dealloc)
2024 			vm_object_deallocate(*object);
2025 	} else {
2026 		free(handle, M_DEVBUF);
2027 		err = ENOMEM;
2028 	}
2029 
2030 	return (err);
2031 }
2032 
2033 static const char *dsp_aliases[] = {
2034 	"dsp_ac3",
2035 	"dsp_mmap",
2036 	"dsp_multich",
2037 	"dsp_spdifout",
2038 	"dsp_spdifin",
2039 };
2040 
2041 static void
2042 dsp_clone(void *arg, struct ucred *cred, char *name, int namelen,
2043     struct cdev **dev)
2044 {
2045 	struct snddev_info *d;
2046 	size_t i;
2047 
2048 	if (*dev != NULL)
2049 		return;
2050 	if (strcmp(name, "dsp") == 0 && dsp_basename_clone)
2051 		goto found;
2052 	for (i = 0; i < nitems(dsp_aliases); i++) {
2053 		if (strcmp(name, dsp_aliases[i]) == 0)
2054 			goto found;
2055 	}
2056 	return;
2057 found:
2058 	bus_topo_lock();
2059 	d = devclass_get_softc(pcm_devclass, snd_unit);
2060 	/*
2061 	 * If we only have a single soundcard attached and we detach it right
2062 	 * before entering dsp_clone(), there is a chance pcm_unregister() will
2063 	 * have returned already, meaning it will have set snd_unit to -1, and
2064 	 * thus devclass_get_softc() will return NULL here.
2065 	 */
2066 	if (DSP_REGISTERED(d)) {
2067 		*dev = d->dsp_dev;
2068 		dev_ref(*dev);
2069 	}
2070 	bus_topo_unlock();
2071 }
2072 
2073 static void
2074 dsp_sysinit(void *p)
2075 {
2076 	if (dsp_ehtag != NULL)
2077 		return;
2078 	dsp_ehtag = EVENTHANDLER_REGISTER(dev_clone, dsp_clone, 0, 1000);
2079 }
2080 
2081 static void
2082 dsp_sysuninit(void *p)
2083 {
2084 	if (dsp_ehtag == NULL)
2085 		return;
2086 	EVENTHANDLER_DEREGISTER(dev_clone, dsp_ehtag);
2087 	dsp_ehtag = NULL;
2088 }
2089 
2090 SYSINIT(dsp_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, dsp_sysinit, NULL);
2091 SYSUNINIT(dsp_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, dsp_sysuninit, NULL);
2092 
2093 static void
2094 dsp_oss_audioinfo_unavail(oss_audioinfo *ai, int unit)
2095 {
2096 	bzero(ai, sizeof(*ai));
2097 	ai->dev = unit;
2098 	snprintf(ai->name, sizeof(ai->name), "pcm%d (unavailable)", unit);
2099 	ai->pid = -1;
2100 	strlcpy(ai->cmd, CHN_COMM_UNUSED, sizeof(ai->cmd));
2101 	ai->card_number = unit;
2102 	ai->port_number = unit;
2103 	ai->mixer_dev = -1;
2104 	ai->legacy_device = unit;
2105 }
2106 
2107 /**
2108  * @brief Handler for SNDCTL_AUDIOINFO.
2109  *
2110  * Gathers information about the audio device specified in ai->dev.  If
2111  * ai->dev == -1, then this function gathers information about the current
2112  * device.  If the call comes in on a non-audio device and ai->dev == -1,
2113  * return EINVAL.
2114  *
2115  * This routine is supposed to go practically straight to the hardware,
2116  * getting capabilities directly from the sound card driver, side-stepping
2117  * the intermediate channel interface.
2118  *
2119  * @note
2120  * Calling threads must not hold any snddev_info or pcm_channel locks.
2121  *
2122  * @param dev		device on which the ioctl was issued
2123  * @param ai		ioctl request data container
2124  * @param ex		flag to distinguish between SNDCTL_AUDIOINFO from
2125  *			SNDCTL_AUDIOINFO_EX
2126  *
2127  * @retval 0		success
2128  * @retval EINVAL	ai->dev specifies an invalid device
2129  */
2130 int
2131 dsp_oss_audioinfo(struct cdev *i_dev, oss_audioinfo *ai, bool ex)
2132 {
2133 	struct pcmchan_caps *caps;
2134 	struct pcm_channel *ch;
2135 	struct snddev_info *d;
2136 	uint32_t fmts;
2137 	int i, minch, maxch, unit;
2138 
2139 	/*
2140 	 * If probing the device that received the ioctl, make sure it's a
2141 	 * DSP device.  (Users may use this ioctl with /dev/mixer and
2142 	 * /dev/midi.)
2143 	 */
2144 	if (ai->dev == -1 && i_dev->si_devsw != &dsp_cdevsw)
2145 		return (EINVAL);
2146 
2147 	bus_topo_lock();
2148 	for (unit = 0; pcm_devclass != NULL &&
2149 	    unit < devclass_get_maxunit(pcm_devclass); unit++) {
2150 		d = devclass_get_softc(pcm_devclass, unit);
2151 		if (!PCM_REGISTERED(d)) {
2152 			if ((ai->dev == -1 && unit == snd_unit) ||
2153 			    ai->dev == unit) {
2154 				dsp_oss_audioinfo_unavail(ai, unit);
2155 				bus_topo_unlock();
2156 				return (0);
2157 			} else {
2158 				d = NULL;
2159 				continue;
2160 			}
2161 		}
2162 
2163 		PCM_UNLOCKASSERT(d);
2164 		PCM_LOCK(d);
2165 		if ((ai->dev == -1 && d->dsp_dev == i_dev) ||
2166 		    (ai->dev == unit)) {
2167 			PCM_UNLOCK(d);
2168 			break;
2169 		} else {
2170 			PCM_UNLOCK(d);
2171 			d = NULL;
2172 		}
2173 	}
2174 	bus_topo_unlock();
2175 
2176 	/* Exhausted the search -- nothing is locked, so return. */
2177 	if (d == NULL)
2178 		return (EINVAL);
2179 
2180 	/* XXX Need Giant magic entry ??? */
2181 
2182 	PCM_UNLOCKASSERT(d);
2183 	PCM_LOCK(d);
2184 
2185 	bzero((void *)ai, sizeof(oss_audioinfo));
2186 	ai->dev = unit;
2187 	strlcpy(ai->name, device_get_desc(d->dev), sizeof(ai->name));
2188 	ai->pid = -1;
2189 	strlcpy(ai->cmd, CHN_COMM_UNKNOWN, sizeof(ai->cmd));
2190 	ai->card_number = unit;
2191 	ai->port_number = unit;
2192 	ai->mixer_dev = (d->mixer_dev != NULL) ? unit : -1;
2193 	ai->legacy_device = unit;
2194 	snprintf(ai->devnode, sizeof(ai->devnode), "/dev/dsp%d", unit);
2195 	ai->enabled = device_is_attached(d->dev) ? 1 : 0;
2196 	ai->next_play_engine = 0;
2197 	ai->next_rec_engine = 0;
2198 	ai->busy = 0;
2199 	ai->caps = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER;
2200 	ai->iformats = 0;
2201 	ai->oformats = 0;
2202 	ai->min_rate = INT_MAX;
2203 	ai->max_rate = 0;
2204 	ai->min_channels = INT_MAX;
2205 	ai->max_channels = 0;
2206 
2207 	/* Gather global information about the device. */
2208 	CHN_FOREACH(ch, d, channels.pcm) {
2209 		CHN_UNLOCKASSERT(ch);
2210 		CHN_LOCK(ch);
2211 
2212 		/*
2213 		 * Skip physical channels if we are servicing SNDCTL_AUDIOINFO,
2214 		 * or VCHANs if we are servicing SNDCTL_AUDIOINFO_EX.
2215 		 *
2216 		 * For SNDCTL_AUDIOINFO do not skip the physical channels if
2217 		 * there are no VCHANs.
2218 		 */
2219 		if ((ex && (ch->flags & CHN_F_VIRTUAL) != 0) ||
2220 		    ((!ex && (ch->flags & CHN_F_VIRTUAL) == 0) &&
2221 		    (d->pvchancount > 0 || d->rvchancount > 0))) {
2222 			CHN_UNLOCK(ch);
2223 			continue;
2224 		}
2225 
2226 		if ((ch->flags & CHN_F_BUSY) == 0) {
2227 			ai->busy |= (ch->direction == PCMDIR_PLAY) ?
2228 			    OPEN_WRITE : OPEN_READ;
2229 		}
2230 
2231 		ai->caps |=
2232 		    ((ch->flags & CHN_F_VIRTUAL) ? PCM_CAP_VIRTUAL : 0) |
2233 		    ((ch->direction == PCMDIR_PLAY) ? PCM_CAP_OUTPUT :
2234 		    PCM_CAP_INPUT);
2235 
2236 		caps = chn_getcaps(ch);
2237 
2238 		minch = INT_MAX;
2239 		maxch = 0;
2240 		fmts = 0;
2241 		for (i = 0; caps->fmtlist[i]; i++) {
2242 			fmts |= AFMT_ENCODING(caps->fmtlist[i]);
2243 			minch = min(AFMT_CHANNEL(caps->fmtlist[i]), minch);
2244 			maxch = max(AFMT_CHANNEL(caps->fmtlist[i]), maxch);
2245 		}
2246 
2247 		if (ch->direction == PCMDIR_PLAY)
2248 			ai->oformats |= fmts;
2249 		else
2250 			ai->iformats |= fmts;
2251 
2252 		if (ex || (pcm_getflags(d->dev) & SD_F_BITPERFECT)) {
2253 			ai->min_rate = min(ai->min_rate, caps->minspeed);
2254 			ai->max_rate = max(ai->max_rate, caps->maxspeed);
2255 		} else {
2256 			ai->min_rate = min(ai->min_rate, feeder_rate_min);
2257 			ai->max_rate = max(ai->max_rate, feeder_rate_max);
2258 		}
2259 		ai->min_channels = min(ai->min_channels, minch);
2260 		ai->max_channels = max(ai->max_channels, maxch);
2261 
2262 		CHN_UNLOCK(ch);
2263 	}
2264 	if (ai->min_rate == INT_MAX)
2265 		ai->min_rate = 0;
2266 	if (ai->min_channels == INT_MAX)
2267 		ai->min_channels = 0;
2268 
2269 	PCM_UNLOCK(d);
2270 
2271 	return (0);
2272 }
2273 
2274 static int
2275 dsp_oss_engineinfo_cb(void *data, void *arg)
2276 {
2277 	struct dsp_cdevpriv *priv = data;
2278 	struct pcm_channel *ch = arg;
2279 
2280 	if (DSP_REGISTERED(priv->sc) && (ch == priv->rdch || ch == priv->wrch))
2281 		return (1);
2282 
2283 	return (0);
2284 }
2285 
2286 /**
2287  * @brief Handler for SNDCTL_ENGINEINFO
2288  *
2289  * Gathers information about the audio device's engine specified in ai->dev.
2290  * If ai->dev == -1, then this function gathers information about the current
2291  * device.  If the call comes in on a non-audio device and ai->dev == -1,
2292  * return EINVAL.
2293  *
2294  * This routine is supposed to go practically straight to the hardware,
2295  * getting capabilities directly from the sound card driver, side-stepping
2296  * the intermediate channel interface.
2297  *
2298  * @note
2299  * Calling threads must not hold any snddev_info or pcm_channel locks.
2300  *
2301  * @param dev		device on which the ioctl was issued
2302  * @param ai		ioctl request data container
2303  *
2304  * @retval 0		success
2305  * @retval EINVAL	ai->dev specifies an invalid device
2306  */
2307 int
2308 dsp_oss_engineinfo(struct cdev *i_dev, oss_audioinfo *ai)
2309 {
2310 	struct pcmchan_caps *caps;
2311 	struct pcm_channel *ch;
2312 	struct snddev_info *d;
2313 	uint32_t fmts;
2314 	int i, nchan, *rates, minch, maxch, unit;
2315 
2316 	/*
2317 	 * If probing the device that received the ioctl, make sure it's a
2318 	 * DSP device.  (Users may use this ioctl with /dev/mixer and
2319 	 * /dev/midi.)
2320 	 */
2321 	if (ai->dev == -1 && i_dev->si_devsw != &dsp_cdevsw)
2322 		return (EINVAL);
2323 
2324 	ch = NULL;
2325 	nchan = 0;
2326 
2327 	/*
2328 	 * Search for the requested audio device (channel).  Start by
2329 	 * iterating over pcm devices.
2330 	 */
2331 	bus_topo_lock();
2332 	for (unit = 0; pcm_devclass != NULL &&
2333 	    unit < devclass_get_maxunit(pcm_devclass); unit++) {
2334 		d = devclass_get_softc(pcm_devclass, unit);
2335 		if (!PCM_REGISTERED(d))
2336 			continue;
2337 
2338 		/* XXX Need Giant magic entry ??? */
2339 
2340 		/* See the note in function docblock */
2341 		PCM_UNLOCKASSERT(d);
2342 		PCM_LOCK(d);
2343 
2344 		CHN_FOREACH(ch, d, channels.pcm) {
2345 			CHN_UNLOCKASSERT(ch);
2346 			CHN_LOCK(ch);
2347 			if ((ai->dev == -1 && devfs_foreach_cdevpriv(
2348 			    i_dev, dsp_oss_engineinfo_cb, ch) != 0) ||
2349 			    ai->dev == nchan)
2350 				break;
2351 			CHN_UNLOCK(ch);
2352 			++nchan;
2353 		}
2354 
2355 		if (ch == NULL) {
2356 			PCM_UNLOCK(d);
2357 			continue;
2358 		}
2359 
2360 		/*
2361 		 * At this point, the following synchronization stuff
2362 		 * has happened:
2363 		 * - a specific PCM device is locked.
2364 		 * - a specific audio channel has been locked, so be
2365 		 *   sure to unlock when exiting;
2366 		 */
2367 
2368 		caps = chn_getcaps(ch);
2369 
2370 		/*
2371 		 * With all handles collected, zero out the user's
2372 		 * container and begin filling in its fields.
2373 		 */
2374 		bzero((void *)ai, sizeof(oss_audioinfo));
2375 
2376 		ai->dev = nchan;
2377 		strlcpy(ai->name, ch->name,  sizeof(ai->name));
2378 
2379 		if ((ch->flags & CHN_F_BUSY) == 0)
2380 			ai->busy = 0;
2381 		else
2382 			ai->busy = (ch->direction == PCMDIR_PLAY) ? OPEN_WRITE : OPEN_READ;
2383 
2384 		ai->pid = ch->pid;
2385 		strlcpy(ai->cmd, ch->comm, sizeof(ai->cmd));
2386 
2387 		/*
2388 		 * These flags stolen from SNDCTL_DSP_GETCAPS handler.
2389 		 * Note, however, that a single channel operates in
2390 		 * only one direction, so PCM_CAP_DUPLEX is out.
2391 		 */
2392 		/**
2393 		 * @todo @c SNDCTL_AUDIOINFO::caps - Make drivers keep
2394 		 *       these in pcmchan::caps?
2395 		 */
2396 		ai->caps = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER |
2397 		    ((ch->flags & CHN_F_VIRTUAL) ? PCM_CAP_VIRTUAL : 0) |
2398 		    ((ch->direction == PCMDIR_PLAY) ? PCM_CAP_OUTPUT : PCM_CAP_INPUT);
2399 
2400 		/*
2401 		 * Collect formats supported @b natively by the
2402 		 * device.  Also determine min/max channels.
2403 		 */
2404 		minch = INT_MAX;
2405 		maxch = 0;
2406 		fmts = 0;
2407 		for (i = 0; caps->fmtlist[i]; i++) {
2408 			fmts |= AFMT_ENCODING(caps->fmtlist[i]);
2409 			minch = min(AFMT_CHANNEL(caps->fmtlist[i]), minch);
2410 			maxch = max(AFMT_CHANNEL(caps->fmtlist[i]), maxch);
2411 		}
2412 
2413 		if (ch->direction == PCMDIR_PLAY)
2414 			ai->oformats = fmts;
2415 		else
2416 			ai->iformats = fmts;
2417 
2418 		/**
2419 		 * @note
2420 		 * @c magic - OSSv4 docs: "Reserved for internal use
2421 		 *    by OSS."
2422 		 *
2423 		 * @par
2424 		 * @c card_number - OSSv4 docs: "Number of the sound
2425 		 *    card where this device belongs or -1 if this
2426 		 *    information is not available.  Applications
2427 		 *    should normally not use this field for any
2428 		 *    purpose."
2429 		 */
2430 		ai->card_number = unit;
2431 		/**
2432 		 * @todo @c song_name - depends first on
2433 		 *          SNDCTL_[GS]ETSONG @todo @c label - depends
2434 		 *          on SNDCTL_[GS]ETLABEL
2435 		 * @todo @c port_number - routing information?
2436 		 */
2437 		ai->port_number = unit;
2438 		ai->mixer_dev = (d->mixer_dev != NULL) ? unit : -1;
2439 		/**
2440 		 * @note
2441 		 * @c legacy_device - OSSv4 docs:  "Obsolete."
2442 		 */
2443 		ai->legacy_device = unit;
2444 		snprintf(ai->devnode, sizeof(ai->devnode), "/dev/dsp%d", unit);
2445 		ai->enabled = device_is_attached(d->dev) ? 1 : 0;
2446 		/**
2447 		 * @note
2448 		 * @c flags - OSSv4 docs: "Reserved for future use."
2449 		 *
2450 		 * @note
2451 		 * @c binding - OSSv4 docs: "Reserved for future use."
2452 		 *
2453 		 * @todo @c handle - haven't decided how to generate
2454 		 *       this yet; bus, vendor, device IDs?
2455 		 */
2456 
2457 		if ((ch->flags & CHN_F_EXCLUSIVE) ||
2458 		    (pcm_getflags(d->dev) & SD_F_BITPERFECT)) {
2459 			ai->min_rate = caps->minspeed;
2460 			ai->max_rate = caps->maxspeed;
2461 		} else {
2462 			ai->min_rate = feeder_rate_min;
2463 			ai->max_rate = feeder_rate_max;
2464 		}
2465 
2466 		ai->min_channels = minch;
2467 		ai->max_channels = maxch;
2468 
2469 		ai->nrates = chn_getrates(ch, &rates);
2470 		if (ai->nrates > OSS_MAX_SAMPLE_RATES)
2471 			ai->nrates = OSS_MAX_SAMPLE_RATES;
2472 
2473 		for (i = 0; i < ai->nrates; i++)
2474 			ai->rates[i] = rates[i];
2475 
2476 		ai->next_play_engine = 0;
2477 		ai->next_rec_engine = 0;
2478 
2479 		CHN_UNLOCK(ch);
2480 		PCM_UNLOCK(d);
2481 		bus_topo_unlock();
2482 
2483 		return (0);
2484 	}
2485 	bus_topo_unlock();
2486 
2487 	/* Exhausted the search -- nothing is locked, so return. */
2488 	return (EINVAL);
2489 }
2490 
2491 /**
2492  * @brief Assigns a PCM channel to a sync group.
2493  *
2494  * Sync groups are used to enable audio operations on multiple devices
2495  * simultaneously.  They may be used with any number of devices and may
2496  * span across applications.  Devices are added to groups with
2497  * the SNDCTL_DSP_SYNCGROUP ioctl, and operations are triggered with the
2498  * SNDCTL_DSP_SYNCSTART ioctl.
2499  *
2500  * If the @c id field of the @c group parameter is set to zero, then a new
2501  * sync group is created.  Otherwise, wrch and rdch (if set) are added to
2502  * the group specified.
2503  *
2504  * @todo As far as memory allocation, should we assume that things are
2505  * 	 okay and allocate with M_WAITOK before acquiring channel locks,
2506  * 	 freeing later if not?
2507  *
2508  * @param wrch	output channel associated w/ device (if any)
2509  * @param rdch	input channel associated w/ device (if any)
2510  * @param group Sync group parameters
2511  *
2512  * @retval 0		success
2513  * @retval non-zero	error to be propagated upstream
2514  */
2515 static int
2516 dsp_oss_syncgroup(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_syncgroup *group)
2517 {
2518 	struct pcmchan_syncmember *smrd, *smwr;
2519 	struct pcmchan_syncgroup *sg;
2520 	int ret, sg_ids[3];
2521 
2522 	smrd = NULL;
2523 	smwr = NULL;
2524 	sg = NULL;
2525 	ret = 0;
2526 
2527 	/*
2528 	 * Free_unr() may sleep, so store released syncgroup IDs until after
2529 	 * all locks are released.
2530 	 */
2531 	sg_ids[0] = sg_ids[1] = sg_ids[2] = 0;
2532 
2533 	PCM_SG_LOCK();
2534 
2535 	/*
2536 	 * - Insert channel(s) into group's member list.
2537 	 * - Set CHN_F_NOTRIGGER on channel(s).
2538 	 * - Stop channel(s).
2539 	 */
2540 
2541 	/*
2542 	 * If device's channels are already mapped to a group, unmap them.
2543 	 */
2544 	if (wrch) {
2545 		CHN_LOCK(wrch);
2546 		sg_ids[0] = chn_syncdestroy(wrch);
2547 	}
2548 
2549 	if (rdch) {
2550 		CHN_LOCK(rdch);
2551 		sg_ids[1] = chn_syncdestroy(rdch);
2552 	}
2553 
2554 	/*
2555 	 * Verify that mode matches character device properites.
2556 	 *  - Bail if PCM_ENABLE_OUTPUT && wrch == NULL.
2557 	 *  - Bail if PCM_ENABLE_INPUT && rdch == NULL.
2558 	 */
2559 	if (((wrch == NULL) && (group->mode & PCM_ENABLE_OUTPUT)) ||
2560 	    ((rdch == NULL) && (group->mode & PCM_ENABLE_INPUT))) {
2561 		ret = EINVAL;
2562 		goto out;
2563 	}
2564 
2565 	/*
2566 	 * An id of zero indicates the user wants to create a new
2567 	 * syncgroup.
2568 	 */
2569 	if (group->id == 0) {
2570 		sg = malloc(sizeof(*sg), M_DEVBUF, M_NOWAIT);
2571 		if (sg != NULL) {
2572 			SLIST_INIT(&sg->members);
2573 			sg->id = alloc_unr(pcmsg_unrhdr);
2574 
2575 			group->id = sg->id;
2576 			SLIST_INSERT_HEAD(&snd_pcm_syncgroups, sg, link);
2577 		} else
2578 			ret = ENOMEM;
2579 	} else {
2580 		SLIST_FOREACH(sg, &snd_pcm_syncgroups, link) {
2581 			if (sg->id == group->id)
2582 				break;
2583 		}
2584 		if (sg == NULL)
2585 			ret = EINVAL;
2586 	}
2587 
2588 	/* Couldn't create or find a syncgroup.  Fail. */
2589 	if (sg == NULL)
2590 		goto out;
2591 
2592 	/*
2593 	 * Allocate a syncmember, assign it and a channel together, and
2594 	 * insert into syncgroup.
2595 	 */
2596 	if (group->mode & PCM_ENABLE_INPUT) {
2597 		smrd = malloc(sizeof(*smrd), M_DEVBUF, M_NOWAIT);
2598 		if (smrd == NULL) {
2599 			ret = ENOMEM;
2600 			goto out;
2601 		}
2602 
2603 		SLIST_INSERT_HEAD(&sg->members, smrd, link);
2604 		smrd->parent = sg;
2605 		smrd->ch = rdch;
2606 
2607 		chn_abort(rdch);
2608 		rdch->flags |= CHN_F_NOTRIGGER;
2609 		rdch->sm = smrd;
2610 	}
2611 
2612 	if (group->mode & PCM_ENABLE_OUTPUT) {
2613 		smwr = malloc(sizeof(*smwr), M_DEVBUF, M_NOWAIT);
2614 		if (smwr == NULL) {
2615 			ret = ENOMEM;
2616 			goto out;
2617 		}
2618 
2619 		SLIST_INSERT_HEAD(&sg->members, smwr, link);
2620 		smwr->parent = sg;
2621 		smwr->ch = wrch;
2622 
2623 		chn_abort(wrch);
2624 		wrch->flags |= CHN_F_NOTRIGGER;
2625 		wrch->sm = smwr;
2626 	}
2627 
2628 out:
2629 	if (ret != 0) {
2630 		free(smrd, M_DEVBUF);
2631 		if ((sg != NULL) && SLIST_EMPTY(&sg->members)) {
2632 			sg_ids[2] = sg->id;
2633 			SLIST_REMOVE(&snd_pcm_syncgroups, sg, pcmchan_syncgroup, link);
2634 			free(sg, M_DEVBUF);
2635 		}
2636 
2637 		if (wrch)
2638 			wrch->sm = NULL;
2639 		if (rdch)
2640 			rdch->sm = NULL;
2641 	}
2642 
2643 	if (wrch)
2644 		CHN_UNLOCK(wrch);
2645 	if (rdch)
2646 		CHN_UNLOCK(rdch);
2647 
2648 	PCM_SG_UNLOCK();
2649 
2650 	if (sg_ids[0])
2651 		free_unr(pcmsg_unrhdr, sg_ids[0]);
2652 	if (sg_ids[1])
2653 		free_unr(pcmsg_unrhdr, sg_ids[1]);
2654 	if (sg_ids[2])
2655 		free_unr(pcmsg_unrhdr, sg_ids[2]);
2656 
2657 	return (ret);
2658 }
2659 
2660 /**
2661  * @brief Launch a sync group into action
2662  *
2663  * Sync groups are established via SNDCTL_DSP_SYNCGROUP.  This function
2664  * iterates over all members, triggering them along the way.
2665  *
2666  * @note Caller must not hold any channel locks.
2667  *
2668  * @param sg_id	sync group identifier
2669  *
2670  * @retval 0	success
2671  * @retval non-zero	error worthy of propagating upstream to user
2672  */
2673 static int
2674 dsp_oss_syncstart(int sg_id)
2675 {
2676 	struct pcmchan_syncmember *sm, *sm_tmp;
2677 	struct pcmchan_syncgroup *sg;
2678 	struct pcm_channel *c;
2679 	int ret, needlocks;
2680 
2681 	/* Get the synclists lock */
2682 	PCM_SG_LOCK();
2683 
2684 	do {
2685 		ret = 0;
2686 		needlocks = 0;
2687 
2688 		/* Search for syncgroup by ID */
2689 		SLIST_FOREACH(sg, &snd_pcm_syncgroups, link) {
2690 			if (sg->id == sg_id)
2691 				break;
2692 		}
2693 
2694 		/* Return EINVAL if not found */
2695 		if (sg == NULL) {
2696 			ret = EINVAL;
2697 			break;
2698 		}
2699 
2700 		/* Any removals resulting in an empty group should've handled this */
2701 		KASSERT(!SLIST_EMPTY(&sg->members), ("found empty syncgroup"));
2702 
2703 		/*
2704 		 * Attempt to lock all member channels - if any are already
2705 		 * locked, unlock those acquired, sleep for a bit, and try
2706 		 * again.
2707 		 */
2708 		SLIST_FOREACH(sm, &sg->members, link) {
2709 			if (CHN_TRYLOCK(sm->ch) == 0) {
2710 				int timo = hz * 5/1000;
2711 				if (timo < 1)
2712 					timo = 1;
2713 
2714 				/* Release all locked channels so far, retry */
2715 				SLIST_FOREACH(sm_tmp, &sg->members, link) {
2716 					/* sm is the member already locked */
2717 					if (sm == sm_tmp)
2718 						break;
2719 					CHN_UNLOCK(sm_tmp->ch);
2720 				}
2721 
2722 				/** @todo Is PRIBIO correct/ */
2723 				ret = msleep(sm, &snd_pcm_syncgroups_mtx,
2724 				    PRIBIO | PCATCH, "pcmsg", timo);
2725 				if (ret == EINTR || ret == ERESTART)
2726 					break;
2727 
2728 				needlocks = 1;
2729 				ret = 0; /* Assumes ret == EAGAIN... */
2730 			}
2731 		}
2732 	} while (needlocks && ret == 0);
2733 
2734 	/* Proceed only if no errors encountered. */
2735 	if (ret == 0) {
2736 		/*
2737 		 * Unlock all members before starting any of them.
2738 		 * Holding multiple channel locks while calling chn_start()
2739 		 * on a virtual channel can trigger the parent, which
2740 		 * acquires PCM_LOCK() while other virtual channels are
2741 		 * still locked -- a lock order reversal.
2742 		 */
2743 		SLIST_FOREACH(sm, &sg->members, link) {
2744 			sm->ch->sm = NULL;
2745 			sm->ch->flags &= ~CHN_F_NOTRIGGER;
2746 			CHN_UNLOCK(sm->ch);
2747 		}
2748 
2749 		/*
2750 		 * Start each channel individually, then remove it from
2751 		 * the sync group and free its member structure.
2752 		 */
2753 		while ((sm = SLIST_FIRST(&sg->members)) != NULL) {
2754 			c = sm->ch;
2755 			CHN_LOCK(c);
2756 			chn_start(c, 1);
2757 			CHN_UNLOCK(c);
2758 			SLIST_REMOVE_HEAD(&sg->members, link);
2759 			free(sm, M_DEVBUF);
2760 		}
2761 
2762 		SLIST_REMOVE(&snd_pcm_syncgroups, sg, pcmchan_syncgroup, link);
2763 		free(sg, M_DEVBUF);
2764 	}
2765 
2766 	PCM_SG_UNLOCK();
2767 
2768 	/*
2769 	 * Free_unr() may sleep, so be sure to give up the syncgroup lock
2770 	 * first.
2771 	 */
2772 	if (ret == 0)
2773 		free_unr(pcmsg_unrhdr, sg_id);
2774 
2775 	return (ret);
2776 }
2777 
2778 /**
2779  * @brief Handler for SNDCTL_DSP_POLICY
2780  *
2781  * The SNDCTL_DSP_POLICY ioctl is a simpler interface to control fragment
2782  * size and count like with SNDCTL_DSP_SETFRAGMENT.  Instead of the user
2783  * specifying those two parameters, s/he simply selects a number from 0..10
2784  * which corresponds to a buffer size.  Smaller numbers request smaller
2785  * buffers with lower latencies (at greater overhead from more frequent
2786  * interrupts), while greater numbers behave in the opposite manner.
2787  *
2788  * The 4Front spec states that a value of 5 should be the default.  However,
2789  * this implementation deviates slightly by using a linear scale without
2790  * consulting drivers.  I.e., even though drivers may have different default
2791  * buffer sizes, a policy argument of 5 will have the same result across
2792  * all drivers.
2793  *
2794  * See http://manuals.opensound.com/developer/SNDCTL_DSP_POLICY.html for
2795  * more information.
2796  *
2797  * @todo When SNDCTL_DSP_COOKEDMODE is supported, it'll be necessary to
2798  * 	 work with hardware drivers directly.
2799  *
2800  * @note PCM channel arguments must not be locked by caller.
2801  *
2802  * @param wrch	Pointer to opened playback channel (optional; may be NULL)
2803  * @param rdch	" recording channel (optional; may be NULL)
2804  * @param policy Integer from [0:10]
2805  *
2806  * @retval 0	constant (for now)
2807  */
2808 static int
2809 dsp_oss_policy(struct pcm_channel *wrch, struct pcm_channel *rdch, int policy)
2810 {
2811 	int ret;
2812 
2813 	if (policy < CHN_POLICY_MIN || policy > CHN_POLICY_MAX)
2814 		return (EIO);
2815 
2816 	/* Default: success */
2817 	ret = 0;
2818 
2819 	if (rdch) {
2820 		CHN_LOCK(rdch);
2821 		ret = chn_setlatency(rdch, policy);
2822 		CHN_UNLOCK(rdch);
2823 	}
2824 
2825 	if (wrch && ret == 0) {
2826 		CHN_LOCK(wrch);
2827 		ret = chn_setlatency(wrch, policy);
2828 		CHN_UNLOCK(wrch);
2829 	}
2830 
2831 	if (ret)
2832 		ret = EIO;
2833 
2834 	return (ret);
2835 }
2836 
2837 /**
2838  * @brief Enable or disable "cooked" mode
2839  *
2840  * This is a handler for @c SNDCTL_DSP_COOKEDMODE.  When in cooked mode, which
2841  * is the default, the sound system handles rate and format conversions
2842  * automatically (ex: user writing 11025Hz/8 bit/unsigned but card only
2843  * operates with 44100Hz/16bit/signed samples).
2844  *
2845  * Disabling cooked mode is intended for applications wanting to mmap()
2846  * a sound card's buffer space directly, bypassing the FreeBSD 2-stage
2847  * feeder architecture, presumably to gain as much control over audio
2848  * hardware as possible.
2849  *
2850  * See @c http://manuals.opensound.com/developer/SNDCTL_DSP_COOKEDMODE.html
2851  * for more details.
2852  *
2853  * @param wrch		playback channel (optional; may be NULL)
2854  * @param rdch		recording channel (optional; may be NULL)
2855  * @param enabled	0 = raw mode, 1 = cooked mode
2856  *
2857  * @retval EINVAL	Operation not yet supported.
2858  */
2859 static int
2860 dsp_oss_cookedmode(struct pcm_channel *wrch, struct pcm_channel *rdch, int enabled)
2861 {
2862 
2863 	/*
2864 	 * XXX I just don't get it. Why don't they call it
2865 	 * "BITPERFECT" ~ SNDCTL_DSP_BITPERFECT !?!?.
2866 	 * This is just plain so confusing, incoherent,
2867 	 * <insert any non-printable characters here>.
2868 	 */
2869 	if (!(enabled == 1 || enabled == 0))
2870 		return (EINVAL);
2871 
2872 	/*
2873 	 * I won't give in. I'm inverting its logic here and now.
2874 	 * Brag all you want, but "BITPERFECT" should be the better
2875 	 * term here.
2876 	 */
2877 	enabled ^= 0x00000001;
2878 
2879 	if (wrch != NULL) {
2880 		CHN_LOCK(wrch);
2881 		wrch->flags &= ~CHN_F_BITPERFECT;
2882 		wrch->flags |= (enabled != 0) ? CHN_F_BITPERFECT : 0x00000000;
2883 		CHN_UNLOCK(wrch);
2884 	}
2885 
2886 	if (rdch != NULL) {
2887 		CHN_LOCK(rdch);
2888 		rdch->flags &= ~CHN_F_BITPERFECT;
2889 		rdch->flags |= (enabled != 0) ? CHN_F_BITPERFECT : 0x00000000;
2890 		CHN_UNLOCK(rdch);
2891 	}
2892 
2893 	return (0);
2894 }
2895 
2896 /**
2897  * @brief Retrieve channel interleaving order
2898  *
2899  * This is the handler for @c SNDCTL_DSP_GET_CHNORDER.
2900  *
2901  * See @c http://manuals.opensound.com/developer/SNDCTL_DSP_GET_CHNORDER.html
2902  * for more details.
2903  *
2904  * @note As the ioctl definition is still under construction, FreeBSD
2905  * 	 does not currently support SNDCTL_DSP_GET_CHNORDER.
2906  *
2907  * @param wrch	playback channel (optional; may be NULL)
2908  * @param rdch	recording channel (optional; may be NULL)
2909  * @param map	channel map (result will be stored there)
2910  *
2911  * @retval EINVAL	Operation not yet supported.
2912  */
2913 static int
2914 dsp_oss_getchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map)
2915 {
2916 	struct pcm_channel *ch;
2917 	int ret;
2918 
2919 	ch = (wrch != NULL) ? wrch : rdch;
2920 	if (ch != NULL) {
2921 		CHN_LOCK(ch);
2922 		ret = chn_oss_getorder(ch, map);
2923 		CHN_UNLOCK(ch);
2924 	} else
2925 		ret = EINVAL;
2926 
2927 	return (ret);
2928 }
2929 
2930 /**
2931  * @brief Specify channel interleaving order
2932  *
2933  * This is the handler for @c SNDCTL_DSP_SET_CHNORDER.
2934  *
2935  * @note As the ioctl definition is still under construction, FreeBSD
2936  * 	 does not currently support @c SNDCTL_DSP_SET_CHNORDER.
2937  *
2938  * @param wrch	playback channel (optional; may be NULL)
2939  * @param rdch	recording channel (optional; may be NULL)
2940  * @param map	channel map
2941  *
2942  * @retval EINVAL	Operation not yet supported.
2943  */
2944 static int
2945 dsp_oss_setchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map)
2946 {
2947 	int ret;
2948 
2949 	ret = 0;
2950 
2951 	if (wrch != NULL) {
2952 		CHN_LOCK(wrch);
2953 		ret = chn_oss_setorder(wrch, map);
2954 		CHN_UNLOCK(wrch);
2955 	}
2956 
2957 	if (ret == 0 && rdch != NULL) {
2958 		CHN_LOCK(rdch);
2959 		ret = chn_oss_setorder(rdch, map);
2960 		CHN_UNLOCK(rdch);
2961 	}
2962 
2963 	return (ret);
2964 }
2965 
2966 static int
2967 dsp_oss_getchannelmask(struct pcm_channel *wrch, struct pcm_channel *rdch,
2968     int *mask)
2969 {
2970 	struct pcm_channel *ch;
2971 	uint32_t chnmask;
2972 	int ret;
2973 
2974 	chnmask = 0;
2975 	ch = (wrch != NULL) ? wrch : rdch;
2976 
2977 	if (ch != NULL) {
2978 		CHN_LOCK(ch);
2979 		ret = chn_oss_getmask(ch, &chnmask);
2980 		CHN_UNLOCK(ch);
2981 	} else
2982 		ret = EINVAL;
2983 
2984 	if (ret == 0)
2985 		*mask = chnmask;
2986 
2987 	return (ret);
2988 }
2989 
2990 static void
2991 dsp_kqdetach(struct knote *kn)
2992 {
2993 	struct pcm_channel *ch = kn->kn_hook;
2994 
2995 	if (ch == NULL)
2996 		return;
2997 	CHN_LOCK(ch);
2998 	knlist_remove(&ch->bufsoft->sel.si_note, kn, 1);
2999 	CHN_UNLOCK(ch);
3000 }
3001 
3002 static int
3003 dsp_kqevent(struct knote *kn, long hint)
3004 {
3005 	struct pcm_channel *ch = kn->kn_hook;
3006 
3007 	CHN_LOCKASSERT(ch);
3008 	if (ch->flags & CHN_F_DEAD) {
3009 		kn->kn_flags |= EV_EOF;
3010 		return (1);
3011 	}
3012 	kn->kn_data = 0;
3013 	if (chn_polltrigger(ch)) {
3014 		if (kn->kn_filter == EVFILT_READ) {
3015 			kn->kn_data = sndbuf_getready(ch->bufsoft);
3016 			if (ch->flags & CHN_F_MMAP)
3017 				kn->kn_kevent.ext[0] = sndbuf_getfreeptr(ch->bufsoft);
3018 			else
3019 				kn->kn_kevent.ext[0] = sndbuf_getready(ch->bufsoft) / ch->bufsoft->align;
3020 		} else {
3021 			kn->kn_data = sndbuf_getfree(ch->bufsoft);
3022 			if (ch->flags & CHN_F_MMAP)
3023 				kn->kn_kevent.ext[0] = sndbuf_getreadyptr(ch->bufsoft);
3024 			else
3025 				kn->kn_kevent.ext[0] = sndbuf_getready(ch->bufsoft) / ch->bufsoft->align;
3026 		}
3027 		kn->kn_kevent.ext[1] = ch->xruns;
3028 	}
3029 
3030 	return (kn->kn_data > 0);
3031 }
3032 
3033 static const struct filterops dsp_filtops = {
3034 	.f_isfd = 1,
3035 	.f_detach = dsp_kqdetach,
3036 	.f_event = dsp_kqevent,
3037 };
3038 
3039 static int
3040 dsp_kqfilter(struct cdev *dev, struct knote *kn)
3041 {
3042 	struct dsp_cdevpriv *priv;
3043 	struct snddev_info *d;
3044 	struct pcm_channel *ch;
3045 	int err = 0;
3046 
3047 	if ((err = devfs_get_cdevpriv((void **)&priv)) != 0)
3048 		return (err);
3049 
3050 	d = priv->sc;
3051 	if (!DSP_REGISTERED(d))
3052 		return (EBADF);
3053 	PCM_GIANT_ENTER(d);
3054 	switch (kn->kn_filter) {
3055 	case EVFILT_READ:
3056 		ch = priv->rdch;
3057 		break;
3058 	case EVFILT_WRITE:
3059 		ch = priv->wrch;
3060 		break;
3061 	default:
3062 		kn->kn_hook = NULL;
3063 		err = EINVAL;
3064 		ch = NULL;
3065 		break;
3066 	}
3067 	if (ch != NULL) {
3068 		kn->kn_fop = &dsp_filtops;
3069 		CHN_LOCK(ch);
3070 		knlist_add(&ch->bufsoft->sel.si_note, kn, 1);
3071 		CHN_UNLOCK(ch);
3072 		kn->kn_hook = ch;
3073 	} else
3074 		err = EINVAL;
3075 	PCM_GIANT_LEAVE(d);
3076 
3077 	return (err);
3078 }
3079 
3080 #ifdef OSSV4_EXPERIMENT
3081 /**
3082  * @brief Retrieve an audio device's label
3083  *
3084  * This is a handler for the @c SNDCTL_GETLABEL ioctl.
3085  *
3086  * See @c http://manuals.opensound.com/developer/SNDCTL_GETLABEL.html
3087  * for more details.
3088  *
3089  * From Hannu@4Front:  "For example ossxmix (just like some HW mixer
3090  * consoles) can show variable "labels" for certain controls. By default
3091  * the application name (say quake) is shown as the label but
3092  * applications may change the labels themselves."
3093  *
3094  * @note As the ioctl definition is still under construction, FreeBSD
3095  * 	 does not currently support @c SNDCTL_GETLABEL.
3096  *
3097  * @param wrch	playback channel (optional; may be NULL)
3098  * @param rdch	recording channel (optional; may be NULL)
3099  * @param label	label gets copied here
3100  *
3101  * @retval EINVAL	Operation not yet supported.
3102  */
3103 static int
3104 dsp_oss_getlabel(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_label_t *label)
3105 {
3106 	return (EINVAL);
3107 }
3108 
3109 /**
3110  * @brief Specify an audio device's label
3111  *
3112  * This is a handler for the @c SNDCTL_SETLABEL ioctl.  Please see the
3113  * comments for @c dsp_oss_getlabel immediately above.
3114  *
3115  * See @c http://manuals.opensound.com/developer/SNDCTL_GETLABEL.html
3116  * for more details.
3117  *
3118  * @note As the ioctl definition is still under construction, FreeBSD
3119  * 	 does not currently support SNDCTL_SETLABEL.
3120  *
3121  * @param wrch	playback channel (optional; may be NULL)
3122  * @param rdch	recording channel (optional; may be NULL)
3123  * @param label	label gets copied from here
3124  *
3125  * @retval EINVAL	Operation not yet supported.
3126  */
3127 static int
3128 dsp_oss_setlabel(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_label_t *label)
3129 {
3130 	return (EINVAL);
3131 }
3132 
3133 /**
3134  * @brief Retrieve name of currently played song
3135  *
3136  * This is a handler for the @c SNDCTL_GETSONG ioctl.  Audio players could
3137  * tell the system the name of the currently playing song, which would be
3138  * visible in @c /dev/sndstat.
3139  *
3140  * See @c http://manuals.opensound.com/developer/SNDCTL_GETSONG.html
3141  * for more details.
3142  *
3143  * @note As the ioctl definition is still under construction, FreeBSD
3144  * 	 does not currently support SNDCTL_GETSONG.
3145  *
3146  * @param wrch	playback channel (optional; may be NULL)
3147  * @param rdch	recording channel (optional; may be NULL)
3148  * @param song	song name gets copied here
3149  *
3150  * @retval EINVAL	Operation not yet supported.
3151  */
3152 static int
3153 dsp_oss_getsong(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *song)
3154 {
3155 	return (EINVAL);
3156 }
3157 
3158 /**
3159  * @brief Retrieve name of currently played song
3160  *
3161  * This is a handler for the @c SNDCTL_SETSONG ioctl.  Audio players could
3162  * tell the system the name of the currently playing song, which would be
3163  * visible in @c /dev/sndstat.
3164  *
3165  * See @c http://manuals.opensound.com/developer/SNDCTL_SETSONG.html
3166  * for more details.
3167  *
3168  * @note As the ioctl definition is still under construction, FreeBSD
3169  * 	 does not currently support SNDCTL_SETSONG.
3170  *
3171  * @param wrch	playback channel (optional; may be NULL)
3172  * @param rdch	recording channel (optional; may be NULL)
3173  * @param song	song name gets copied from here
3174  *
3175  * @retval EINVAL	Operation not yet supported.
3176  */
3177 static int
3178 dsp_oss_setsong(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *song)
3179 {
3180 	return (EINVAL);
3181 }
3182 
3183 /**
3184  * @brief Rename a device
3185  *
3186  * This is a handler for the @c SNDCTL_SETNAME ioctl.
3187  *
3188  * See @c http://manuals.opensound.com/developer/SNDCTL_SETNAME.html for
3189  * more details.
3190  *
3191  * From Hannu@4Front:  "This call is used to change the device name
3192  * reported in /dev/sndstat and ossinfo. So instead of  using some generic
3193  * 'OSS loopback audio (MIDI) driver' the device may be given a meaningfull
3194  * name depending on the current context (for example 'OSS virtual wave table
3195  * synth' or 'VoIP link to London')."
3196  *
3197  * @note As the ioctl definition is still under construction, FreeBSD
3198  * 	 does not currently support SNDCTL_SETNAME.
3199  *
3200  * @param wrch	playback channel (optional; may be NULL)
3201  * @param rdch	recording channel (optional; may be NULL)
3202  * @param name	new device name gets copied from here
3203  *
3204  * @retval EINVAL	Operation not yet supported.
3205  */
3206 static int
3207 dsp_oss_setname(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_longname_t *name)
3208 {
3209 	return (EINVAL);
3210 }
3211 #endif	/* !OSSV4_EXPERIMENT */
3212