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