xref: /illumos-gate/usr/src/uts/common/io/audio/impl/audio_engine.c (revision 23524732d002da91177f82bdfa44378749661577)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (C) 4Front Technologies 1996-2008.
23  *
24  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #include <sys/types.h>
29 #include <sys/list.h>
30 #include <sys/sysmacros.h>
31 #include <sys/ddi.h>
32 #include <sys/sunddi.h>
33 #include <sys/callb.h>
34 #include <sys/kstat.h>
35 #include <sys/note.h>
36 
37 #include "audio_impl.h"
38 
39 /*
40  * Audio Engine functions.
41  */
42 
43 audio_dev_t *
44 audio_dev_alloc(dev_info_t *dip, int instance)
45 {
46 	audio_dev_t *d;
47 
48 	/*
49 	 * For a card with multiple independent audio ports on it, we
50 	 * allow the driver to provide a different instance numbering
51 	 * scheme than the standard DDI instance number.  (This is
52 	 * sort of like the PPA numbering scheme used by NIC drivers
53 	 * -- by default PPA == instance, but sometimes we need more
54 	 * flexibility.)
55 	 */
56 	if (instance == 0) {
57 		instance = ddi_get_instance(dip);
58 	}
59 	/* generally this shouldn't occur */
60 	if (instance > AUDIO_MN_INST_MASK) {
61 		audio_dev_warn(NULL, "bad instance number for %s (%d)",
62 		    ddi_driver_name(dip), instance);
63 		return (NULL);
64 	}
65 
66 	if ((d = kmem_zalloc(sizeof (*d), KM_NOSLEEP)) == NULL) {
67 		audio_dev_warn(NULL, "unable to allocate audio device struct");
68 		return (NULL);
69 	}
70 	d->d_dip = dip;
71 	d->d_number = -1;
72 	d->d_major = ddi_driver_major(dip);
73 	d->d_instance = instance;
74 	d->d_pcmvol = 100;
75 	mutex_init(&d->d_lock, NULL, MUTEX_DRIVER, NULL);
76 	cv_init(&d->d_cv, NULL, CV_DRIVER, NULL);
77 	rw_init(&d->d_ctrl_lock, NULL, RW_DRIVER, NULL);
78 	rw_init(&d->d_clnt_lock, NULL, RW_DRIVER, NULL);
79 	list_create(&d->d_clients, sizeof (struct audio_client),
80 	    offsetof(struct audio_client, c_dev_linkage));
81 	list_create(&d->d_engines, sizeof (struct audio_engine),
82 	    offsetof(struct audio_engine, e_dev_linkage));
83 	list_create(&d->d_controls, sizeof (struct audio_ctrl),
84 	    offsetof(struct audio_ctrl, ctrl_linkage));
85 	list_create(&d->d_hwinfo, sizeof (struct audio_infostr),
86 	    offsetof(struct audio_infostr, i_linkage));
87 	(void) snprintf(d->d_name, sizeof (d->d_name), "%s#%d",
88 	    ddi_driver_name(dip), instance);
89 
90 	return (d);
91 }
92 
93 void
94 audio_dev_free(audio_dev_t *d)
95 {
96 	struct audio_infostr *isp;
97 	while ((isp = list_remove_head(&d->d_hwinfo)) != NULL) {
98 		kmem_free(isp, sizeof (*isp));
99 	}
100 	if (d->d_pcmvol_ctrl != NULL) {
101 		audio_dev_del_control(d->d_pcmvol_ctrl);
102 	}
103 	list_destroy(&d->d_hwinfo);
104 	list_destroy(&d->d_engines);
105 	list_destroy(&d->d_controls);
106 	list_destroy(&d->d_clients);
107 	rw_destroy(&d->d_ctrl_lock);
108 	mutex_destroy(&d->d_lock);
109 	cv_destroy(&d->d_cv);
110 	rw_destroy(&d->d_clnt_lock);
111 	kmem_free(d, sizeof (*d));
112 }
113 
114 void
115 audio_dev_set_description(audio_dev_t *d, const char *desc)
116 {
117 	(void) strlcpy(d->d_desc, desc, sizeof (d->d_desc));
118 }
119 
120 void
121 audio_dev_set_version(audio_dev_t *d, const char *vers)
122 {
123 	(void) strlcpy(d->d_vers, vers, sizeof (d->d_vers));
124 }
125 
126 void
127 audio_dev_add_info(audio_dev_t *d, const char *info)
128 {
129 	struct audio_infostr *isp;
130 
131 	/* failure to add information structure is not critical */
132 	isp = kmem_zalloc(sizeof (*isp), KM_NOSLEEP);
133 	if (isp == NULL) {
134 		audio_dev_warn(d, "unable to allocate information structure");
135 	} else {
136 		(void) snprintf(isp->i_line, sizeof (isp->i_line), info);
137 		list_insert_tail(&d->d_hwinfo, isp);
138 	}
139 }
140 
141 void
142 audio_engine_consume(audio_engine_t *e)
143 {
144 	mutex_enter(&e->e_lock);
145 	e->e_tail = ENG_COUNT(e);
146 	if (e->e_tail > e->e_head) {
147 		/* want more data than we have, not much we can do */
148 		e->e_errors++;
149 		e->e_underruns++;
150 	}
151 	auimpl_output_callback(e);
152 	mutex_exit(&e->e_lock);
153 }
154 
155 void
156 audio_engine_produce(audio_engine_t *e)
157 {
158 	mutex_enter(&e->e_lock);
159 	e->e_head = ENG_COUNT(e);
160 	if ((e->e_head - e->e_tail) > e->e_nframes) {
161 		/* no room for engine data, not much we can do */
162 		e->e_errors++;
163 		e->e_overruns++;
164 	}
165 	auimpl_input_callback(e);
166 	mutex_exit(&e->e_lock);
167 }
168 
169 void
170 audio_engine_reset(audio_engine_t *e)
171 {
172 	char	*buf;
173 	char	*ptr;
174 	int	nfr;
175 	int	tail;
176 
177 
178 	if ((e->e_flags & (ENGINE_INPUT | ENGINE_OUTPUT)) == 0) {
179 		/* engine not open, nothing to do */
180 		return;
181 	}
182 
183 	buf = kmem_alloc(e->e_nbytes, KM_SLEEP);
184 	ptr = buf;
185 
186 	mutex_enter(&e->e_lock);
187 
188 	tail = e->e_tidx;
189 	nfr = min(e->e_head - e->e_tail, e->e_nframes);
190 	while (nfr) {
191 		int	cnt;
192 		int	nbytes;
193 
194 		cnt = min((e->e_nframes - tail), nfr);
195 		nbytes = cnt * e->e_framesz;
196 
197 		bcopy(e->e_data + (tail * e->e_framesz), ptr, nbytes);
198 		ptr += nbytes;
199 		tail += cnt;
200 		if (tail >= e->e_framesz) {
201 			tail -= e->e_framesz;
202 		}
203 		nfr -= cnt;
204 	}
205 
206 	nfr = min(e->e_head - e->e_tail, e->e_nframes);
207 	if (e->e_flags & ENGINE_INPUT) {
208 		/* record */
209 		e->e_hidx = 0;
210 		e->e_tidx = (e->e_nframes - nfr) % e->e_nframes;
211 	} else {
212 		/* play */
213 		e->e_hidx = nfr % e->e_nframes;
214 		e->e_tidx = 0;
215 	}
216 
217 	/* relocate from scratch area to destination */
218 	bcopy(buf, e->e_data + (e->e_tidx * e->e_framesz), nfr * e->e_framesz);
219 	mutex_exit(&e->e_lock);
220 
221 	kmem_free(buf, e->e_nbytes);
222 }
223 
224 audio_engine_t *
225 audio_engine_alloc(audio_engine_ops_t *ops, unsigned flags)
226 {
227 	int i;
228 	audio_engine_t *e;
229 
230 	if (ops->audio_engine_version != AUDIO_ENGINE_VERSION) {
231 		audio_dev_warn(NULL, "audio engine version mismatch: %d != %d",
232 		    ops->audio_engine_version, AUDIO_ENGINE_VERSION);
233 		return (NULL);
234 	}
235 
236 	/* NB: The ops vector must be held in persistent storage! */
237 	e = kmem_zalloc(sizeof (audio_engine_t), KM_NOSLEEP);
238 	if (e == NULL) {
239 		audio_dev_warn(NULL, "unable to allocate engine struct");
240 		return (NULL);
241 	}
242 	e->e_ops = *ops;
243 	mutex_init(&e->e_lock, NULL, MUTEX_DRIVER, NULL);
244 	list_create(&e->e_streams, sizeof (struct audio_stream),
245 	    offsetof(struct audio_stream, s_eng_linkage));
246 
247 	for (i = 0; i < AUDIO_MAX_CHANNELS; i++) {
248 		e->e_chbufs[i] = kmem_zalloc(sizeof (int32_t) * AUDIO_CHBUFS,
249 		    KM_NOSLEEP);
250 		if (e->e_chbufs[i] == NULL) {
251 			audio_dev_warn(NULL, "unable to allocate channel buf");
252 			audio_engine_free(e);
253 			return (NULL);
254 		}
255 	}
256 
257 	e->e_flags = flags & ENGINE_DRIVER_FLAGS;
258 	return (e);
259 }
260 
261 void
262 audio_engine_free(audio_engine_t *e)
263 {
264 	int i;
265 
266 	for (i = 0; i < AUDIO_MAX_CHANNELS; i++) {
267 		if (e->e_chbufs[i] != NULL) {
268 			kmem_free(e->e_chbufs[i],
269 			    sizeof (int32_t) * AUDIO_CHBUFS);
270 		}
271 	}
272 	list_destroy(&e->e_streams);
273 	mutex_destroy(&e->e_lock);
274 	kmem_free(e, sizeof (*e));
275 }
276 
277 static list_t auimpl_devs_by_index;
278 static list_t auimpl_devs_by_number;
279 static krwlock_t auimpl_dev_lock;
280 
281 /*
282  * Not for public consumption: Private interfaces.
283  */
284 void
285 auimpl_dev_hold(audio_dev_t *d)
286 {
287 	/* bump the reference count */
288 	mutex_enter(&d->d_lock);
289 	d->d_refcnt++;
290 	mutex_exit(&d->d_lock);
291 }
292 
293 audio_dev_t *
294 auimpl_dev_hold_by_devt(dev_t dev)
295 {
296 	audio_dev_t *d;
297 	major_t major;
298 	int instance;
299 	list_t *l = &auimpl_devs_by_index;
300 
301 	major = getmajor(dev);
302 	instance = (getminor(dev) >> AUDIO_MN_INST_SHIFT) & AUDIO_MN_INST_MASK;
303 
304 	rw_enter(&auimpl_dev_lock, RW_READER);
305 
306 	for (d = list_head(l); d; d = list_next(l, d)) {
307 		if ((d->d_major == major) && (d->d_instance == instance)) {
308 			auimpl_dev_hold(d);
309 			break;
310 		}
311 	}
312 
313 	rw_exit(&auimpl_dev_lock);
314 	return (d);
315 }
316 
317 audio_dev_t *
318 auimpl_dev_hold_by_index(int index)
319 {
320 	audio_dev_t *d;
321 	list_t *l = &auimpl_devs_by_index;
322 
323 	rw_enter(&auimpl_dev_lock, RW_READER);
324 
325 	for (d = list_head(l); d; d = list_next(l, d)) {
326 		if (d->d_index == index) {
327 			auimpl_dev_hold(d);
328 			break;
329 		}
330 	}
331 
332 	rw_exit(&auimpl_dev_lock);
333 	return (d);
334 }
335 
336 void
337 auimpl_dev_release(audio_dev_t *d)
338 {
339 	mutex_enter(&d->d_lock);
340 	d->d_refcnt--;
341 	mutex_exit(&d->d_lock);
342 }
343 
344 int
345 auimpl_choose_format(int fmts)
346 {
347 	/*
348 	 * Choose the very best format we can.  We choose 24 bit in
349 	 * preference to 32 bit because we mix in 24 bit.  We do that
350 	 * to allow overflows to fit within 32-bits.  (Very few humans
351 	 * can tell a difference between 24 and 32 bit audio anyway.)
352 	 */
353 	if (fmts & AUDIO_FORMAT_S24_NE)
354 		return (AUDIO_FORMAT_S24_NE);
355 
356 	if (fmts & AUDIO_FORMAT_S32_NE)
357 		return (AUDIO_FORMAT_S32_NE);
358 
359 	if (fmts & AUDIO_FORMAT_S24_OE)
360 		return (AUDIO_FORMAT_S24_OE);
361 
362 	if (fmts & AUDIO_FORMAT_S32_OE)
363 		return (AUDIO_FORMAT_S32_OE);
364 
365 	if (fmts & AUDIO_FORMAT_S16_NE)
366 		return (AUDIO_FORMAT_S16_NE);
367 
368 	if (fmts & AUDIO_FORMAT_S16_OE)
369 		return (AUDIO_FORMAT_S16_OE);
370 
371 	if (fmts & AUDIO_FORMAT_AC3)
372 		return (AUDIO_FORMAT_AC3);
373 
374 	return (AUDIO_FORMAT_NONE);
375 }
376 
377 int
378 auimpl_engine_open(audio_dev_t *d, int fmts, int flags, audio_stream_t *sp)
379 {
380 	audio_engine_t	*e = NULL;
381 	list_t		*list;
382 	unsigned	caps;
383 	int		priority = 0;
384 	int		rv = ENODEV;
385 	int		sampsz;
386 	int		i;
387 
388 	/*
389 	 * Engine selection:
390 	 *
391 	 * We try hard to avoid consuming an engine that can be used
392 	 * for another purpose.
393 	 *
394 	 */
395 
396 	/*
397 	 * Which direction are we opening.  (We must open exactly
398 	 * one direction, otherwise the open is meaningless.)
399 	 */
400 	if (flags & ENGINE_OUTPUT)
401 		caps = ENGINE_OUTPUT_CAP;
402 	else if (flags & ENGINE_INPUT)
403 		caps = ENGINE_INPUT_CAP;
404 	else
405 		return (EINVAL);
406 
407 	list = &d->d_engines;
408 
409 	mutex_enter(&d->d_lock);
410 
411 	/*
412 	 * First we want to know if we already have "default" input
413 	 * and output engines.
414 	 */
415 
416 again:
417 
418 	for (audio_engine_t *t = list_head(list); t; t = list_next(list, t)) {
419 		int	mypri;
420 
421 		/* make sure the engine can do what we want it to */
422 		mutex_enter(&t->e_lock);
423 		if ((((t->e_flags & caps) & caps) == 0) ||
424 		    ((ENG_FORMAT(t) & fmts) == 0)) {
425 			mutex_exit(&t->e_lock);
426 			continue;
427 		}
428 
429 		/* if engine is in exclusive use, can't do it */
430 		if (t->e_flags & ENGINE_EXCLUSIVE) {
431 			mutex_exit(&t->e_lock);
432 			rv = EBUSY;
433 			continue;
434 		}
435 
436 		/* if engine is in incompatible use, can't do it */
437 		if (((flags & ENGINE_INPUT) && (t->e_flags & ENGINE_OUTPUT)) ||
438 		    ((flags & ENGINE_OUTPUT) && (t->e_flags & ENGINE_INPUT))) {
439 			mutex_exit(&t->e_lock);
440 			rv = EBUSY;
441 			continue;
442 		}
443 
444 		/*
445 		 * In order to support as many different possible
446 		 * output streams (e.g. AC3 passthru or AC3 decode),
447 		 * or multiple exclusive outputs, we treat audio
448 		 * engines as *precious*.
449 		 *
450 		 * This means that we will try hard to reuse an
451 		 * existing allocated engine.  This may not be the
452 		 * optimal performance configuration (especially if we
453 		 * wanted to avoid rate conversion, for example), but
454 		 * it should have fewer cases where the configuration
455 		 * results in denying service to any client.
456 		 */
457 
458 		rv = 0;
459 		mypri = 2000;
460 
461 		/* try not to pick on idle engines */
462 		if (list_is_empty(&t->e_streams)) {
463 			mypri -= 1000;
464 		}
465 
466 		/* try not to pick on duplex engines first */
467 		if ((t->e_flags & ENGINE_CAPS) != caps) {
468 			mypri -= 100;
469 		}
470 
471 		/* try not to pick on engines that can do other formats */
472 		if (t->e_format & ~fmts) {
473 			mypri -= 10;
474 		}
475 
476 		if (mypri > priority) {
477 			if (e != NULL) {
478 				mutex_exit(&e->e_lock);
479 			}
480 			e = t;
481 			priority = mypri;
482 		} else {
483 			mutex_exit(&t->e_lock);
484 		}
485 	}
486 
487 	if ((rv == EBUSY) && ((flags & ENGINE_NDELAY) == 0)) {
488 		ASSERT(e == NULL);
489 		if (cv_wait_sig(&d->d_cv, &d->d_lock) == 0) {
490 			mutex_exit(&d->d_lock);
491 			return (EINTR);
492 		}
493 		goto again;
494 	}
495 
496 	if (rv != 0) {
497 		ASSERT(e == NULL);
498 		mutex_exit(&d->d_lock);
499 		return (rv);
500 	}
501 
502 	ASSERT(e != NULL);
503 	ASSERT(mutex_owned(&e->e_lock));
504 
505 	/*
506 	 * If the engine is already open, there is no need for further
507 	 * work.  The first open will be relatively expensive, but
508 	 * subsequent opens should be as cheap as possible.
509 	 */
510 	if (!list_is_empty(&e->e_streams)) {
511 		rv = 0;
512 		goto ok;
513 	}
514 
515 	e->e_format = ENG_FORMAT(e);
516 	e->e_nchan = ENG_CHANNELS(e);
517 	e->e_rate = ENG_RATE(e);
518 
519 	/* Find out the "best" sample format supported by the device */
520 	switch (e->e_format) {
521 	case AUDIO_FORMAT_S24_NE:
522 		e->e_export = auimpl_export_24ne;
523 		e->e_import = auimpl_import_24ne;
524 		sampsz = 4;
525 		break;
526 	case AUDIO_FORMAT_S32_NE:
527 		e->e_export = auimpl_export_32ne;
528 		e->e_import = auimpl_import_32ne;
529 		sampsz = 4;
530 		break;
531 	case AUDIO_FORMAT_S24_OE:
532 		e->e_export = auimpl_export_24oe;
533 		e->e_import = auimpl_import_24oe;
534 		sampsz = 4;
535 		break;
536 	case AUDIO_FORMAT_S32_OE:
537 		e->e_export = auimpl_export_32oe;
538 		e->e_import = auimpl_import_32oe;
539 		sampsz = 4;
540 		break;
541 	case AUDIO_FORMAT_S16_NE:
542 		e->e_export = auimpl_export_16ne;
543 		e->e_import = auimpl_import_16ne;
544 		sampsz = 2;
545 		break;
546 	case AUDIO_FORMAT_S16_OE:
547 		e->e_export = auimpl_export_16oe;
548 		e->e_import = auimpl_import_16oe;
549 		sampsz = 2;
550 		break;
551 	case AUDIO_FORMAT_AC3:
552 		e->e_export = auimpl_export_24ne;
553 		e->e_import = auimpl_import_24ne;
554 		flags |= ENGINE_EXCLUSIVE;
555 		sampsz = 2;
556 		break;
557 	default:
558 		audio_dev_warn(d, "bad format");
559 		rv = ENOTSUP;
560 		goto done;
561 	}
562 
563 	/* sanity test a few values */
564 	if ((e->e_nchan < 0) || (e->e_nchan > AUDIO_MAX_CHANNELS) ||
565 	    (e->e_rate < 5000) || (e->e_rate > 192000)) {
566 		audio_dev_warn(d, "bad engine channels or rate");
567 		rv = EINVAL;
568 		goto done;
569 	}
570 
571 	rv = ENG_OPEN(e, &e->e_fragfr, &e->e_nfrags, &e->e_data);
572 	if (rv != 0) {
573 		audio_dev_warn(d, "unable to open engine");
574 		goto done;
575 	}
576 	if ((e->e_fragfr < 1) || (e->e_data == NULL)) {
577 		audio_dev_warn(d, "improper engine configuration");
578 		rv = EINVAL;
579 		goto done;
580 	}
581 
582 	if ((e->e_fragfr > AUDIO_CHBUFS) || (e->e_nfrags < 2)) {
583 		rv = EINVAL;
584 		audio_dev_warn(d, "invalid fragment configuration");
585 		goto done;
586 	}
587 
588 	e->e_framesz = e->e_nchan * sampsz;
589 	e->e_fragbytes = e->e_fragfr * e->e_framesz;
590 	e->e_nframes = e->e_nfrags * e->e_fragfr;
591 	e->e_intrs = e->e_rate / e->e_fragfr;
592 	e->e_nbytes = e->e_nframes * e->e_framesz;
593 	e->e_head = 0;
594 	e->e_tail = 0;
595 	e->e_hidx = 0;
596 	e->e_tidx = 0;
597 	e->e_limiter_state = 0x10000;
598 	bzero(e->e_data, e->e_nbytes);
599 
600 	for (i = 0; i < e->e_nchan; i++) {
601 		if (e->e_ops.audio_engine_chinfo == NULL) {
602 			e->e_choffs[i] = i;
603 			e->e_chincr[i] = e->e_nchan;
604 		} else {
605 			ENG_CHINFO(e, i, &e->e_choffs[i], &e->e_chincr[i]);
606 		}
607 	}
608 
609 	e->e_flags |= (ENGINE_OPEN | (flags & (ENGINE_OUTPUT | ENGINE_INPUT)));
610 
611 	/*
612 	 * Start the output callback to populate the engine on
613 	 * startup.  This avoids a false underrun when we're first
614 	 * starting up.
615 	 */
616 	if (flags & ENGINE_OUTPUT) {
617 		auimpl_output_callback(e);
618 	}
619 
620 	/*
621 	 * Start the engine up now.
622 	 *
623 	 * AC3: Note that this will need to be modified for AC3, since
624 	 * for AC3 we can't start the device until we actually have
625 	 * some data for it from the application.  Probably the best
626 	 * way to do this would be to add a flag, ENGINE_DEFERRED or
627 	 * somesuch.
628 	 */
629 	if (e->e_ops.audio_engine_start != NULL) {
630 		rv = ENG_START(e);
631 		if (rv != 0) {
632 			ENG_CLOSE(e);
633 			goto done;
634 		}
635 	}
636 
637 ok:
638 	sp->s_phys_parms->p_rate = e->e_rate;
639 	sp->s_phys_parms->p_nchan = e->e_nchan;
640 
641 	list_insert_tail(&e->e_streams, sp);
642 	sp->s_engine = e;
643 
644 done:
645 	mutex_exit(&e->e_lock);
646 	mutex_exit(&d->d_lock);
647 	return (rv);
648 }
649 
650 void
651 auimpl_engine_close(audio_stream_t *sp)
652 {
653 	audio_engine_t	*e = sp->s_engine;
654 	audio_dev_t	*d;
655 
656 	if (e == NULL)
657 		return;
658 
659 	d = e->e_dev;
660 
661 	mutex_enter(&d->d_lock);
662 	mutex_enter(&e->e_lock);
663 	sp->s_engine = NULL;
664 	list_remove(&e->e_streams, sp);
665 	if (list_is_empty(&e->e_streams)) {
666 		/* if last client holding engine open, close it all down */
667 		if (e->e_ops.audio_engine_stop != NULL)
668 			ENG_STOP(e);
669 		e->e_flags &= ENGINE_DRIVER_FLAGS;
670 		ENG_CLOSE(e);
671 	}
672 	mutex_exit(&e->e_lock);
673 
674 	cv_broadcast(&d->d_cv);
675 	mutex_exit(&d->d_lock);
676 }
677 
678 int
679 audio_dev_register(audio_dev_t *d)
680 {
681 	list_t *l;
682 	audio_dev_t *srch;
683 	int start;
684 
685 	/*
686 	 * Make sure we don't automatically unload.  This prevents
687 	 * loss of hardware settings when no audio clients are
688 	 * running.
689 	 */
690 	(void) ddi_prop_update_int(DDI_DEV_T_NONE, d->d_dip,
691 	    DDI_NO_AUTODETACH, 1);
692 
693 	/*
694 	 * This does an in-order insertion, finding the first available
695 	 * free index.  "Special" devices (ones without any actual engines)
696 	 * are all numbered 0.  There should only be one of them anyway.
697 	 * All others start at one.
698 	 */
699 	if (d->d_flags & DEV_SNDSTAT_CAP) {
700 		start = 0;
701 	} else {
702 		start = 1;
703 	}
704 	d->d_index = start;
705 	rw_enter(&auimpl_dev_lock, RW_WRITER);
706 	l = &auimpl_devs_by_index;
707 	for (srch = list_head(l); srch; srch = list_next(l, srch)) {
708 		/* skip over special nodes */
709 		if (srch->d_index < start)
710 			continue;
711 		if (srch->d_index > d->d_index) {
712 			/* found a free spot! */
713 			break;
714 		}
715 		d->d_index++;
716 	}
717 	/*
718 	 * NB: If srch is NULL, then list_insert_before puts
719 	 * it on the tail of the list.  So if we didn't find a
720 	 * hole, then that's where we want it.
721 	 */
722 	list_insert_before(l, srch, d);
723 
724 	/* insert in order by number */
725 	l = &auimpl_devs_by_number;
726 	for (srch = list_head(l); srch; srch = list_next(l, srch)) {
727 		if (srch->d_number >= d->d_number) {
728 			break;
729 		}
730 	}
731 	list_insert_before(l, srch, d);
732 
733 	rw_exit(&auimpl_dev_lock);
734 
735 	if (auimpl_create_minors(d) != 0) {
736 		rw_enter(&auimpl_dev_lock, RW_WRITER);
737 		auimpl_remove_minors(d);
738 		list_remove(&auimpl_devs_by_index, d);
739 		list_remove(&auimpl_devs_by_number, d);
740 		rw_exit(&auimpl_dev_lock);
741 		return (DDI_FAILURE);
742 	}
743 
744 	return (DDI_SUCCESS);
745 }
746 
747 int
748 audio_dev_unregister(audio_dev_t *d)
749 {
750 	rw_enter(&auimpl_dev_lock, RW_WRITER);
751 
752 	mutex_enter(&d->d_lock);
753 	/* if we are still in use, we can't unregister */
754 	if (d->d_refcnt) {
755 		mutex_exit(&d->d_lock);
756 		rw_exit(&auimpl_dev_lock);
757 		return (DDI_FAILURE);
758 	}
759 	auimpl_remove_minors(d);
760 	list_remove(&auimpl_devs_by_index, d);
761 	list_remove(&auimpl_devs_by_number, d);
762 	mutex_exit(&d->d_lock);
763 
764 	rw_exit(&auimpl_dev_lock);
765 
766 	return (DDI_SUCCESS);
767 }
768 
769 static int
770 auimpl_engine_ksupdate(kstat_t *ksp, int rw)
771 {
772 	audio_engine_t *e = ksp->ks_private;
773 	struct audio_stats *st = &e->e_stats;
774 
775 	if (rw == KSTAT_WRITE) {
776 		return (EACCES);
777 	}
778 
779 	mutex_enter(&e->e_lock);
780 	st->st_head.value.ui64 = e->e_head;
781 	st->st_tail.value.ui64 = e->e_tail;
782 	st->st_flags.value.ui32 = e->e_flags;
783 	st->st_fragfr.value.ui32 = e->e_fragfr;
784 	st->st_nfrags.value.ui32 = e->e_nfrags;
785 	st->st_framesz.value.ui32 = e->e_framesz;
786 	st->st_nbytes.value.ui32 = e->e_nbytes;
787 	st->st_hidx.value.ui32 = e->e_hidx;
788 	st->st_tidx.value.ui32 = e->e_tidx;
789 	st->st_format.value.ui32 = e->e_format;
790 	st->st_nchan.value.ui32 = e->e_nchan;
791 	st->st_rate.value.ui32 = e->e_rate;
792 	st->st_intrs.value.ui32 = e->e_intrs;
793 	st->st_errors.value.ui32 = e->e_errors;
794 	st->st_engine_underruns.value.ui32 = e->e_underruns;
795 	st->st_engine_overruns.value.ui32 = e->e_overruns;
796 	st->st_stream_underruns.value.ui32 = e->e_stream_underruns;
797 	st->st_stream_overruns.value.ui32 = e->e_stream_overruns;
798 	st->st_suspended.value.ui32 = e->e_suspended;
799 	mutex_exit(&e->e_lock);
800 
801 	return (0);
802 }
803 
804 static void
805 auimpl_engine_ksinit(audio_dev_t *d, audio_engine_t *e)
806 {
807 	char			name[32];
808 	struct audio_stats	*st;
809 
810 	(void) snprintf(name, sizeof (name), "engine_%d", e->e_num);
811 
812 	e->e_ksp = kstat_create(ddi_driver_name(d->d_dip), d->d_instance,
813 	    name, "misc", KSTAT_TYPE_NAMED,
814 	    sizeof (struct audio_stats) / sizeof (kstat_named_t), 0);
815 
816 	if (e->e_ksp == NULL) {
817 		audio_dev_warn(d, "unable to initialize kstats");
818 		return;
819 	}
820 
821 	st = &e->e_stats;
822 	e->e_ksp->ks_data = st;
823 	e->e_ksp->ks_private = e;
824 	e->e_ksp->ks_lock = NULL;
825 	e->e_ksp->ks_update = auimpl_engine_ksupdate;
826 	kstat_named_init(&st->st_head, "head", KSTAT_DATA_UINT64);
827 	kstat_named_init(&st->st_tail, "tail", KSTAT_DATA_UINT64);
828 	kstat_named_init(&st->st_flags, "flags", KSTAT_DATA_UINT32);
829 	kstat_named_init(&st->st_fragfr, "fragfr", KSTAT_DATA_UINT32);
830 	kstat_named_init(&st->st_nfrags, "nfrags", KSTAT_DATA_UINT32);
831 	kstat_named_init(&st->st_framesz, "framesz", KSTAT_DATA_UINT32);
832 	kstat_named_init(&st->st_nbytes, "nbytes", KSTAT_DATA_UINT32);
833 	kstat_named_init(&st->st_hidx, "hidx", KSTAT_DATA_UINT32);
834 	kstat_named_init(&st->st_tidx, "tidx", KSTAT_DATA_UINT32);
835 	kstat_named_init(&st->st_format, "format", KSTAT_DATA_UINT32);
836 	kstat_named_init(&st->st_nchan, "channels", KSTAT_DATA_UINT32);
837 	kstat_named_init(&st->st_rate, "rate", KSTAT_DATA_UINT32);
838 	kstat_named_init(&st->st_intrs, "intrhz", KSTAT_DATA_UINT32);
839 	kstat_named_init(&st->st_errors, "errors", KSTAT_DATA_UINT32);
840 	kstat_named_init(&st->st_engine_overruns, "engine_overruns",
841 	    KSTAT_DATA_UINT32);
842 	kstat_named_init(&st->st_engine_underruns, "engine_underruns",
843 	    KSTAT_DATA_UINT32);
844 	kstat_named_init(&st->st_stream_overruns, "stream_overruns",
845 	    KSTAT_DATA_UINT32);
846 	kstat_named_init(&st->st_stream_underruns, "stream_underruns",
847 	    KSTAT_DATA_UINT32);
848 	kstat_named_init(&st->st_suspended, "suspended", KSTAT_DATA_UINT32);
849 	kstat_install(e->e_ksp);
850 }
851 
852 void
853 audio_dev_add_engine(audio_dev_t *d, audio_engine_t *e)
854 {
855 	e->e_num = d->d_engno++;
856 
857 	mutex_enter(&d->d_lock);
858 
859 	auimpl_engine_ksinit(d, e);
860 
861 	/* check for duplex */
862 	if ((e->e_flags & ENGINE_OUTPUT_CAP) && (d->d_flags & DEV_INPUT_CAP)) {
863 		d->d_flags |= DEV_DUPLEX_CAP;
864 	}
865 	if ((e->e_flags & ENGINE_INPUT_CAP) && (d->d_flags & DEV_OUTPUT_CAP)) {
866 		d->d_flags |= DEV_DUPLEX_CAP;
867 	}
868 	/* add in the direction caps -- must be done after duplex above */
869 	if (e->e_flags & ENGINE_OUTPUT_CAP) {
870 		d->d_flags |= DEV_OUTPUT_CAP;
871 	}
872 	if (e->e_flags & ENGINE_INPUT_CAP) {
873 		d->d_flags |= DEV_INPUT_CAP;
874 	}
875 
876 	list_insert_tail(&d->d_engines, e);
877 	e->e_dev = d;
878 	mutex_exit(&d->d_lock);
879 }
880 
881 void
882 audio_dev_remove_engine(audio_dev_t *d, audio_engine_t *e)
883 {
884 	mutex_enter(&d->d_lock);
885 	list_remove(&d->d_engines, e);
886 	e->e_dev = NULL;
887 	if (e->e_ksp)
888 		kstat_delete(e->e_ksp);
889 	e->e_ksp = NULL;
890 	mutex_exit(&d->d_lock);
891 }
892 
893 /*
894  * Change the number.
895  */
896 void
897 auclnt_set_dev_number(audio_dev_t *d, int num)
898 {
899 	list_t		*l = &auimpl_devs_by_number;
900 	audio_dev_t	*srch;
901 
902 	/* reorder our list */
903 	rw_enter(&auimpl_dev_lock, RW_WRITER);
904 	d->d_number = num;
905 	list_remove(l, d);
906 	for (srch = list_head(l); srch; srch = list_next(l, srch)) {
907 		if (srch->d_number >= d->d_number) {
908 			break;
909 		}
910 	}
911 	list_insert_before(l, srch, d);
912 
913 	rw_exit(&auimpl_dev_lock);
914 }
915 
916 void
917 auclnt_walk_devs(int (*walker)(audio_dev_t *, void *), void *arg)
918 {
919 	audio_dev_t	*d;
920 	boolean_t	cont;
921 	list_t		*l;
922 
923 	l = &auimpl_devs_by_index;
924 	rw_enter(&auimpl_dev_lock, RW_READER);
925 	for (d = list_head(l); d; d = list_next(l, d)) {
926 		mutex_enter(&d->d_lock);
927 		cont = walker(d, arg);
928 		mutex_exit(&d->d_lock);
929 		if (cont == AUDIO_WALK_STOP)
930 			break;
931 	}
932 	rw_exit(&auimpl_dev_lock);
933 }
934 
935 void
936 auclnt_walk_devs_by_number(int (*walker)(audio_dev_t *, void *), void *arg)
937 {
938 	audio_dev_t	*d;
939 	boolean_t	cont;
940 	list_t		*l;
941 
942 	l = &auimpl_devs_by_number;
943 	rw_enter(&auimpl_dev_lock, RW_READER);
944 	for (d = list_head(l); d; d = list_next(l, d)) {
945 		mutex_enter(&d->d_lock);
946 		cont = walker(d, arg);
947 		mutex_exit(&d->d_lock);
948 		if (cont == AUDIO_WALK_STOP)
949 			break;
950 	}
951 	rw_exit(&auimpl_dev_lock);
952 }
953 
954 void
955 auclnt_dev_walk_engines(audio_dev_t *d,
956     int (*walker)(audio_engine_t *, void *),
957     void *arg)
958 {
959 	audio_engine_t *e;
960 	list_t *l = &d->d_engines;
961 
962 	mutex_enter(&d->d_lock);
963 	for (e = list_head(l); e != NULL; e = list_next(l, e)) {
964 		if (walker(e, arg) == AUDIO_WALK_STOP) {
965 			break;
966 		}
967 	}
968 	mutex_exit(&d->d_lock);
969 }
970 
971 int
972 auclnt_engine_get_format(audio_engine_t *e)
973 {
974 	return (ENG_FORMAT(e));
975 }
976 
977 int
978 auclnt_engine_get_channels(audio_engine_t *e)
979 {
980 	return (ENG_CHANNELS(e));
981 }
982 
983 int
984 auclnt_engine_get_rate(audio_engine_t *e)
985 {
986 	return (ENG_RATE(e));
987 }
988 
989 unsigned
990 auclnt_engine_get_capab(audio_engine_t *e)
991 {
992 	unsigned capab = 0;
993 
994 	if (e->e_flags & ENGINE_INPUT_CAP) {
995 		capab |= AUDIO_CLIENT_CAP_RECORD;
996 	}
997 	if (e->e_flags & ENGINE_OUTPUT_CAP) {
998 		capab |= AUDIO_CLIENT_CAP_PLAY;
999 	}
1000 	return (capab);
1001 }
1002 
1003 static void
1004 auimpl_walk_engines(int (*walker)(audio_engine_t *, void *), void *arg)
1005 {
1006 	audio_dev_t	*d;
1007 	audio_engine_t	*e;
1008 	list_t		*l1;
1009 	list_t		*l2;
1010 	boolean_t	done = B_FALSE;
1011 
1012 	rw_enter(&auimpl_dev_lock, RW_READER);
1013 	l1 = &auimpl_devs_by_index;
1014 	for (d = list_head(l1); d; d = list_next(l1, d)) {
1015 		mutex_enter(&d->d_lock);
1016 		l2 = &d->d_engines;
1017 		for (e = list_head(l2); e; e = list_next(l2, e)) {
1018 			if (walker(e, arg) == AUDIO_WALK_STOP) {
1019 				done = B_TRUE;
1020 				break;
1021 			}
1022 		}
1023 		mutex_exit(&d->d_lock);
1024 		if (done)
1025 			break;
1026 	}
1027 	rw_exit(&auimpl_dev_lock);
1028 }
1029 
1030 /*
1031  * This function suspends an engine.  The intent is to pause the
1032  * engine temporarily so that it does not underrun while user threads
1033  * are suspended.  The driver is still responsible for actually doing
1034  * the driver suspend work -- all this does is put the engine in a
1035  * paused state.  It does not prevent, for example, threads from
1036  * accessing the hardware.
1037  *
1038  * A properly implemented driver won't even be aware of the existence
1039  * of this routine -- the driver will just handle the suspend &
1040  * resume.  At the point of suspend & resume, the driver will see that
1041  * the engines are not running (as if all threads had "paused" it).
1042  *
1043  * Failure to execute either of the routines below is not critical,
1044  * but will probably lead to underruns and overflows as the kernel
1045  * driver gets resumed well in advance of the time when user threads
1046  * are ready to start operation.
1047  */
1048 static int
1049 auimpl_engine_suspend(audio_engine_t *e, void *dontcare)
1050 {
1051 	_NOTE(ARGUNUSED(dontcare));
1052 
1053 	mutex_enter(&e->e_lock);
1054 	e->e_suspended = B_TRUE;
1055 	mutex_exit(&e->e_lock);
1056 
1057 	return (AUDIO_WALK_CONTINUE);
1058 }
1059 
1060 static int
1061 auimpl_engine_resume(audio_engine_t *e, void *dontcare)
1062 {
1063 	_NOTE(ARGUNUSED(dontcare));
1064 	mutex_enter(&e->e_lock);
1065 	e->e_suspended = B_FALSE;
1066 	mutex_exit(&e->e_lock);
1067 	return (AUDIO_WALK_CONTINUE);
1068 }
1069 
1070 boolean_t
1071 auimpl_cpr(void *arg, int code)
1072 {
1073 	_NOTE(ARGUNUSED(arg));
1074 
1075 	switch (code) {
1076 	case CB_CODE_CPR_CHKPT:
1077 		auimpl_walk_engines(auimpl_engine_suspend, NULL);
1078 		return (B_TRUE);
1079 
1080 	case CB_CODE_CPR_RESUME:
1081 		auimpl_walk_engines(auimpl_engine_resume, NULL);
1082 		return (B_TRUE);
1083 
1084 	default:
1085 		return (B_FALSE);
1086 	}
1087 }
1088 
1089 static callb_id_t	auimpl_cpr_id = 0;
1090 
1091 void
1092 auimpl_dev_init(void)
1093 {
1094 	rw_init(&auimpl_dev_lock, NULL, RW_DRIVER, NULL);
1095 	list_create(&auimpl_devs_by_index, sizeof (struct audio_dev),
1096 	    offsetof(struct audio_dev, d_by_index));
1097 	list_create(&auimpl_devs_by_number, sizeof (struct audio_dev),
1098 	    offsetof(struct audio_dev, d_by_number));
1099 
1100 	/*
1101 	 * We "borrow" the CB_CL_CPR_PM class, which gets executed at
1102 	 * about the right time for us.  It would be nice to have a
1103 	 * new CB_CL_CPR_AUDIO class, but it isn't critical at this
1104 	 * point.
1105 	 *
1106 	 * Note that we don't care about our thread id.
1107 	 */
1108 	auimpl_cpr_id = callb_add(auimpl_cpr, NULL, CB_CL_CPR_PM, "audio_cpr");
1109 }
1110 
1111 void
1112 auimpl_dev_fini(void)
1113 {
1114 	(void) callb_delete(auimpl_cpr_id);
1115 	list_destroy(&auimpl_devs_by_index);
1116 	list_destroy(&auimpl_devs_by_number);
1117 	rw_destroy(&auimpl_dev_lock);
1118 }
1119 
1120 void
1121 audio_engine_set_private(audio_engine_t *eng, void *prv)
1122 {
1123 	eng->e_private = prv;
1124 }
1125 
1126 void *
1127 audio_engine_get_private(audio_engine_t *eng)
1128 {
1129 	return (eng->e_private);
1130 }
1131 
1132 void
1133 audio_dump_bytes(const uint8_t *w, int dcount)
1134 {
1135 	char		line[64];
1136 	char		*s;
1137 	int		i;
1138 	const int	wrap = 16;
1139 
1140 	s = line;
1141 	line[0] = 0;
1142 
1143 	cmn_err(CE_NOTE, "starting @ %p", (void *)w);
1144 	for (i = 0; i < dcount; i++) {
1145 
1146 		(void) sprintf(s, " %02x", *w);
1147 		s += strlen(s);
1148 		w++;
1149 
1150 		if ((i % wrap) == (wrap - 1)) {
1151 			cmn_err(CE_NOTE, "%08x:%s", i - (wrap - 1), line);
1152 			line[0] = 0;
1153 			s = line;
1154 		}
1155 	}
1156 
1157 	if ((i % wrap) != 0) {
1158 		cmn_err(CE_NOTE, "%08x:%s", i - (i % wrap), line);
1159 	}
1160 }
1161 
1162 void
1163 audio_dump_words(const uint16_t *w, int dcount)
1164 {
1165 	char		line[64];
1166 	char		*s;
1167 	int		i;
1168 	const int	wrap = 8;
1169 
1170 	s = line;
1171 	line[0] = 0;
1172 
1173 	cmn_err(CE_NOTE, "starting @ %p", (void *)w);
1174 	for (i = 0; i < dcount; i++) {
1175 
1176 		(void) sprintf(s, " %04x", *w);
1177 		s += strlen(s);
1178 		w++;
1179 
1180 		if ((i % wrap) == (wrap - 1)) {
1181 			cmn_err(CE_NOTE, "%08x:%s", i - (wrap - 1), line);
1182 			line[0] = 0;
1183 			s = line;
1184 		}
1185 	}
1186 
1187 	if ((i % wrap) != 0) {
1188 		cmn_err(CE_NOTE, "%08x:%s", i - (i % wrap), line);
1189 	}
1190 }
1191 
1192 void
1193 audio_dump_dwords(const uint32_t *w, int dcount)
1194 {
1195 	char		line[128];
1196 	char		*s;
1197 	int		i;
1198 	const int	wrap = 4;
1199 
1200 	s = line;
1201 	line[0] = 0;
1202 
1203 	cmn_err(CE_NOTE, "starting @ %p", (void *)w);
1204 	for (i = 0; i < dcount; i++) {
1205 
1206 		(void) sprintf(s, " %08x", *w);
1207 		s += strlen(s);
1208 		w++;
1209 
1210 		if ((i % wrap) == (wrap - 1)) {
1211 			cmn_err(CE_NOTE, "%08x:%s", i - (wrap - 1), line);
1212 			line[0] = 0;
1213 			s = line;
1214 		}
1215 	}
1216 
1217 	if ((i % wrap) != 0) {
1218 		cmn_err(CE_NOTE, "%08x:%s", i - (i % wrap), line);
1219 	}
1220 }
1221