xref: /freebsd/sys/dev/sound/pcm/sound.c (revision 13d826ff947d9026f98e317e7385b22abfc0eace)
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  * Copyright (c) 1997 Luigi Rizzo
8  * All rights reserved.
9  * Copyright (c) 2024 The FreeBSD Foundation
10  *
11  * Portions of this software were developed by Christos Margiolis
12  * <christos@FreeBSD.org> under sponsorship from the FreeBSD Foundation.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #ifdef HAVE_KERNEL_OPTION_HEADERS
37 #include "opt_snd.h"
38 #endif
39 
40 #include <dev/sound/pcm/sound.h>
41 #include <dev/sound/pcm/ac97.h>
42 #include <dev/sound/pcm/vchan.h>
43 #include <dev/sound/pcm/dsp.h>
44 #include <dev/sound/version.h>
45 #include <sys/limits.h>
46 #include <sys/sysctl.h>
47 
48 #include "feeder_if.h"
49 
50 devclass_t pcm_devclass;
51 
52 int pcm_veto_load = 1;
53 
54 int snd_unit = -1;
55 
56 static int snd_unit_auto = -1;
57 SYSCTL_INT(_hw_snd, OID_AUTO, default_auto, CTLFLAG_RWTUN,
58     &snd_unit_auto, 0, "assign default unit to a newly attached device");
59 
60 int snd_maxautovchans = 16;
61 
62 SYSCTL_NODE(_hw, OID_AUTO, snd, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
63     "Sound driver");
64 
65 static void pcm_sysinit(device_t);
66 
67 /*
68  * XXX I've had enough with people not telling proper version/arch
69  *     while reporting problems, not after 387397913213th questions/requests.
70  */
71 static char snd_driver_version[] =
72     __XSTRING(SND_DRV_VERSION)"/"MACHINE_ARCH;
73 SYSCTL_STRING(_hw_snd, OID_AUTO, version, CTLFLAG_RD, &snd_driver_version,
74     0, "driver version/arch");
75 
76 /**
77  * @brief Unit number allocator for syncgroup IDs
78  */
79 struct unrhdr *pcmsg_unrhdr = NULL;
80 
81 void *
82 snd_mtxcreate(const char *desc, const char *type)
83 {
84 	struct mtx *m;
85 
86 	m = malloc(sizeof(*m), M_DEVBUF, M_WAITOK | M_ZERO);
87 	mtx_init(m, desc, type, MTX_DEF);
88 	return m;
89 }
90 
91 void
92 snd_mtxfree(void *m)
93 {
94 	struct mtx *mtx = m;
95 
96 	mtx_destroy(mtx);
97 	free(mtx, M_DEVBUF);
98 }
99 
100 void
101 snd_mtxassert(void *m)
102 {
103 #ifdef INVARIANTS
104 	struct mtx *mtx = m;
105 
106 	mtx_assert(mtx, MA_OWNED);
107 #endif
108 }
109 
110 int
111 snd_setup_intr(device_t dev, struct resource *res, int flags, driver_intr_t hand, void *param, void **cookiep)
112 {
113 	struct snddev_info *d;
114 
115 	flags &= INTR_MPSAFE;
116 	flags |= INTR_TYPE_AV;
117 	d = device_get_softc(dev);
118 	if (d != NULL && (flags & INTR_MPSAFE))
119 		d->flags |= SD_F_MPSAFE;
120 
121 	return bus_setup_intr(dev, res, flags, NULL, hand, param, cookiep);
122 }
123 
124 int
125 pcm_setvchans(struct snddev_info *d, int direction, int newcnt, int num)
126 {
127 	struct pcm_channel *c, *ch, *nch;
128 	struct pcmchan_caps *caps;
129 	int i, err, vcnt;
130 
131 	PCM_BUSYASSERT(d);
132 
133 	if ((direction == PCMDIR_PLAY && d->playcount < 1) ||
134 	    (direction == PCMDIR_REC && d->reccount < 1))
135 		return (ENODEV);
136 
137 	if (!(d->flags & SD_F_AUTOVCHAN))
138 		return (EINVAL);
139 
140 	if (newcnt < 0 || newcnt > SND_MAXVCHANS)
141 		return (E2BIG);
142 
143 	if (direction == PCMDIR_PLAY)
144 		vcnt = d->pvchancount;
145 	else if (direction == PCMDIR_REC)
146 		vcnt = d->rvchancount;
147 	else
148 		return (EINVAL);
149 
150 	if (newcnt > vcnt) {
151 		KASSERT(num == -1 ||
152 		    (num >= 0 && num < SND_MAXVCHANS && (newcnt - 1) == vcnt),
153 		    ("bogus vchan_create() request num=%d newcnt=%d vcnt=%d",
154 		    num, newcnt, vcnt));
155 		/* add new vchans - find a parent channel first */
156 		ch = NULL;
157 		CHN_FOREACH(c, d, channels.pcm) {
158 			CHN_LOCK(c);
159 			if (c->direction == direction &&
160 			    ((c->flags & CHN_F_HAS_VCHAN) || (vcnt == 0 &&
161 			    c->refcount < 1 &&
162 			    !(c->flags & (CHN_F_BUSY | CHN_F_VIRTUAL))))) {
163 				/*
164 				 * Reuse hw channel with vchans already
165 				 * created.
166 				 */
167 				if (c->flags & CHN_F_HAS_VCHAN) {
168 					ch = c;
169 					break;
170 				}
171 				/*
172 				 * No vchans ever created, look for
173 				 * channels with supported formats.
174 				 */
175 				caps = chn_getcaps(c);
176 				if (caps == NULL) {
177 					CHN_UNLOCK(c);
178 					continue;
179 				}
180 				for (i = 0; caps->fmtlist[i] != 0; i++) {
181 					if (caps->fmtlist[i] & AFMT_CONVERTIBLE)
182 						break;
183 				}
184 				if (caps->fmtlist[i] != 0) {
185 					ch = c;
186 				    	break;
187 				}
188 			}
189 			CHN_UNLOCK(c);
190 		}
191 		if (ch == NULL)
192 			return (EBUSY);
193 		ch->flags |= CHN_F_BUSY;
194 		err = 0;
195 		while (err == 0 && newcnt > vcnt) {
196 			err = vchan_create(ch, num);
197 			if (err == 0)
198 				vcnt++;
199 			else if (err == E2BIG && newcnt > vcnt)
200 				device_printf(d->dev,
201 				    "%s: err=%d Maximum channel reached.\n",
202 				    __func__, err);
203 		}
204 		if (vcnt == 0)
205 			ch->flags &= ~CHN_F_BUSY;
206 		CHN_UNLOCK(ch);
207 		if (err != 0)
208 			return (err);
209 	} else if (newcnt < vcnt) {
210 		KASSERT(num == -1,
211 		    ("bogus vchan_destroy() request num=%d", num));
212 		CHN_FOREACH(c, d, channels.pcm) {
213 			CHN_LOCK(c);
214 			if (c->direction != direction ||
215 			    CHN_EMPTY(c, children) ||
216 			    !(c->flags & CHN_F_HAS_VCHAN)) {
217 				CHN_UNLOCK(c);
218 				continue;
219 			}
220 			CHN_FOREACH_SAFE(ch, c, nch, children) {
221 				CHN_LOCK(ch);
222 				if (vcnt == 1 && c->refcount > 0) {
223 					CHN_UNLOCK(ch);
224 					break;
225 				}
226 				if (!(ch->flags & CHN_F_BUSY) &&
227 				    ch->refcount < 1) {
228 					err = vchan_destroy(ch);
229 					if (err == 0)
230 						vcnt--;
231 				} else
232 					CHN_UNLOCK(ch);
233 				if (vcnt == newcnt)
234 					break;
235 			}
236 			CHN_UNLOCK(c);
237 			break;
238 		}
239 	}
240 
241 	return (0);
242 }
243 
244 /* return error status and a locked channel */
245 int
246 pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction,
247     pid_t pid, char *comm)
248 {
249 	struct pcm_channel *c;
250 	int err, vchancount, vchan_num;
251 	bool retry;
252 
253 	KASSERT(d != NULL && ch != NULL &&
254 	    (direction == PCMDIR_PLAY || direction == PCMDIR_REC),
255 	    ("%s(): invalid d=%p ch=%p direction=%d pid=%d",
256 	    __func__, d, ch, direction, pid));
257 	PCM_BUSYASSERT(d);
258 
259 	*ch = NULL;
260 	vchan_num = 0;
261 	vchancount = (direction == PCMDIR_PLAY) ? d->pvchancount :
262 	    d->rvchancount;
263 
264 	retry = false;
265 retry_chnalloc:
266 	err = ENOTSUP;
267 	/* scan for a free channel */
268 	CHN_FOREACH(c, d, channels.pcm) {
269 		CHN_LOCK(c);
270 		if (c->direction == direction && (c->flags & CHN_F_VIRTUAL)) {
271 			if (vchancount < snd_maxautovchans &&
272 			    vchan_num < c->unit) {
273 			    	CHN_UNLOCK(c);
274 				goto vchan_alloc;
275 			}
276 			vchan_num++;
277 		}
278 		if (c->direction == direction && !(c->flags & CHN_F_BUSY)) {
279 			c->flags |= CHN_F_BUSY;
280 			c->pid = pid;
281 			strlcpy(c->comm, (comm != NULL) ? comm :
282 			    CHN_COMM_UNKNOWN, sizeof(c->comm));
283 			*ch = c;
284 			return (0);
285 		} else if (c->direction == direction && (c->flags & CHN_F_BUSY))
286 			err = EBUSY;
287 		CHN_UNLOCK(c);
288 	}
289 
290 	/*
291 	 * We came from retry_chnalloc and still didn't find a free channel.
292 	 */
293 	if (retry)
294 		return (err);
295 
296 vchan_alloc:
297 	/* no channel available */
298 	if (!(vchancount > 0 && vchancount < snd_maxautovchans))
299 		return (err);
300 	err = pcm_setvchans(d, direction, vchancount + 1, -1);
301 	if (err == 0) {
302 		retry = true;
303 		goto retry_chnalloc;
304 	}
305 
306 	return (err);
307 }
308 
309 static void
310 pcm_setmaxautovchans(struct snddev_info *d, int num)
311 {
312 	PCM_BUSYASSERT(d);
313 
314 	if (num < 0)
315 		return;
316 
317 	if (num >= 0 && d->pvchancount > num)
318 		(void)pcm_setvchans(d, PCMDIR_PLAY, num, -1);
319 	else if (num > 0 && d->pvchancount == 0)
320 		(void)pcm_setvchans(d, PCMDIR_PLAY, 1, -1);
321 
322 	if (num >= 0 && d->rvchancount > num)
323 		(void)pcm_setvchans(d, PCMDIR_REC, num, -1);
324 	else if (num > 0 && d->rvchancount == 0)
325 		(void)pcm_setvchans(d, PCMDIR_REC, 1, -1);
326 }
327 
328 static int
329 sysctl_hw_snd_default_unit(SYSCTL_HANDLER_ARGS)
330 {
331 	struct snddev_info *d;
332 	int error, unit;
333 
334 	unit = snd_unit;
335 	error = sysctl_handle_int(oidp, &unit, 0, req);
336 	if (error == 0 && req->newptr != NULL) {
337 		d = devclass_get_softc(pcm_devclass, unit);
338 		if (!PCM_REGISTERED(d) || CHN_EMPTY(d, channels.pcm))
339 			return EINVAL;
340 		snd_unit = unit;
341 		snd_unit_auto = 0;
342 	}
343 	return (error);
344 }
345 /* XXX: do we need a way to let the user change the default unit? */
346 SYSCTL_PROC(_hw_snd, OID_AUTO, default_unit,
347     CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_ANYBODY | CTLFLAG_NEEDGIANT, 0,
348     sizeof(int), sysctl_hw_snd_default_unit, "I",
349     "default sound device");
350 
351 static int
352 sysctl_hw_snd_maxautovchans(SYSCTL_HANDLER_ARGS)
353 {
354 	struct snddev_info *d;
355 	int i, v, error;
356 
357 	v = snd_maxautovchans;
358 	error = sysctl_handle_int(oidp, &v, 0, req);
359 	if (error == 0 && req->newptr != NULL) {
360 		if (v < 0)
361 			v = 0;
362 		if (v > SND_MAXVCHANS)
363 			v = SND_MAXVCHANS;
364 		snd_maxautovchans = v;
365 		for (i = 0; pcm_devclass != NULL &&
366 		    i < devclass_get_maxunit(pcm_devclass); i++) {
367 			d = devclass_get_softc(pcm_devclass, i);
368 			if (!PCM_REGISTERED(d))
369 				continue;
370 			PCM_ACQUIRE_QUICK(d);
371 			pcm_setmaxautovchans(d, v);
372 			PCM_RELEASE_QUICK(d);
373 		}
374 	}
375 	return (error);
376 }
377 SYSCTL_PROC(_hw_snd, OID_AUTO, maxautovchans,
378     CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0, sizeof(int),
379     sysctl_hw_snd_maxautovchans, "I",
380     "maximum virtual channel");
381 
382 struct pcm_channel *
383 pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, int num, void *devinfo)
384 {
385 	struct pcm_channel *ch;
386 	int direction, err, rpnum, *pnum, max;
387 	int type, unit;
388 	char *dirs, *devname, buf[CHN_NAMELEN];
389 
390 	PCM_BUSYASSERT(d);
391 	PCM_LOCKASSERT(d);
392 	KASSERT(num >= -1, ("invalid num=%d", num));
393 
394 	switch (dir) {
395 	case PCMDIR_PLAY:
396 		dirs = "play";
397 		direction = PCMDIR_PLAY;
398 		pnum = &d->playcount;
399 		type = SND_DEV_DSPHW_PLAY;
400 		max = SND_MAXHWCHAN;
401 		break;
402 	case PCMDIR_PLAY_VIRTUAL:
403 		dirs = "virtual_play";
404 		direction = PCMDIR_PLAY;
405 		pnum = &d->pvchancount;
406 		type = SND_DEV_DSPHW_VPLAY;
407 		max = SND_MAXVCHANS;
408 		break;
409 	case PCMDIR_REC:
410 		dirs = "record";
411 		direction = PCMDIR_REC;
412 		pnum = &d->reccount;
413 		type = SND_DEV_DSPHW_REC;
414 		max = SND_MAXHWCHAN;
415 		break;
416 	case PCMDIR_REC_VIRTUAL:
417 		dirs = "virtual_record";
418 		direction = PCMDIR_REC;
419 		pnum = &d->rvchancount;
420 		type = SND_DEV_DSPHW_VREC;
421 		max = SND_MAXVCHANS;
422 		break;
423 	default:
424 		return (NULL);
425 	}
426 
427 	unit = (num == -1) ? 0 : num;
428 
429 	if (*pnum >= max || unit >= max)
430 		return (NULL);
431 
432 	rpnum = 0;
433 
434 	CHN_FOREACH(ch, d, channels.pcm) {
435 		if (ch->type != type)
436 			continue;
437 		if (unit == ch->unit && num != -1) {
438 			device_printf(d->dev,
439 			    "channel num=%d allocated!\n", unit);
440 			return (NULL);
441 		}
442 		unit++;
443 		if (unit >= max) {
444 			device_printf(d->dev,
445 			    "chan=%d > %d\n", unit, max);
446 			return (NULL);
447 		}
448 		rpnum++;
449 	}
450 
451 	if (*pnum != rpnum) {
452 		device_printf(d->dev,
453 		    "%s(): WARNING: pnum screwed : dirs=%s pnum=%d rpnum=%d\n",
454 		    __func__, dirs, *pnum, rpnum);
455 		return (NULL);
456 	}
457 
458 	PCM_UNLOCK(d);
459 	ch = malloc(sizeof(*ch), M_DEVBUF, M_WAITOK | M_ZERO);
460 	ch->methods = kobj_create(cls, M_DEVBUF, M_WAITOK | M_ZERO);
461 	ch->type = type;
462 	ch->unit = unit;
463 	ch->pid = -1;
464 	strlcpy(ch->comm, CHN_COMM_UNUSED, sizeof(ch->comm));
465 	ch->parentsnddev = d;
466 	ch->parentchannel = parent;
467 	ch->dev = d->dev;
468 	ch->trigger = PCMTRIG_STOP;
469 	devname = dsp_unit2name(buf, sizeof(buf), ch);
470 	if (devname == NULL) {
471 		device_printf(d->dev, "Failed to query device name");
472 		kobj_delete(ch->methods, M_DEVBUF);
473 		free(ch, M_DEVBUF);
474 		return (NULL);
475 	}
476 	snprintf(ch->name, sizeof(ch->name), "%s:%s:%s",
477 	    device_get_nameunit(ch->dev), dirs, devname);
478 
479 	err = chn_init(ch, devinfo, dir, direction);
480 	PCM_LOCK(d);
481 	if (err) {
482 		device_printf(d->dev, "chn_init(%s) failed: err = %d\n",
483 		    ch->name, err);
484 		kobj_delete(ch->methods, M_DEVBUF);
485 		free(ch, M_DEVBUF);
486 		return (NULL);
487 	}
488 
489 	return (ch);
490 }
491 
492 int
493 pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch)
494 {
495 	PCM_BUSYASSERT(d);
496 	PCM_LOCKASSERT(d);
497 	KASSERT(ch != NULL && (ch->direction == PCMDIR_PLAY ||
498 	    ch->direction == PCMDIR_REC), ("Invalid pcm channel"));
499 
500 	CHN_INSERT_SORT_ASCEND(d, ch, channels.pcm);
501 
502 	switch (ch->type) {
503 	case SND_DEV_DSPHW_PLAY:
504 		d->playcount++;
505 		break;
506 	case SND_DEV_DSPHW_VPLAY:
507 		d->pvchancount++;
508 		break;
509 	case SND_DEV_DSPHW_REC:
510 		d->reccount++;
511 		break;
512 	case SND_DEV_DSPHW_VREC:
513 		d->rvchancount++;
514 		break;
515 	default:
516 		break;
517 	}
518 
519 	return (0);
520 }
521 
522 int
523 pcm_chn_remove(struct snddev_info *d, struct pcm_channel *ch)
524 {
525 	struct pcm_channel *tmp;
526 
527 	PCM_BUSYASSERT(d);
528 	PCM_LOCKASSERT(d);
529 
530 	tmp = NULL;
531 
532 	CHN_FOREACH(tmp, d, channels.pcm) {
533 		if (tmp == ch)
534 			break;
535 	}
536 
537 	if (tmp != ch)
538 		return (EINVAL);
539 
540 	CHN_REMOVE(d, ch, channels.pcm);
541 
542 	switch (ch->type) {
543 	case SND_DEV_DSPHW_PLAY:
544 		d->playcount--;
545 		break;
546 	case SND_DEV_DSPHW_VPLAY:
547 		d->pvchancount--;
548 		break;
549 	case SND_DEV_DSPHW_REC:
550 		d->reccount--;
551 		break;
552 	case SND_DEV_DSPHW_VREC:
553 		d->rvchancount--;
554 		break;
555 	default:
556 		break;
557 	}
558 
559 	return (0);
560 }
561 
562 int
563 pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo)
564 {
565 	struct snddev_info *d = device_get_softc(dev);
566 	struct pcm_channel *ch;
567 	int err;
568 
569 	PCM_BUSYASSERT(d);
570 
571 	PCM_LOCK(d);
572 	ch = pcm_chn_create(d, NULL, cls, dir, -1, devinfo);
573 	if (!ch) {
574 		device_printf(d->dev, "pcm_chn_create(%s, %d, %p) failed\n",
575 		    cls->name, dir, devinfo);
576 		PCM_UNLOCK(d);
577 		return (ENODEV);
578 	}
579 
580 	err = pcm_chn_add(d, ch);
581 	PCM_UNLOCK(d);
582 	if (err) {
583 		device_printf(d->dev, "pcm_chn_add(%s) failed, err=%d\n",
584 		    ch->name, err);
585 		chn_kill(ch);
586 	}
587 
588 	return (err);
589 }
590 
591 static void
592 pcm_killchans(struct snddev_info *d)
593 {
594 	struct pcm_channel *ch;
595 	int error;
596 	bool found;
597 
598 	PCM_BUSYASSERT(d);
599 	do {
600 		found = false;
601 		CHN_FOREACH(ch, d, channels.pcm) {
602 			CHN_LOCK(ch);
603 			/*
604 			 * Make sure no channel has went to sleep in the
605 			 * meantime.
606 			 */
607 			chn_shutdown(ch);
608 			/*
609 			 * We have to give a thread sleeping in chn_sleep() a
610 			 * chance to observe that the channel is dead.
611 			 */
612 			if ((ch->flags & CHN_F_SLEEPING) == 0) {
613 				found = true;
614 				CHN_UNLOCK(ch);
615 				break;
616 			}
617 			CHN_UNLOCK(ch);
618 		}
619 
620 		/*
621 		 * All channels are still sleeping. Sleep for a bit and try
622 		 * again to see if any of them is awake now.
623 		 */
624 		if (!found) {
625 			pause_sbt("pcmkillchans", SBT_1MS * 5, 0, 0);
626 			continue;
627 		}
628 
629 		PCM_LOCK(d);
630 		error = pcm_chn_remove(d, ch);
631 		PCM_UNLOCK(d);
632 		if (error == 0)
633 			chn_kill(ch);
634 	} while (!CHN_EMPTY(d, channels.pcm));
635 }
636 
637 static int
638 pcm_best_unit(int old)
639 {
640 	struct snddev_info *d;
641 	int i, best, bestprio, prio;
642 
643 	best = -1;
644 	bestprio = -100;
645 	for (i = 0; pcm_devclass != NULL &&
646 	    i < devclass_get_maxunit(pcm_devclass); i++) {
647 		d = devclass_get_softc(pcm_devclass, i);
648 		if (!PCM_REGISTERED(d))
649 			continue;
650 		prio = 0;
651 		if (d->playcount == 0)
652 			prio -= 10;
653 		if (d->reccount == 0)
654 			prio -= 2;
655 		if (prio > bestprio || (prio == bestprio && i == old)) {
656 			best = i;
657 			bestprio = prio;
658 		}
659 	}
660 	return (best);
661 }
662 
663 int
664 pcm_setstatus(device_t dev, char *str)
665 {
666 	struct snddev_info *d = device_get_softc(dev);
667 
668 	/* should only be called once */
669 	if (d->flags & SD_F_REGISTERED)
670 		return (EINVAL);
671 
672 	PCM_BUSYASSERT(d);
673 
674 	if (d->playcount == 0 || d->reccount == 0)
675 		d->flags |= SD_F_SIMPLEX;
676 
677 	if (d->playcount > 0 || d->reccount > 0)
678 		d->flags |= SD_F_AUTOVCHAN;
679 
680 	pcm_setmaxautovchans(d, snd_maxautovchans);
681 
682 	strlcpy(d->status, str, SND_STATUSLEN);
683 
684 	PCM_LOCK(d);
685 
686 	/* Done, we're ready.. */
687 	d->flags |= SD_F_REGISTERED;
688 
689 	PCM_RELEASE(d);
690 
691 	PCM_UNLOCK(d);
692 
693 	/*
694 	 * Create all sysctls once SD_F_REGISTERED is set else
695 	 * tunable sysctls won't work:
696 	 */
697 	pcm_sysinit(dev);
698 
699 	if (snd_unit_auto < 0)
700 		snd_unit_auto = (snd_unit < 0) ? 1 : 0;
701 	if (snd_unit < 0 || snd_unit_auto > 1)
702 		snd_unit = device_get_unit(dev);
703 	else if (snd_unit_auto == 1)
704 		snd_unit = pcm_best_unit(snd_unit);
705 
706 	return (0);
707 }
708 
709 uint32_t
710 pcm_getflags(device_t dev)
711 {
712 	struct snddev_info *d = device_get_softc(dev);
713 
714 	return d->flags;
715 }
716 
717 void
718 pcm_setflags(device_t dev, uint32_t val)
719 {
720 	struct snddev_info *d = device_get_softc(dev);
721 
722 	d->flags = val;
723 }
724 
725 void *
726 pcm_getdevinfo(device_t dev)
727 {
728 	struct snddev_info *d = device_get_softc(dev);
729 
730 	return d->devinfo;
731 }
732 
733 unsigned int
734 pcm_getbuffersize(device_t dev, unsigned int minbufsz, unsigned int deflt, unsigned int maxbufsz)
735 {
736 	struct snddev_info *d = device_get_softc(dev);
737 	int sz, x;
738 
739 	sz = 0;
740 	if (resource_int_value(device_get_name(dev), device_get_unit(dev), "buffersize", &sz) == 0) {
741 		x = sz;
742 		RANGE(sz, minbufsz, maxbufsz);
743 		if (x != sz)
744 			device_printf(dev, "'buffersize=%d' hint is out of range (%d-%d), using %d\n", x, minbufsz, maxbufsz, sz);
745 		x = minbufsz;
746 		while (x < sz)
747 			x <<= 1;
748 		if (x > sz)
749 			x >>= 1;
750 		if (x != sz) {
751 			device_printf(dev, "'buffersize=%d' hint is not a power of 2, using %d\n", sz, x);
752 			sz = x;
753 		}
754 	} else {
755 		sz = deflt;
756 	}
757 
758 	d->bufsz = sz;
759 
760 	return sz;
761 }
762 
763 static int
764 sysctl_dev_pcm_bitperfect(SYSCTL_HANDLER_ARGS)
765 {
766 	struct snddev_info *d;
767 	int err, val;
768 
769 	d = oidp->oid_arg1;
770 	if (!PCM_REGISTERED(d))
771 		return (ENODEV);
772 
773 	PCM_LOCK(d);
774 	PCM_WAIT(d);
775 	val = (d->flags & SD_F_BITPERFECT) ? 1 : 0;
776 	PCM_ACQUIRE(d);
777 	PCM_UNLOCK(d);
778 
779 	err = sysctl_handle_int(oidp, &val, 0, req);
780 
781 	if (err == 0 && req->newptr != NULL) {
782 		if (!(val == 0 || val == 1)) {
783 			PCM_RELEASE_QUICK(d);
784 			return (EINVAL);
785 		}
786 
787 		PCM_LOCK(d);
788 
789 		d->flags &= ~SD_F_BITPERFECT;
790 		d->flags |= (val != 0) ? SD_F_BITPERFECT : 0;
791 
792 		PCM_RELEASE(d);
793 		PCM_UNLOCK(d);
794 	} else
795 		PCM_RELEASE_QUICK(d);
796 
797 	return (err);
798 }
799 
800 static u_int8_t
801 pcm_mode_init(struct snddev_info *d)
802 {
803 	u_int8_t mode = 0;
804 
805 	if (d->playcount > 0)
806 		mode |= PCM_MODE_PLAY;
807 	if (d->reccount > 0)
808 		mode |= PCM_MODE_REC;
809 	if (d->mixer_dev != NULL)
810 		mode |= PCM_MODE_MIXER;
811 
812 	return (mode);
813 }
814 
815 static void
816 pcm_sysinit(device_t dev)
817 {
818   	struct snddev_info *d = device_get_softc(dev);
819 	u_int8_t mode;
820 
821 	mode = pcm_mode_init(d);
822 
823 	/* XXX: a user should be able to set this with a control tool, the
824 	   sysadmin then needs min+max sysctls for this */
825 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
826 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
827             OID_AUTO, "buffersize", CTLFLAG_RD, &d->bufsz, 0, "allocated buffer size");
828 	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
829 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
830 	    "bitperfect", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, d,
831 	    sizeof(d), sysctl_dev_pcm_bitperfect, "I",
832 	    "bit-perfect playback/recording (0=disable, 1=enable)");
833 	SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
834 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
835 	    OID_AUTO, "mode", CTLFLAG_RD, NULL, mode,
836 	    "mode (1=mixer, 2=play, 4=rec. The values are OR'ed if more than "
837 	    "one mode is supported)");
838 	if (d->flags & SD_F_AUTOVCHAN)
839 		vchan_initsys(dev);
840 	if (d->flags & SD_F_EQ)
841 		feeder_eq_initsys(dev);
842 }
843 
844 int
845 pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
846 {
847 	struct snddev_info *d;
848 	int i;
849 
850 	if (pcm_veto_load) {
851 		device_printf(dev, "disabled due to an error while initialising: %d\n", pcm_veto_load);
852 
853 		return EINVAL;
854 	}
855 
856 	d = device_get_softc(dev);
857 	d->dev = dev;
858 	d->lock = snd_mtxcreate(device_get_nameunit(dev), "sound cdev");
859 	cv_init(&d->cv, device_get_nameunit(dev));
860 	PCM_ACQUIRE_QUICK(d);
861 #if 0
862 	/*
863 	 * d->flags should be cleared by the allocator of the softc.
864 	 * We cannot clear this field here because several devices set
865 	 * this flag before calling pcm_register().
866 	 */
867 	d->flags = 0;
868 #endif
869 	i = 0;
870 	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
871 	    "vpc", &i) != 0 || i != 0)
872 		d->flags |= SD_F_VPC;
873 
874 	if (resource_int_value(device_get_name(dev), device_get_unit(dev),
875 	    "bitperfect", &i) == 0 && i != 0)
876 		d->flags |= SD_F_BITPERFECT;
877 
878 	d->devinfo = devinfo;
879 	d->reccount = 0;
880 	d->playcount = 0;
881 	d->pvchancount = 0;
882 	d->rvchancount = 0;
883 	d->pvchanrate = 0;
884 	d->pvchanformat = 0;
885 	d->rvchanrate = 0;
886 	d->rvchanformat = 0;
887 
888 	CHN_INIT(d, channels.pcm);
889 	CHN_INIT(d, channels.pcm.busy);
890 	CHN_INIT(d, channels.pcm.opened);
891 
892 	/* XXX This is incorrect, but lets play along for now. */
893 	if ((numplay == 0 || numrec == 0) && numplay != numrec)
894 		d->flags |= SD_F_SIMPLEX;
895 
896 	sysctl_ctx_init(&d->play_sysctl_ctx);
897 	d->play_sysctl_tree = SYSCTL_ADD_NODE(&d->play_sysctl_ctx,
898 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "play",
899 	    CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "playback channels node");
900 	sysctl_ctx_init(&d->rec_sysctl_ctx);
901 	d->rec_sysctl_tree = SYSCTL_ADD_NODE(&d->rec_sysctl_ctx,
902 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "rec",
903 	    CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "recording channels node");
904 
905 	if (numplay > 0 || numrec > 0)
906 		d->flags |= SD_F_AUTOVCHAN;
907 
908 	sndstat_register(dev, d->status);
909 
910 	return (dsp_make_dev(dev));
911 }
912 
913 int
914 pcm_unregister(device_t dev)
915 {
916 	struct snddev_info *d;
917 	struct pcm_channel *ch;
918 
919 	d = device_get_softc(dev);
920 
921 	if (!PCM_ALIVE(d)) {
922 		device_printf(dev, "unregister: device not configured\n");
923 		return (0);
924 	}
925 
926 	PCM_LOCK(d);
927 	PCM_WAIT(d);
928 
929 	d->flags |= SD_F_DETACHING;
930 
931 	PCM_ACQUIRE(d);
932 	PCM_UNLOCK(d);
933 
934 	CHN_FOREACH(ch, d, channels.pcm) {
935 		CHN_LOCK(ch);
936 		/*
937 		 * Do not wait for the timeout in chn_read()/chn_write(). Wake
938 		 * up the sleeping thread and kill the channel.
939 		 */
940 		chn_shutdown(ch);
941 		chn_abort(ch);
942 		CHN_UNLOCK(ch);
943 	}
944 
945 	/* remove /dev/sndstat entry first */
946 	sndstat_unregister(dev);
947 
948 	PCM_LOCK(d);
949 	d->flags |= SD_F_DYING;
950 	d->flags &= ~SD_F_REGISTERED;
951 	PCM_UNLOCK(d);
952 
953 	if (d->play_sysctl_tree != NULL) {
954 		sysctl_ctx_free(&d->play_sysctl_ctx);
955 		d->play_sysctl_tree = NULL;
956 	}
957 	if (d->rec_sysctl_tree != NULL) {
958 		sysctl_ctx_free(&d->rec_sysctl_ctx);
959 		d->rec_sysctl_tree = NULL;
960 	}
961 
962 	dsp_destroy_dev(dev);
963 	(void)mixer_uninit(dev);
964 
965 	pcm_killchans(d);
966 
967 	PCM_LOCK(d);
968 	PCM_RELEASE(d);
969 	cv_destroy(&d->cv);
970 	PCM_UNLOCK(d);
971 	snd_mtxfree(d->lock);
972 
973 	if (snd_unit == device_get_unit(dev)) {
974 		snd_unit = pcm_best_unit(-1);
975 		if (snd_unit_auto == 0)
976 			snd_unit_auto = 1;
977 	}
978 
979 	return (0);
980 }
981 
982 /************************************************************************/
983 
984 /**
985  * @brief	Handle OSSv4 SNDCTL_SYSINFO ioctl.
986  *
987  * @param si	Pointer to oss_sysinfo struct where information about the
988  * 		sound subsystem will be written/copied.
989  *
990  * This routine returns information about the sound system, such as the
991  * current OSS version, number of audio, MIDI, and mixer drivers, etc.
992  * Also includes a bitmask showing which of the above types of devices
993  * are open (busy).
994  *
995  * @note
996  * Calling threads must not hold any snddev_info or pcm_channel locks.
997  *
998  * @author	Ryan Beasley <ryanb@FreeBSD.org>
999  */
1000 void
1001 sound_oss_sysinfo(oss_sysinfo *si)
1002 {
1003 	static char si_product[] = "FreeBSD native OSS ABI";
1004 	static char si_version[] = __XSTRING(__FreeBSD_version);
1005 	static char si_license[] = "BSD";
1006 	static int intnbits = sizeof(int) * 8;	/* Better suited as macro?
1007 						   Must pester a C guru. */
1008 
1009 	struct snddev_info *d;
1010 	struct pcm_channel *c;
1011 	int i, j, ncards;
1012 
1013 	ncards = 0;
1014 
1015 	strlcpy(si->product, si_product, sizeof(si->product));
1016 	strlcpy(si->version, si_version, sizeof(si->version));
1017 	si->versionnum = SOUND_VERSION;
1018 	strlcpy(si->license, si_license, sizeof(si->license));
1019 
1020 	/*
1021 	 * Iterate over PCM devices and their channels, gathering up data
1022 	 * for the numaudios, ncards, and openedaudio fields.
1023 	 */
1024 	si->numaudios = 0;
1025 	bzero((void *)&si->openedaudio, sizeof(si->openedaudio));
1026 
1027 	j = 0;
1028 
1029 	for (i = 0; pcm_devclass != NULL &&
1030 	    i < devclass_get_maxunit(pcm_devclass); i++) {
1031 		d = devclass_get_softc(pcm_devclass, i);
1032 		if (!PCM_REGISTERED(d))
1033 			continue;
1034 
1035 		/* XXX Need Giant magic entry ??? */
1036 
1037 		/* See note in function's docblock */
1038 		PCM_UNLOCKASSERT(d);
1039 		PCM_LOCK(d);
1040 
1041 		si->numaudios += PCM_CHANCOUNT(d);
1042 		++ncards;
1043 
1044 		CHN_FOREACH(c, d, channels.pcm) {
1045 			CHN_UNLOCKASSERT(c);
1046 			CHN_LOCK(c);
1047 			if (c->flags & CHN_F_BUSY)
1048 				si->openedaudio[j / intnbits] |=
1049 				    (1 << (j % intnbits));
1050 			CHN_UNLOCK(c);
1051 			j++;
1052 		}
1053 
1054 		PCM_UNLOCK(d);
1055 	}
1056 	si->numaudioengines = si->numaudios;
1057 
1058 	si->numsynths = 0;	/* OSSv4 docs:  this field is obsolete */
1059 	/**
1060 	 * @todo	Collect num{midis,timers}.
1061 	 *
1062 	 * Need access to sound/midi/midi.c::midistat_lock in order
1063 	 * to safely touch midi_devices and get a head count of, well,
1064 	 * MIDI devices.  midistat_lock is a global static (i.e., local to
1065 	 * midi.c), but midi_devices is a regular global; should the mutex
1066 	 * be publicized, or is there another way to get this information?
1067 	 *
1068 	 * NB:	MIDI/sequencer stuff is currently on hold.
1069 	 */
1070 	si->nummidis = 0;
1071 	si->numtimers = 0;
1072 	si->nummixers = mixer_count;
1073 	si->numcards = ncards;
1074 		/* OSSv4 docs:	Intended only for test apps; API doesn't
1075 		   really have much of a concept of cards.  Shouldn't be
1076 		   used by applications. */
1077 
1078 	/**
1079 	 * @todo	Fill in "busy devices" fields.
1080 	 *
1081 	 *  si->openedmidi = " MIDI devices
1082 	 */
1083 	bzero((void *)&si->openedmidi, sizeof(si->openedmidi));
1084 
1085 	/*
1086 	 * Si->filler is a reserved array, but according to docs each
1087 	 * element should be set to -1.
1088 	 */
1089 	for (i = 0; i < sizeof(si->filler)/sizeof(si->filler[0]); i++)
1090 		si->filler[i] = -1;
1091 }
1092 
1093 int
1094 sound_oss_card_info(oss_card_info *si)
1095 {
1096 	struct snddev_info *d;
1097 	int i, ncards;
1098 
1099 	ncards = 0;
1100 
1101 	for (i = 0; pcm_devclass != NULL &&
1102 	    i < devclass_get_maxunit(pcm_devclass); i++) {
1103 		d = devclass_get_softc(pcm_devclass, i);
1104 		if (!PCM_REGISTERED(d))
1105 			continue;
1106 
1107 		if (ncards++ != si->card)
1108 			continue;
1109 
1110 		PCM_UNLOCKASSERT(d);
1111 		PCM_LOCK(d);
1112 
1113 		strlcpy(si->shortname, device_get_nameunit(d->dev),
1114 		    sizeof(si->shortname));
1115 		strlcpy(si->longname, device_get_desc(d->dev),
1116 		    sizeof(si->longname));
1117 		strlcpy(si->hw_info, d->status, sizeof(si->hw_info));
1118 		si->intr_count = si->ack_count = 0;
1119 
1120 		PCM_UNLOCK(d);
1121 
1122 		return (0);
1123 	}
1124 	return (ENXIO);
1125 }
1126 
1127 /************************************************************************/
1128 
1129 static int
1130 sound_modevent(module_t mod, int type, void *data)
1131 {
1132 	int ret;
1133 
1134 	ret = 0;
1135 	switch (type) {
1136 		case MOD_LOAD:
1137 			pcm_devclass = devclass_create("pcm");
1138 			pcmsg_unrhdr = new_unrhdr(1, INT_MAX, NULL);
1139 			break;
1140 		case MOD_UNLOAD:
1141 			if (pcmsg_unrhdr != NULL) {
1142 				delete_unrhdr(pcmsg_unrhdr);
1143 				pcmsg_unrhdr = NULL;
1144 			}
1145 			break;
1146 		case MOD_SHUTDOWN:
1147 			break;
1148 		default:
1149 			ret = ENOTSUP;
1150 	}
1151 
1152 	return ret;
1153 }
1154 
1155 DEV_MODULE(sound, sound_modevent, NULL);
1156 MODULE_VERSION(sound, SOUND_MODVER);
1157