xref: /illumos-gate/usr/src/uts/common/io/audio/impl/audio_engine.c (revision 3d78e6ab42c6ffc02ee9dbd101ff2551b77cb45f)
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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
25  */
26 
27 #include <sys/types.h>
28 #include <sys/list.h>
29 #include <sys/sysmacros.h>
30 #include <sys/ddi.h>
31 #include <sys/sunddi.h>
32 #include <sys/callb.h>
33 #include <sys/kstat.h>
34 #include <sys/note.h>
35 
36 #include "audio_impl.h"
37 
38 /*
39  * Audio Engine functions.
40  */
41 
42 /*
43  * Globals
44  */
45 uint_t		audio_intrhz = AUDIO_INTRHZ;
46 /*
47  * We need to operate at fairly high interrupt priority to avoid
48  * underruns due to other less time sensitive processing.
49  */
50 int		audio_priority = DDI_IPL_8;
51 
52 audio_dev_t *
53 audio_dev_alloc(dev_info_t *dip, int instance)
54 {
55 	audio_dev_t *d;
56 
57 	/*
58 	 * For a card with multiple independent audio ports on it, we
59 	 * allow the driver to provide a different instance numbering
60 	 * scheme than the standard DDI instance number.  (This is
61 	 * sort of like the PPA numbering scheme used by NIC drivers
62 	 * -- by default PPA == instance, but sometimes we need more
63 	 * flexibility.)
64 	 */
65 	if (instance == 0) {
66 		instance = ddi_get_instance(dip);
67 	}
68 	/* generally this shouldn't occur */
69 	if (instance > AUDIO_MN_INST_MASK) {
70 		audio_dev_warn(NULL, "bad instance number for %s (%d)",
71 		    ddi_driver_name(dip), instance);
72 		return (NULL);
73 	}
74 
75 	if ((d = kmem_zalloc(sizeof (*d), KM_NOSLEEP)) == NULL) {
76 		audio_dev_warn(NULL, "unable to allocate audio device struct");
77 		return (NULL);
78 	}
79 	d->d_dip = dip;
80 	d->d_number = -1;
81 	d->d_major = ddi_driver_major(dip);
82 	d->d_instance = instance;
83 	d->d_pcmvol = 100;
84 	mutex_init(&d->d_lock, NULL, MUTEX_DRIVER, NULL);
85 	cv_init(&d->d_cv, NULL, CV_DRIVER, NULL);
86 	mutex_init(&d->d_ctrl_lock, NULL, MUTEX_DRIVER, NULL);
87 	cv_init(&d->d_ctrl_cv, NULL, CV_DRIVER, NULL);
88 	list_create(&d->d_clients, sizeof (struct audio_client),
89 	    offsetof(struct audio_client, c_dev_linkage));
90 	list_create(&d->d_engines, sizeof (struct audio_engine),
91 	    offsetof(struct audio_engine, e_dev_linkage));
92 	list_create(&d->d_controls, sizeof (struct audio_ctrl),
93 	    offsetof(struct audio_ctrl, ctrl_linkage));
94 	list_create(&d->d_hwinfo, sizeof (struct audio_infostr),
95 	    offsetof(struct audio_infostr, i_linkage));
96 	(void) snprintf(d->d_name, sizeof (d->d_name), "%s#%d",
97 	    ddi_driver_name(dip), instance);
98 
99 	return (d);
100 }
101 
102 void
103 audio_dev_free(audio_dev_t *d)
104 {
105 	struct audio_infostr *isp;
106 
107 	while ((isp = list_remove_head(&d->d_hwinfo)) != NULL) {
108 		kmem_free(isp, sizeof (*isp));
109 	}
110 	if (d->d_pcmvol_ctrl != NULL) {
111 		audio_dev_del_control(d->d_pcmvol_ctrl);
112 	}
113 	list_destroy(&d->d_hwinfo);
114 	list_destroy(&d->d_engines);
115 	list_destroy(&d->d_controls);
116 	list_destroy(&d->d_clients);
117 	mutex_destroy(&d->d_ctrl_lock);
118 	mutex_destroy(&d->d_lock);
119 	cv_destroy(&d->d_cv);
120 	cv_destroy(&d->d_ctrl_cv);
121 	kmem_free(d, sizeof (*d));
122 }
123 
124 void
125 audio_dev_set_description(audio_dev_t *d, const char *desc)
126 {
127 	(void) strlcpy(d->d_desc, desc, sizeof (d->d_desc));
128 }
129 
130 void
131 audio_dev_set_version(audio_dev_t *d, const char *vers)
132 {
133 	(void) strlcpy(d->d_vers, vers, sizeof (d->d_vers));
134 }
135 
136 void
137 audio_dev_add_info(audio_dev_t *d, const char *info)
138 {
139 	struct audio_infostr *isp;
140 
141 	/* failure to add information structure is not critical */
142 	isp = kmem_zalloc(sizeof (*isp), KM_NOSLEEP);
143 	if (isp == NULL) {
144 		audio_dev_warn(d, "unable to allocate information structure");
145 	} else {
146 		(void) snprintf(isp->i_line, sizeof (isp->i_line), info);
147 		list_insert_tail(&d->d_hwinfo, isp);
148 	}
149 }
150 
151 static void
152 auimpl_engine_reset(audio_engine_t *e)
153 {
154 	char	*buf;
155 	char	*ptr;
156 	int	nfr, resid, cnt;
157 	int	tidx;
158 
159 	tidx = e->e_tidx;
160 	nfr = min(e->e_head - e->e_tail, e->e_nframes);
161 	buf = kmem_alloc(nfr * e->e_framesz, KM_SLEEP);
162 	ptr = buf;
163 	cnt = 0;
164 
165 	ASSERT(e->e_nframes);
166 
167 	for (resid = nfr; resid; resid -= cnt) {
168 		int	nbytes;
169 
170 		cnt = min((e->e_nframes - tidx), resid);
171 		nbytes = cnt * e->e_framesz;
172 
173 		bcopy(e->e_data + (tidx * e->e_framesz), ptr, nbytes);
174 		ptr += nbytes;
175 		tidx += cnt;
176 		if (tidx == e->e_nframes) {
177 			tidx = 0;
178 		}
179 	}
180 
181 	if (e->e_flags & ENGINE_INPUT) {
182 		/* record */
183 		e->e_hidx = 0;
184 		e->e_tidx = (e->e_nframes - nfr) % e->e_nframes;
185 	} else {
186 		/* play */
187 		e->e_hidx = nfr % e->e_nframes;
188 		e->e_tidx = 0;
189 	}
190 
191 	/* relocate from scratch area to destination */
192 	bcopy(buf, e->e_data + (e->e_tidx * e->e_framesz), nfr * e->e_framesz);
193 	kmem_free(buf, nfr * e->e_framesz);
194 }
195 
196 static volatile uint_t auimpl_engno = 0;
197 
198 audio_engine_t *
199 audio_engine_alloc(audio_engine_ops_t *ops, uint_t flags)
200 {
201 	int i;
202 	audio_engine_t *e;
203 	char tname[32];
204 	int num;
205 
206 	if (ops->audio_engine_version != AUDIO_ENGINE_VERSION) {
207 		audio_dev_warn(NULL, "audio engine version mismatch: %d != %d",
208 		    ops->audio_engine_version, AUDIO_ENGINE_VERSION);
209 		return (NULL);
210 	}
211 
212 	/* NB: The ops vector must be held in persistent storage! */
213 	e = kmem_zalloc(sizeof (audio_engine_t), KM_NOSLEEP);
214 	if (e == NULL) {
215 		audio_dev_warn(NULL, "unable to allocate engine struct");
216 		return (NULL);
217 	}
218 	e->e_ops = *ops;
219 	mutex_init(&e->e_lock, NULL, MUTEX_DRIVER,
220 	    DDI_INTR_PRI(audio_priority));
221 	cv_init(&e->e_cv, NULL, CV_DRIVER, NULL);
222 	list_create(&e->e_streams, sizeof (struct audio_stream),
223 	    offsetof(struct audio_stream, s_eng_linkage));
224 
225 	for (i = 0; i < AUDIO_MAX_CHANNELS; i++) {
226 		e->e_chbufs[i] = kmem_zalloc(sizeof (int32_t) * AUDIO_CHBUFS,
227 		    KM_NOSLEEP);
228 		if (e->e_chbufs[i] == NULL) {
229 			audio_dev_warn(NULL, "unable to allocate channel buf");
230 			audio_engine_free(e);
231 			return (NULL);
232 		}
233 	}
234 
235 	num = atomic_inc_uint_nv(&auimpl_engno);
236 
237 	(void) snprintf(tname, sizeof (tname), "audio_engine_%d", num);
238 
239 	e->e_flags = flags & ENGINE_DRIVER_FLAGS;
240 	return (e);
241 }
242 
243 void
244 audio_engine_free(audio_engine_t *e)
245 {
246 	int i;
247 
248 	for (i = 0; i < AUDIO_MAX_CHANNELS; i++) {
249 		if (e->e_chbufs[i] != NULL) {
250 			kmem_free(e->e_chbufs[i],
251 			    sizeof (int32_t) * AUDIO_CHBUFS);
252 		}
253 	}
254 
255 	list_destroy(&e->e_streams);
256 	mutex_destroy(&e->e_lock);
257 	cv_destroy(&e->e_cv);
258 	kmem_free(e, sizeof (*e));
259 }
260 
261 static list_t auimpl_devs_by_index;
262 static list_t auimpl_devs_by_number;
263 static krwlock_t auimpl_dev_lock;
264 
265 /*
266  * Not for public consumption: Private interfaces.
267  */
268 void
269 auimpl_dev_hold(audio_dev_t *d)
270 {
271 	/* bump the reference count */
272 	mutex_enter(&d->d_lock);
273 	d->d_refcnt++;
274 	mutex_exit(&d->d_lock);
275 }
276 
277 audio_dev_t *
278 auimpl_dev_hold_by_devt(dev_t dev)
279 {
280 	audio_dev_t *d;
281 	major_t major;
282 	int instance;
283 	list_t *l = &auimpl_devs_by_index;
284 
285 	major = getmajor(dev);
286 	instance = (getminor(dev) >> AUDIO_MN_INST_SHIFT) & AUDIO_MN_INST_MASK;
287 
288 	rw_enter(&auimpl_dev_lock, RW_READER);
289 
290 	for (d = list_head(l); d; d = list_next(l, d)) {
291 		if ((d->d_major == major) && (d->d_instance == instance)) {
292 			auimpl_dev_hold(d);
293 			break;
294 		}
295 	}
296 
297 	rw_exit(&auimpl_dev_lock);
298 	return (d);
299 }
300 
301 audio_dev_t *
302 auimpl_dev_hold_by_index(int index)
303 {
304 	audio_dev_t *d;
305 	list_t *l = &auimpl_devs_by_index;
306 
307 	rw_enter(&auimpl_dev_lock, RW_READER);
308 
309 	for (d = list_head(l); d; d = list_next(l, d)) {
310 		if (d->d_index == index) {
311 			auimpl_dev_hold(d);
312 			break;
313 		}
314 	}
315 
316 	rw_exit(&auimpl_dev_lock);
317 	return (d);
318 }
319 
320 void
321 auimpl_dev_release(audio_dev_t *d)
322 {
323 	mutex_enter(&d->d_lock);
324 	d->d_refcnt--;
325 	mutex_exit(&d->d_lock);
326 }
327 
328 int
329 auimpl_choose_format(int fmts)
330 {
331 	/*
332 	 * Choose the very best format we can.  We choose 24 bit in
333 	 * preference to 32 bit because we mix in 24 bit.  We do that
334 	 * to allow overflows to fit within 32-bits.  (Very few humans
335 	 * can tell a difference between 24 and 32 bit audio anyway.)
336 	 */
337 	if (fmts & AUDIO_FORMAT_S24_NE)
338 		return (AUDIO_FORMAT_S24_NE);
339 
340 	if (fmts & AUDIO_FORMAT_S32_NE)
341 		return (AUDIO_FORMAT_S32_NE);
342 
343 	if (fmts & AUDIO_FORMAT_S24_OE)
344 		return (AUDIO_FORMAT_S24_OE);
345 
346 	if (fmts & AUDIO_FORMAT_S32_OE)
347 		return (AUDIO_FORMAT_S32_OE);
348 
349 	if (fmts & AUDIO_FORMAT_S16_NE)
350 		return (AUDIO_FORMAT_S16_NE);
351 
352 	if (fmts & AUDIO_FORMAT_S16_OE)
353 		return (AUDIO_FORMAT_S16_OE);
354 
355 	if (fmts & AUDIO_FORMAT_AC3)
356 		return (AUDIO_FORMAT_AC3);
357 
358 	return (AUDIO_FORMAT_NONE);
359 }
360 
361 int
362 auimpl_engine_open(audio_stream_t *sp, int flags)
363 {
364 	return (auimpl_engine_setup(sp, flags, NULL, FORMAT_MSK_NONE));
365 }
366 
367 
368 int
369 auimpl_engine_setup(audio_stream_t *sp, int flags, audio_parms_t *parms,
370     uint_t mask)
371 {
372 	audio_dev_t	*d = sp->s_client->c_dev;
373 	audio_engine_t	*e = NULL;
374 	audio_parms_t	uparms;
375 	list_t		*list;
376 	uint_t		cap;
377 	int		priority = 0;
378 	int		rv = ENODEV;
379 	int		sampsz;
380 	int		i;
381 	int		fragfr;
382 	int		fmts;
383 
384 
385 	mutex_enter(&d->d_lock);
386 
387 	uparms = *sp->s_user_parms;
388 	if (mask & FORMAT_MSK_FMT)
389 		uparms.p_format = parms->p_format;
390 	if (mask & FORMAT_MSK_RATE)
391 		uparms.p_rate = parms->p_rate;
392 	if (mask & FORMAT_MSK_CHAN)
393 		uparms.p_nchan = parms->p_nchan;
394 
395 	/*
396 	 * Which direction are we opening?  (We must open exactly
397 	 * one direction, otherwise the open is meaningless.)
398 	 */
399 
400 	if (sp == &sp->s_client->c_ostream) {
401 		cap = ENGINE_OUTPUT_CAP;
402 		flags |= ENGINE_OUTPUT;
403 	} else {
404 		cap = ENGINE_INPUT_CAP;
405 		flags |= ENGINE_INPUT;
406 	}
407 
408 	if (uparms.p_format == AUDIO_FORMAT_AC3) {
409 		fmts = AUDIO_FORMAT_AC3;
410 		flags |= ENGINE_EXCLUSIVE;
411 	} else {
412 		fmts = AUDIO_FORMAT_PCM;
413 	}
414 
415 	list = &d->d_engines;
416 
417 
418 	/* If the device is suspended, wait for it to resume. */
419 	while (d->d_suspended) {
420 		cv_wait(&d->d_ctrl_cv, &d->d_lock);
421 	}
422 
423 again:
424 
425 	for (audio_engine_t *t = list_head(list); t; t = list_next(list, t)) {
426 		int		mypri;
427 		int		r;
428 
429 		/* Make sure the engine can do what we want it to. */
430 		mutex_enter(&t->e_lock);
431 
432 		if ((t->e_flags & cap) == 0) {
433 			mutex_exit(&t->e_lock);
434 			continue;
435 		}
436 
437 		/*
438 		 * Open the engine early, as the inquiries to rate and format
439 		 * may not be accurate until this is done.
440 		 */
441 		if (list_is_empty(&t->e_streams)) {
442 			if (ENG_OPEN(t, flags, &t->e_nframes, &t->e_data)) {
443 				mutex_exit(&t->e_lock);
444 				rv = EIO;
445 				continue;
446 			}
447 		}
448 
449 		if ((ENG_FORMAT(t) & fmts) == 0) {
450 			if (list_is_empty(&t->e_streams))
451 				ENG_CLOSE(t);
452 			mutex_exit(&t->e_lock);
453 			continue;
454 		}
455 
456 
457 		/* If it is in failed state, don't use this engine. */
458 		if (t->e_failed) {
459 			if (list_is_empty(&t->e_streams))
460 				ENG_CLOSE(t);
461 			mutex_exit(&t->e_lock);
462 			rv = rv ? EIO : 0;
463 			continue;
464 		}
465 
466 		/*
467 		 * If the engine is in exclusive use, we can't use it.
468 		 * This is intended for use with AC3 or digital
469 		 * streams that cannot tolerate mixing.
470 		 */
471 		if ((t->e_flags & ENGINE_EXCLUSIVE) && (t != sp->s_engine)) {
472 			if (list_is_empty(&t->e_streams))
473 				ENG_CLOSE(t);
474 			mutex_exit(&t->e_lock);
475 			rv = rv ? EBUSY : 0;
476 			continue;
477 		}
478 
479 		/*
480 		 * If the engine is in use incompatibly, we can't use
481 		 * it.  This should only happen for half-duplex audio
482 		 * devices.  I've not seen any of these that are
483 		 * recent enough to be supported by Solaris.
484 		 */
485 		if (((flags & ENGINE_INPUT) && (t->e_flags & ENGINE_OUTPUT)) ||
486 		    ((flags & ENGINE_OUTPUT) && (t->e_flags & ENGINE_INPUT))) {
487 			if (list_is_empty(&t->e_streams))
488 				ENG_CLOSE(t);
489 			mutex_exit(&t->e_lock);
490 			/* Only override the ENODEV or EIO. */
491 			rv = rv ? EBUSY : 0;
492 			continue;
493 		}
494 
495 		/*
496 		 * In order to support as many different possible
497 		 * output streams (e.g. AC3 passthru or AC3 decode),
498 		 * or multiple exclusive outputs, we treat audio
499 		 * engines as *precious*.
500 		 *
501 		 * This means that we will try hard to reuse an
502 		 * existing allocated engine.  This may not be the
503 		 * optimal performance configuration (especially if we
504 		 * wanted to avoid rate conversion, for example), but
505 		 * it should have fewer cases where the configuration
506 		 * results in denying service to any client.
507 		 */
508 
509 		/*
510 		 * This engine *can* support us, so we should no longer
511 		 * have a failure mode.
512 		 */
513 		rv = 0;
514 		mypri = (1U << 0);
515 
516 
517 		/*
518 		 * Mixing is cheap, so try not to pick on idle
519 		 * engines.  This avoids burning bus bandwidth (which
520 		 * may be precious for certain classes of traffic).
521 		 * Note that idleness is given a low priority compared
522 		 * to the other considerations.
523 		 *
524 		 * We also use this opportunity open the engine, if
525 		 * not already done so, so that our parameter
526 		 * inquiries will be valid.
527 		 */
528 		if (!list_is_empty(&t->e_streams))
529 			mypri |= (1U << 1);
530 
531 		/*
532 		 * Slight preference is given to reuse an engine that
533 		 * we might already be using.
534 		 */
535 		if (t == sp->s_engine)
536 			mypri |= (1U << 2);
537 
538 
539 		/*
540 		 * Sample rate conversion avoidance.  Upsampling
541 		 * requires multiplications and is moderately
542 		 * expensive.  Downsampling requires division and is
543 		 * quite expensive, and hence to be avoided if at all
544 		 * possible.
545 		 */
546 		r = ENG_RATE(t);
547 		if (uparms.p_rate == r) {
548 			/*
549 			 * No conversion needed at all.  This is ideal.
550 			 */
551 			mypri |= (1U << 4) | (1U << 3);
552 		} else {
553 			int src, dst;
554 
555 			if (flags & ENGINE_INPUT) {
556 				src = r;
557 				dst = uparms.p_rate;
558 			} else {
559 				src = uparms.p_rate;
560 				dst = r;
561 			}
562 			if ((src < dst) && ((dst % src) == 0)) {
563 				/*
564 				 * Pure upsampling only. This
565 				 * penalizes any engine which requires
566 				 * downsampling.
567 				 */
568 				mypri |= (1U << 3);
569 			}
570 		}
571 
572 		/*
573 		 * Try not to pick on duplex engines.  This way we
574 		 * leave engines that can be used for recording or
575 		 * playback available as such.  All modern drivers
576 		 * use separate unidirectional engines for playback
577 		 * and record.
578 		 */
579 		if ((t->e_flags & ENGINE_CAPS) == cap) {
580 			mypri |= (1U << 5);
581 		}
582 
583 		/*
584 		 * Try not to pick on engines that can do other
585 		 * formats.  This will generally be false, but if it
586 		 * happens we pretty strongly avoid using a limited
587 		 * resource.
588 		 */
589 		if ((t->e_format & ~fmts) == 0) {
590 			mypri |= (1U << 6);
591 		}
592 
593 		if (mypri > priority) {
594 			if (e != NULL) {
595 				/*
596 				 * If we opened this for our own use
597 				 * and we are no longer using it, then
598 				 * close it back down.
599 				 */
600 				if (list_is_empty(&e->e_streams))
601 					ENG_CLOSE(e);
602 				mutex_exit(&e->e_lock);
603 			}
604 			e = t;
605 			priority = mypri;
606 		} else {
607 			mutex_exit(&t->e_lock);
608 		}
609 
610 		/*
611 		 * Locking: at this point, if we have an engine, "e", it is
612 		 * locked.  No other engines should have a lock held.
613 		 */
614 	}
615 
616 	if ((rv == EBUSY) && ((flags & ENGINE_NDELAY) == 0)) {
617 		ASSERT(e == NULL);
618 		if (cv_wait_sig(&d->d_cv, &d->d_lock) == 0) {
619 			mutex_exit(&d->d_lock);
620 			return (EINTR);
621 		}
622 		goto again;
623 	}
624 
625 	if (rv != 0) {
626 		ASSERT(e == NULL);
627 		mutex_exit(&d->d_lock);
628 		return (rv);
629 	}
630 
631 	ASSERT(e != NULL);
632 	ASSERT(mutex_owned(&e->e_lock));
633 
634 	if (sp->s_engine && (sp->s_engine != e)) {
635 		/*
636 		 * If this represents a potential engine change, then
637 		 * we close off everything, and start anew. This turns
638 		 * out to be vastly simpler than trying to close all
639 		 * the races associated with a true hand off.  This
640 		 * ought to be relatively uncommon (changing engines).
641 		 */
642 
643 		/* Drop the new reference. */
644 		if (list_is_empty(&e->e_streams))
645 			ENG_CLOSE(e);
646 		mutex_exit(&e->e_lock);
647 		mutex_exit(&d->d_lock);
648 
649 		auimpl_engine_close(sp);
650 
651 		/* Try again. */
652 		return (auimpl_engine_setup(sp, flags, parms, mask));
653 	}
654 
655 	if (sp->s_engine == NULL) {
656 		/*
657 		 * Add a reference to this engine if we don't already
658 		 * have one.
659 		 */
660 		sp->s_engine = e;
661 
662 		if (!list_is_empty(&e->e_streams)) {
663 			/*
664 			 * If the engine is already open, there is no
665 			 * need for further work.  The first open will
666 			 * be relatively expensive, but subsequent
667 			 * opens should be as cheap as possible.
668 			 */
669 			list_insert_tail(&e->e_streams, sp);
670 			goto ok;
671 		}
672 		list_insert_tail(&e->e_streams, sp);
673 
674 	} else {
675 		ASSERT(sp->s_engine == e);
676 		/*
677 		 * No change in engine... hence don't reprogram the
678 		 * engine, and don't change references.
679 		 */
680 		goto ok;
681 	}
682 
683 	e->e_format = ENG_FORMAT(e);
684 	e->e_nchan = ENG_CHANNELS(e);
685 	e->e_rate = ENG_RATE(e);
686 
687 	/* Select format converters for the engine. */
688 	switch (e->e_format) {
689 	case AUDIO_FORMAT_S24_NE:
690 		e->e_export = auimpl_export_24ne;
691 		e->e_import = auimpl_import_24ne;
692 		sampsz = 4;
693 		break;
694 	case AUDIO_FORMAT_S32_NE:
695 		e->e_export = auimpl_export_32ne;
696 		e->e_import = auimpl_import_32ne;
697 		sampsz = 4;
698 		break;
699 	case AUDIO_FORMAT_S24_OE:
700 		e->e_export = auimpl_export_24oe;
701 		e->e_import = auimpl_import_24oe;
702 		sampsz = 4;
703 		break;
704 	case AUDIO_FORMAT_S32_OE:
705 		e->e_export = auimpl_export_32oe;
706 		e->e_import = auimpl_import_32oe;
707 		sampsz = 4;
708 		break;
709 	case AUDIO_FORMAT_S16_NE:
710 		e->e_export = auimpl_export_16ne;
711 		e->e_import = auimpl_import_16ne;
712 		sampsz = 2;
713 		break;
714 	case AUDIO_FORMAT_S16_OE:
715 		e->e_export = auimpl_export_16oe;
716 		e->e_import = auimpl_import_16oe;
717 		sampsz = 2;
718 		break;
719 	case AUDIO_FORMAT_AC3:
720 		e->e_export = auimpl_export_24ne;
721 		e->e_import = auimpl_import_24ne;
722 		flags |= ENGINE_EXCLUSIVE;
723 		sampsz = 2;
724 		break;
725 	default:
726 		audio_dev_warn(d, "bad format");
727 		rv = ENOTSUP;
728 		goto done;
729 	}
730 
731 	fragfr = e->e_rate / audio_intrhz;
732 	if ((fragfr > AUDIO_CHBUFS) || (fragfr < 1)) {
733 		audio_dev_warn(d, "invalid fragment configration");
734 		rv = EINVAL;
735 		goto done;
736 	}
737 
738 	/* Sanity test a few values. */
739 	if ((e->e_nchan < 0) || (e->e_nchan > AUDIO_MAX_CHANNELS) ||
740 	    (e->e_rate < 5000) || (e->e_rate > 192000)) {
741 		audio_dev_warn(d, "bad engine channels or rate");
742 		rv = EINVAL;
743 		goto done;
744 	}
745 
746 	if ((e->e_nframes <= (fragfr * 2)) || (e->e_data == NULL)) {
747 		audio_dev_warn(d, "improper engine configuration");
748 		rv = EINVAL;
749 		goto done;
750 	}
751 
752 	e->e_framesz = e->e_nchan * sampsz;
753 	e->e_fragfr = fragfr;
754 	e->e_head = 0;
755 	e->e_tail = 0;
756 	e->e_hidx = 0;
757 	e->e_tidx = 0;
758 	e->e_limiter_state = 0x10000;
759 	bzero(e->e_data, e->e_nframes * e->e_framesz);
760 
761 	if (e->e_ops.audio_engine_playahead == NULL) {
762 		e->e_playahead = (fragfr * 3) / 2;
763 	} else {
764 		e->e_playahead = ENG_PLAYAHEAD(e);
765 		/*
766 		 * Need to have at least a fragment plus some extra to
767 		 * avoid underruns.
768 		 */
769 		if (e->e_playahead < ((fragfr * 3) / 2)) {
770 			e->e_playahead = (fragfr * 3) / 2;
771 		}
772 
773 		/*
774 		 * Impossible to queue more frames than FIFO can hold.
775 		 */
776 		if (e->e_playahead > e->e_nframes) {
777 			e->e_playahead = (fragfr * 3) / 2;
778 		}
779 	}
780 
781 	for (i = 0; i < e->e_nchan; i++) {
782 		if (e->e_ops.audio_engine_chinfo == NULL) {
783 			e->e_choffs[i] = i;
784 			e->e_chincr[i] = e->e_nchan;
785 		} else {
786 			ENG_CHINFO(e, i, &e->e_choffs[i], &e->e_chincr[i]);
787 		}
788 	}
789 
790 	e->e_flags |= flags;
791 
792 	/*
793 	 * Arrange for the engine to be started.  We defer this to the
794 	 * periodic callback, to ensure that the start happens near
795 	 * the edge of the periodic callback.  This is necessary to
796 	 * ensure that the first fragment processed is about the same
797 	 * size as the usual fragment size.  (Basically, the problem
798 	 * is that we have only 10 msec resolution with the periodic
799 	 * interface, whch is rather unfortunate.)
800 	 */
801 	e->e_need_start = B_TRUE;
802 
803 	if (flags & ENGINE_OUTPUT) {
804 		/*
805 		 * Start the output callback to populate the engine on
806 		 * startup.  This avoids a false underrun when we're
807 		 * first starting up.
808 		 */
809 		auimpl_output_preload(e);
810 
811 		e->e_periodic = ddi_periodic_add(auimpl_output_callback, e,
812 		    NANOSEC / audio_intrhz, audio_priority);
813 	} else {
814 		e->e_periodic = ddi_periodic_add(auimpl_input_callback, e,
815 		    NANOSEC / audio_intrhz, audio_priority);
816 	}
817 
818 ok:
819 	sp->s_phys_parms->p_rate = e->e_rate;
820 	sp->s_phys_parms->p_nchan = e->e_nchan;
821 
822 	/* Configure the engine. */
823 	mutex_enter(&sp->s_lock);
824 	rv = auimpl_format_setup(sp, parms, mask);
825 	mutex_exit(&sp->s_lock);
826 
827 done:
828 	mutex_exit(&e->e_lock);
829 	mutex_exit(&d->d_lock);
830 
831 	return (rv);
832 }
833 
834 void
835 auimpl_engine_close(audio_stream_t *sp)
836 {
837 	audio_engine_t	*e = sp->s_engine;
838 	audio_dev_t	*d;
839 
840 	if (e == NULL)
841 		return;
842 
843 	d = e->e_dev;
844 
845 	mutex_enter(&d->d_lock);
846 	while (d->d_suspended) {
847 		cv_wait(&d->d_ctrl_cv, &d->d_lock);
848 	}
849 
850 	mutex_enter(&e->e_lock);
851 	sp->s_engine = NULL;
852 	list_remove(&e->e_streams, sp);
853 	if (list_is_empty(&e->e_streams)) {
854 		ENG_STOP(e);
855 		ddi_periodic_delete(e->e_periodic);
856 		e->e_periodic = 0;
857 		e->e_flags &= ENGINE_DRIVER_FLAGS;
858 		ENG_CLOSE(e);
859 	}
860 	mutex_exit(&e->e_lock);
861 
862 	cv_broadcast(&d->d_cv);
863 	mutex_exit(&d->d_lock);
864 }
865 
866 int
867 audio_dev_register(audio_dev_t *d)
868 {
869 	list_t *l;
870 	audio_dev_t *srch;
871 	int start;
872 
873 	/*
874 	 * Make sure we don't automatically unload.  This prevents
875 	 * loss of hardware settings when no audio clients are
876 	 * running.
877 	 */
878 	(void) ddi_prop_update_int(DDI_DEV_T_NONE, d->d_dip,
879 	    DDI_NO_AUTODETACH, 1);
880 
881 	/*
882 	 * This does an in-order insertion, finding the first available
883 	 * free index.  "Special" devices (ones without any actual engines)
884 	 * are all numbered 0.  There should only be one of them anyway.
885 	 * All others start at one.
886 	 */
887 	if (d->d_flags & DEV_SNDSTAT_CAP) {
888 		start = 0;
889 	} else {
890 		start = 1;
891 	}
892 	d->d_index = start;
893 
894 	rw_enter(&auimpl_dev_lock, RW_WRITER);
895 	l = &auimpl_devs_by_index;
896 	for (srch = list_head(l); srch; srch = list_next(l, srch)) {
897 		/* skip over special nodes */
898 		if (srch->d_index < start)
899 			continue;
900 		if (srch->d_index > d->d_index) {
901 			/* found a free spot! */
902 			break;
903 		}
904 		d->d_index++;
905 	}
906 	/*
907 	 * NB: If srch is NULL, then list_insert_before puts
908 	 * it on the tail of the list.  So if we didn't find a
909 	 * hole, then that's where we want it.
910 	 */
911 	list_insert_before(l, srch, d);
912 
913 	/* insert in order by number */
914 	l = &auimpl_devs_by_number;
915 	for (srch = list_head(l); srch; srch = list_next(l, srch)) {
916 		if (srch->d_number >= d->d_number) {
917 			break;
918 		}
919 	}
920 	list_insert_before(l, srch, d);
921 
922 	rw_exit(&auimpl_dev_lock);
923 
924 	if (auimpl_create_minors(d) != 0) {
925 		rw_enter(&auimpl_dev_lock, RW_WRITER);
926 		auimpl_remove_minors(d);
927 		list_remove(&auimpl_devs_by_index, d);
928 		list_remove(&auimpl_devs_by_number, d);
929 		rw_exit(&auimpl_dev_lock);
930 		return (DDI_FAILURE);
931 	}
932 
933 	return (DDI_SUCCESS);
934 }
935 
936 int
937 audio_dev_unregister(audio_dev_t *d)
938 {
939 	rw_enter(&auimpl_dev_lock, RW_WRITER);
940 
941 	mutex_enter(&d->d_lock);
942 	/* if we are still in use, we can't unregister */
943 	if (d->d_refcnt) {
944 		mutex_exit(&d->d_lock);
945 		rw_exit(&auimpl_dev_lock);
946 		return (DDI_FAILURE);
947 	}
948 	auimpl_remove_minors(d);
949 	list_remove(&auimpl_devs_by_index, d);
950 	list_remove(&auimpl_devs_by_number, d);
951 	mutex_exit(&d->d_lock);
952 
953 	rw_exit(&auimpl_dev_lock);
954 
955 	return (DDI_SUCCESS);
956 }
957 
958 static int
959 auimpl_engine_ksupdate(kstat_t *ksp, int rw)
960 {
961 	audio_engine_t *e = ksp->ks_private;
962 	struct audio_stats *st = &e->e_stats;
963 
964 	if (rw == KSTAT_WRITE) {
965 		return (EACCES);
966 	}
967 
968 	mutex_enter(&e->e_lock);
969 	st->st_head.value.ui64 = e->e_head;
970 	st->st_tail.value.ui64 = e->e_tail;
971 	st->st_flags.value.ui32 = e->e_flags;
972 	st->st_nbytes.value.ui32 = e->e_framesz * e->e_nframes;
973 	st->st_framesz.value.ui32 = e->e_framesz;
974 	st->st_hidx.value.ui32 = e->e_hidx;
975 	st->st_tidx.value.ui32 = e->e_tidx;
976 	st->st_format.value.ui32 = e->e_format;
977 	st->st_nchan.value.ui32 = e->e_nchan;
978 	st->st_rate.value.ui32 = e->e_rate;
979 	st->st_errors.value.ui32 = e->e_errors;
980 	st->st_engine_underruns.value.ui32 = e->e_underruns;
981 	st->st_engine_overruns.value.ui32 = e->e_overruns;
982 	st->st_stream_underruns.value.ui32 = e->e_stream_underruns;
983 	st->st_stream_overruns.value.ui32 = e->e_stream_overruns;
984 	st->st_suspended.value.ui32 = e->e_suspended;
985 	st->st_failed.value.ui32 = e->e_failed;
986 	st->st_playahead.value.ui32 = e->e_playahead;
987 	mutex_exit(&e->e_lock);
988 
989 	return (0);
990 }
991 
992 static void
993 auimpl_engine_ksinit(audio_dev_t *d, audio_engine_t *e)
994 {
995 	char			name[32];
996 	struct audio_stats	*st;
997 
998 	(void) snprintf(name, sizeof (name), "engine_%d", e->e_num);
999 
1000 	e->e_ksp = kstat_create(ddi_driver_name(d->d_dip), d->d_instance,
1001 	    name, "misc", KSTAT_TYPE_NAMED,
1002 	    sizeof (struct audio_stats) / sizeof (kstat_named_t), 0);
1003 
1004 	if (e->e_ksp == NULL) {
1005 		audio_dev_warn(d, "unable to initialize kstats");
1006 		return;
1007 	}
1008 
1009 	st = &e->e_stats;
1010 	e->e_ksp->ks_data = st;
1011 	e->e_ksp->ks_private = e;
1012 	e->e_ksp->ks_lock = NULL;
1013 	e->e_ksp->ks_update = auimpl_engine_ksupdate;
1014 	kstat_named_init(&st->st_head, "head", KSTAT_DATA_UINT64);
1015 	kstat_named_init(&st->st_tail, "tail", KSTAT_DATA_UINT64);
1016 	kstat_named_init(&st->st_flags, "flags", KSTAT_DATA_UINT32);
1017 	kstat_named_init(&st->st_nbytes, "nbytes", KSTAT_DATA_UINT32);
1018 	kstat_named_init(&st->st_framesz, "framesz", KSTAT_DATA_UINT32);
1019 	kstat_named_init(&st->st_hidx, "hidx", KSTAT_DATA_UINT32);
1020 	kstat_named_init(&st->st_tidx, "tidx", KSTAT_DATA_UINT32);
1021 	kstat_named_init(&st->st_format, "format", KSTAT_DATA_UINT32);
1022 	kstat_named_init(&st->st_nchan, "channels", KSTAT_DATA_UINT32);
1023 	kstat_named_init(&st->st_rate, "rate", KSTAT_DATA_UINT32);
1024 	kstat_named_init(&st->st_errors, "errors", KSTAT_DATA_UINT32);
1025 	kstat_named_init(&st->st_engine_overruns, "engine_overruns",
1026 	    KSTAT_DATA_UINT32);
1027 	kstat_named_init(&st->st_engine_underruns, "engine_underruns",
1028 	    KSTAT_DATA_UINT32);
1029 	kstat_named_init(&st->st_stream_overruns, "stream_overruns",
1030 	    KSTAT_DATA_UINT32);
1031 	kstat_named_init(&st->st_stream_underruns, "stream_underruns",
1032 	    KSTAT_DATA_UINT32);
1033 	kstat_named_init(&st->st_playahead, "playahead", KSTAT_DATA_UINT32);
1034 	kstat_named_init(&st->st_suspended, "suspended", KSTAT_DATA_UINT32);
1035 	kstat_named_init(&st->st_failed, "failed", KSTAT_DATA_UINT32);
1036 	kstat_install(e->e_ksp);
1037 }
1038 
1039 void
1040 audio_dev_add_engine(audio_dev_t *d, audio_engine_t *e)
1041 {
1042 	mutex_enter(&d->d_lock);
1043 
1044 	e->e_num = d->d_engno++;
1045 
1046 	auimpl_engine_ksinit(d, e);
1047 
1048 	/* check for duplex */
1049 	if ((e->e_flags & ENGINE_OUTPUT_CAP) && (d->d_flags & DEV_INPUT_CAP)) {
1050 		d->d_flags |= DEV_DUPLEX_CAP;
1051 	}
1052 	if ((e->e_flags & ENGINE_INPUT_CAP) && (d->d_flags & DEV_OUTPUT_CAP)) {
1053 		d->d_flags |= DEV_DUPLEX_CAP;
1054 	}
1055 	/* add in the direction caps -- must be done after duplex above */
1056 	if (e->e_flags & ENGINE_OUTPUT_CAP) {
1057 		d->d_flags |= DEV_OUTPUT_CAP;
1058 	}
1059 	if (e->e_flags & ENGINE_INPUT_CAP) {
1060 		d->d_flags |= DEV_INPUT_CAP;
1061 	}
1062 
1063 	list_insert_tail(&d->d_engines, e);
1064 	e->e_dev = d;
1065 	mutex_exit(&d->d_lock);
1066 }
1067 
1068 void
1069 audio_dev_remove_engine(audio_dev_t *d, audio_engine_t *e)
1070 {
1071 	mutex_enter(&d->d_lock);
1072 	list_remove(&d->d_engines, e);
1073 	e->e_dev = NULL;
1074 	if (e->e_ksp)
1075 		kstat_delete(e->e_ksp);
1076 	e->e_ksp = NULL;
1077 	mutex_exit(&d->d_lock);
1078 }
1079 
1080 /*
1081  * Change the number.
1082  */
1083 void
1084 auclnt_set_dev_number(audio_dev_t *d, int num)
1085 {
1086 	list_t		*l = &auimpl_devs_by_number;
1087 	audio_dev_t	*srch;
1088 
1089 	/* reorder our list */
1090 	rw_enter(&auimpl_dev_lock, RW_WRITER);
1091 	d->d_number = num;
1092 	list_remove(l, d);
1093 	for (srch = list_head(l); srch; srch = list_next(l, srch)) {
1094 		if (srch->d_number >= d->d_number) {
1095 			break;
1096 		}
1097 	}
1098 	list_insert_before(l, srch, d);
1099 
1100 	rw_exit(&auimpl_dev_lock);
1101 }
1102 
1103 void
1104 auclnt_walk_devs(int (*walker)(audio_dev_t *, void *), void *arg)
1105 {
1106 	audio_dev_t	*d;
1107 	boolean_t	cont;
1108 	list_t		*l;
1109 
1110 	l = &auimpl_devs_by_index;
1111 	rw_enter(&auimpl_dev_lock, RW_READER);
1112 	for (d = list_head(l); d; d = list_next(l, d)) {
1113 		cont = walker(d, arg);
1114 		if (cont == AUDIO_WALK_STOP)
1115 			break;
1116 	}
1117 	rw_exit(&auimpl_dev_lock);
1118 }
1119 
1120 void
1121 auclnt_walk_devs_by_number(int (*walker)(audio_dev_t *, void *), void *arg)
1122 {
1123 	audio_dev_t	*d;
1124 	boolean_t	cont;
1125 	list_t		*l;
1126 
1127 	l = &auimpl_devs_by_number;
1128 	rw_enter(&auimpl_dev_lock, RW_READER);
1129 	for (d = list_head(l); d; d = list_next(l, d)) {
1130 		cont = walker(d, arg);
1131 		if (cont == AUDIO_WALK_STOP)
1132 			break;
1133 	}
1134 	rw_exit(&auimpl_dev_lock);
1135 }
1136 
1137 void
1138 auclnt_dev_walk_engines(audio_dev_t *d,
1139     int (*walker)(audio_engine_t *, void *),
1140     void *arg)
1141 {
1142 	audio_engine_t *e;
1143 	list_t *l = &d->d_engines;
1144 
1145 	mutex_enter(&d->d_lock);
1146 	for (e = list_head(l); e != NULL; e = list_next(l, e)) {
1147 		if (walker(e, arg) == AUDIO_WALK_STOP) {
1148 			break;
1149 		}
1150 	}
1151 	mutex_exit(&d->d_lock);
1152 }
1153 
1154 int
1155 auclnt_engine_get_format(audio_engine_t *e)
1156 {
1157 	return (ENG_FORMAT(e));
1158 }
1159 
1160 int
1161 auclnt_engine_get_channels(audio_engine_t *e)
1162 {
1163 	return (ENG_CHANNELS(e));
1164 }
1165 
1166 int
1167 auclnt_engine_get_rate(audio_engine_t *e)
1168 {
1169 	return (ENG_RATE(e));
1170 }
1171 
1172 uint_t
1173 auclnt_engine_get_capab(audio_engine_t *e)
1174 {
1175 	uint_t capab = 0;
1176 
1177 	if (e->e_flags & ENGINE_INPUT_CAP) {
1178 		capab |= AUDIO_CLIENT_CAP_RECORD;
1179 	}
1180 	if (e->e_flags & ENGINE_OUTPUT_CAP) {
1181 		capab |= AUDIO_CLIENT_CAP_PLAY;
1182 	}
1183 	return (capab);
1184 }
1185 
1186 /*
1187  * This function suspends an engine.  The intent is to pause the
1188  * engine temporarily so that it does not underrun while user threads
1189  * are suspended.  The driver is still responsible for actually doing
1190  * the driver suspend work -- all this does is put the engine in a
1191  * paused state.  It does not prevent, for example, threads from
1192  * accessing the hardware.
1193  *
1194  * A properly implemented driver won't even be aware of the existence
1195  * of this routine -- the driver will just handle the suspend &
1196  * resume.  At the point of suspend & resume, the driver will see that
1197  * the engines are not running (as if all threads had "paused" it).
1198  *
1199  * Failure to execute either of the routines below is not critical,
1200  * but will probably lead to underruns and overflows as the kernel
1201  * driver gets resumed well in advance of the time when user threads
1202  * are ready to start operation.
1203  */
1204 static void
1205 auimpl_engine_suspend(audio_engine_t *e)
1206 {
1207 	ASSERT(mutex_owned(&e->e_lock));
1208 
1209 	if (e->e_failed || e->e_suspended) {
1210 		e->e_suspended = B_TRUE;
1211 		return;
1212 	}
1213 	e->e_suspended = B_TRUE;
1214 	if (e->e_flags & ENGINE_INPUT) {
1215 		e->e_head = ENG_COUNT(e);
1216 		ENG_STOP(e);
1217 	}
1218 	if (e->e_flags & ENGINE_OUTPUT) {
1219 		e->e_tail = ENG_COUNT(e);
1220 		ENG_STOP(e);
1221 	}
1222 }
1223 
1224 static void
1225 auimpl_engine_resume(audio_engine_t *e)
1226 {
1227 	ASSERT(mutex_owned(&e->e_lock));
1228 	ASSERT(e->e_suspended);
1229 
1230 	if (e->e_failed) {
1231 		/* No longer suspended, but still failed! */
1232 		e->e_suspended = B_FALSE;
1233 		return;
1234 	}
1235 
1236 	if (e->e_flags & (ENGINE_INPUT | ENGINE_OUTPUT)) {
1237 
1238 		auimpl_engine_reset(e);
1239 
1240 		if (e->e_flags & ENGINE_OUTPUT) {
1241 			auimpl_output_preload(e);
1242 		}
1243 
1244 		e->e_need_start = B_TRUE;
1245 	}
1246 	e->e_suspended = B_FALSE;
1247 	cv_broadcast(&e->e_cv);
1248 }
1249 
1250 static int
1251 auimpl_dev_suspend(audio_dev_t *d, void *dontcare)
1252 {
1253 	list_t		*l;
1254 	audio_engine_t	*e;
1255 
1256 	_NOTE(ARGUNUSED(dontcare));
1257 
1258 	mutex_enter(&d->d_lock);
1259 	mutex_enter(&d->d_ctrl_lock);
1260 	if (d->d_suspended) {
1261 		d->d_suspended++;
1262 		mutex_exit(&d->d_ctrl_lock);
1263 		mutex_exit(&d->d_lock);
1264 		return (AUDIO_WALK_CONTINUE);
1265 	}
1266 
1267 	d->d_suspended++;
1268 
1269 	(void) auimpl_save_controls(d);
1270 	mutex_exit(&d->d_ctrl_lock);
1271 
1272 	l = &d->d_engines;
1273 	for (e = list_head(l); e != NULL; e = list_next(l, e)) {
1274 		mutex_enter(&e->e_lock);
1275 		auimpl_engine_suspend(e);
1276 		mutex_exit(&e->e_lock);
1277 	}
1278 	mutex_exit(&d->d_lock);
1279 
1280 	return (AUDIO_WALK_CONTINUE);
1281 }
1282 
1283 static int
1284 auimpl_dev_resume(audio_dev_t *d, void *dontcare)
1285 {
1286 	list_t		*l;
1287 	audio_engine_t	*e;
1288 
1289 	_NOTE(ARGUNUSED(dontcare));
1290 
1291 	mutex_enter(&d->d_lock);
1292 	mutex_enter(&d->d_ctrl_lock);
1293 
1294 	ASSERT(d->d_suspended);
1295 	d->d_suspended--;
1296 	if (d->d_suspended) {
1297 		mutex_exit(&d->d_ctrl_lock);
1298 		mutex_exit(&d->d_lock);
1299 		return (AUDIO_WALK_CONTINUE);
1300 	}
1301 
1302 	(void) auimpl_restore_controls(d);
1303 	cv_broadcast(&d->d_ctrl_cv);
1304 	mutex_exit(&d->d_ctrl_lock);
1305 
1306 	l = &d->d_engines;
1307 	for (e = list_head(l); e != NULL; e = list_next(l, e)) {
1308 		mutex_enter(&e->e_lock);
1309 		auimpl_engine_resume(e);
1310 		mutex_exit(&e->e_lock);
1311 	}
1312 	mutex_exit(&d->d_lock);
1313 
1314 	return (AUDIO_WALK_CONTINUE);
1315 }
1316 
1317 boolean_t
1318 auimpl_cpr(void *arg, int code)
1319 {
1320 	_NOTE(ARGUNUSED(arg));
1321 
1322 	switch (code) {
1323 	case CB_CODE_CPR_CHKPT:
1324 		auclnt_walk_devs(auimpl_dev_suspend, NULL);
1325 		return (B_TRUE);
1326 
1327 	case CB_CODE_CPR_RESUME:
1328 		auclnt_walk_devs(auimpl_dev_resume, NULL);
1329 		return (B_TRUE);
1330 
1331 	default:
1332 		return (B_FALSE);
1333 	}
1334 }
1335 
1336 void
1337 audio_dev_suspend(audio_dev_t *d)
1338 {
1339 	(void) auimpl_dev_suspend(d, NULL);
1340 }
1341 
1342 void
1343 audio_dev_resume(audio_dev_t *d)
1344 {
1345 	(void) auimpl_dev_resume(d, NULL);
1346 }
1347 
1348 static callb_id_t	auimpl_cpr_id = 0;
1349 
1350 void
1351 auimpl_dev_init(void)
1352 {
1353 	rw_init(&auimpl_dev_lock, NULL, RW_DRIVER, NULL);
1354 	list_create(&auimpl_devs_by_index, sizeof (struct audio_dev),
1355 	    offsetof(struct audio_dev, d_by_index));
1356 	list_create(&auimpl_devs_by_number, sizeof (struct audio_dev),
1357 	    offsetof(struct audio_dev, d_by_number));
1358 
1359 	/*
1360 	 * We "borrow" the CB_CL_CPR_PM class, which gets executed at
1361 	 * about the right time for us.  It would be nice to have a
1362 	 * new CB_CL_CPR_AUDIO class, but it isn't critical at this
1363 	 * point.
1364 	 *
1365 	 * Note that we don't care about our thread id.
1366 	 */
1367 	auimpl_cpr_id = callb_add(auimpl_cpr, NULL, CB_CL_CPR_PM, "audio_cpr");
1368 }
1369 
1370 void
1371 auimpl_dev_fini(void)
1372 {
1373 	(void) callb_delete(auimpl_cpr_id);
1374 	list_destroy(&auimpl_devs_by_index);
1375 	list_destroy(&auimpl_devs_by_number);
1376 	rw_destroy(&auimpl_dev_lock);
1377 }
1378 
1379 void
1380 audio_engine_set_private(audio_engine_t *eng, void *prv)
1381 {
1382 	eng->e_private = prv;
1383 }
1384 
1385 void *
1386 audio_engine_get_private(audio_engine_t *eng)
1387 {
1388 	return (eng->e_private);
1389 }
1390 
1391 void
1392 audio_dump_bytes(const uint8_t *w, int dcount)
1393 {
1394 	char		line[64];
1395 	char		*s;
1396 	int		i;
1397 	const int	wrap = 16;
1398 
1399 	s = line;
1400 	line[0] = 0;
1401 
1402 	cmn_err(CE_NOTE, "starting @ %p", (void *)w);
1403 	for (i = 0; i < dcount; i++) {
1404 
1405 		(void) sprintf(s, " %02x", *w);
1406 		s += strlen(s);
1407 		w++;
1408 
1409 		if ((i % wrap) == (wrap - 1)) {
1410 			cmn_err(CE_NOTE, "%08x:%s", i - (wrap - 1), line);
1411 			line[0] = 0;
1412 			s = line;
1413 		}
1414 	}
1415 
1416 	if ((i % wrap) != 0) {
1417 		cmn_err(CE_NOTE, "%08x:%s", i - (i % wrap), line);
1418 	}
1419 }
1420 
1421 void
1422 audio_dump_words(const uint16_t *w, int dcount)
1423 {
1424 	char		line[64];
1425 	char		*s;
1426 	int		i;
1427 	const int	wrap = 8;
1428 
1429 	s = line;
1430 	line[0] = 0;
1431 
1432 	cmn_err(CE_NOTE, "starting @ %p", (void *)w);
1433 	for (i = 0; i < dcount; i++) {
1434 
1435 		(void) sprintf(s, " %04x", *w);
1436 		s += strlen(s);
1437 		w++;
1438 
1439 		if ((i % wrap) == (wrap - 1)) {
1440 			cmn_err(CE_NOTE, "%08x:%s", i - (wrap - 1), line);
1441 			line[0] = 0;
1442 			s = line;
1443 		}
1444 	}
1445 
1446 	if ((i % wrap) != 0) {
1447 		cmn_err(CE_NOTE, "%08x:%s", i - (i % wrap), line);
1448 	}
1449 }
1450 
1451 void
1452 audio_dump_dwords(const uint32_t *w, int dcount)
1453 {
1454 	char		line[128];
1455 	char		*s;
1456 	int		i;
1457 	const int	wrap = 4;
1458 
1459 	s = line;
1460 	line[0] = 0;
1461 
1462 	cmn_err(CE_NOTE, "starting @ %p", (void *)w);
1463 	for (i = 0; i < dcount; i++) {
1464 
1465 		(void) sprintf(s, " %08x", *w);
1466 		s += strlen(s);
1467 		w++;
1468 
1469 		if ((i % wrap) == (wrap - 1)) {
1470 			cmn_err(CE_NOTE, "%08x:%s", i - (wrap - 1), line);
1471 			line[0] = 0;
1472 			s = line;
1473 		}
1474 	}
1475 
1476 	if ((i % wrap) != 0) {
1477 		cmn_err(CE_NOTE, "%08x:%s", i - (i % wrap), line);
1478 	}
1479 }
1480