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