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