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