1 /*- 2 * Copyright (c) 1999 Cameron Grant <cg@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: src/sys/dev/sound/pcm/dsp.c,v 1.80.2.6 2006/04/04 17:43:48 ariff Exp $ 27 * $DragonFly: src/sys/dev/sound/pcm/dsp.c,v 1.17 2008/02/28 17:19:11 tgen Exp $ 28 */ 29 30 #include <sys/param.h> 31 #include <sys/queue.h> 32 #include <sys/event.h> 33 34 #include <dev/sound/pcm/dsp.h> 35 #include <dev/sound/pcm/sound.h> 36 37 SND_DECLARE_FILE("$DragonFly: src/sys/dev/sound/pcm/dsp.c,v 1.17 2008/02/28 17:19:11 tgen Exp $"); 38 39 #define OLDPCM_IOCTL 40 41 static d_open_t dsp_open; 42 static d_close_t dsp_close; 43 static d_read_t dsp_read; 44 static d_write_t dsp_write; 45 static d_ioctl_t dsp_ioctl; 46 static d_poll_t dsp_poll; 47 static d_kqfilter_t dsp_kqfilter; 48 static d_mmap_t dsp_mmap; 49 50 static void dsp_filter_detach(struct knote *); 51 static int dsp_filter_read(struct knote *, long); 52 static int dsp_filter_write(struct knote *, long); 53 54 struct dev_ops dsp_cdevsw = { 55 { "dsp", SND_CDEV_MAJOR, 0}, 56 /*.d_flags = D_NEEDGIANT,*/ 57 .d_open = dsp_open, 58 .d_close = dsp_close, 59 .d_read = dsp_read, 60 .d_write = dsp_write, 61 .d_ioctl = dsp_ioctl, 62 .d_poll = dsp_poll, 63 .d_kqfilter = dsp_kqfilter, 64 .d_mmap = dsp_mmap, 65 }; 66 67 struct snddev_info * 68 dsp_get_info(struct cdev *dev) 69 { 70 struct snddev_info *d; 71 int unit; 72 73 unit = PCMUNIT(dev); 74 if (unit >= devclass_get_maxunit(pcm_devclass)) 75 return NULL; 76 d = devclass_get_softc(pcm_devclass, unit); 77 78 return d; 79 } 80 81 static u_int32_t 82 dsp_get_flags(struct cdev *dev) 83 { 84 device_t bdev; 85 int unit; 86 87 unit = PCMUNIT(dev); 88 if (unit >= devclass_get_maxunit(pcm_devclass)) 89 return 0xffffffff; 90 bdev = devclass_get_device(pcm_devclass, unit); 91 92 return pcm_getflags(bdev); 93 } 94 95 static void 96 dsp_set_flags(struct cdev *dev, u_int32_t flags) 97 { 98 device_t bdev; 99 int unit; 100 101 unit = PCMUNIT(dev); 102 if (unit >= devclass_get_maxunit(pcm_devclass)) 103 return; 104 bdev = devclass_get_device(pcm_devclass, unit); 105 106 pcm_setflags(bdev, flags); 107 } 108 109 /* 110 * return the channels associated with an open device instance. 111 * set the priority if the device is simplex and one direction (only) is 112 * specified. 113 * lock channels specified. 114 */ 115 static int 116 getchns(struct cdev *dev, struct pcm_channel **rdch, struct pcm_channel **wrch, u_int32_t prio) 117 { 118 struct snddev_info *d; 119 u_int32_t flags; 120 121 flags = dsp_get_flags(dev); 122 d = dsp_get_info(dev); 123 pcm_inprog(d, 1); 124 pcm_lock(d); 125 KASSERT((flags & SD_F_PRIO_SET) != SD_F_PRIO_SET, \ 126 ("getchns: read and write both prioritised")); 127 128 if ((flags & SD_F_PRIO_SET) == 0 && (prio != (SD_F_PRIO_RD | SD_F_PRIO_WR))) { 129 flags |= prio & (SD_F_PRIO_RD | SD_F_PRIO_WR); 130 dsp_set_flags(dev, flags); 131 } 132 133 *rdch = dev->si_drv1; 134 *wrch = dev->si_drv2; 135 if ((flags & SD_F_SIMPLEX) && (flags & SD_F_PRIO_SET)) { 136 if (prio) { 137 if (*rdch && flags & SD_F_PRIO_WR) { 138 dev->si_drv1 = NULL; 139 *rdch = pcm_getfakechan(d); 140 } else if (*wrch && flags & SD_F_PRIO_RD) { 141 dev->si_drv2 = NULL; 142 *wrch = pcm_getfakechan(d); 143 } 144 } 145 146 pcm_getfakechan(d)->flags |= CHN_F_BUSY; 147 } 148 pcm_unlock(d); 149 150 if (*rdch && *rdch != pcm_getfakechan(d) && (prio & SD_F_PRIO_RD)) 151 CHN_LOCK(*rdch); 152 if (*wrch && *wrch != pcm_getfakechan(d) && (prio & SD_F_PRIO_WR)) 153 CHN_LOCK(*wrch); 154 155 return 0; 156 } 157 158 /* unlock specified channels */ 159 static void 160 relchns(struct cdev *dev, struct pcm_channel *rdch, struct pcm_channel *wrch, u_int32_t prio) 161 { 162 struct snddev_info *d; 163 164 d = dsp_get_info(dev); 165 if (wrch && wrch != pcm_getfakechan(d) && (prio & SD_F_PRIO_WR)) 166 CHN_UNLOCK(wrch); 167 if (rdch && rdch != pcm_getfakechan(d) && (prio & SD_F_PRIO_RD)) 168 CHN_UNLOCK(rdch); 169 pcm_inprog(d, -1); 170 } 171 172 static int 173 dsp_open(struct dev_open_args *ap) 174 { 175 struct cdev *i_dev = ap->a_head.a_dev; 176 struct thread *td = curthread; 177 int flags = ap->a_oflags; 178 struct pcm_channel *rdch, *wrch; 179 struct snddev_info *d = NULL; 180 struct snddev_channel *sce = NULL; 181 u_int32_t fmt = AFMT_U8; 182 int error; 183 int chnum; 184 185 if (i_dev == NULL) { 186 error = ENODEV; 187 goto out; 188 } 189 190 d = dsp_get_info(i_dev); 191 SLIST_FOREACH(sce, &d->channels, link) { 192 if (sce->dsp_dev == i_dev) 193 break; 194 } 195 196 if (sce == NULL) { 197 error = ENODEV; 198 goto out; 199 } 200 201 if (td == NULL) { 202 error = ENODEV; 203 goto out; 204 } 205 206 if ((flags & (FREAD | FWRITE)) == 0) { 207 error = EINVAL; 208 goto out; 209 } 210 211 chnum = PCMCHAN(i_dev); 212 213 /* lock snddev so nobody else can monkey with it */ 214 pcm_lock(d); 215 216 rdch = i_dev->si_drv1; 217 wrch = i_dev->si_drv2; 218 219 if (rdch || wrch || ((dsp_get_flags(i_dev) & SD_F_SIMPLEX) && 220 (flags & (FREAD | FWRITE)) == (FREAD | FWRITE))) { 221 /* simplex or not, better safe than sorry. */ 222 pcm_unlock(d); 223 error = EBUSY; 224 goto out; 225 } 226 227 /* 228 * if we get here, the open request is valid- either: 229 * * we were previously not open 230 * * we were open for play xor record and the opener wants 231 * the non-open direction 232 */ 233 if (flags & FREAD) { 234 /* open for read */ 235 pcm_unlock(d); 236 error = pcm_chnalloc(d, &rdch, PCMDIR_REC, td->td_proc->p_pid, chnum); 237 if (error != 0 && error != EBUSY && chnum != -1 && (flags & FWRITE)) 238 error = pcm_chnalloc(d, &rdch, PCMDIR_REC, td->td_proc->p_pid, -1); 239 240 if (error == 0 && (chn_reset(rdch, fmt) || 241 (fmt && chn_setspeed(rdch, DSP_DEFAULT_SPEED)))) 242 error = ENODEV; 243 244 if (error != 0) { 245 if (rdch) 246 pcm_chnrelease(rdch); 247 goto out; 248 } 249 250 pcm_chnref(rdch, 1); 251 CHN_UNLOCK(rdch); 252 pcm_lock(d); 253 } 254 255 if (flags & FWRITE) { 256 /* open for write */ 257 pcm_unlock(d); 258 error = pcm_chnalloc(d, &wrch, PCMDIR_PLAY, td->td_proc->p_pid, chnum); 259 if (error != 0 && error != EBUSY && chnum != -1 && (flags & FREAD)) 260 error = pcm_chnalloc(d, &wrch, PCMDIR_PLAY, td->td_proc->p_pid, -1); 261 262 if (error == 0 && (chn_reset(wrch, fmt) || 263 (fmt && chn_setspeed(wrch, DSP_DEFAULT_SPEED)))) 264 error = ENODEV; 265 266 if (error != 0) { 267 if (wrch) 268 pcm_chnrelease(wrch); 269 if (rdch) { 270 /* 271 * Lock, deref and release previously created record channel 272 */ 273 CHN_LOCK(rdch); 274 pcm_chnref(rdch, -1); 275 pcm_chnrelease(rdch); 276 } 277 278 goto out; 279 } 280 281 pcm_chnref(wrch, 1); 282 CHN_UNLOCK(wrch); 283 pcm_lock(d); 284 } 285 286 i_dev->si_drv1 = rdch; 287 i_dev->si_drv2 = wrch; 288 289 sce->open++; 290 291 pcm_unlock(d); 292 return 0; 293 294 out: 295 if (i_dev != NULL && sce != NULL && sce->open == 0) { 296 pcm_lock(d); 297 destroy_dev(i_dev); 298 sce->dsp_dev = NULL; 299 pcm_unlock(d); 300 } 301 return (error); 302 } 303 304 static int 305 dsp_close(struct dev_close_args *ap) 306 { 307 struct cdev *i_dev = ap->a_head.a_dev; 308 struct pcm_channel *rdch, *wrch; 309 struct snddev_info *d; 310 struct snddev_channel *sce = NULL; 311 int refs; 312 313 d = dsp_get_info(i_dev); 314 pcm_lock(d); 315 rdch = i_dev->si_drv1; 316 wrch = i_dev->si_drv2; 317 i_dev->si_drv1 = NULL; 318 i_dev->si_drv2 = NULL; 319 320 SLIST_FOREACH(sce, &d->channels, link) { 321 if (sce->dsp_dev == i_dev) 322 break; 323 } 324 sce->dsp_dev = NULL; 325 destroy_dev(i_dev); 326 327 pcm_unlock(d); 328 329 if (rdch || wrch) { 330 refs = 0; 331 if (rdch) { 332 CHN_LOCK(rdch); 333 refs += pcm_chnref(rdch, -1); 334 chn_abort(rdch); /* won't sleep */ 335 rdch->flags &= ~(CHN_F_RUNNING | CHN_F_MAPPED | CHN_F_DEAD); 336 chn_reset(rdch, 0); 337 pcm_chnrelease(rdch); 338 } 339 if (wrch) { 340 CHN_LOCK(wrch); 341 refs += pcm_chnref(wrch, -1); 342 /* 343 * XXX: Maybe the right behaviour is to abort on non_block. 344 * It seems that mplayer flushes the audio queue by quickly 345 * closing and re-opening. In FBSD, there's a long pause 346 * while the audio queue flushes that I presume isn't there in 347 * linux. 348 */ 349 chn_flush(wrch); /* may sleep */ 350 wrch->flags &= ~(CHN_F_RUNNING | CHN_F_MAPPED | CHN_F_DEAD); 351 chn_reset(wrch, 0); 352 pcm_chnrelease(wrch); 353 } 354 355 pcm_lock(d); 356 /* 357 * If there are no more references, release the channels. 358 */ 359 if (refs == 0) { 360 if (pcm_getfakechan(d)) 361 pcm_getfakechan(d)->flags = 0; 362 /* What is this?!? */ 363 dsp_set_flags(i_dev, dsp_get_flags(i_dev) & ~SD_F_TRANSIENT); 364 } 365 pcm_unlock(d); 366 } 367 return 0; 368 } 369 370 static int 371 dsp_read(struct dev_read_args *ap) 372 { 373 struct cdev *i_dev = ap->a_head.a_dev; 374 struct uio *buf = ap->a_uio; 375 int flag = ap->a_ioflag; 376 struct pcm_channel *rdch, *wrch; 377 int ret; 378 379 getchns(i_dev, &rdch, &wrch, SD_F_PRIO_RD); 380 381 KASSERT(rdch, ("dsp_read: nonexistant channel")); 382 KASSERT(rdch->flags & CHN_F_BUSY, ("dsp_read: nonbusy channel")); 383 384 if (rdch->flags & (CHN_F_MAPPED | CHN_F_DEAD)) { 385 relchns(i_dev, rdch, wrch, SD_F_PRIO_RD); 386 return EINVAL; 387 } 388 if (!(rdch->flags & CHN_F_RUNNING)) 389 rdch->flags |= CHN_F_RUNNING; 390 ret = chn_read(rdch, buf, flag); 391 relchns(i_dev, rdch, wrch, SD_F_PRIO_RD); 392 393 return ret; 394 } 395 396 static int 397 dsp_write(struct dev_write_args *ap) 398 { 399 struct cdev *i_dev = ap->a_head.a_dev; 400 struct uio *buf = ap->a_uio; 401 int flag = ap->a_ioflag; 402 struct pcm_channel *rdch, *wrch; 403 int ret; 404 405 getchns(i_dev, &rdch, &wrch, SD_F_PRIO_WR); 406 407 KASSERT(wrch, ("dsp_write: nonexistant channel")); 408 KASSERT(wrch->flags & CHN_F_BUSY, ("dsp_write: nonbusy channel")); 409 410 if (wrch->flags & (CHN_F_MAPPED | CHN_F_DEAD)) { 411 relchns(i_dev, rdch, wrch, SD_F_PRIO_WR); 412 return EINVAL; 413 } 414 if (!(wrch->flags & CHN_F_RUNNING)) 415 wrch->flags |= CHN_F_RUNNING; 416 ret = chn_write(wrch, buf, flag); 417 relchns(i_dev, rdch, wrch, SD_F_PRIO_WR); 418 419 return ret; 420 } 421 422 static int 423 dsp_ioctl(struct dev_ioctl_args *ap) 424 { 425 struct cdev *i_dev = ap->a_head.a_dev; 426 u_long cmd = ap->a_cmd; 427 caddr_t arg = ap->a_data; 428 struct pcm_channel *chn, *rdch, *wrch; 429 struct snddev_info *d; 430 int kill; 431 int ret = 0, *arg_i = (int *)arg, tmp; 432 433 d = dsp_get_info(i_dev); 434 getchns(i_dev, &rdch, &wrch, 0); 435 436 kill = 0; 437 if (wrch && (wrch->flags & CHN_F_DEAD)) 438 kill |= 1; 439 if (rdch && (rdch->flags & CHN_F_DEAD)) 440 kill |= 2; 441 if (kill == 3) { 442 relchns(i_dev, rdch, wrch, 0); 443 return EINVAL; 444 } 445 if (kill & 1) 446 wrch = NULL; 447 if (kill & 2) 448 rdch = NULL; 449 450 /* 451 * 4Front OSS specifies that dsp devices allow mixer controls to 452 * control PCM == their volume. 453 */ 454 if (IOCGROUP(cmd) == 'M') { 455 /* 456 * For now only set the channel volume for vchans, pass 457 * all others to the mixer. 458 */ 459 if (wrch != NULL && wrch->flags & CHN_F_VIRTUAL && 460 (cmd & 0xff) == SOUND_MIXER_PCM) { 461 if ((cmd & MIXER_WRITE(0)) == MIXER_WRITE(0)) { 462 int vol_raw = *(int *)arg; 463 int vol_left, vol_right; 464 465 vol_left = min(vol_raw & 0x00ff, 100); 466 vol_right = min((vol_raw & 0xff00) >> 8, 100); 467 ret = chn_setvolume(wrch, vol_left, vol_right); 468 } else { 469 *(int *)arg = wrch->volume; 470 } 471 } else { 472 ap->a_head.a_dev = d->mixer_dev; 473 ret = mixer_ioctl(ap); 474 } 475 476 relchns(i_dev, rdch, wrch, 0); 477 return ret; 478 } 479 480 switch(cmd) { 481 #ifdef OLDPCM_IOCTL 482 /* 483 * we start with the new ioctl interface. 484 */ 485 case AIONWRITE: /* how many bytes can write ? */ 486 if (wrch) { 487 CHN_LOCK(wrch); 488 /* 489 if (wrch && wrch->bufhard.dl) 490 while (chn_wrfeed(wrch) == 0); 491 */ 492 *arg_i = sndbuf_getfree(wrch->bufsoft); 493 CHN_UNLOCK(wrch); 494 } else { 495 *arg_i = 0; 496 ret = EINVAL; 497 } 498 break; 499 500 case AIOSSIZE: /* set the current blocksize */ 501 { 502 struct snd_size *p = (struct snd_size *)arg; 503 504 p->play_size = 0; 505 p->rec_size = 0; 506 if (wrch) { 507 CHN_LOCK(wrch); 508 chn_setblocksize(wrch, 2, p->play_size); 509 p->play_size = sndbuf_getblksz(wrch->bufsoft); 510 CHN_UNLOCK(wrch); 511 } 512 if (rdch) { 513 CHN_LOCK(rdch); 514 chn_setblocksize(rdch, 2, p->rec_size); 515 p->rec_size = sndbuf_getblksz(rdch->bufsoft); 516 CHN_UNLOCK(rdch); 517 } 518 } 519 break; 520 case AIOGSIZE: /* get the current blocksize */ 521 { 522 struct snd_size *p = (struct snd_size *)arg; 523 524 if (wrch) { 525 CHN_LOCK(wrch); 526 p->play_size = sndbuf_getblksz(wrch->bufsoft); 527 CHN_UNLOCK(wrch); 528 } 529 if (rdch) { 530 CHN_LOCK(rdch); 531 p->rec_size = sndbuf_getblksz(rdch->bufsoft); 532 CHN_UNLOCK(rdch); 533 } 534 } 535 break; 536 537 case AIOSFMT: 538 case AIOGFMT: 539 { 540 snd_chan_param *p = (snd_chan_param *)arg; 541 542 if (cmd == AIOSFMT && 543 ((p->play_format != 0 && p->play_rate == 0) || 544 (p->rec_format != 0 && p->rec_rate == 0))) { 545 ret = EINVAL; 546 break; 547 } 548 if (wrch) { 549 CHN_LOCK(wrch); 550 if (cmd == AIOSFMT && p->play_format != 0) { 551 chn_setformat(wrch, p->play_format); 552 chn_setspeed(wrch, p->play_rate); 553 } 554 p->play_rate = wrch->speed; 555 p->play_format = wrch->format; 556 CHN_UNLOCK(wrch); 557 } else { 558 p->play_rate = 0; 559 p->play_format = 0; 560 } 561 if (rdch) { 562 CHN_LOCK(rdch); 563 if (cmd == AIOSFMT && p->rec_format != 0) { 564 chn_setformat(rdch, p->rec_format); 565 chn_setspeed(rdch, p->rec_rate); 566 } 567 p->rec_rate = rdch->speed; 568 p->rec_format = rdch->format; 569 CHN_UNLOCK(rdch); 570 } else { 571 p->rec_rate = 0; 572 p->rec_format = 0; 573 } 574 } 575 break; 576 577 case AIOGCAP: /* get capabilities */ 578 { 579 snd_capabilities *p = (snd_capabilities *)arg; 580 struct pcmchan_caps *pcaps = NULL, *rcaps = NULL; 581 struct cdev *pdev; 582 583 if (rdch) { 584 CHN_LOCK(rdch); 585 rcaps = chn_getcaps(rdch); 586 } 587 if (wrch) { 588 CHN_LOCK(wrch); 589 pcaps = chn_getcaps(wrch); 590 } 591 p->rate_min = max(rcaps? rcaps->minspeed : 0, 592 pcaps? pcaps->minspeed : 0); 593 p->rate_max = min(rcaps? rcaps->maxspeed : 1000000, 594 pcaps? pcaps->maxspeed : 1000000); 595 p->bufsize = min(rdch? sndbuf_getsize(rdch->bufsoft) : 1000000, 596 wrch? sndbuf_getsize(wrch->bufsoft) : 1000000); 597 /* XXX bad on sb16 */ 598 p->formats = (rdch? chn_getformats(rdch) : 0xffffffff) & 599 (wrch? chn_getformats(wrch) : 0xffffffff); 600 if (rdch && wrch) 601 p->formats |= (dsp_get_flags(i_dev) & SD_F_SIMPLEX)? 0 : AFMT_FULLDUPLEX; 602 pdev = d->mixer_dev; 603 p->mixers = 1; /* default: one mixer */ 604 p->inputs = pdev->si_drv1? mix_getdevs(pdev->si_drv1) : 0; 605 p->left = p->right = 100; 606 if (rdch) 607 CHN_UNLOCK(rdch); 608 if (wrch) 609 CHN_UNLOCK(wrch); 610 } 611 break; 612 613 case AIOSTOP: 614 if (*arg_i == AIOSYNC_PLAY && wrch) { 615 CHN_LOCK(wrch); 616 *arg_i = chn_abort(wrch); 617 CHN_UNLOCK(wrch); 618 } else if (*arg_i == AIOSYNC_CAPTURE && rdch) { 619 CHN_LOCK(rdch); 620 *arg_i = chn_abort(rdch); 621 CHN_UNLOCK(rdch); 622 } else { 623 kprintf("AIOSTOP: bad channel 0x%x\n", *arg_i); 624 *arg_i = 0; 625 } 626 break; 627 628 case AIOSYNC: 629 kprintf("AIOSYNC chan 0x%03lx pos %lu unimplemented\n", 630 ((snd_sync_parm *)arg)->chan, ((snd_sync_parm *)arg)->pos); 631 break; 632 #endif 633 /* 634 * here follow the standard ioctls (filio.h etc.) 635 */ 636 case FIONREAD: /* get # bytes to read */ 637 if (rdch) { 638 CHN_LOCK(rdch); 639 /* if (rdch && rdch->bufhard.dl) 640 while (chn_rdfeed(rdch) == 0); 641 */ 642 *arg_i = sndbuf_getready(rdch->bufsoft); 643 CHN_UNLOCK(rdch); 644 } else { 645 *arg_i = 0; 646 ret = EINVAL; 647 } 648 break; 649 650 case FIOASYNC: /*set/clear async i/o */ 651 DEB( kprintf("FIOASYNC\n") ; ) 652 break; 653 654 case SNDCTL_DSP_NONBLOCK: 655 case FIONBIO: /* set/clear non-blocking i/o */ 656 if (rdch) { 657 CHN_LOCK(rdch); 658 if (*arg_i) 659 rdch->flags |= CHN_F_NBIO; 660 else 661 rdch->flags &= ~CHN_F_NBIO; 662 CHN_UNLOCK(rdch); 663 } 664 if (wrch) { 665 CHN_LOCK(wrch); 666 if (*arg_i) 667 wrch->flags |= CHN_F_NBIO; 668 else 669 wrch->flags &= ~CHN_F_NBIO; 670 CHN_UNLOCK(wrch); 671 } 672 break; 673 674 /* 675 * Finally, here is the linux-compatible ioctl interface 676 */ 677 #define THE_REAL_SNDCTL_DSP_GETBLKSIZE _IOWR('P', 4, int) 678 case THE_REAL_SNDCTL_DSP_GETBLKSIZE: 679 case SNDCTL_DSP_GETBLKSIZE: 680 chn = wrch ? wrch : rdch; 681 if (chn) { 682 CHN_LOCK(chn); 683 *arg_i = sndbuf_getblksz(chn->bufsoft); 684 CHN_UNLOCK(chn); 685 } else { 686 *arg_i = 0; 687 ret = EINVAL; 688 } 689 break ; 690 691 case SNDCTL_DSP_SETBLKSIZE: 692 RANGE(*arg_i, 16, 65536); 693 if (wrch) { 694 CHN_LOCK(wrch); 695 chn_setblocksize(wrch, 2, *arg_i); 696 CHN_UNLOCK(wrch); 697 } 698 if (rdch) { 699 CHN_LOCK(rdch); 700 chn_setblocksize(rdch, 2, *arg_i); 701 CHN_UNLOCK(rdch); 702 } 703 break; 704 705 case SNDCTL_DSP_RESET: 706 DEB(kprintf("dsp reset\n")); 707 if (wrch) { 708 CHN_LOCK(wrch); 709 chn_abort(wrch); 710 chn_resetbuf(wrch); 711 CHN_UNLOCK(wrch); 712 } 713 if (rdch) { 714 CHN_LOCK(rdch); 715 chn_abort(rdch); 716 chn_resetbuf(rdch); 717 CHN_UNLOCK(rdch); 718 } 719 break; 720 721 case SNDCTL_DSP_SYNC: 722 DEB(kprintf("dsp sync\n")); 723 /* chn_sync may sleep */ 724 if (wrch) { 725 CHN_LOCK(wrch); 726 chn_sync(wrch, sndbuf_getsize(wrch->bufsoft) - 4); 727 CHN_UNLOCK(wrch); 728 } 729 break; 730 731 case SNDCTL_DSP_SPEED: 732 /* chn_setspeed may sleep */ 733 tmp = 0; 734 if (wrch) { 735 CHN_LOCK(wrch); 736 ret = chn_setspeed(wrch, *arg_i); 737 tmp = wrch->speed; 738 CHN_UNLOCK(wrch); 739 } 740 if (rdch && ret == 0) { 741 CHN_LOCK(rdch); 742 ret = chn_setspeed(rdch, *arg_i); 743 if (tmp == 0) 744 tmp = rdch->speed; 745 CHN_UNLOCK(rdch); 746 } 747 *arg_i = tmp; 748 break; 749 750 case SOUND_PCM_READ_RATE: 751 chn = wrch ? wrch : rdch; 752 if (chn) { 753 CHN_LOCK(chn); 754 *arg_i = chn->speed; 755 CHN_UNLOCK(chn); 756 } else { 757 *arg_i = 0; 758 ret = EINVAL; 759 } 760 break; 761 762 case SNDCTL_DSP_STEREO: 763 tmp = -1; 764 *arg_i = (*arg_i)? AFMT_STEREO : 0; 765 if (wrch) { 766 CHN_LOCK(wrch); 767 ret = chn_setformat(wrch, (wrch->format & ~AFMT_STEREO) | *arg_i); 768 tmp = (wrch->format & AFMT_STEREO)? 1 : 0; 769 CHN_UNLOCK(wrch); 770 } 771 if (rdch && ret == 0) { 772 CHN_LOCK(rdch); 773 ret = chn_setformat(rdch, (rdch->format & ~AFMT_STEREO) | *arg_i); 774 if (tmp == -1) 775 tmp = (rdch->format & AFMT_STEREO)? 1 : 0; 776 CHN_UNLOCK(rdch); 777 } 778 *arg_i = tmp; 779 break; 780 781 case SOUND_PCM_WRITE_CHANNELS: 782 /* case SNDCTL_DSP_CHANNELS: ( == SOUND_PCM_WRITE_CHANNELS) */ 783 if (*arg_i != 0) { 784 tmp = 0; 785 *arg_i = (*arg_i != 1)? AFMT_STEREO : 0; 786 if (wrch) { 787 CHN_LOCK(wrch); 788 ret = chn_setformat(wrch, (wrch->format & ~AFMT_STEREO) | *arg_i); 789 tmp = (wrch->format & AFMT_STEREO)? 2 : 1; 790 CHN_UNLOCK(wrch); 791 } 792 if (rdch && ret == 0) { 793 CHN_LOCK(rdch); 794 ret = chn_setformat(rdch, (rdch->format & ~AFMT_STEREO) | *arg_i); 795 if (tmp == 0) 796 tmp = (rdch->format & AFMT_STEREO)? 2 : 1; 797 CHN_UNLOCK(rdch); 798 } 799 *arg_i = tmp; 800 } else { 801 chn = wrch ? wrch : rdch; 802 CHN_LOCK(chn); 803 *arg_i = (chn->format & AFMT_STEREO) ? 2 : 1; 804 CHN_UNLOCK(chn); 805 } 806 break; 807 808 case SOUND_PCM_READ_CHANNELS: 809 chn = wrch ? wrch : rdch; 810 if (chn) { 811 CHN_LOCK(chn); 812 *arg_i = (chn->format & AFMT_STEREO) ? 2 : 1; 813 CHN_UNLOCK(chn); 814 } else { 815 *arg_i = 0; 816 ret = EINVAL; 817 } 818 break; 819 820 case SNDCTL_DSP_GETFMTS: /* returns a mask of supported fmts */ 821 chn = wrch ? wrch : rdch; 822 if (chn) { 823 CHN_LOCK(chn); 824 *arg_i = chn_getformats(chn); 825 CHN_UNLOCK(chn); 826 } else { 827 *arg_i = 0; 828 ret = EINVAL; 829 } 830 break ; 831 832 case SNDCTL_DSP_SETFMT: /* sets _one_ format */ 833 if ((*arg_i != AFMT_QUERY)) { 834 tmp = 0; 835 if (wrch) { 836 CHN_LOCK(wrch); 837 ret = chn_setformat(wrch, (*arg_i) | (wrch->format & AFMT_STEREO)); 838 tmp = wrch->format & ~AFMT_STEREO; 839 CHN_UNLOCK(wrch); 840 } 841 if (rdch && ret == 0) { 842 CHN_LOCK(rdch); 843 ret = chn_setformat(rdch, (*arg_i) | (rdch->format & AFMT_STEREO)); 844 if (tmp == 0) 845 tmp = rdch->format & ~AFMT_STEREO; 846 CHN_UNLOCK(rdch); 847 } 848 *arg_i = tmp; 849 } else { 850 chn = wrch ? wrch : rdch; 851 CHN_LOCK(chn); 852 *arg_i = chn->format & ~AFMT_STEREO; 853 CHN_UNLOCK(chn); 854 } 855 break; 856 857 case SNDCTL_DSP_SETFRAGMENT: 858 DEB(kprintf("SNDCTL_DSP_SETFRAGMENT 0x%08x\n", *(int *)arg)); 859 { 860 u_int32_t fragln = (*arg_i) & 0x0000ffff; 861 u_int32_t maxfrags = ((*arg_i) & 0xffff0000) >> 16; 862 u_int32_t fragsz; 863 u_int32_t r_maxfrags, r_fragsz; 864 865 RANGE(fragln, 4, 16); 866 fragsz = 1 << fragln; 867 868 if (maxfrags == 0) 869 maxfrags = CHN_2NDBUFMAXSIZE / fragsz; 870 if (maxfrags < 2) 871 maxfrags = 2; 872 if (maxfrags * fragsz > CHN_2NDBUFMAXSIZE) 873 maxfrags = CHN_2NDBUFMAXSIZE / fragsz; 874 875 DEB(kprintf("SNDCTL_DSP_SETFRAGMENT %d frags, %d sz\n", maxfrags, fragsz)); 876 if (rdch) { 877 CHN_LOCK(rdch); 878 ret = chn_setblocksize(rdch, maxfrags, fragsz); 879 r_maxfrags = sndbuf_getblkcnt(rdch->bufsoft); 880 r_fragsz = sndbuf_getblksz(rdch->bufsoft); 881 CHN_UNLOCK(rdch); 882 } else { 883 r_maxfrags = maxfrags; 884 r_fragsz = fragsz; 885 } 886 if (wrch && ret == 0) { 887 CHN_LOCK(wrch); 888 ret = chn_setblocksize(wrch, maxfrags, fragsz); 889 maxfrags = sndbuf_getblkcnt(wrch->bufsoft); 890 fragsz = sndbuf_getblksz(wrch->bufsoft); 891 CHN_UNLOCK(wrch); 892 } else { /* use whatever came from the read channel */ 893 maxfrags = r_maxfrags; 894 fragsz = r_fragsz; 895 } 896 897 fragln = 0; 898 while (fragsz > 1) { 899 fragln++; 900 fragsz >>= 1; 901 } 902 *arg_i = (maxfrags << 16) | fragln; 903 } 904 break; 905 906 case SNDCTL_DSP_GETISPACE: 907 /* return the size of data available in the input queue */ 908 { 909 audio_buf_info *a = (audio_buf_info *)arg; 910 if (rdch) { 911 struct snd_dbuf *bs = rdch->bufsoft; 912 913 CHN_LOCK(rdch); 914 a->bytes = sndbuf_getready(bs); 915 a->fragments = a->bytes / sndbuf_getblksz(bs); 916 a->fragstotal = sndbuf_getblkcnt(bs); 917 a->fragsize = sndbuf_getblksz(bs); 918 CHN_UNLOCK(rdch); 919 } 920 } 921 break; 922 923 case SNDCTL_DSP_GETOSPACE: 924 /* return space available in the output queue */ 925 { 926 audio_buf_info *a = (audio_buf_info *)arg; 927 if (wrch) { 928 struct snd_dbuf *bs = wrch->bufsoft; 929 930 CHN_LOCK(wrch); 931 /* XXX abusive DMA update: chn_wrupdate(wrch); */ 932 a->bytes = sndbuf_getfree(bs); 933 a->fragments = a->bytes / sndbuf_getblksz(bs); 934 a->fragstotal = sndbuf_getblkcnt(bs); 935 a->fragsize = sndbuf_getblksz(bs); 936 CHN_UNLOCK(wrch); 937 } 938 } 939 break; 940 941 case SNDCTL_DSP_GETIPTR: 942 { 943 count_info *a = (count_info *)arg; 944 if (rdch) { 945 struct snd_dbuf *bs = rdch->bufsoft; 946 947 CHN_LOCK(rdch); 948 /* XXX abusive DMA update: chn_rdupdate(rdch); */ 949 a->bytes = sndbuf_gettotal(bs); 950 a->blocks = sndbuf_getblocks(bs) - rdch->blocks; 951 a->ptr = sndbuf_getreadyptr(bs); 952 rdch->blocks = sndbuf_getblocks(bs); 953 CHN_UNLOCK(rdch); 954 } else 955 ret = EINVAL; 956 } 957 break; 958 959 case SNDCTL_DSP_GETOPTR: 960 { 961 count_info *a = (count_info *)arg; 962 if (wrch) { 963 struct snd_dbuf *bs = wrch->bufsoft; 964 965 CHN_LOCK(wrch); 966 /* XXX abusive DMA update: chn_wrupdate(wrch); */ 967 a->bytes = sndbuf_gettotal(bs); 968 a->blocks = sndbuf_getblocks(bs) - wrch->blocks; 969 a->ptr = sndbuf_getreadyptr(bs); 970 wrch->blocks = sndbuf_getblocks(bs); 971 CHN_UNLOCK(wrch); 972 } else 973 ret = EINVAL; 974 } 975 break; 976 977 case SNDCTL_DSP_GETCAPS: 978 *arg_i = DSP_CAP_REALTIME | DSP_CAP_MMAP | DSP_CAP_TRIGGER; 979 if (rdch && wrch && !(dsp_get_flags(i_dev) & SD_F_SIMPLEX)) 980 *arg_i |= DSP_CAP_DUPLEX; 981 break; 982 983 case SOUND_PCM_READ_BITS: 984 chn = wrch ? wrch : rdch; 985 if (chn) { 986 CHN_LOCK(chn); 987 if (chn->format & AFMT_8BIT) 988 *arg_i = 8; 989 else if (chn->format & AFMT_16BIT) 990 *arg_i = 16; 991 else if (chn->format & AFMT_24BIT) 992 *arg_i = 24; 993 else if (chn->format & AFMT_32BIT) 994 *arg_i = 32; 995 else 996 ret = EINVAL; 997 CHN_UNLOCK(chn); 998 } else { 999 *arg_i = 0; 1000 ret = EINVAL; 1001 } 1002 break; 1003 1004 case SNDCTL_DSP_SETTRIGGER: 1005 if (rdch) { 1006 CHN_LOCK(rdch); 1007 rdch->flags &= ~(CHN_F_TRIGGERED | CHN_F_NOTRIGGER); 1008 if (*arg_i & PCM_ENABLE_INPUT) 1009 chn_start(rdch, 1); 1010 else 1011 rdch->flags |= CHN_F_NOTRIGGER; 1012 CHN_UNLOCK(rdch); 1013 } 1014 if (wrch) { 1015 CHN_LOCK(wrch); 1016 wrch->flags &= ~(CHN_F_TRIGGERED | CHN_F_NOTRIGGER); 1017 if (*arg_i & PCM_ENABLE_OUTPUT) 1018 chn_start(wrch, 1); 1019 else 1020 wrch->flags |= CHN_F_NOTRIGGER; 1021 CHN_UNLOCK(wrch); 1022 } 1023 break; 1024 1025 case SNDCTL_DSP_GETTRIGGER: 1026 *arg_i = 0; 1027 if (wrch) { 1028 CHN_LOCK(wrch); 1029 if (wrch->flags & CHN_F_TRIGGERED) 1030 *arg_i |= PCM_ENABLE_OUTPUT; 1031 CHN_UNLOCK(wrch); 1032 } 1033 if (rdch) { 1034 CHN_LOCK(rdch); 1035 if (rdch->flags & CHN_F_TRIGGERED) 1036 *arg_i |= PCM_ENABLE_INPUT; 1037 CHN_UNLOCK(rdch); 1038 } 1039 break; 1040 1041 case SNDCTL_DSP_GETODELAY: 1042 if (wrch) { 1043 struct snd_dbuf *b = wrch->bufhard; 1044 struct snd_dbuf *bs = wrch->bufsoft; 1045 1046 CHN_LOCK(wrch); 1047 /* XXX abusive DMA update: chn_wrupdate(wrch); */ 1048 *arg_i = sndbuf_getready(b) + sndbuf_getready(bs); 1049 CHN_UNLOCK(wrch); 1050 } else 1051 ret = EINVAL; 1052 break; 1053 1054 case SNDCTL_DSP_POST: 1055 if (wrch) { 1056 CHN_LOCK(wrch); 1057 wrch->flags &= ~CHN_F_NOTRIGGER; 1058 chn_start(wrch, 1); 1059 CHN_UNLOCK(wrch); 1060 } 1061 break; 1062 1063 case SNDCTL_DSP_SETDUPLEX: 1064 /* 1065 * switch to full-duplex mode if card is in half-duplex 1066 * mode and is able to work in full-duplex mode 1067 */ 1068 if (rdch && wrch && (dsp_get_flags(i_dev) & SD_F_SIMPLEX)) 1069 dsp_set_flags(i_dev, dsp_get_flags(i_dev)^SD_F_SIMPLEX); 1070 break; 1071 1072 case SNDCTL_DSP_MAPINBUF: 1073 case SNDCTL_DSP_MAPOUTBUF: 1074 case SNDCTL_DSP_SETSYNCRO: 1075 /* undocumented */ 1076 1077 case SNDCTL_DSP_SUBDIVIDE: 1078 case SOUND_PCM_WRITE_FILTER: 1079 case SOUND_PCM_READ_FILTER: 1080 /* dunno what these do, don't sound important */ 1081 1082 default: 1083 DEB(kprintf("default ioctl fn 0x%08lx fail\n", cmd)); 1084 ret = EINVAL; 1085 break; 1086 } 1087 relchns(i_dev, rdch, wrch, 0); 1088 return ret; 1089 } 1090 1091 static int 1092 dsp_poll(struct dev_poll_args *ap) 1093 { 1094 struct cdev *i_dev = ap->a_head.a_dev; 1095 int events = ap->a_events; 1096 struct thread *td = curthread; 1097 struct pcm_channel *wrch = NULL, *rdch = NULL; 1098 int ret, e; 1099 1100 ret = 0; 1101 getchns(i_dev, &rdch, &wrch, SD_F_PRIO_RD | SD_F_PRIO_WR); 1102 1103 if (wrch) { 1104 e = (events & (POLLOUT | POLLWRNORM)); 1105 if (e) 1106 ret |= chn_poll(wrch, e, td); 1107 } 1108 if (rdch) { 1109 e = (events & (POLLIN | POLLRDNORM)); 1110 if (e) 1111 ret |= chn_poll(rdch, e, td); 1112 } 1113 relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR); 1114 1115 ap->a_events = ret; 1116 return (0); 1117 } 1118 1119 static struct filterops dsp_read_filtops = 1120 { 1, NULL, dsp_filter_detach, dsp_filter_read }; 1121 static struct filterops dsp_write_filtops = 1122 { 1, NULL, dsp_filter_detach, dsp_filter_write }; 1123 1124 static int 1125 dsp_kqfilter(struct dev_kqfilter_args *ap) 1126 { 1127 struct knote *kn = ap->a_kn; 1128 struct klist *klist; 1129 struct cdev *i_dev = ap->a_head.a_dev; 1130 struct pcm_channel *wrch = NULL, *rdch = NULL; 1131 struct snd_dbuf *bs; 1132 1133 getchns(i_dev, &rdch, &wrch, SD_F_PRIO_RD | SD_F_PRIO_WR); 1134 ap->a_result = 1; 1135 switch (kn->kn_filter) { 1136 case EVFILT_READ: 1137 if (rdch) { 1138 kn->kn_fop = &dsp_read_filtops; 1139 kn->kn_hook = (caddr_t)rdch; 1140 bs = rdch->bufsoft; 1141 ap->a_result = 0; 1142 } 1143 break; 1144 case EVFILT_WRITE: 1145 if (wrch) { 1146 kn->kn_fop = &dsp_write_filtops; 1147 kn->kn_hook = (caddr_t)wrch; 1148 bs = wrch->bufsoft; 1149 ap->a_result = 0; 1150 } 1151 break; 1152 } 1153 1154 if (ap->a_result == 0) { 1155 crit_enter(); 1156 klist = &sndbuf_getsel(bs)->si_note; 1157 SLIST_INSERT_HEAD(klist, kn, kn_selnext); 1158 crit_exit(); 1159 } 1160 1161 relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR); 1162 1163 return (0); 1164 } 1165 1166 static void 1167 dsp_filter_detach(struct knote *kn) 1168 { 1169 struct pcm_channel *ch = (struct pcm_channel *)kn->kn_hook; 1170 struct snd_dbuf *bs = ch->bufsoft; 1171 struct klist *klist; 1172 1173 CHN_LOCK(ch); 1174 crit_enter(); 1175 klist = &sndbuf_getsel(bs)->si_note; 1176 SLIST_REMOVE(klist, kn, knote, kn_selnext); 1177 crit_exit(); 1178 CHN_UNLOCK(ch); 1179 } 1180 1181 static int 1182 dsp_filter_read(struct knote *kn, long hint) 1183 { 1184 struct pcm_channel *rdch = (struct pcm_channel *)kn->kn_hook; 1185 struct thread *td = curthread; 1186 int ready; 1187 1188 CHN_LOCK(rdch); 1189 ready = chn_poll(rdch, 1, td); 1190 CHN_UNLOCK(rdch); 1191 1192 return (ready); 1193 } 1194 1195 static int 1196 dsp_filter_write(struct knote *kn, long hint) 1197 { 1198 struct pcm_channel *wrch = (struct pcm_channel *)kn->kn_hook; 1199 struct thread *td = curthread; 1200 int ready; 1201 1202 CHN_LOCK(wrch); 1203 ready = chn_poll(wrch, 1, td); 1204 CHN_UNLOCK(wrch); 1205 1206 return (ready); 1207 } 1208 1209 static int 1210 dsp_mmap(struct dev_mmap_args *ap) 1211 { 1212 struct cdev *i_dev = ap->a_head.a_dev; 1213 vm_offset_t offset = ap->a_offset; 1214 int nprot = ap->a_nprot; 1215 struct pcm_channel *wrch = NULL, *rdch = NULL, *c; 1216 1217 if (nprot & PROT_EXEC) 1218 return -1; 1219 1220 getchns(i_dev, &rdch, &wrch, SD_F_PRIO_RD | SD_F_PRIO_WR); 1221 #if 0 1222 /* 1223 * XXX the linux api uses the nprot to select read/write buffer 1224 * our vm system doesn't allow this, so force write buffer 1225 */ 1226 1227 if (wrch && (nprot & PROT_WRITE)) { 1228 c = wrch; 1229 } else if (rdch && (nprot & PROT_READ)) { 1230 c = rdch; 1231 } else { 1232 return -1; 1233 } 1234 #else 1235 c = wrch; 1236 #endif 1237 1238 if (c == NULL) { 1239 relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR); 1240 return -1; 1241 } 1242 1243 if (offset >= sndbuf_getsize(c->bufsoft)) { 1244 relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR); 1245 return -1; 1246 } 1247 1248 if (!(c->flags & CHN_F_MAPPED)) 1249 c->flags |= CHN_F_MAPPED; 1250 1251 ap->a_result = atop(vtophys(sndbuf_getbufofs(c->bufsoft, offset))); 1252 relchns(i_dev, rdch, wrch, SD_F_PRIO_RD | SD_F_PRIO_WR); 1253 1254 return (0); 1255 } 1256 1257 /* 1258 * for i = 0 to channels of device N 1259 * if dspN.i isn't busy and in the right dir, create a dev_t and return it 1260 */ 1261 int 1262 dsp_clone(struct dev_clone_args *ap) 1263 { 1264 struct cdev *i_dev = ap->a_head.a_dev; 1265 struct cdev *pdev; 1266 struct snddev_info *pcm_dev; 1267 struct snddev_channel *pcm_chan; 1268 struct pcm_channel *c; 1269 int err = EBUSY; 1270 int dir; 1271 1272 pcm_dev = dsp_get_info(i_dev); 1273 1274 if (pcm_dev == NULL) 1275 return (ENODEV); 1276 1277 dir = ap->a_mode & FWRITE ? PCMDIR_PLAY : PCMDIR_REC; 1278 1279 retry_chnalloc: 1280 SLIST_FOREACH(pcm_chan, &pcm_dev->channels, link) { 1281 c = pcm_chan->channel; 1282 CHN_LOCK(c); 1283 pdev = pcm_chan->dsp_dev; 1284 1285 /* 1286 * Make sure that the channel has not been assigned 1287 * to a device yet (and vice versa). 1288 * The direction has to match and the channel may not 1289 * be busy. 1290 * dsp_open will use exactly this channel number to 1291 * avoid (possible?) races between clone and open. 1292 */ 1293 if (pdev == NULL && c->direction == dir && 1294 !(c->flags & CHN_F_BUSY)) { 1295 CHN_UNLOCK(c); 1296 pcm_lock(pcm_dev); 1297 pcm_chan->dsp_dev = make_only_dev(&dsp_cdevsw, 1298 PCMMKMINOR(PCMUNIT(i_dev), pcm_chan->chan_num), 1299 UID_ROOT, GID_WHEEL, 1300 0666, 1301 "%s.%d", 1302 devtoname(i_dev), 1303 pcm_chan->chan_num); 1304 pcm_unlock(pcm_dev); 1305 1306 ap->a_dev = pcm_chan->dsp_dev; 1307 return (0); 1308 } 1309 CHN_UNLOCK(c); 1310 1311 #if DEBUG 1312 if ((pdev != NULL) && (pdev->si_drv1 == NULL) && (pdev->si_drv2 == NULL)) { 1313 kprintf("%s: dangling device\n", devtoname(pdev)); 1314 } 1315 #endif 1316 } 1317 1318 /* no channel available, create vchannel */ 1319 if (dir == PCMDIR_PLAY && 1320 pcm_dev->vchancount > 0 && 1321 pcm_dev->vchancount < snd_maxautovchans && 1322 pcm_dev->devcount < PCMMAXCHAN) { 1323 err = pcm_setvchans(pcm_dev, pcm_dev->vchancount + 1); 1324 if (err == 0) 1325 goto retry_chnalloc; 1326 /* 1327 * If we can't use vchans, because the main output is 1328 * blocked for something else, we should not return 1329 * any vchan create error, but the more descriptive 1330 * EBUSY. 1331 * After all, the user didn't ask us to clone, but 1332 * only opened /dev/dsp. 1333 */ 1334 err = EBUSY; 1335 } 1336 1337 return (err); 1338 } 1339