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