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