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