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