1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org> 5 * Portions Copyright (c) Ryan Beasley <ryan.beasley@gmail.com> - GSoC 2006 6 * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org> 7 * Copyright (c) 1997 Luigi Rizzo 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #ifdef HAVE_KERNEL_OPTION_HEADERS 33 #include "opt_snd.h" 34 #endif 35 36 #include <dev/sound/pcm/sound.h> 37 #include <dev/sound/pcm/ac97.h> 38 #include <dev/sound/pcm/vchan.h> 39 #include <dev/sound/pcm/dsp.h> 40 #include <dev/sound/version.h> 41 #include <sys/limits.h> 42 #include <sys/sysctl.h> 43 44 #include "feeder_if.h" 45 46 devclass_t pcm_devclass; 47 48 int pcm_veto_load = 1; 49 50 int snd_unit = -1; 51 52 static int snd_unit_auto = -1; 53 SYSCTL_INT(_hw_snd, OID_AUTO, default_auto, CTLFLAG_RWTUN, 54 &snd_unit_auto, 0, "assign default unit to a newly attached device"); 55 56 int snd_maxautovchans = 16; 57 58 SYSCTL_NODE(_hw, OID_AUTO, snd, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 59 "Sound driver"); 60 61 static void pcm_sysinit(device_t); 62 63 /* 64 * XXX I've had enough with people not telling proper version/arch 65 * while reporting problems, not after 387397913213th questions/requests. 66 */ 67 static char snd_driver_version[] = 68 __XSTRING(SND_DRV_VERSION)"/"MACHINE_ARCH; 69 SYSCTL_STRING(_hw_snd, OID_AUTO, version, CTLFLAG_RD, &snd_driver_version, 70 0, "driver version/arch"); 71 72 /** 73 * @brief Unit number allocator for syncgroup IDs 74 */ 75 struct unrhdr *pcmsg_unrhdr = NULL; 76 77 void * 78 snd_mtxcreate(const char *desc, const char *type) 79 { 80 struct mtx *m; 81 82 m = malloc(sizeof(*m), M_DEVBUF, M_WAITOK | M_ZERO); 83 mtx_init(m, desc, type, MTX_DEF); 84 return m; 85 } 86 87 void 88 snd_mtxfree(void *m) 89 { 90 struct mtx *mtx = m; 91 92 mtx_destroy(mtx); 93 free(mtx, M_DEVBUF); 94 } 95 96 void 97 snd_mtxassert(void *m) 98 { 99 #ifdef INVARIANTS 100 struct mtx *mtx = m; 101 102 mtx_assert(mtx, MA_OWNED); 103 #endif 104 } 105 106 int 107 snd_setup_intr(device_t dev, struct resource *res, int flags, driver_intr_t hand, void *param, void **cookiep) 108 { 109 struct snddev_info *d; 110 111 flags &= INTR_MPSAFE; 112 flags |= INTR_TYPE_AV; 113 d = device_get_softc(dev); 114 if (d != NULL && (flags & INTR_MPSAFE)) 115 d->flags |= SD_F_MPSAFE; 116 117 return bus_setup_intr(dev, res, flags, NULL, hand, param, cookiep); 118 } 119 120 int 121 pcm_setvchans(struct snddev_info *d, int direction, int newcnt, int num) 122 { 123 struct pcm_channel *c, *ch, *nch; 124 struct pcmchan_caps *caps; 125 int i, err, vcnt; 126 127 PCM_BUSYASSERT(d); 128 129 if ((direction == PCMDIR_PLAY && d->playcount < 1) || 130 (direction == PCMDIR_REC && d->reccount < 1)) 131 return (ENODEV); 132 133 if (!(d->flags & SD_F_AUTOVCHAN)) 134 return (EINVAL); 135 136 if (newcnt < 0 || newcnt > SND_MAXVCHANS) 137 return (E2BIG); 138 139 if (direction == PCMDIR_PLAY) 140 vcnt = d->pvchancount; 141 else if (direction == PCMDIR_REC) 142 vcnt = d->rvchancount; 143 else 144 return (EINVAL); 145 146 if (newcnt > vcnt) { 147 KASSERT(num == -1 || 148 (num >= 0 && num < SND_MAXVCHANS && (newcnt - 1) == vcnt), 149 ("bogus vchan_create() request num=%d newcnt=%d vcnt=%d", 150 num, newcnt, vcnt)); 151 /* add new vchans - find a parent channel first */ 152 ch = NULL; 153 CHN_FOREACH(c, d, channels.pcm) { 154 CHN_LOCK(c); 155 if (c->direction == direction && 156 ((c->flags & CHN_F_HAS_VCHAN) || (vcnt == 0 && 157 c->refcount < 1 && 158 !(c->flags & (CHN_F_BUSY | CHN_F_VIRTUAL))))) { 159 /* 160 * Reuse hw channel with vchans already 161 * created. 162 */ 163 if (c->flags & CHN_F_HAS_VCHAN) { 164 ch = c; 165 break; 166 } 167 /* 168 * No vchans ever created, look for 169 * channels with supported formats. 170 */ 171 caps = chn_getcaps(c); 172 if (caps == NULL) { 173 CHN_UNLOCK(c); 174 continue; 175 } 176 for (i = 0; caps->fmtlist[i] != 0; i++) { 177 if (caps->fmtlist[i] & AFMT_CONVERTIBLE) 178 break; 179 } 180 if (caps->fmtlist[i] != 0) { 181 ch = c; 182 break; 183 } 184 } 185 CHN_UNLOCK(c); 186 } 187 if (ch == NULL) 188 return (EBUSY); 189 ch->flags |= CHN_F_BUSY; 190 err = 0; 191 while (err == 0 && newcnt > vcnt) { 192 err = vchan_create(ch, num); 193 if (err == 0) 194 vcnt++; 195 else if (err == E2BIG && newcnt > vcnt) 196 device_printf(d->dev, 197 "%s: err=%d Maximum channel reached.\n", 198 __func__, err); 199 } 200 if (vcnt == 0) 201 ch->flags &= ~CHN_F_BUSY; 202 CHN_UNLOCK(ch); 203 if (err != 0) 204 return (err); 205 } else if (newcnt < vcnt) { 206 KASSERT(num == -1, 207 ("bogus vchan_destroy() request num=%d", num)); 208 CHN_FOREACH(c, d, channels.pcm) { 209 CHN_LOCK(c); 210 if (c->direction != direction || 211 CHN_EMPTY(c, children) || 212 !(c->flags & CHN_F_HAS_VCHAN)) { 213 CHN_UNLOCK(c); 214 continue; 215 } 216 CHN_FOREACH_SAFE(ch, c, nch, children) { 217 CHN_LOCK(ch); 218 if (vcnt == 1 && c->refcount > 0) { 219 CHN_UNLOCK(ch); 220 break; 221 } 222 if (!(ch->flags & CHN_F_BUSY) && 223 ch->refcount < 1) { 224 err = vchan_destroy(ch); 225 if (err == 0) 226 vcnt--; 227 } else 228 CHN_UNLOCK(ch); 229 if (vcnt == newcnt) 230 break; 231 } 232 CHN_UNLOCK(c); 233 break; 234 } 235 } 236 237 return (0); 238 } 239 240 /* return error status and a locked channel */ 241 int 242 pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction, 243 pid_t pid, char *comm, int devunit) 244 { 245 struct pcm_channel *c; 246 int err, vchancount, vchan_num; 247 248 KASSERT(d != NULL && ch != NULL && (devunit == -1 || 249 !(devunit & ~(SND_U_MASK | SND_D_MASK | SND_C_MASK))) && 250 (direction == PCMDIR_PLAY || direction == PCMDIR_REC), 251 ("%s(): invalid d=%p ch=%p direction=%d pid=%d devunit=%d", 252 __func__, d, ch, direction, pid, devunit)); 253 PCM_BUSYASSERT(d); 254 255 /* Double check again. */ 256 if (devunit != -1) { 257 switch (snd_unit2d(devunit)) { 258 case SND_DEV_DSPHW_PLAY: 259 case SND_DEV_DSPHW_VPLAY: 260 if (direction != PCMDIR_PLAY) 261 return (ENOTSUP); 262 break; 263 case SND_DEV_DSPHW_REC: 264 case SND_DEV_DSPHW_VREC: 265 if (direction != PCMDIR_REC) 266 return (ENOTSUP); 267 break; 268 default: 269 if (!(direction == PCMDIR_PLAY || 270 direction == PCMDIR_REC)) 271 return (ENOTSUP); 272 break; 273 } 274 } 275 276 *ch = NULL; 277 vchan_num = 0; 278 vchancount = (direction == PCMDIR_PLAY) ? d->pvchancount : 279 d->rvchancount; 280 281 retry_chnalloc: 282 err = ENOTSUP; 283 /* scan for a free channel */ 284 CHN_FOREACH(c, d, channels.pcm) { 285 CHN_LOCK(c); 286 if (devunit == -1 && c->direction == direction && 287 (c->flags & CHN_F_VIRTUAL)) { 288 if (vchancount < snd_maxautovchans && 289 vchan_num < CHN_CHAN(c)) { 290 CHN_UNLOCK(c); 291 goto vchan_alloc; 292 } 293 vchan_num++; 294 } 295 if (c->direction == direction && !(c->flags & CHN_F_BUSY) && 296 (devunit == -1 || devunit == -2 || c->unit == devunit)) { 297 c->flags |= CHN_F_BUSY; 298 c->pid = pid; 299 strlcpy(c->comm, (comm != NULL) ? comm : 300 CHN_COMM_UNKNOWN, sizeof(c->comm)); 301 *ch = c; 302 return (0); 303 } else if (c->unit == devunit) { 304 if (c->direction != direction) 305 err = ENOTSUP; 306 else if (c->flags & CHN_F_BUSY) 307 err = EBUSY; 308 else 309 err = EINVAL; 310 CHN_UNLOCK(c); 311 return (err); 312 } else if ((devunit == -1 || devunit == -2) && 313 c->direction == direction && (c->flags & CHN_F_BUSY)) 314 err = EBUSY; 315 CHN_UNLOCK(c); 316 } 317 318 if (devunit == -2) 319 return (err); 320 321 vchan_alloc: 322 /* no channel available */ 323 if (devunit == -1 || snd_unit2d(devunit) == SND_DEV_DSPHW_VPLAY || 324 snd_unit2d(devunit) == SND_DEV_DSPHW_VREC) { 325 if (!(vchancount > 0 && vchancount < snd_maxautovchans) && 326 (devunit == -1 || snd_unit2c(devunit) < snd_maxautovchans)) 327 return (err); 328 err = pcm_setvchans(d, direction, vchancount + 1, 329 (devunit == -1) ? -1 : snd_unit2c(devunit)); 330 if (err == 0) { 331 if (devunit == -1) 332 devunit = -2; 333 goto retry_chnalloc; 334 } 335 } 336 337 return (err); 338 } 339 340 /* release a locked channel and unlock it */ 341 int 342 pcm_chnrelease(struct pcm_channel *c) 343 { 344 PCM_BUSYASSERT(c->parentsnddev); 345 CHN_LOCKASSERT(c); 346 347 c->flags &= ~CHN_F_BUSY; 348 c->pid = -1; 349 strlcpy(c->comm, CHN_COMM_UNUSED, sizeof(c->comm)); 350 CHN_UNLOCK(c); 351 352 return (0); 353 } 354 355 int 356 pcm_chnref(struct pcm_channel *c, int ref) 357 { 358 PCM_BUSYASSERT(c->parentsnddev); 359 CHN_LOCKASSERT(c); 360 361 c->refcount += ref; 362 363 return (c->refcount); 364 } 365 366 static void 367 pcm_setmaxautovchans(struct snddev_info *d, int num) 368 { 369 PCM_BUSYASSERT(d); 370 371 if (num < 0) 372 return; 373 374 if (num >= 0 && d->pvchancount > num) 375 (void)pcm_setvchans(d, PCMDIR_PLAY, num, -1); 376 else if (num > 0 && d->pvchancount == 0) 377 (void)pcm_setvchans(d, PCMDIR_PLAY, 1, -1); 378 379 if (num >= 0 && d->rvchancount > num) 380 (void)pcm_setvchans(d, PCMDIR_REC, num, -1); 381 else if (num > 0 && d->rvchancount == 0) 382 (void)pcm_setvchans(d, PCMDIR_REC, 1, -1); 383 } 384 385 static int 386 sysctl_hw_snd_default_unit(SYSCTL_HANDLER_ARGS) 387 { 388 struct snddev_info *d; 389 int error, unit; 390 391 unit = snd_unit; 392 error = sysctl_handle_int(oidp, &unit, 0, req); 393 if (error == 0 && req->newptr != NULL) { 394 d = devclass_get_softc(pcm_devclass, unit); 395 if (!PCM_REGISTERED(d) || CHN_EMPTY(d, channels.pcm)) 396 return EINVAL; 397 snd_unit = unit; 398 snd_unit_auto = 0; 399 } 400 return (error); 401 } 402 /* XXX: do we need a way to let the user change the default unit? */ 403 SYSCTL_PROC(_hw_snd, OID_AUTO, default_unit, 404 CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_ANYBODY | CTLFLAG_NEEDGIANT, 0, 405 sizeof(int), sysctl_hw_snd_default_unit, "I", 406 "default sound device"); 407 408 static int 409 sysctl_hw_snd_maxautovchans(SYSCTL_HANDLER_ARGS) 410 { 411 struct snddev_info *d; 412 int i, v, error; 413 414 v = snd_maxautovchans; 415 error = sysctl_handle_int(oidp, &v, 0, req); 416 if (error == 0 && req->newptr != NULL) { 417 if (v < 0) 418 v = 0; 419 if (v > SND_MAXVCHANS) 420 v = SND_MAXVCHANS; 421 snd_maxautovchans = v; 422 for (i = 0; pcm_devclass != NULL && 423 i < devclass_get_maxunit(pcm_devclass); i++) { 424 d = devclass_get_softc(pcm_devclass, i); 425 if (!PCM_REGISTERED(d)) 426 continue; 427 PCM_ACQUIRE_QUICK(d); 428 pcm_setmaxautovchans(d, v); 429 PCM_RELEASE_QUICK(d); 430 } 431 } 432 return (error); 433 } 434 SYSCTL_PROC(_hw_snd, OID_AUTO, maxautovchans, 435 CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0, sizeof(int), 436 sysctl_hw_snd_maxautovchans, "I", 437 "maximum virtual channel"); 438 439 struct pcm_channel * 440 pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, int num, void *devinfo) 441 { 442 struct pcm_channel *ch; 443 int direction, err, rpnum, *pnum, max; 444 int udc, device, chan; 445 char *dirs, *devname, buf[CHN_NAMELEN]; 446 447 PCM_BUSYASSERT(d); 448 PCM_LOCKASSERT(d); 449 KASSERT(num >= -1, ("invalid num=%d", num)); 450 451 switch (dir) { 452 case PCMDIR_PLAY: 453 dirs = "play"; 454 direction = PCMDIR_PLAY; 455 pnum = &d->playcount; 456 device = SND_DEV_DSPHW_PLAY; 457 max = SND_MAXHWCHAN; 458 break; 459 case PCMDIR_PLAY_VIRTUAL: 460 dirs = "virtual"; 461 direction = PCMDIR_PLAY; 462 pnum = &d->pvchancount; 463 device = SND_DEV_DSPHW_VPLAY; 464 max = SND_MAXVCHANS; 465 break; 466 case PCMDIR_REC: 467 dirs = "record"; 468 direction = PCMDIR_REC; 469 pnum = &d->reccount; 470 device = SND_DEV_DSPHW_REC; 471 max = SND_MAXHWCHAN; 472 break; 473 case PCMDIR_REC_VIRTUAL: 474 dirs = "virtual"; 475 direction = PCMDIR_REC; 476 pnum = &d->rvchancount; 477 device = SND_DEV_DSPHW_VREC; 478 max = SND_MAXVCHANS; 479 break; 480 default: 481 return (NULL); 482 } 483 484 chan = (num == -1) ? 0 : num; 485 486 if (*pnum >= max || chan >= max) 487 return (NULL); 488 489 rpnum = 0; 490 491 CHN_FOREACH(ch, d, channels.pcm) { 492 if (CHN_DEV(ch) != device) 493 continue; 494 if (chan == CHN_CHAN(ch)) { 495 if (num != -1) { 496 device_printf(d->dev, 497 "channel num=%d allocated!\n", chan); 498 return (NULL); 499 } 500 chan++; 501 if (chan >= max) { 502 device_printf(d->dev, 503 "chan=%d > %d\n", chan, max); 504 return (NULL); 505 } 506 } 507 rpnum++; 508 } 509 510 if (*pnum != rpnum) { 511 device_printf(d->dev, 512 "%s(): WARNING: pnum screwed : dirs=%s pnum=%d rpnum=%d\n", 513 __func__, dirs, *pnum, rpnum); 514 return (NULL); 515 } 516 517 udc = snd_mkunit(device_get_unit(d->dev), device, chan); 518 devname = dsp_unit2name(buf, sizeof(buf), udc); 519 520 if (devname == NULL) { 521 device_printf(d->dev, 522 "Failed to query device name udc=0x%08x\n", udc); 523 return (NULL); 524 } 525 526 PCM_UNLOCK(d); 527 ch = malloc(sizeof(*ch), M_DEVBUF, M_WAITOK | M_ZERO); 528 ch->methods = kobj_create(cls, M_DEVBUF, M_WAITOK | M_ZERO); 529 ch->unit = udc; 530 ch->pid = -1; 531 strlcpy(ch->comm, CHN_COMM_UNUSED, sizeof(ch->comm)); 532 ch->parentsnddev = d; 533 ch->parentchannel = parent; 534 ch->dev = d->dev; 535 ch->trigger = PCMTRIG_STOP; 536 snprintf(ch->name, sizeof(ch->name), "%s:%s:%s", 537 device_get_nameunit(ch->dev), dirs, devname); 538 539 err = chn_init(ch, devinfo, dir, direction); 540 PCM_LOCK(d); 541 if (err) { 542 device_printf(d->dev, "chn_init(%s) failed: err = %d\n", 543 ch->name, err); 544 kobj_delete(ch->methods, M_DEVBUF); 545 free(ch, M_DEVBUF); 546 return (NULL); 547 } 548 549 return (ch); 550 } 551 552 int 553 pcm_chn_destroy(struct pcm_channel *ch) 554 { 555 struct snddev_info *d __diagused; 556 int err; 557 558 d = ch->parentsnddev; 559 PCM_BUSYASSERT(d); 560 561 err = chn_kill(ch); 562 if (err) { 563 device_printf(ch->dev, "chn_kill(%s) failed, err = %d\n", 564 ch->name, err); 565 return (err); 566 } 567 568 kobj_delete(ch->methods, M_DEVBUF); 569 free(ch, M_DEVBUF); 570 571 return (0); 572 } 573 574 int 575 pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch) 576 { 577 PCM_BUSYASSERT(d); 578 PCM_LOCKASSERT(d); 579 KASSERT(ch != NULL && (ch->direction == PCMDIR_PLAY || 580 ch->direction == PCMDIR_REC), ("Invalid pcm channel")); 581 582 CHN_INSERT_SORT_ASCEND(d, ch, channels.pcm); 583 584 switch (CHN_DEV(ch)) { 585 case SND_DEV_DSPHW_PLAY: 586 d->playcount++; 587 break; 588 case SND_DEV_DSPHW_VPLAY: 589 d->pvchancount++; 590 break; 591 case SND_DEV_DSPHW_REC: 592 d->reccount++; 593 break; 594 case SND_DEV_DSPHW_VREC: 595 d->rvchancount++; 596 break; 597 default: 598 break; 599 } 600 601 d->devcount++; 602 603 return (0); 604 } 605 606 int 607 pcm_chn_remove(struct snddev_info *d, struct pcm_channel *ch) 608 { 609 struct pcm_channel *tmp; 610 611 PCM_BUSYASSERT(d); 612 PCM_LOCKASSERT(d); 613 614 tmp = NULL; 615 616 CHN_FOREACH(tmp, d, channels.pcm) { 617 if (tmp == ch) 618 break; 619 } 620 621 if (tmp != ch) 622 return (EINVAL); 623 624 CHN_REMOVE(d, ch, channels.pcm); 625 626 switch (CHN_DEV(ch)) { 627 case SND_DEV_DSPHW_PLAY: 628 d->playcount--; 629 break; 630 case SND_DEV_DSPHW_VPLAY: 631 d->pvchancount--; 632 break; 633 case SND_DEV_DSPHW_REC: 634 d->reccount--; 635 break; 636 case SND_DEV_DSPHW_VREC: 637 d->rvchancount--; 638 break; 639 default: 640 break; 641 } 642 643 d->devcount--; 644 645 return (0); 646 } 647 648 int 649 pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo) 650 { 651 struct snddev_info *d = device_get_softc(dev); 652 struct pcm_channel *ch; 653 int err; 654 655 PCM_BUSYASSERT(d); 656 657 PCM_LOCK(d); 658 ch = pcm_chn_create(d, NULL, cls, dir, -1, devinfo); 659 if (!ch) { 660 device_printf(d->dev, "pcm_chn_create(%s, %d, %p) failed\n", 661 cls->name, dir, devinfo); 662 PCM_UNLOCK(d); 663 return (ENODEV); 664 } 665 666 err = pcm_chn_add(d, ch); 667 PCM_UNLOCK(d); 668 if (err) { 669 device_printf(d->dev, "pcm_chn_add(%s) failed, err=%d\n", 670 ch->name, err); 671 pcm_chn_destroy(ch); 672 } 673 674 return (err); 675 } 676 677 static int 678 pcm_killchan(device_t dev) 679 { 680 struct snddev_info *d = device_get_softc(dev); 681 struct pcm_channel *ch; 682 int error; 683 684 PCM_BUSYASSERT(d); 685 686 ch = CHN_FIRST(d, channels.pcm); 687 688 PCM_LOCK(d); 689 error = pcm_chn_remove(d, ch); 690 PCM_UNLOCK(d); 691 if (error) 692 return (error); 693 return (pcm_chn_destroy(ch)); 694 } 695 696 static int 697 pcm_best_unit(int old) 698 { 699 struct snddev_info *d; 700 int i, best, bestprio, prio; 701 702 best = -1; 703 bestprio = -100; 704 for (i = 0; pcm_devclass != NULL && 705 i < devclass_get_maxunit(pcm_devclass); i++) { 706 d = devclass_get_softc(pcm_devclass, i); 707 if (!PCM_REGISTERED(d)) 708 continue; 709 prio = 0; 710 if (d->playcount == 0) 711 prio -= 10; 712 if (d->reccount == 0) 713 prio -= 2; 714 if (prio > bestprio || (prio == bestprio && i == old)) { 715 best = i; 716 bestprio = prio; 717 } 718 } 719 return (best); 720 } 721 722 int 723 pcm_setstatus(device_t dev, char *str) 724 { 725 struct snddev_info *d = device_get_softc(dev); 726 727 /* should only be called once */ 728 if (d->flags & SD_F_REGISTERED) 729 return (EINVAL); 730 731 PCM_BUSYASSERT(d); 732 733 if (d->playcount == 0 || d->reccount == 0) 734 d->flags |= SD_F_SIMPLEX; 735 736 if (d->playcount > 0 || d->reccount > 0) 737 d->flags |= SD_F_AUTOVCHAN; 738 739 pcm_setmaxautovchans(d, snd_maxautovchans); 740 741 strlcpy(d->status, str, SND_STATUSLEN); 742 743 PCM_LOCK(d); 744 745 /* Done, we're ready.. */ 746 d->flags |= SD_F_REGISTERED; 747 748 PCM_RELEASE(d); 749 750 PCM_UNLOCK(d); 751 752 /* 753 * Create all sysctls once SD_F_REGISTERED is set else 754 * tunable sysctls won't work: 755 */ 756 pcm_sysinit(dev); 757 758 if (snd_unit_auto < 0) 759 snd_unit_auto = (snd_unit < 0) ? 1 : 0; 760 if (snd_unit < 0 || snd_unit_auto > 1) 761 snd_unit = device_get_unit(dev); 762 else if (snd_unit_auto == 1) 763 snd_unit = pcm_best_unit(snd_unit); 764 765 return (0); 766 } 767 768 uint32_t 769 pcm_getflags(device_t dev) 770 { 771 struct snddev_info *d = device_get_softc(dev); 772 773 return d->flags; 774 } 775 776 void 777 pcm_setflags(device_t dev, uint32_t val) 778 { 779 struct snddev_info *d = device_get_softc(dev); 780 781 d->flags = val; 782 } 783 784 void * 785 pcm_getdevinfo(device_t dev) 786 { 787 struct snddev_info *d = device_get_softc(dev); 788 789 return d->devinfo; 790 } 791 792 unsigned int 793 pcm_getbuffersize(device_t dev, unsigned int minbufsz, unsigned int deflt, unsigned int maxbufsz) 794 { 795 struct snddev_info *d = device_get_softc(dev); 796 int sz, x; 797 798 sz = 0; 799 if (resource_int_value(device_get_name(dev), device_get_unit(dev), "buffersize", &sz) == 0) { 800 x = sz; 801 RANGE(sz, minbufsz, maxbufsz); 802 if (x != sz) 803 device_printf(dev, "'buffersize=%d' hint is out of range (%d-%d), using %d\n", x, minbufsz, maxbufsz, sz); 804 x = minbufsz; 805 while (x < sz) 806 x <<= 1; 807 if (x > sz) 808 x >>= 1; 809 if (x != sz) { 810 device_printf(dev, "'buffersize=%d' hint is not a power of 2, using %d\n", sz, x); 811 sz = x; 812 } 813 } else { 814 sz = deflt; 815 } 816 817 d->bufsz = sz; 818 819 return sz; 820 } 821 822 static int 823 sysctl_dev_pcm_bitperfect(SYSCTL_HANDLER_ARGS) 824 { 825 struct snddev_info *d; 826 int err, val; 827 828 d = oidp->oid_arg1; 829 if (!PCM_REGISTERED(d)) 830 return (ENODEV); 831 832 PCM_LOCK(d); 833 PCM_WAIT(d); 834 val = (d->flags & SD_F_BITPERFECT) ? 1 : 0; 835 PCM_ACQUIRE(d); 836 PCM_UNLOCK(d); 837 838 err = sysctl_handle_int(oidp, &val, 0, req); 839 840 if (err == 0 && req->newptr != NULL) { 841 if (!(val == 0 || val == 1)) { 842 PCM_RELEASE_QUICK(d); 843 return (EINVAL); 844 } 845 846 PCM_LOCK(d); 847 848 d->flags &= ~SD_F_BITPERFECT; 849 d->flags |= (val != 0) ? SD_F_BITPERFECT : 0; 850 851 PCM_RELEASE(d); 852 PCM_UNLOCK(d); 853 } else 854 PCM_RELEASE_QUICK(d); 855 856 return (err); 857 } 858 859 static u_int8_t 860 pcm_mode_init(struct snddev_info *d) 861 { 862 u_int8_t mode = 0; 863 864 if (d->playcount > 0) 865 mode |= PCM_MODE_PLAY; 866 if (d->reccount > 0) 867 mode |= PCM_MODE_REC; 868 if (d->mixer_dev != NULL) 869 mode |= PCM_MODE_MIXER; 870 871 return (mode); 872 } 873 874 static void 875 pcm_sysinit(device_t dev) 876 { 877 struct snddev_info *d = device_get_softc(dev); 878 u_int8_t mode; 879 880 mode = pcm_mode_init(d); 881 882 /* XXX: a user should be able to set this with a control tool, the 883 sysadmin then needs min+max sysctls for this */ 884 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 885 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 886 OID_AUTO, "buffersize", CTLFLAG_RD, &d->bufsz, 0, "allocated buffer size"); 887 SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 888 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, 889 "bitperfect", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, d, 890 sizeof(d), sysctl_dev_pcm_bitperfect, "I", 891 "bit-perfect playback/recording (0=disable, 1=enable)"); 892 SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev), 893 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 894 OID_AUTO, "mode", CTLFLAG_RD, NULL, mode, 895 "mode (1=mixer, 2=play, 4=rec. The values are OR'ed if more than one" 896 "mode is supported)"); 897 if (d->flags & SD_F_AUTOVCHAN) 898 vchan_initsys(dev); 899 if (d->flags & SD_F_EQ) 900 feeder_eq_initsys(dev); 901 } 902 903 int 904 pcm_register(device_t dev, void *devinfo, int numplay, int numrec) 905 { 906 struct snddev_info *d; 907 int i; 908 909 if (pcm_veto_load) { 910 device_printf(dev, "disabled due to an error while initialising: %d\n", pcm_veto_load); 911 912 return EINVAL; 913 } 914 915 if (device_get_unit(dev) > PCMMAXUNIT) { 916 device_printf(dev, "PCMMAXUNIT reached : unit=%d > %d\n", 917 device_get_unit(dev), PCMMAXUNIT); 918 device_printf(dev, 919 "Use 'hw.snd.maxunit' tunable to raise the limit.\n"); 920 return ENODEV; 921 } 922 923 d = device_get_softc(dev); 924 d->dev = dev; 925 d->lock = snd_mtxcreate(device_get_nameunit(dev), "sound cdev"); 926 cv_init(&d->cv, device_get_nameunit(dev)); 927 PCM_ACQUIRE_QUICK(d); 928 #if 0 929 /* 930 * d->flags should be cleared by the allocator of the softc. 931 * We cannot clear this field here because several devices set 932 * this flag before calling pcm_register(). 933 */ 934 d->flags = 0; 935 #endif 936 i = 0; 937 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 938 "vpc", &i) != 0 || i != 0) 939 d->flags |= SD_F_VPC; 940 941 if (resource_int_value(device_get_name(dev), device_get_unit(dev), 942 "bitperfect", &i) == 0 && i != 0) 943 d->flags |= SD_F_BITPERFECT; 944 945 d->devinfo = devinfo; 946 d->devcount = 0; 947 d->reccount = 0; 948 d->playcount = 0; 949 d->pvchancount = 0; 950 d->rvchancount = 0; 951 d->pvchanrate = 0; 952 d->pvchanformat = 0; 953 d->rvchanrate = 0; 954 d->rvchanformat = 0; 955 956 CHN_INIT(d, channels.pcm); 957 CHN_INIT(d, channels.pcm.busy); 958 CHN_INIT(d, channels.pcm.opened); 959 960 /* XXX This is incorrect, but lets play along for now. */ 961 if ((numplay == 0 || numrec == 0) && numplay != numrec) 962 d->flags |= SD_F_SIMPLEX; 963 964 sysctl_ctx_init(&d->play_sysctl_ctx); 965 d->play_sysctl_tree = SYSCTL_ADD_NODE(&d->play_sysctl_ctx, 966 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "play", 967 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "playback channels node"); 968 sysctl_ctx_init(&d->rec_sysctl_ctx); 969 d->rec_sysctl_tree = SYSCTL_ADD_NODE(&d->rec_sysctl_ctx, 970 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "rec", 971 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "recording channels node"); 972 973 if (numplay > 0 || numrec > 0) 974 d->flags |= SD_F_AUTOVCHAN; 975 976 sndstat_register(dev, d->status); 977 978 return (dsp_make_dev(dev)); 979 } 980 981 int 982 pcm_unregister(device_t dev) 983 { 984 struct snddev_info *d; 985 struct pcm_channel *ch; 986 987 d = device_get_softc(dev); 988 989 if (!PCM_ALIVE(d)) { 990 device_printf(dev, "unregister: device not configured\n"); 991 return (0); 992 } 993 994 PCM_LOCK(d); 995 PCM_WAIT(d); 996 997 d->flags |= SD_F_DETACHING; 998 999 PCM_ACQUIRE(d); 1000 PCM_UNLOCK(d); 1001 1002 CHN_FOREACH(ch, d, channels.pcm) { 1003 CHN_LOCK(ch); 1004 if (ch->flags & CHN_F_SLEEPING) { 1005 /* 1006 * We are detaching, so do not wait for the timeout in 1007 * chn_read()/chn_write(). Wake up the thread and kill 1008 * the channel immediately. 1009 */ 1010 CHN_BROADCAST(&ch->intr_cv); 1011 ch->flags |= CHN_F_DEAD; 1012 } 1013 chn_abort(ch); 1014 CHN_UNLOCK(ch); 1015 } 1016 1017 dsp_destroy_dev(dev); 1018 1019 (void)mixer_uninit(dev); 1020 1021 /* remove /dev/sndstat entry first */ 1022 sndstat_unregister(dev); 1023 1024 PCM_LOCK(d); 1025 d->flags |= SD_F_DYING; 1026 d->flags &= ~SD_F_REGISTERED; 1027 PCM_UNLOCK(d); 1028 1029 if (d->play_sysctl_tree != NULL) { 1030 sysctl_ctx_free(&d->play_sysctl_ctx); 1031 d->play_sysctl_tree = NULL; 1032 } 1033 if (d->rec_sysctl_tree != NULL) { 1034 sysctl_ctx_free(&d->rec_sysctl_ctx); 1035 d->rec_sysctl_tree = NULL; 1036 } 1037 1038 while (!CHN_EMPTY(d, channels.pcm)) 1039 pcm_killchan(dev); 1040 1041 PCM_LOCK(d); 1042 PCM_RELEASE(d); 1043 cv_destroy(&d->cv); 1044 PCM_UNLOCK(d); 1045 snd_mtxfree(d->lock); 1046 1047 if (snd_unit == device_get_unit(dev)) { 1048 snd_unit = pcm_best_unit(-1); 1049 if (snd_unit_auto == 0) 1050 snd_unit_auto = 1; 1051 } 1052 1053 return (0); 1054 } 1055 1056 /************************************************************************/ 1057 1058 /** 1059 * @brief Handle OSSv4 SNDCTL_SYSINFO ioctl. 1060 * 1061 * @param si Pointer to oss_sysinfo struct where information about the 1062 * sound subsystem will be written/copied. 1063 * 1064 * This routine returns information about the sound system, such as the 1065 * current OSS version, number of audio, MIDI, and mixer drivers, etc. 1066 * Also includes a bitmask showing which of the above types of devices 1067 * are open (busy). 1068 * 1069 * @note 1070 * Calling threads must not hold any snddev_info or pcm_channel locks. 1071 * 1072 * @author Ryan Beasley <ryanb@FreeBSD.org> 1073 */ 1074 void 1075 sound_oss_sysinfo(oss_sysinfo *si) 1076 { 1077 static char si_product[] = "FreeBSD native OSS ABI"; 1078 static char si_version[] = __XSTRING(__FreeBSD_version); 1079 static char si_license[] = "BSD"; 1080 static int intnbits = sizeof(int) * 8; /* Better suited as macro? 1081 Must pester a C guru. */ 1082 1083 struct snddev_info *d; 1084 struct pcm_channel *c; 1085 int i, j, ncards; 1086 1087 ncards = 0; 1088 1089 strlcpy(si->product, si_product, sizeof(si->product)); 1090 strlcpy(si->version, si_version, sizeof(si->version)); 1091 si->versionnum = SOUND_VERSION; 1092 strlcpy(si->license, si_license, sizeof(si->license)); 1093 1094 /* 1095 * Iterate over PCM devices and their channels, gathering up data 1096 * for the numaudios, ncards, and openedaudio fields. 1097 */ 1098 si->numaudios = 0; 1099 bzero((void *)&si->openedaudio, sizeof(si->openedaudio)); 1100 1101 j = 0; 1102 1103 for (i = 0; pcm_devclass != NULL && 1104 i < devclass_get_maxunit(pcm_devclass); i++) { 1105 d = devclass_get_softc(pcm_devclass, i); 1106 if (!PCM_REGISTERED(d)) 1107 continue; 1108 1109 /* XXX Need Giant magic entry ??? */ 1110 1111 /* See note in function's docblock */ 1112 PCM_UNLOCKASSERT(d); 1113 PCM_LOCK(d); 1114 1115 si->numaudios += d->devcount; 1116 ++ncards; 1117 1118 CHN_FOREACH(c, d, channels.pcm) { 1119 CHN_UNLOCKASSERT(c); 1120 CHN_LOCK(c); 1121 if (c->flags & CHN_F_BUSY) 1122 si->openedaudio[j / intnbits] |= 1123 (1 << (j % intnbits)); 1124 CHN_UNLOCK(c); 1125 j++; 1126 } 1127 1128 PCM_UNLOCK(d); 1129 } 1130 si->numaudioengines = si->numaudios; 1131 1132 si->numsynths = 0; /* OSSv4 docs: this field is obsolete */ 1133 /** 1134 * @todo Collect num{midis,timers}. 1135 * 1136 * Need access to sound/midi/midi.c::midistat_lock in order 1137 * to safely touch midi_devices and get a head count of, well, 1138 * MIDI devices. midistat_lock is a global static (i.e., local to 1139 * midi.c), but midi_devices is a regular global; should the mutex 1140 * be publicized, or is there another way to get this information? 1141 * 1142 * NB: MIDI/sequencer stuff is currently on hold. 1143 */ 1144 si->nummidis = 0; 1145 si->numtimers = 0; 1146 si->nummixers = mixer_count; 1147 si->numcards = ncards; 1148 /* OSSv4 docs: Intended only for test apps; API doesn't 1149 really have much of a concept of cards. Shouldn't be 1150 used by applications. */ 1151 1152 /** 1153 * @todo Fill in "busy devices" fields. 1154 * 1155 * si->openedmidi = " MIDI devices 1156 */ 1157 bzero((void *)&si->openedmidi, sizeof(si->openedmidi)); 1158 1159 /* 1160 * Si->filler is a reserved array, but according to docs each 1161 * element should be set to -1. 1162 */ 1163 for (i = 0; i < sizeof(si->filler)/sizeof(si->filler[0]); i++) 1164 si->filler[i] = -1; 1165 } 1166 1167 int 1168 sound_oss_card_info(oss_card_info *si) 1169 { 1170 struct snddev_info *d; 1171 int i, ncards; 1172 1173 ncards = 0; 1174 1175 for (i = 0; pcm_devclass != NULL && 1176 i < devclass_get_maxunit(pcm_devclass); i++) { 1177 d = devclass_get_softc(pcm_devclass, i); 1178 if (!PCM_REGISTERED(d)) 1179 continue; 1180 1181 if (ncards++ != si->card) 1182 continue; 1183 1184 PCM_UNLOCKASSERT(d); 1185 PCM_LOCK(d); 1186 1187 strlcpy(si->shortname, device_get_nameunit(d->dev), 1188 sizeof(si->shortname)); 1189 strlcpy(si->longname, device_get_desc(d->dev), 1190 sizeof(si->longname)); 1191 strlcpy(si->hw_info, d->status, sizeof(si->hw_info)); 1192 si->intr_count = si->ack_count = 0; 1193 1194 PCM_UNLOCK(d); 1195 1196 return (0); 1197 } 1198 return (ENXIO); 1199 } 1200 1201 /************************************************************************/ 1202 1203 static int 1204 sound_modevent(module_t mod, int type, void *data) 1205 { 1206 int ret; 1207 1208 ret = 0; 1209 switch (type) { 1210 case MOD_LOAD: 1211 pcm_devclass = devclass_create("pcm"); 1212 pcmsg_unrhdr = new_unrhdr(1, INT_MAX, NULL); 1213 break; 1214 case MOD_UNLOAD: 1215 if (pcmsg_unrhdr != NULL) { 1216 delete_unrhdr(pcmsg_unrhdr); 1217 pcmsg_unrhdr = NULL; 1218 } 1219 break; 1220 case MOD_SHUTDOWN: 1221 break; 1222 default: 1223 ret = ENOTSUP; 1224 } 1225 1226 return ret; 1227 } 1228 1229 DEV_MODULE(sound, sound_modevent, NULL); 1230 MODULE_VERSION(sound, SOUND_MODVER); 1231