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