Lines Matching +full:- +full:chn +full:- +full:disabled
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org>
5 * Portions Copyright (c) Ryan Beasley <ryan.beasley@gmail.com> - GSoC 2006
8 * Copyright (c) 2024-2025 The FreeBSD Foundation
60 "linux mmap compatibility (-1=force disable 0=auto 1=force enable)");
67 #define DSP_REGISTERED(x) (PCM_REGISTERED(x) && (x)->dsp_dev != NULL)
130 err = make_dev_s(&devargs, &sc->dsp_dev, "dsp%d", unit); in dsp_make_dev()
146 destroy_dev(d->dsp_dev); in dsp_destroy_dev()
152 if (priv->rdch != NULL && DSP_F_READ(prio)) in dsp_lock_chans()
153 CHN_LOCK(priv->rdch); in dsp_lock_chans()
154 if (priv->wrch != NULL && DSP_F_WRITE(prio)) in dsp_lock_chans()
155 CHN_LOCK(priv->wrch); in dsp_lock_chans()
161 if (priv->rdch != NULL && DSP_F_READ(prio)) in dsp_unlock_chans()
162 CHN_UNLOCK(priv->rdch); in dsp_unlock_chans()
163 if (priv->wrch != NULL && DSP_F_WRITE(prio)) in dsp_unlock_chans()
164 CHN_UNLOCK(priv->wrch); in dsp_unlock_chans()
183 pid = td->td_proc->p_pid; in dsp_chn_alloc()
184 comm = td->td_proc->p_comm; in dsp_chn_alloc()
186 vdir_enabled = (direction == PCMDIR_PLAY && d->flags & SD_F_PVCHANS) || in dsp_chn_alloc()
187 (direction == PCMDIR_REC && d->flags & SD_F_RVCHANS); in dsp_chn_alloc()
192 if (c->direction != direction) { in dsp_chn_alloc()
197 if ((c->flags & CHN_F_BUSY) == 0 || in dsp_chn_alloc()
198 (vdir_enabled && (c->flags & CHN_F_HAS_VCHAN))) in dsp_chn_alloc()
207 * - vchans are enabled, add a new vchan to the primary channel. in dsp_chn_alloc()
208 * - vchans are disabled, use the primary channel directly. in dsp_chn_alloc()
210 if (vdir_enabled && ((c->flags & CHN_F_BUSY) == 0 || in dsp_chn_alloc()
211 c->flags & CHN_F_HAS_VCHAN)) { in dsp_chn_alloc()
217 } else if ((c->flags & CHN_F_BUSY) == 0) { in dsp_chn_alloc()
224 (*ch)->flags |= CHN_F_BUSY; in dsp_chn_alloc()
226 (*ch)->flags |= CHN_F_NBIO; in dsp_chn_alloc()
228 (*ch)->flags |= CHN_F_EXCLUSIVE; in dsp_chn_alloc()
229 (*ch)->pid = pid; in dsp_chn_alloc()
230 strlcpy((*ch)->comm, (comm != NULL) ? comm : CHN_COMM_UNKNOWN, in dsp_chn_alloc()
231 sizeof((*ch)->comm)); in dsp_chn_alloc()
233 if ((err = chn_reset(*ch, (*ch)->format, (*ch)->speed)) != 0) in dsp_chn_alloc()
253 d = priv->sc; in dsp_close()
264 rdch = priv->rdch; in dsp_close()
265 wrch = priv->wrch; in dsp_close()
301 rdch->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP | in dsp_close()
305 if (rdch->flags & CHN_F_VIRTUAL) { in dsp_close()
306 parent = rdch->parentchannel; in dsp_close()
325 wrch->flags &= ~(CHN_F_RUNNING | CHN_F_MMAP | in dsp_close()
329 if (wrch->flags & CHN_F_VIRTUAL) { in dsp_close()
330 parent = wrch->parentchannel; in dsp_close()
361 d = i_dev->si_drv1; in dsp_open()
369 priv->sc = d; in dsp_open()
385 ((DSP_F_READ(flags) && d->reccount == 0) || in dsp_open()
386 (DSP_F_WRITE(flags) && d->playcount == 0))) in dsp_open()
388 if (pcm_getflags(d->dev) & SD_F_SIMPLEX) { in dsp_open()
396 if (d->playcount > 0) in dsp_open()
398 else if (d->reccount > 0) in dsp_open()
402 if (ch->direction == PCMDIR_PLAY) in dsp_open()
404 else if (ch->direction == PCMDIR_REC) in dsp_open()
414 if (ch->direction != dir) in dsp_open()
433 error = dsp_chn_alloc(d, &priv->wrch, PCMDIR_PLAY, flags, td); in dsp_open()
440 CHN_INSERT_HEAD(d, priv->wrch, channels.pcm.opened); in dsp_open()
444 error = dsp_chn_alloc(d, &priv->rdch, PCMDIR_REC, flags, td); in dsp_open()
451 CHN_INSERT_HEAD(d, priv->rdch, channels.pcm.opened); in dsp_open()
469 d = priv->sc; in dsp_io_ops()
475 switch (buf->uio_rw) { in dsp_io_ops()
477 ch = priv->rdch; in dsp_io_ops()
481 ch = priv->wrch; in dsp_io_ops()
491 if (!(ch->flags & CHN_F_BUSY) || in dsp_io_ops()
492 (ch->flags & (CHN_F_MMAP | CHN_F_DEAD))) { in dsp_io_ops()
496 } else if (!(ch->flags & CHN_F_RUNNING)) in dsp_io_ops()
497 ch->flags |= CHN_F_RUNNING; in dsp_io_ops()
504 ch->inprog++; in dsp_io_ops()
506 ch->inprog--; in dsp_io_ops()
508 CHN_BROADCAST(&ch->cv); in dsp_io_ops()
546 d = priv->sc; in dsp_ioctl_channel()
547 if (!PCM_REGISTERED(d) || !(pcm_getflags(d->dev) & SD_F_VPC)) in dsp_ioctl_channel()
548 return (-1); in dsp_ioctl_channel()
554 rdch = priv->rdch; in dsp_ioctl_channel()
555 wrch = priv->wrch; in dsp_ioctl_channel()
568 if (!(ch->feederflags & (1 << FEEDER_VOLUME))) { in dsp_ioctl_channel()
577 if (ch->direction == PCMDIR_REC) { in dsp_ioctl_channel()
584 if (ch->direction != PCMDIR_PLAY) in dsp_ioctl_channel()
593 if (ch->direction != PCMDIR_REC) in dsp_ioctl_channel()
612 if (ch->direction == PCMDIR_REC) { in dsp_ioctl_channel()
619 if (ch->direction != PCMDIR_PLAY) in dsp_ioctl_channel()
627 if (ch->direction != PCMDIR_REC) in dsp_ioctl_channel()
637 if (ch->direction == PCMDIR_REC) in dsp_ioctl_channel()
697 struct pcm_channel *chn, *rdch, *wrch; in dsp_ioctl() local
705 d = priv->sc; in dsp_ioctl()
714 chn = NULL; in dsp_ioctl()
723 if (ret != -1) { in dsp_ioctl()
728 if (d->mixer_dev != NULL) { in dsp_ioctl()
730 ret = mixer_ioctl_cmd(d->mixer_dev, cmd, arg, -1, td, in dsp_ioctl()
776 rdch = priv->rdch; in dsp_ioctl()
777 wrch = priv->wrch; in dsp_ioctl()
779 if (wrch != NULL && (wrch->flags & CHN_F_DEAD)) in dsp_ioctl()
781 if (rdch != NULL && (rdch->flags & CHN_F_DEAD)) in dsp_ioctl()
794 if (wrch && wrch->bufhard.dl) in dsp_ioctl()
797 *arg_i = sndbuf_getfree(wrch->bufsoft); in dsp_ioctl()
809 p->play_size = 0; in dsp_ioctl()
810 p->rec_size = 0; in dsp_ioctl()
814 chn_setblocksize(wrch, 2, p->play_size); in dsp_ioctl()
815 p->play_size = wrch->bufsoft->blksz; in dsp_ioctl()
820 chn_setblocksize(rdch, 2, p->rec_size); in dsp_ioctl()
821 p->rec_size = rdch->bufsoft->blksz; in dsp_ioctl()
833 p->play_size = wrch->bufsoft->blksz; in dsp_ioctl()
838 p->rec_size = rdch->bufsoft->blksz; in dsp_ioctl()
859 p->play_rate = p32->play_rate; in dsp_ioctl()
860 p->rec_rate = p32->rec_rate; in dsp_ioctl()
861 p->play_format = p32->play_format; in dsp_ioctl()
862 p->rec_format = p32->rec_format; in dsp_ioctl()
866 ((p->play_format != 0 && p->play_rate == 0) || in dsp_ioctl()
867 (p->rec_format != 0 && p->rec_rate == 0))) { in dsp_ioctl()
874 if (cmd == AIOSFMT && p->play_format != 0) { in dsp_ioctl()
876 SND_FORMAT(p->play_format, in dsp_ioctl()
877 AFMT_CHANNEL(wrch->format), in dsp_ioctl()
878 AFMT_EXTCHANNEL(wrch->format))); in dsp_ioctl()
879 chn_setspeed(wrch, p->play_rate); in dsp_ioctl()
881 p->play_rate = wrch->speed; in dsp_ioctl()
882 p->play_format = AFMT_ENCODING(wrch->format); in dsp_ioctl()
885 p->play_rate = 0; in dsp_ioctl()
886 p->play_format = 0; in dsp_ioctl()
890 if (cmd == AIOSFMT && p->rec_format != 0) { in dsp_ioctl()
892 SND_FORMAT(p->rec_format, in dsp_ioctl()
893 AFMT_CHANNEL(rdch->format), in dsp_ioctl()
894 AFMT_EXTCHANNEL(rdch->format))); in dsp_ioctl()
895 chn_setspeed(rdch, p->rec_rate); in dsp_ioctl()
897 p->rec_rate = rdch->speed; in dsp_ioctl()
898 p->rec_format = AFMT_ENCODING(rdch->format); in dsp_ioctl()
901 p->rec_rate = 0; in dsp_ioctl()
902 p->rec_format = 0; in dsp_ioctl()
907 p32->play_rate = p->play_rate; in dsp_ioctl()
908 p32->rec_rate = p->rec_rate; in dsp_ioctl()
909 p32->play_format = p->play_format; in dsp_ioctl()
910 p32->rec_format = p->rec_format; in dsp_ioctl()
930 p->rate_min = p32->rate_min; in dsp_ioctl()
931 p->rate_max = p32->rate_max; in dsp_ioctl()
932 p->formats = p32->formats; in dsp_ioctl()
933 p->bufsize = p32->bufsize; in dsp_ioctl()
934 p->mixers = p32->mixers; in dsp_ioctl()
935 p->inputs = p32->inputs; in dsp_ioctl()
936 p->left = p32->left; in dsp_ioctl()
937 p->right = p32->right; in dsp_ioctl()
949 p->rate_min = max(rcaps? rcaps->minspeed : 0, in dsp_ioctl()
950 pcaps? pcaps->minspeed : 0); in dsp_ioctl()
951 p->rate_max = min(rcaps? rcaps->maxspeed : 1000000, in dsp_ioctl()
952 pcaps? pcaps->maxspeed : 1000000); in dsp_ioctl()
953 p->bufsize = min(rdch? rdch->bufsoft->bufsize : 1000000, in dsp_ioctl()
954 wrch? wrch->bufsoft->bufsize : 1000000); in dsp_ioctl()
956 p->formats = (rdch? chn_getformats(rdch) : 0xffffffff) & in dsp_ioctl()
959 p->formats |= in dsp_ioctl()
960 (pcm_getflags(d->dev) & SD_F_SIMPLEX) ? 0 : in dsp_ioctl()
963 pdev = d->mixer_dev; in dsp_ioctl()
964 p->mixers = 1; /* default: one mixer */ in dsp_ioctl()
965 p->inputs = pdev->si_drv1? mix_getdevs(pdev->si_drv1) : 0; in dsp_ioctl()
966 p->left = p->right = 100; in dsp_ioctl()
974 p32->rate_min = p->rate_min; in dsp_ioctl()
975 p32->rate_max = p->rate_max; in dsp_ioctl()
976 p32->formats = p->formats; in dsp_ioctl()
977 p32->bufsize = p->bufsize; in dsp_ioctl()
978 p32->mixers = p->mixers; in dsp_ioctl()
979 p32->inputs = p->inputs; in dsp_ioctl()
980 p32->left = p->left; in dsp_ioctl()
981 p32->right = p->right; in dsp_ioctl()
1004 ((snd_sync_parm *)arg)->chan, ((snd_sync_parm *)arg)->pos); in dsp_ioctl()
1009 /* if (rdch && rdch->bufhard.dl) in dsp_ioctl()
1012 *arg_i = sndbuf_getready(rdch->bufsoft); in dsp_ioctl()
1024 case SNDCTL_DSP_NONBLOCK: /* set non-blocking i/o */ in dsp_ioctl()
1025 case FIONBIO: /* set/clear non-blocking i/o */ in dsp_ioctl()
1029 rdch->flags |= CHN_F_NBIO; in dsp_ioctl()
1031 rdch->flags &= ~CHN_F_NBIO; in dsp_ioctl()
1037 wrch->flags |= CHN_F_NBIO; in dsp_ioctl()
1039 wrch->flags &= ~CHN_F_NBIO; in dsp_ioctl()
1045 chn = wrch ? wrch : rdch; in dsp_ioctl()
1046 if (chn) { in dsp_ioctl()
1047 CHN_LOCK(chn); in dsp_ioctl()
1048 *arg_i = chn->bufsoft->blksz; in dsp_ioctl()
1049 CHN_UNLOCK(chn); in dsp_ioctl()
1105 tmp = wrch->speed; in dsp_ioctl()
1112 tmp = rdch->speed; in dsp_ioctl()
1120 chn = wrch ? wrch : rdch; in dsp_ioctl()
1121 if (chn) { in dsp_ioctl()
1122 CHN_LOCK(chn); in dsp_ioctl()
1123 *arg_i = chn->speed; in dsp_ioctl()
1124 CHN_UNLOCK(chn); in dsp_ioctl()
1132 tmp = -1; in dsp_ioctl()
1138 SND_FORMAT(wrch->format, *arg_i, 0)); in dsp_ioctl()
1139 tmp = (AFMT_CHANNEL(wrch->format) > 1)? 1 : 0; in dsp_ioctl()
1145 SND_FORMAT(rdch->format, *arg_i, 0)); in dsp_ioctl()
1146 if (tmp == -1) in dsp_ioctl()
1147 tmp = (AFMT_CHANNEL(rdch->format) > 1)? 1 : 0; in dsp_ioctl()
1171 if (!(pcm_getflags(d->dev) & SD_F_BITPERFECT)) { in dsp_ioctl()
1179 ext = m->ext; in dsp_ioctl()
1186 SND_FORMAT(wrch->format, *arg_i, ext)); in dsp_ioctl()
1187 tmp = AFMT_CHANNEL(wrch->format); in dsp_ioctl()
1193 SND_FORMAT(rdch->format, *arg_i, ext)); in dsp_ioctl()
1195 tmp = AFMT_CHANNEL(rdch->format); in dsp_ioctl()
1201 chn = wrch ? wrch : rdch; in dsp_ioctl()
1202 CHN_LOCK(chn); in dsp_ioctl()
1203 *arg_i = AFMT_CHANNEL(chn->format); in dsp_ioctl()
1204 CHN_UNLOCK(chn); in dsp_ioctl()
1209 chn = wrch ? wrch : rdch; in dsp_ioctl()
1210 if (chn) { in dsp_ioctl()
1211 CHN_LOCK(chn); in dsp_ioctl()
1212 *arg_i = AFMT_CHANNEL(chn->format); in dsp_ioctl()
1213 CHN_UNLOCK(chn); in dsp_ioctl()
1221 chn = wrch ? wrch : rdch; in dsp_ioctl()
1222 if (chn) { in dsp_ioctl()
1223 CHN_LOCK(chn); in dsp_ioctl()
1224 *arg_i = chn_getformats(chn); in dsp_ioctl()
1225 CHN_UNLOCK(chn); in dsp_ioctl()
1239 AFMT_CHANNEL(wrch->format), in dsp_ioctl()
1240 AFMT_EXTCHANNEL(wrch->format))); in dsp_ioctl()
1241 tmp = wrch->format; in dsp_ioctl()
1247 AFMT_CHANNEL(rdch->format), in dsp_ioctl()
1248 AFMT_EXTCHANNEL(rdch->format))); in dsp_ioctl()
1250 tmp = rdch->format; in dsp_ioctl()
1256 chn = wrch ? wrch : rdch; in dsp_ioctl()
1257 CHN_LOCK(chn); in dsp_ioctl()
1258 *arg_i = AFMT_ENCODING(chn->format); in dsp_ioctl()
1259 CHN_UNLOCK(chn); in dsp_ioctl()
1286 r_maxfrags = rdch->bufsoft->blkcnt; in dsp_ioctl()
1287 r_fragsz = rdch->bufsoft->blksz; in dsp_ioctl()
1296 maxfrags = wrch->bufsoft->blkcnt; in dsp_ioctl()
1297 fragsz = wrch->bufsoft->blksz; in dsp_ioctl()
1319 struct snd_dbuf *bs = rdch->bufsoft; in dsp_ioctl()
1322 a->bytes = sndbuf_getready(bs); in dsp_ioctl()
1323 a->fragments = a->bytes / bs->blksz; in dsp_ioctl()
1324 a->fragstotal = bs->blkcnt; in dsp_ioctl()
1325 a->fragsize = bs->blksz; in dsp_ioctl()
1337 struct snd_dbuf *bs = wrch->bufsoft; in dsp_ioctl()
1340 a->bytes = sndbuf_getfree(bs); in dsp_ioctl()
1341 a->fragments = a->bytes / bs->blksz; in dsp_ioctl()
1342 a->fragstotal = bs->blkcnt; in dsp_ioctl()
1343 a->fragsize = bs->blksz; in dsp_ioctl()
1354 struct snd_dbuf *bs = rdch->bufsoft; in dsp_ioctl()
1357 a->bytes = bs->total; in dsp_ioctl()
1358 a->blocks = sndbuf_getblocks(bs) - rdch->blocks; in dsp_ioctl()
1359 a->ptr = sndbuf_getfreeptr(bs); in dsp_ioctl()
1360 rdch->blocks = sndbuf_getblocks(bs); in dsp_ioctl()
1371 struct snd_dbuf *bs = wrch->bufsoft; in dsp_ioctl()
1374 a->bytes = bs->total; in dsp_ioctl()
1375 a->blocks = sndbuf_getblocks(bs) - wrch->blocks; in dsp_ioctl()
1376 a->ptr = sndbuf_getreadyptr(bs); in dsp_ioctl()
1377 wrch->blocks = sndbuf_getblocks(bs); in dsp_ioctl()
1387 if (rdch && wrch && !(pcm_getflags(d->dev) & SD_F_SIMPLEX)) in dsp_ioctl()
1389 if (rdch && (rdch->flags & CHN_F_VIRTUAL) != 0) in dsp_ioctl()
1391 if (wrch && (wrch->flags & CHN_F_VIRTUAL) != 0) in dsp_ioctl()
1397 chn = wrch ? wrch : rdch; in dsp_ioctl()
1398 if (chn) { in dsp_ioctl()
1399 CHN_LOCK(chn); in dsp_ioctl()
1400 if (chn->format & AFMT_8BIT) in dsp_ioctl()
1402 else if (chn->format & AFMT_16BIT) in dsp_ioctl()
1404 else if (chn->format & AFMT_24BIT) in dsp_ioctl()
1406 else if (chn->format & AFMT_32BIT) in dsp_ioctl()
1410 CHN_UNLOCK(chn); in dsp_ioctl()
1420 rdch->flags &= ~CHN_F_NOTRIGGER; in dsp_ioctl()
1426 rdch->flags |= CHN_F_NOTRIGGER; in dsp_ioctl()
1432 wrch->flags &= ~CHN_F_NOTRIGGER; in dsp_ioctl()
1438 wrch->flags |= CHN_F_NOTRIGGER; in dsp_ioctl()
1448 if (wrch->flags & CHN_F_TRIGGERED) in dsp_ioctl()
1454 if (rdch->flags & CHN_F_TRIGGERED) in dsp_ioctl()
1462 struct snd_dbuf *bs = wrch->bufsoft; in dsp_ioctl()
1474 wrch->flags &= ~CHN_F_NOTRIGGER; in dsp_ioctl()
1482 * switch to full-duplex mode if card is in half-duplex in dsp_ioctl()
1483 * mode and is able to work in full-duplex mode in dsp_ioctl()
1486 if (rdch && wrch && (pcm_getflags(d->dev) & SD_F_SIMPLEX)) in dsp_ioctl()
1487 pcm_setflags(d->dev, pcm_getflags(d->dev)^SD_F_SIMPLEX); in dsp_ioctl()
1499 chn = rdch; in dsp_ioctl()
1505 chn = rdch; in dsp_ioctl()
1511 chn = wrch; in dsp_ioctl()
1517 chn = wrch; in dsp_ioctl()
1520 ret = dsp_ioctl_channel(priv, chn, xcmd, arg); in dsp_ioctl()
1521 if (ret != -1) { in dsp_ioctl()
1526 if (d->mixer_dev != NULL) { in dsp_ioctl()
1528 ret = mixer_ioctl_cmd(d->mixer_dev, xcmd, arg, -1, td, in dsp_ioctl()
1539 if (d->mixer_dev != NULL) { in dsp_ioctl()
1541 ret = mixer_ioctl_cmd(d->mixer_dev, cmd, arg, -1, td, in dsp_ioctl()
1558 ei->dev = 0; in dsp_ioctl()
1559 ei->ctrl = 0; in dsp_ioctl()
1560 ei->version = 0; /* static for now */ in dsp_ioctl()
1561 ei->strindex[0] = 0; in dsp_ioctl()
1564 ei->nvalues = 1; in dsp_ioctl()
1565 strlcpy(ei->strings, wrch->name, in dsp_ioctl()
1566 sizeof(ei->strings)); in dsp_ioctl()
1568 ei->nvalues = 0; in dsp_ioctl()
1569 ei->strings[0] = '\0'; in dsp_ioctl()
1589 * Flush the software (pre-feed) buffer, but try to minimize playback in dsp_ioctl()
1599 while (wrch->inprog != 0) in dsp_ioctl()
1600 cv_wait(&wrch->cv, &wrch->lock); in dsp_ioctl()
1601 bs = wrch->bufsoft; in dsp_ioctl()
1602 if ((bs->shadbuf != NULL) && (sndbuf_getready(bs) > 0)) { in dsp_ioctl()
1603 bs->sl = sndbuf_getready(bs); in dsp_ioctl()
1604 sndbuf_dispose(bs, bs->shadbuf, sndbuf_getready(bs)); in dsp_ioctl()
1623 while (wrch->inprog != 0) in dsp_ioctl()
1624 cv_wait(&wrch->cv, &wrch->lock); in dsp_ioctl()
1625 bs = wrch->bufsoft; in dsp_ioctl()
1626 if ((bs->shadbuf != NULL) && (bs->sl > 0)) { in dsp_ioctl()
1628 sndbuf_acquire(bs, bs->shadbuf, bs->sl); in dsp_ioctl()
1629 bs->sl = 0; in dsp_ioctl()
1650 chn = (cmd == SNDCTL_DSP_CURRENT_OPTR) ? wrch : rdch; in dsp_ioctl()
1651 if (chn == NULL) in dsp_ioctl()
1659 CHN_LOCK(chn); in dsp_ioctl()
1660 bs = chn->bufsoft; in dsp_ioctl()
1661 oc->samples = bs->total / bs->align; in dsp_ioctl()
1662 oc->fifo_samples = sndbuf_getready(bs) / bs->align; in dsp_ioctl()
1663 CHN_UNLOCK(chn); in dsp_ioctl()
1669 chn = (cmd == SNDCTL_DSP_HALT_OUTPUT) ? wrch : rdch; in dsp_ioctl()
1670 if (chn == NULL) in dsp_ioctl()
1673 CHN_LOCK(chn); in dsp_ioctl()
1674 chn_abort(chn); in dsp_ioctl()
1675 CHN_UNLOCK(chn); in dsp_ioctl()
1686 wrch->lw = (*arg_i > 1) ? *arg_i : 1; in dsp_ioctl()
1691 rdch->lw = (*arg_i > 1) ? *arg_i : 1; in dsp_ioctl()
1722 ei->play_underruns = wrch->xruns; in dsp_ioctl()
1723 wrch->xruns = 0; in dsp_ioctl()
1728 ei->rec_overruns = rdch->xruns; in dsp_ioctl()
1729 rdch->xruns = 0; in dsp_ioctl()
1735 ei32->play_underruns = ei->play_underruns; in dsp_ioctl()
1736 ei32->rec_overruns = ei->rec_overruns; in dsp_ioctl()
1737 ei32->play_ptradjust = ei->play_ptradjust; in dsp_ioctl()
1738 ei32->rec_ptradjust = ei->rec_ptradjust; in dsp_ioctl()
1739 ei32->play_errorcount = ei->play_errorcount; in dsp_ioctl()
1740 ei32->rec_errorcount = ei->rec_errorcount; in dsp_ioctl()
1741 ei32->play_lasterror = ei->play_lasterror; in dsp_ioctl()
1742 ei32->rec_lasterror = ei->rec_lasterror; in dsp_ioctl()
1743 ei32->play_errorparm = ei->play_errorparm; in dsp_ioctl()
1744 ei32->rec_errorparm = ei->rec_errorparm; in dsp_ioctl()
1770 if (!(pcm_getflags(d->dev) & SD_F_BITPERFECT)) in dsp_ioctl()
1799 chn = (cmd == SNDCTL_DSP_GETOPEAKS) ? wrch : rdch; in dsp_ioctl()
1800 if (chn == NULL) in dsp_ioctl()
1806 CHN_LOCK(chn); in dsp_ioctl()
1807 ret = chn_getpeaks(chn, &lpeak, &rpeak); in dsp_ioctl()
1808 if (ret == -1) in dsp_ioctl()
1814 CHN_UNLOCK(chn); in dsp_ioctl()
1869 d = priv->sc; in dsp_poll()
1880 wrch = priv->wrch; in dsp_poll()
1881 rdch = priv->rdch; in dsp_poll()
1883 if (wrch != NULL && !(wrch->flags & CHN_F_DEAD)) { in dsp_poll()
1889 if (rdch != NULL && !(rdch->flags & CHN_F_DEAD)) { in dsp_poll()
1929 * https://lists.freebsd.org/pipermail/freebsd-emulation/2007-June/003698.html in dsp_mmap_single()
1951 d = priv->sc; in dsp_mmap_single()
1958 wrch = priv->wrch; in dsp_mmap_single()
1959 rdch = priv->rdch; in dsp_mmap_single()
1962 if (c == NULL || (c->flags & CHN_F_MMAP_INVALID) || in dsp_mmap_single()
1963 (*offset + size) > c->bufsoft->allocsize || in dsp_mmap_single()
1964 (wrch != NULL && (wrch->flags & CHN_F_MMAP_INVALID)) || in dsp_mmap_single()
1965 (rdch != NULL && (rdch->flags & CHN_F_MMAP_INVALID))) { in dsp_mmap_single()
1972 wrch->flags |= CHN_F_MMAP; in dsp_mmap_single()
1974 rdch->flags |= CHN_F_MMAP; in dsp_mmap_single()
1976 *offset = (uintptr_t)sndbuf_getbufofs(c->bufsoft, *offset); in dsp_mmap_single()
1979 size, nprot, *offset, curthread->td_ucred); in dsp_mmap_single()
2018 * have returned already, meaning it will have set snd_unit to -1, and in dsp_clone()
2022 *dev = d->dsp_dev; in dsp_clone()
2052 ai->dev = unit; in dsp_oss_audioinfo_unavail()
2053 snprintf(ai->name, sizeof(ai->name), "pcm%d (unavailable)", unit); in dsp_oss_audioinfo_unavail()
2054 ai->pid = -1; in dsp_oss_audioinfo_unavail()
2055 strlcpy(ai->cmd, CHN_COMM_UNUSED, sizeof(ai->cmd)); in dsp_oss_audioinfo_unavail()
2056 ai->card_number = unit; in dsp_oss_audioinfo_unavail()
2057 ai->port_number = unit; in dsp_oss_audioinfo_unavail()
2058 ai->mixer_dev = -1; in dsp_oss_audioinfo_unavail()
2059 ai->legacy_device = unit; in dsp_oss_audioinfo_unavail()
2065 * Gathers information about the audio device specified in ai->dev. If
2066 * ai->dev == -1, then this function gathers information about the current
2067 * device. If the call comes in on a non-audio device and ai->dev == -1,
2071 * getting capabilities directly from the sound card driver, side-stepping
2083 * @retval EINVAL ai->dev specifies an invalid device
2099 if (ai->dev == -1 && i_dev->si_devsw != &dsp_cdevsw) in dsp_oss_audioinfo()
2107 if ((ai->dev == -1 && unit == snd_unit) || in dsp_oss_audioinfo()
2108 ai->dev == unit) { in dsp_oss_audioinfo()
2120 if ((ai->dev == -1 && d->dsp_dev == i_dev) || in dsp_oss_audioinfo()
2121 (ai->dev == unit)) { in dsp_oss_audioinfo()
2131 /* Exhausted the search -- nothing is locked, so return. */ in dsp_oss_audioinfo()
2141 ai->dev = unit; in dsp_oss_audioinfo()
2142 strlcpy(ai->name, device_get_desc(d->dev), sizeof(ai->name)); in dsp_oss_audioinfo()
2143 ai->pid = -1; in dsp_oss_audioinfo()
2144 strlcpy(ai->cmd, CHN_COMM_UNKNOWN, sizeof(ai->cmd)); in dsp_oss_audioinfo()
2145 ai->card_number = unit; in dsp_oss_audioinfo()
2146 ai->port_number = unit; in dsp_oss_audioinfo()
2147 ai->mixer_dev = (d->mixer_dev != NULL) ? unit : -1; in dsp_oss_audioinfo()
2148 ai->legacy_device = unit; in dsp_oss_audioinfo()
2149 snprintf(ai->devnode, sizeof(ai->devnode), "/dev/dsp%d", unit); in dsp_oss_audioinfo()
2150 ai->enabled = device_is_attached(d->dev) ? 1 : 0; in dsp_oss_audioinfo()
2151 ai->next_play_engine = 0; in dsp_oss_audioinfo()
2152 ai->next_rec_engine = 0; in dsp_oss_audioinfo()
2153 ai->busy = 0; in dsp_oss_audioinfo()
2154 ai->caps = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER; in dsp_oss_audioinfo()
2155 ai->iformats = 0; in dsp_oss_audioinfo()
2156 ai->oformats = 0; in dsp_oss_audioinfo()
2157 ai->min_rate = INT_MAX; in dsp_oss_audioinfo()
2158 ai->max_rate = 0; in dsp_oss_audioinfo()
2159 ai->min_channels = INT_MAX; in dsp_oss_audioinfo()
2160 ai->max_channels = 0; in dsp_oss_audioinfo()
2174 if ((ex && (ch->flags & CHN_F_VIRTUAL) != 0) || in dsp_oss_audioinfo()
2175 ((!ex && (ch->flags & CHN_F_VIRTUAL) == 0) && in dsp_oss_audioinfo()
2176 (d->pvchancount > 0 || d->rvchancount > 0))) { in dsp_oss_audioinfo()
2181 if ((ch->flags & CHN_F_BUSY) == 0) { in dsp_oss_audioinfo()
2182 ai->busy |= (ch->direction == PCMDIR_PLAY) ? in dsp_oss_audioinfo()
2186 ai->caps |= in dsp_oss_audioinfo()
2187 ((ch->flags & CHN_F_VIRTUAL) ? PCM_CAP_VIRTUAL : 0) | in dsp_oss_audioinfo()
2188 ((ch->direction == PCMDIR_PLAY) ? PCM_CAP_OUTPUT : in dsp_oss_audioinfo()
2196 for (i = 0; caps->fmtlist[i]; i++) { in dsp_oss_audioinfo()
2197 fmts |= AFMT_ENCODING(caps->fmtlist[i]); in dsp_oss_audioinfo()
2198 minch = min(AFMT_CHANNEL(caps->fmtlist[i]), minch); in dsp_oss_audioinfo()
2199 maxch = max(AFMT_CHANNEL(caps->fmtlist[i]), maxch); in dsp_oss_audioinfo()
2202 if (ch->direction == PCMDIR_PLAY) in dsp_oss_audioinfo()
2203 ai->oformats |= fmts; in dsp_oss_audioinfo()
2205 ai->iformats |= fmts; in dsp_oss_audioinfo()
2207 if (ex || (pcm_getflags(d->dev) & SD_F_BITPERFECT)) { in dsp_oss_audioinfo()
2208 ai->min_rate = min(ai->min_rate, caps->minspeed); in dsp_oss_audioinfo()
2209 ai->max_rate = max(ai->max_rate, caps->maxspeed); in dsp_oss_audioinfo()
2211 ai->min_rate = min(ai->min_rate, feeder_rate_min); in dsp_oss_audioinfo()
2212 ai->max_rate = max(ai->max_rate, feeder_rate_max); in dsp_oss_audioinfo()
2214 ai->min_channels = min(ai->min_channels, minch); in dsp_oss_audioinfo()
2215 ai->max_channels = max(ai->max_channels, maxch); in dsp_oss_audioinfo()
2219 if (ai->min_rate == INT_MAX) in dsp_oss_audioinfo()
2220 ai->min_rate = 0; in dsp_oss_audioinfo()
2221 if (ai->min_channels == INT_MAX) in dsp_oss_audioinfo()
2222 ai->min_channels = 0; in dsp_oss_audioinfo()
2235 if (DSP_REGISTERED(priv->sc) && (ch == priv->rdch || ch == priv->wrch)) in dsp_oss_engineinfo_cb()
2244 * Gathers information about the audio device's engine specified in ai->dev.
2245 * If ai->dev == -1, then this function gathers information about the current
2246 * device. If the call comes in on a non-audio device and ai->dev == -1,
2250 * getting capabilities directly from the sound card driver, side-stepping
2260 * @retval EINVAL ai->dev specifies an invalid device
2276 if (ai->dev == -1 && i_dev->si_devsw != &dsp_cdevsw) in dsp_oss_engineinfo()
2302 if ((ai->dev == -1 && devfs_foreach_cdevpriv( in dsp_oss_engineinfo()
2304 ai->dev == nchan) in dsp_oss_engineinfo()
2318 * - a specific PCM device is locked. in dsp_oss_engineinfo()
2319 * - a specific audio channel has been locked, so be in dsp_oss_engineinfo()
2331 ai->dev = nchan; in dsp_oss_engineinfo()
2332 strlcpy(ai->name, ch->name, sizeof(ai->name)); in dsp_oss_engineinfo()
2334 if ((ch->flags & CHN_F_BUSY) == 0) in dsp_oss_engineinfo()
2335 ai->busy = 0; in dsp_oss_engineinfo()
2337 ai->busy = (ch->direction == PCMDIR_PLAY) ? OPEN_WRITE : OPEN_READ; in dsp_oss_engineinfo()
2339 ai->pid = ch->pid; in dsp_oss_engineinfo()
2340 strlcpy(ai->cmd, ch->comm, sizeof(ai->cmd)); in dsp_oss_engineinfo()
2348 * @todo @c SNDCTL_AUDIOINFO::caps - Make drivers keep in dsp_oss_engineinfo()
2351 ai->caps = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER | in dsp_oss_engineinfo()
2352 ((ch->flags & CHN_F_VIRTUAL) ? PCM_CAP_VIRTUAL : 0) | in dsp_oss_engineinfo()
2353 ((ch->direction == PCMDIR_PLAY) ? PCM_CAP_OUTPUT : PCM_CAP_INPUT); in dsp_oss_engineinfo()
2362 for (i = 0; caps->fmtlist[i]; i++) { in dsp_oss_engineinfo()
2363 fmts |= AFMT_ENCODING(caps->fmtlist[i]); in dsp_oss_engineinfo()
2364 minch = min(AFMT_CHANNEL(caps->fmtlist[i]), minch); in dsp_oss_engineinfo()
2365 maxch = max(AFMT_CHANNEL(caps->fmtlist[i]), maxch); in dsp_oss_engineinfo()
2368 if (ch->direction == PCMDIR_PLAY) in dsp_oss_engineinfo()
2369 ai->oformats = fmts; in dsp_oss_engineinfo()
2371 ai->iformats = fmts; in dsp_oss_engineinfo()
2375 * @c magic - OSSv4 docs: "Reserved for internal use in dsp_oss_engineinfo()
2379 * @c card_number - OSSv4 docs: "Number of the sound in dsp_oss_engineinfo()
2380 * card where this device belongs or -1 if this in dsp_oss_engineinfo()
2385 ai->card_number = unit; in dsp_oss_engineinfo()
2387 * @todo @c song_name - depends first on in dsp_oss_engineinfo()
2388 * SNDCTL_[GS]ETSONG @todo @c label - depends in dsp_oss_engineinfo()
2390 * @todo @c port_number - routing information? in dsp_oss_engineinfo()
2392 ai->port_number = unit; in dsp_oss_engineinfo()
2393 ai->mixer_dev = (d->mixer_dev != NULL) ? unit : -1; in dsp_oss_engineinfo()
2396 * @c legacy_device - OSSv4 docs: "Obsolete." in dsp_oss_engineinfo()
2398 ai->legacy_device = unit; in dsp_oss_engineinfo()
2399 snprintf(ai->devnode, sizeof(ai->devnode), "/dev/dsp%d", unit); in dsp_oss_engineinfo()
2400 ai->enabled = device_is_attached(d->dev) ? 1 : 0; in dsp_oss_engineinfo()
2403 * @c flags - OSSv4 docs: "Reserved for future use." in dsp_oss_engineinfo()
2406 * @c binding - OSSv4 docs: "Reserved for future use." in dsp_oss_engineinfo()
2408 * @todo @c handle - haven't decided how to generate in dsp_oss_engineinfo()
2412 if ((ch->flags & CHN_F_EXCLUSIVE) || in dsp_oss_engineinfo()
2413 (pcm_getflags(d->dev) & SD_F_BITPERFECT)) { in dsp_oss_engineinfo()
2414 ai->min_rate = caps->minspeed; in dsp_oss_engineinfo()
2415 ai->max_rate = caps->maxspeed; in dsp_oss_engineinfo()
2417 ai->min_rate = feeder_rate_min; in dsp_oss_engineinfo()
2418 ai->max_rate = feeder_rate_max; in dsp_oss_engineinfo()
2421 ai->min_channels = minch; in dsp_oss_engineinfo()
2422 ai->max_channels = maxch; in dsp_oss_engineinfo()
2424 ai->nrates = chn_getrates(ch, &rates); in dsp_oss_engineinfo()
2425 if (ai->nrates > OSS_MAX_SAMPLE_RATES) in dsp_oss_engineinfo()
2426 ai->nrates = OSS_MAX_SAMPLE_RATES; in dsp_oss_engineinfo()
2428 for (i = 0; i < ai->nrates; i++) in dsp_oss_engineinfo()
2429 ai->rates[i] = rates[i]; in dsp_oss_engineinfo()
2431 ai->next_play_engine = 0; in dsp_oss_engineinfo()
2432 ai->next_rec_engine = 0; in dsp_oss_engineinfo()
2442 /* Exhausted the search -- nothing is locked, so return. */ in dsp_oss_engineinfo()
2468 * @retval non-zero error to be propagated upstream
2491 * - Insert channel(s) into group's member list. in dsp_oss_syncgroup()
2492 * - Set CHN_F_NOTRIGGER on channel(s). in dsp_oss_syncgroup()
2493 * - Stop channel(s). in dsp_oss_syncgroup()
2511 * - Bail if PCM_ENABLE_OUTPUT && wrch == NULL. in dsp_oss_syncgroup()
2512 * - Bail if PCM_ENABLE_INPUT && rdch == NULL. in dsp_oss_syncgroup()
2514 if (((wrch == NULL) && (group->mode & PCM_ENABLE_OUTPUT)) || in dsp_oss_syncgroup()
2515 ((rdch == NULL) && (group->mode & PCM_ENABLE_INPUT))) { in dsp_oss_syncgroup()
2524 if (group->id == 0) { in dsp_oss_syncgroup()
2527 SLIST_INIT(&sg->members); in dsp_oss_syncgroup()
2528 sg->id = alloc_unr(pcmsg_unrhdr); in dsp_oss_syncgroup()
2530 group->id = sg->id; in dsp_oss_syncgroup()
2536 if (sg->id == group->id) in dsp_oss_syncgroup()
2551 if (group->mode & PCM_ENABLE_INPUT) { in dsp_oss_syncgroup()
2558 SLIST_INSERT_HEAD(&sg->members, smrd, link); in dsp_oss_syncgroup()
2559 smrd->parent = sg; in dsp_oss_syncgroup()
2560 smrd->ch = rdch; in dsp_oss_syncgroup()
2563 rdch->flags |= CHN_F_NOTRIGGER; in dsp_oss_syncgroup()
2564 rdch->sm = smrd; in dsp_oss_syncgroup()
2567 if (group->mode & PCM_ENABLE_OUTPUT) { in dsp_oss_syncgroup()
2574 SLIST_INSERT_HEAD(&sg->members, smwr, link); in dsp_oss_syncgroup()
2575 smwr->parent = sg; in dsp_oss_syncgroup()
2576 smwr->ch = wrch; in dsp_oss_syncgroup()
2579 wrch->flags |= CHN_F_NOTRIGGER; in dsp_oss_syncgroup()
2580 wrch->sm = smwr; in dsp_oss_syncgroup()
2587 if ((sg != NULL) && SLIST_EMPTY(&sg->members)) { in dsp_oss_syncgroup()
2588 sg_ids[2] = sg->id; in dsp_oss_syncgroup()
2594 wrch->sm = NULL; in dsp_oss_syncgroup()
2596 rdch->sm = NULL; in dsp_oss_syncgroup()
2627 * @retval non-zero error worthy of propagating upstream to user
2646 if (sg->id == sg_id) in dsp_oss_syncstart()
2657 KASSERT(!SLIST_EMPTY(&sg->members), ("found empty syncgroup")); in dsp_oss_syncstart()
2660 * Attempt to lock all member channels - if any are already in dsp_oss_syncstart()
2664 SLIST_FOREACH(sm, &sg->members, link) { in dsp_oss_syncstart()
2665 if (CHN_TRYLOCK(sm->ch) == 0) { in dsp_oss_syncstart()
2671 SLIST_FOREACH(sm_tmp, &sg->members, link) { in dsp_oss_syncstart()
2675 CHN_UNLOCK(sm_tmp->ch); in dsp_oss_syncstart()
2693 while ((sm = SLIST_FIRST(&sg->members)) != NULL) { in dsp_oss_syncstart()
2694 SLIST_REMOVE_HEAD(&sg->members, link); in dsp_oss_syncstart()
2696 c = sm->ch; in dsp_oss_syncstart()
2697 c->sm = NULL; in dsp_oss_syncstart()
2699 c->flags &= ~CHN_F_NOTRIGGER; in dsp_oss_syncstart()
2789 * a sound card's buffer space directly, bypassing the FreeBSD 2-stage
2810 * <insert any non-printable characters here>. in dsp_oss_cookedmode()
2824 wrch->flags &= ~CHN_F_BITPERFECT; in dsp_oss_cookedmode()
2825 wrch->flags |= (enabled != 0) ? CHN_F_BITPERFECT : 0x00000000; in dsp_oss_cookedmode()
2831 rdch->flags &= ~CHN_F_BITPERFECT; in dsp_oss_cookedmode()
2832 rdch->flags |= (enabled != 0) ? CHN_F_BITPERFECT : 0x00000000; in dsp_oss_cookedmode()
2936 struct pcm_channel *ch = kn->kn_hook; in dsp_kqdetach()
2941 knlist_remove(&ch->bufsoft->sel.si_note, kn, 1); in dsp_kqdetach()
2948 struct pcm_channel *ch = kn->kn_hook; in dsp_kqevent()
2951 if (ch->flags & CHN_F_DEAD) { in dsp_kqevent()
2952 kn->kn_flags |= EV_EOF; in dsp_kqevent()
2955 kn->kn_data = 0; in dsp_kqevent()
2957 if (kn->kn_filter == EVFILT_READ) in dsp_kqevent()
2958 kn->kn_data = sndbuf_getready(ch->bufsoft); in dsp_kqevent()
2960 kn->kn_data = sndbuf_getfree(ch->bufsoft); in dsp_kqevent()
2963 return (kn->kn_data > 0); in dsp_kqevent()
2983 d = priv->sc; in dsp_kqfilter()
2987 switch (kn->kn_filter) { in dsp_kqfilter()
2989 ch = priv->rdch; in dsp_kqfilter()
2992 ch = priv->wrch; in dsp_kqfilter()
2995 kn->kn_hook = NULL; in dsp_kqfilter()
3001 kn->kn_fop = &dsp_filtops; in dsp_kqfilter()
3003 knlist_add(&ch->bufsoft->sel.si_note, kn, 1); in dsp_kqfilter()
3005 kn->kn_hook = ch; in dsp_kqfilter()