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