31#ifdef HAVE_KERNEL_OPTION_HEADERS
38#include <sys/rwlock.h>
39#include <sys/sysent.h>
42#include <vm/vm_object.h>
43#include <vm/vm_page.h>
44#include <vm/vm_pager.h>
49SYSCTL_INT(_hw_snd, OID_AUTO, compat_linux_mmap, CTLFLAG_RWTUN,
51 "linux mmap compatibility (-1=force disable 0=auto 1=force enable)");
54SYSCTL_INT(_hw_snd, OID_AUTO, basename_clone, CTLFLAG_RWTUN,
56 "DSP basename cloning (0: Disable; 1: Enabled)");
65#define PCM_RDCH(x) (((struct dsp_cdevinfo *)(x)->si_drv1)->rdch)
66#define PCM_WRCH(x) (((struct dsp_cdevinfo *)(x)->si_drv1)->wrch)
67#define PCM_VOLCH(x) (((struct dsp_cdevinfo *)(x)->si_drv1)->volch)
68#define PCM_SIMPLEX(x) (((struct dsp_cdevinfo *)(x)->si_drv1)->simplex)
70#define DSP_CDEVINFO_CACHESIZE 8
72#define DSP_REGISTERED(x, y) (PCM_REGISTERED(x) && \
73 (y) != NULL && (y)->si_drv1 != NULL)
87 .d_version = D_VERSION,
110#ifdef OSSV4_EXPERIMENT
131 return ((bdev != NULL) ?
pcm_getflags(bdev) : 0xffffffff);
239 (
"bogus %s(), what are you trying to accomplish here?", __func__));
249 TAILQ_FOREACH(cdi, &d->dsp_cdevinfo_pool, link) {
257 TAILQ_REMOVE(&d->dsp_cdevinfo_pool, cdi, link);
258 TAILQ_INSERT_TAIL(&d->dsp_cdevinfo_pool, cdi, link);
263 cdi = malloc(
sizeof(*cdi), M_DEVBUF, M_WAITOK | M_ZERO);
270 TAILQ_INSERT_TAIL(&d->dsp_cdevinfo_pool, cdi, link);
287 (
"bogus %s(), what are you trying to accomplish here?", __func__));
303 TAILQ_REMOVE(&d->dsp_cdevinfo_pool, cdi, link);
304 TAILQ_INSERT_HEAD(&d->dsp_cdevinfo_pool, cdi, link);
312 TAILQ_FOREACH_SAFE(cdi, &d->dsp_cdevinfo_pool, link, tmp) {
313 if (cdi->
busy != 0) {
315 if (cdi->
rdch != NULL)
317 if (cdi->
wrch != NULL)
322 TAILQ_REMOVE(&d->dsp_cdevinfo_pool, cdi, link);
337 KASSERT(d != NULL, (
"NULL snddev_info"));
341 TAILQ_INIT(&d->dsp_cdevinfo_pool);
343 cdi = malloc(
sizeof(*cdi), M_DEVBUF, M_WAITOK | M_ZERO);
344 TAILQ_INSERT_HEAD(&d->dsp_cdevinfo_pool, cdi, link);
353 KASSERT(d != NULL, (
"NULL snddev_info"));
357 cdi = TAILQ_FIRST(&d->dsp_cdevinfo_pool);
358 while (cdi != NULL) {
359 tmp = TAILQ_NEXT(cdi, link);
363 TAILQ_INIT(&d->dsp_cdevinfo_pool);
379#define DSP_F_VALID(x) ((x) & (FREAD | FWRITE))
380#define DSP_F_DUPLEX(x) (((x) & (FREAD | FWRITE)) == (FREAD | FWRITE))
381#define DSP_F_SIMPLEX(x) (!DSP_F_DUPLEX(x))
382#define DSP_F_READ(x) ((x) & FREAD)
383#define DSP_F_WRITE(x) ((x) & FWRITE)
423 {
SND_DEV_DSP,
"dsp_multich",
".",
"dsp", 0, 0, 0, 0,
426 {
SND_DEV_DSP,
"dsp_spdifout",
".",
"dsp", 0, 0, 0, 0,
429 {
SND_DEV_DSP,
"dsp_spdifin",
".",
"dsp", 0, 0, 0, 0,
434#define DSP_FIXUP_ERROR() do { \
435 prio = dsp_get_flags(i_dev); \
436 if (!DSP_F_VALID(flags)) \
438 if (!DSP_F_DUPLEX(flags) && \
439 ((DSP_F_READ(flags) && d->reccount == 0) || \
440 (DSP_F_WRITE(flags) && d->playcount == 0))) \
442 else if (!DSP_F_DUPLEX(flags) && (prio & SD_F_SIMPLEX) && \
443 ((DSP_F_READ(flags) && (prio & SD_F_PRIO_WR)) || \
444 (DSP_F_WRITE(flags) && (prio & SD_F_PRIO_RD)))) \
446 else if (DSP_REGISTERED(d, i_dev)) \
451dsp_open(
struct cdev *i_dev,
int flags,
int mode,
struct thread *td)
456 int i,
error, rderror, wrerror, devtype, wdevunit, rdevunit;
459 if (i_dev == NULL || td == NULL)
531 wdevunit = dev2unit(i_dev);
545 rdevunit = dev2unit(i_dev);
554 panic(
"impossible devtype %d", devtype);
570 td->td_proc->p_pid, td->td_proc->p_comm, rdevunit);
594 if (
flags & O_NONBLOCK)
608 td->td_proc->p_pid, td->td_proc->p_comm, wdevunit);
641 if (
flags & O_NONBLOCK)
659 KASSERT(wrch == NULL, (
"wrch=%p not null!", wrch));
663 KASSERT(rdch == NULL, (
"rdch=%p not null!", rdch));
668 if (wrch == NULL && rdch == NULL) {
705 int sg_ids, rdref, wdref;
731 else if (volch == wrch)
745 if (rdch != NULL || wrch != NULL) {
827 KASSERT(i_dev != NULL &&
buf != NULL &&
828 (
buf->uio_rw == UIO_READ ||
buf->uio_rw == UIO_WRITE),
829 (
"%s(): io train wreck!", __func__));
837 switch (
buf->uio_rw) {
849 panic(
"invalid/corrupted uio direction: %d",
buf->uio_rw);
855 runpid =
buf->uio_td->td_proc->p_pid;
857 getchns(i_dev, &rdch, &wrch, prio);
859 if (*ch == NULL || !((*ch)->flags &
CHN_F_BUSY)) {
860 if (rdch != NULL || wrch != NULL)
861 relchns(i_dev, rdch, wrch, prio);
868 relchns(i_dev, rdch, wrch, prio);
882 ret = chn_io(*ch,
buf);
887 relchns(i_dev, rdch, wrch, prio);
913 KASSERT(
dev != NULL && volch != NULL,
914 (
"%s(): NULL query dev=%p volch=%p", __func__,
dev, volch));
987 if (j == SOUND_MIXER_RECLEV && rdch != NULL)
989 else if (j == SOUND_MIXER_PCM && wrch != NULL)
1016 switch (cmd & ~0xff) {
1017 case MIXER_WRITE(0):
1019 case SOUND_MIXER_MUTE:
1026 case SOUND_MIXER_PCM:
1029 left = *(
int *)arg & 0x7f;
1030 right = ((*(
int *)arg) >> 8) & 0x7f;
1035 case SOUND_MIXER_RECLEV:
1038 left = *(
int *)arg & 0x7f;
1039 right = ((*(
int *)arg) >> 8) & 0x7f;
1052 case SOUND_MIXER_MUTE:
1056 *(
int *)arg = mute << SOUND_MIXER_RECLEV;
1058 *(
int *)arg = mute << SOUND_MIXER_PCM;
1061 case SOUND_MIXER_PCM:
1069 case SOUND_MIXER_RECLEV:
1077 case SOUND_MIXER_DEVMASK:
1078 case SOUND_MIXER_CAPS:
1079 case SOUND_MIXER_STEREODEVS:
1081 *(
int *)arg = SOUND_MASK_RECLEV;
1083 *(
int *)arg = SOUND_MASK_PCM;
1099dsp_ioctl(
struct cdev *i_dev, u_long cmd, caddr_t arg,
int mode,
1105 int *arg_i, ret, tmp;
1118 if (IOCGROUP(cmd) ==
'M') {
1119 if (cmd == OSS_GETVERSION) {
1120 *arg_i = SOUND_VERSION;
1147 if (IOCGROUP(cmd) ==
'X') {
1150 case SNDCTL_SYSINFO:
1153 case SNDCTL_CARDINFO:
1156 case SNDCTL_AUDIOINFO:
1157 case SNDCTL_AUDIOINFO_EX:
1158 case SNDCTL_ENGINEINFO:
1161 case SNDCTL_MIXERINFO:
1172 getchns(i_dev, &rdch, &wrch, 0);
1179 if (wrch == NULL && rdch == NULL) {
1206 struct snd_size *p = (
struct snd_size *)arg;
1228 struct snd_size *p = (
struct snd_size *)arg;
1246 snd_chan_param *p = (snd_chan_param *)arg;
1248 if (cmd == AIOSFMT &&
1249 ((p->play_format != 0 && p->play_rate == 0) ||
1250 (p->rec_format != 0 && p->rec_rate == 0))) {
1257 if (cmd == AIOSFMT && p->play_format != 0) {
1264 p->play_rate = wrch->
speed;
1273 if (cmd == AIOSFMT && p->rec_format != 0) {
1280 p->rec_rate = rdch->
speed;
1293 snd_capabilities *p = (snd_capabilities *)arg;
1306 p->rate_min =
max(rcaps? rcaps->minspeed : 0,
1308 p->rate_max = min(rcaps? rcaps->maxspeed : 1000000,
1319 p->inputs = pdev->si_drv1?
mix_getdevs(pdev->si_drv1) : 0;
1320 p->left = p->right = 100;
1330 if (*arg_i == AIOSYNC_PLAY && wrch) {
1334 }
else if (*arg_i == AIOSYNC_CAPTURE && rdch) {
1339 printf(
"AIOSTOP: bad channel 0x%x\n", *arg_i);
1345 printf(
"AIOSYNC chan 0x%03lx pos %lu unimplemented\n",
1346 ((snd_sync_parm *)arg)->
chan, ((snd_sync_parm *)arg)->pos);
1367 DEB( printf(
"FIOASYNC\n") ; )
1370 case SNDCTL_DSP_NONBLOCK:
1374 if (cmd == SNDCTL_DSP_NONBLOCK || *arg_i)
1377 rdch->
flags &= ~CHN_F_NBIO;
1382 if (cmd == SNDCTL_DSP_NONBLOCK || *arg_i)
1385 wrch->
flags &= ~CHN_F_NBIO;
1393#define THE_REAL_SNDCTL_DSP_GETBLKSIZE _IOWR('P', 4, int)
1395 case SNDCTL_DSP_GETBLKSIZE:
1396 chn = wrch ? wrch : rdch;
1407 case SNDCTL_DSP_SETBLKSIZE:
1408 RANGE(*arg_i, 16, 65536);
1423 case SNDCTL_DSP_RESET:
1424 DEB(printf(
"dsp reset\n"));
1439 case SNDCTL_DSP_SYNC:
1440 DEB(printf(
"dsp sync\n"));
1449 case SNDCTL_DSP_SPEED:
1459 if (rdch && ret == 0) {
1470 case SOUND_PCM_READ_RATE:
1471 chn = wrch ? wrch : rdch;
1474 *arg_i = chn->
speed;
1482 case SNDCTL_DSP_STEREO:
1484 *arg_i = (*arg_i)? 2 : 1;
1493 if (rdch && ret == 0) {
1505 case SOUND_PCM_WRITE_CHANNELS:
1534 if (rdch && ret == 0) {
1545 chn = wrch ? wrch : rdch;
1552 case SOUND_PCM_READ_CHANNELS:
1553 chn = wrch ? wrch : rdch;
1564 case SNDCTL_DSP_GETFMTS:
1565 chn = wrch ? wrch : rdch;
1576 case SNDCTL_DSP_SETFMT:
1577 if (*arg_i != AFMT_QUERY) {
1588 if (rdch && ret == 0) {
1600 chn = wrch ? wrch : rdch;
1607 case SNDCTL_DSP_SETFRAGMENT:
1608 DEB(printf(
"SNDCTL_DSP_SETFRAGMENT 0x%08x\n", *(
int *)arg));
1610 uint32_t fragln = (*arg_i) & 0x0000ffff;
1611 uint32_t maxfrags = ((*arg_i) & 0xffff0000) >> 16;
1613 uint32_t r_maxfrags, r_fragsz;
1615 RANGE(fragln, 4, 16);
1616 fragsz = 1 << fragln;
1625 DEB(printf(
"SNDCTL_DSP_SETFRAGMENT %d frags, %d sz\n", maxfrags, fragsz));
1634 r_maxfrags = maxfrags;
1637 if (wrch && ret == 0) {
1644 maxfrags = r_maxfrags;
1650 while (fragsz > 1) {
1654 *arg_i = (maxfrags << 16) | fragln;
1658 case SNDCTL_DSP_GETISPACE:
1661 audio_buf_info *a = (audio_buf_info *)arg;
1676 case SNDCTL_DSP_GETOSPACE:
1679 audio_buf_info *a = (audio_buf_info *)arg;
1695 case SNDCTL_DSP_GETIPTR:
1697 count_info *a = (count_info *)arg;
1713 case SNDCTL_DSP_GETOPTR:
1715 count_info *a = (count_info *)arg;
1731 case SNDCTL_DSP_GETCAPS:
1733 *arg_i = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER;
1735 *arg_i |= PCM_CAP_DUPLEX;
1737 *arg_i |= PCM_CAP_VIRTUAL;
1739 *arg_i |= PCM_CAP_VIRTUAL;
1743 case SOUND_PCM_READ_BITS:
1744 chn = wrch ? wrch : rdch;
1764 case SNDCTL_DSP_SETTRIGGER:
1767 rdch->
flags &= ~CHN_F_NOTRIGGER;
1768 if (*arg_i & PCM_ENABLE_INPUT)
1779 wrch->
flags &= ~CHN_F_NOTRIGGER;
1780 if (*arg_i & PCM_ENABLE_OUTPUT)
1791 case SNDCTL_DSP_GETTRIGGER:
1796 *arg_i |= PCM_ENABLE_OUTPUT;
1802 *arg_i |= PCM_ENABLE_INPUT;
1807 case SNDCTL_DSP_GETODELAY:
1819 case SNDCTL_DSP_POST:
1822 wrch->
flags &= ~CHN_F_NOTRIGGER;
1828 case SNDCTL_DSP_SETDUPLEX:
1844 case SNDCTL_DSP_GETRECVOL:
1846 xcmd = SOUND_MIXER_READ_RECLEV;
1850 case SNDCTL_DSP_SETRECVOL:
1852 xcmd = SOUND_MIXER_WRITE_RECLEV;
1856 case SNDCTL_DSP_GETPLAYVOL:
1858 xcmd = SOUND_MIXER_READ_PCM;
1862 case SNDCTL_DSP_SETPLAYVOL:
1864 xcmd = SOUND_MIXER_WRITE_PCM;
1884 case SNDCTL_DSP_GET_RECSRC_NAMES:
1885 case SNDCTL_DSP_GET_RECSRC:
1886 case SNDCTL_DSP_SET_RECSRC:
1902 case SNDCTL_DSP_GET_PLAYTGT_NAMES:
1904 oss_mixer_enuminfo *ei;
1905 ei = (oss_mixer_enuminfo *)arg;
1909 ei->strindex[0] = 0;
1913 strlcpy(ei->strings, wrch->
name,
1914 sizeof(ei->strings));
1917 ei->strings[0] =
'\0';
1921 case SNDCTL_DSP_GET_PLAYTGT:
1922 case SNDCTL_DSP_SET_PLAYTGT:
1935 case SNDCTL_DSP_SILENCE:
1947 while (wrch->
inprog != 0)
1948 cv_wait(&wrch->
cv, wrch->
lock);
1960 case SNDCTL_DSP_SKIP:
1971 while (wrch->
inprog != 0)
1972 cv_wait(&wrch->
cv, wrch->
lock);
1974 if ((bs->
shadbuf != NULL) && (bs->
sl > 0)) {
1984 case SNDCTL_DSP_CURRENT_OPTR:
1985 case SNDCTL_DSP_CURRENT_IPTR:
1998 chn = (cmd == SNDCTL_DSP_CURRENT_OPTR) ? wrch : rdch;
2005 oss_count_t *oc = (oss_count_t *)arg;
2021 case SNDCTL_DSP_HALT_OUTPUT:
2022 case SNDCTL_DSP_HALT_INPUT:
2023 chn = (cmd == SNDCTL_DSP_HALT_OUTPUT) ? wrch : rdch;
2033 case SNDCTL_DSP_LOW_WATER:
2040 wrch->
lw = (*arg_i > 1) ? *arg_i : 1;
2045 rdch->
lw = (*arg_i > 1) ? *arg_i : 1;
2050 case SNDCTL_DSP_GETERROR:
2059 audio_errinfo *ei = (audio_errinfo *)arg;
2061 bzero((
void *)ei,
sizeof(*ei));
2065 ei->play_underruns = wrch->
xruns;
2071 ei->rec_overruns = rdch->
xruns;
2078 case SNDCTL_DSP_SYNCGROUP:
2084 case SNDCTL_DSP_SYNCSTART:
2090 case SNDCTL_DSP_POLICY:
2096 case SNDCTL_DSP_COOKEDMODE:
2102 case SNDCTL_DSP_GET_CHNORDER:
2107 case SNDCTL_DSP_SET_CHNORDER:
2112 case SNDCTL_DSP_GETCHANNELMASK:
2117 case SNDCTL_DSP_BIND_CHANNEL:
2120#ifdef OSSV4_EXPERIMENT
2125 case SNDCTL_DSP_GETOPEAKS:
2126 case SNDCTL_DSP_GETIPEAKS:
2127 chn = (cmd == SNDCTL_DSP_GETOPEAKS) ? wrch : rdch;
2131 oss_peaks_t *op = (oss_peaks_t *)arg;
2150 case SNDCTL_GETLABEL:
2151 ret = dsp_oss_getlabel(wrch, rdch, (oss_label_t *)arg);
2153 case SNDCTL_SETLABEL:
2154 ret = dsp_oss_setlabel(wrch, rdch, (oss_label_t *)arg);
2156 case SNDCTL_GETSONG:
2157 ret = dsp_oss_getsong(wrch, rdch, (oss_longname_t *)arg);
2159 case SNDCTL_SETSONG:
2160 ret = dsp_oss_setsong(wrch, rdch, (oss_longname_t *)arg);
2162 case SNDCTL_SETNAME:
2163 ret = dsp_oss_setname(wrch, rdch, (oss_longname_t *)arg);
2171 case SNDCTL_DSP_READCTL:
2172 case SNDCTL_DSP_WRITECTL:
2178 case SNDCTL_DSP_MAPINBUF:
2179 case SNDCTL_DSP_MAPOUTBUF:
2180 case SNDCTL_DSP_SETSYNCRO:
2183 case SNDCTL_DSP_SUBDIVIDE:
2184 case SOUND_PCM_WRITE_FILTER:
2185 case SOUND_PCM_READ_FILTER:
2189 DEB(printf(
"default ioctl fn 0x%08lx fail\n", cmd));
2200dsp_poll(
struct cdev *i_dev,
int events,
struct thread *td)
2209 return (events & (POLLHUP | POLLPRI | POLLIN |
2210 POLLRDNORM | POLLOUT | POLLWRNORM));
2221 e = (events & (POLLOUT | POLLWRNORM));
2227 e = (events & (POLLIN | POLLRDNORM));
2240dsp_mmap(
struct cdev *i_dev, vm_ooffset_t offset, vm_paddr_t *paddr,
2241 int nprot, vm_memattr_t *memattr)
2248 *paddr = vtophys(
offset);
2254 vm_size_t size,
struct vm_object **
object,
int nprot)
2270 SV_CURPROC_ABI() != SV_ABI_LINUX)))
2281 if ((nprot & (PROT_READ | PROT_WRITE)) == 0)
2292 c = ((nprot & PROT_WRITE) != 0) ? wrch : rdch;
2309 *
object = vm_pager_allocate(OBJT_DEVICE, i_dev,
2314 if (*
object == NULL)
2325 len = strlen(namep);
2326 if (strncmp(
name, namep,
len) != 0)
2331 if (isdigit(*
name) == 0)
2339 for (*u = 0; isdigit(*
name) != 0;
name++) {
2347 return ((
use_sep == 0) ? 0 : ENODEV);
2354 if (*
name ==
'0' &&
name[1] !=
'\0')
2357 for (*
c = 0; isdigit(*
name) != 0;
name++) {
2373 char *
name,
int namelen,
struct cdev **
dev)
2378 int i,
unit, udcmask, cunit, devtype, devhw, devcmax, tumax;
2379 char *devname, *devcmp, *devsep;
2395 for (i = 0;
unit == -1 &&
2401 if (devname == NULL)
2405 if (strcmp(
name, devcmp) == 0) {
2435 (
"overflow: devcmax=%d, dsp_cmax=%d", devcmax,
dsp_cmax));
2436 if (cunit > devcmax) {
2443 if (
c->
unit != udcmask) {
2448 udcmask &= ~snd_c2unit(cunit);
2470 goto dsp_clone_alloc;
2479 udcmask &= ~snd_c2unit(cunit);
2485 goto dsp_clone_alloc;
2498 UID_ROOT, GID_WHEEL, 0666,
"%s%d%s%d",
2499 devname,
unit, devsep, cunit);
2526 EVENTHANDLER_DEREGISTER(dev_clone,
dsp_ehtag);
2538 KASSERT(
buf != NULL &&
len != 0,
2539 (
"bogus buf=%p len=%ju",
buf, (uintmax_t)
len));
2593 int i, nchan, *
rates, minch, maxch;
2601 if (ai->dev == -1 && i_dev->si_devsw != &
dsp_cdevsw)
2628 if (ai->dev == -1) {
2635 }
else if (ai->dev == nchan) {
2639 if (devname != NULL)
2645 if (devname != NULL) {
2660 bzero((
void *)ai,
sizeof(oss_audioinfo));
2663 strlcpy(ai->name, ch->
name,
sizeof(ai->name));
2688 ai->caps = PCM_CAP_REALTIME | PCM_CAP_MMAP | PCM_CAP_TRIGGER |
2705 for (i = 0; caps->
fmtlist[i]; i++) {
2708 minch = (minch == 0) ? 2 : minch;
2712 maxch = (maxch == 0) ? 1 : maxch;
2717 ai->oformats =
fmts;
2719 ai->iformats =
fmts;
2733 ai->card_number = -1;
2740 ai->port_number = -1;
2746 ai->real_device = -1;
2747 strlcpy(ai->devnode,
"/dev/",
sizeof(ai->devnode));
2748 strlcat(ai->devnode, devname,
sizeof(ai->devnode));
2749 ai->enabled = device_is_attached(d->
dev) ? 1 : 0;
2763 ai->min_channels = minch;
2764 ai->max_channels = maxch;
2767 if (ai->nrates > OSS_MAX_SAMPLE_RATES)
2768 ai->nrates = OSS_MAX_SAMPLE_RATES;
2770 for (i = 0; i < ai->nrates; i++)
2771 ai->rates[i] =
rates[i];
2773 ai->next_play_engine = 0;
2774 ai->next_rec_engine = 0;
2781 if (devname != NULL)
2829 sg_ids[0] = sg_ids[1] = sg_ids[2] = 0;
2857 if (((wrch == NULL) && (group->mode & PCM_ENABLE_OUTPUT)) ||
2858 ((rdch == NULL) && (group->mode & PCM_ENABLE_INPUT))) {
2867 if (group->id == 0) {
2870 SLIST_INIT(&sg->members);
2879 if (sg->
id == group->id)
2894 if (group->mode & PCM_ENABLE_INPUT) {
2901 SLIST_INSERT_HEAD(&sg->members, smrd, link);
2910 if (group->mode & PCM_ENABLE_OUTPUT) {
2917 SLIST_INSERT_HEAD(&sg->members, smwr, link);
2929 free(smrd, M_DEVBUF);
2930 if ((sg != NULL) && SLIST_EMPTY(&sg->members)) {
2989 if (sg->
id == sg_id)
3000 KASSERT(!SLIST_EMPTY(&sg->members), (
"found empty syncgroup"));
3007 SLIST_FOREACH(
sm, &sg->members, link) {
3009 int timo = hz * 5/1000;
3014 SLIST_FOREACH(sm_tmp, &sg->members, link) {
3023 PRIBIO | PCATCH,
"pcmsg", timo);
3024 if (ret == EINTR || ret == ERESTART)
3031 }
while (needlocks && ret == 0);
3036 while ((
sm = SLIST_FIRST(&sg->members)) != NULL) {
3037 SLIST_REMOVE_HEAD(&sg->members, link);
3042 c->
flags &= ~CHN_F_NOTRIGGER;
3111 if (wrch && ret == 0) {
3155 if (!(enabled == 1 || enabled == 0))
3163 enabled ^= 0x00000001;
3167 wrch->
flags &= ~CHN_F_BITPERFECT;
3174 rdch->
flags &= ~CHN_F_BITPERFECT;
3205 ch = (wrch != NULL) ? wrch : rdch;
3243 if (ret == 0 && rdch != NULL) {
3261 ch = (wrch != NULL) ? wrch : rdch;
3276#ifdef OSSV4_EXPERIMENT
u_int64_t sndbuf_gettotal(struct snd_dbuf *b)
int sndbuf_acquire(struct snd_dbuf *b, u_int8_t *from, unsigned int count)
Acquire buffer space to extend ready area.
unsigned int sndbuf_getblkcnt(struct snd_dbuf *b)
unsigned int sndbuf_getalign(struct snd_dbuf *b)
unsigned int sndbuf_getblksz(struct snd_dbuf *b)
unsigned int sndbuf_getfreeptr(struct snd_dbuf *b)
void sndbuf_fillsilence(struct snd_dbuf *b)
Zap buffer contents, resetting "ready area" fields.
unsigned int sndbuf_getfree(struct snd_dbuf *b)
unsigned int sndbuf_getready(struct snd_dbuf *b)
unsigned int sndbuf_getsize(struct snd_dbuf *b)
void sndbuf_softreset(struct snd_dbuf *b)
Reset buffer w/o flushing statistics.
unsigned int sndbuf_gethwptr(struct snd_dbuf *b)
void * sndbuf_getbufofs(struct snd_dbuf *b, unsigned int ofs)
u_int64_t sndbuf_getblocks(struct snd_dbuf *b)
int sndbuf_dispose(struct snd_dbuf *b, u_int8_t *to, unsigned int count)
Dispose samples from channel buffer, increasing size of ready area.
unsigned int sndbuf_getreadyptr(struct snd_dbuf *b)
int chn_reset(struct pcm_channel *c, uint32_t fmt, uint32_t spd)
void chn_vpc_reset(struct pcm_channel *c, int vc, int force)
int chn_syncdestroy(struct pcm_channel *c)
Remove channel from a sync group, if there is one.
int chn_flush(struct pcm_channel *c)
int chn_read(struct pcm_channel *c, struct uio *buf)
int chn_setspeed(struct pcm_channel *c, uint32_t speed)
int chn_setvolume_multi(struct pcm_channel *c, int vc, int left, int right, int center)
int chn_oss_setorder(struct pcm_channel *c, unsigned long long *map)
int chn_poll(struct pcm_channel *c, int ev, struct thread *td)
int chn_setlatency(struct pcm_channel *c, int latency)
struct pcmchan_caps * chn_getcaps(struct pcm_channel *c)
int chn_abort(struct pcm_channel *c)
int chn_setformat(struct pcm_channel *c, uint32_t format)
int chn_oss_getorder(struct pcm_channel *c, unsigned long long *map)
int chn_setblocksize(struct pcm_channel *c, int blkcnt, int blksz)
int chn_getrates(struct pcm_channel *c, int **rates)
Fetch array of supported discrete sample rates.
int chn_oss_getmask(struct pcm_channel *c, uint32_t *retmask)
void chn_resetbuf(struct pcm_channel *c)
int chn_sync(struct pcm_channel *c, int threshold)
struct pcm_synclist snd_pcm_syncgroups
syncgroups' master list
int chn_write(struct pcm_channel *c, struct uio *buf)
u_int32_t chn_getformats(struct pcm_channel *c)
u_int32_t chn_start(struct pcm_channel *c, int force)
int chn_getptr(struct pcm_channel *c)
Queries sound driver for sample-aligned hardware buffer pointer index.
struct mtx snd_pcm_syncgroups_mtx
Channel sync group lock.
int chn_setmute_multi(struct pcm_channel *c, int vc, int mute)
#define CHN_UNLOCKASSERT(c)
#define CHN_GETVOLUME(x, y, z)
#define CHN_F_MMAP_INVALID
#define CHN_GETMUTE(x, y, z)
#define CHN_INSERT_HEAD(x, y, z)
#define CHN_FOREACH(x, y, z)
#define CHN_REMOVE(x, y, z)
#define CHN_2NDBUFMAXSIZE
struct pcmchan_matrix * m
struct snd_clone_entry * snd_clone_alloc(struct snd_clone *c, struct cdev **dev, int *unit, int tmask)
int snd_clone_setmaxunit(struct snd_clone *c, int maxunit)
int snd_clone_acquire(struct cdev *dev)
void snd_clone_register(struct snd_clone_entry *ce, struct cdev *dev)
int snd_clone_release(struct cdev *dev)
int snd_clone_getmaxunit(struct snd_clone *c)
int snd_clone_unref(struct cdev *dev)
int snd_clone_ref(struct cdev *dev)
#define snd_clone_disabled(x)
static d_write_t dsp_write
static int dsp_basename_clone
void dsp_cdevinfo_init(struct snddev_info *d)
static int dsp_mmap_allow_prot_exec
static void dsp_cdevinfo_alloc(struct cdev *dev, struct pcm_channel *rdch, struct pcm_channel *wrch, struct pcm_channel *volch)
static int dsp_oss_cookedmode(struct pcm_channel *wrch, struct pcm_channel *rdch, int enabled)
Enable or disable "cooked" mode.
static void dsp_clone(void *arg, struct ucred *cred, char *name, int namelen, struct cdev **dev)
static int dsp_oss_getchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map)
Retrieve channel interleaving order.
static int dsp_oss_syncgroup(struct pcm_channel *wrch, struct pcm_channel *rdch, oss_syncgroup *group)
Assigns a PCM channel to a sync group.
static uint32_t dsp_get_flags(struct cdev *dev)
static int dsp_oss_getchannelmask(struct pcm_channel *wrch, struct pcm_channel *rdch, int *mask)
static void dsp_sysuninit(void *p)
SYSINIT(dsp_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, dsp_sysinit, NULL)
static struct snddev_info * dsp_get_info(struct cdev *dev)
SYSCTL_INT(_hw_snd, OID_AUTO, compat_linux_mmap, CTLFLAG_RWTUN, &dsp_mmap_allow_prot_exec, 0, "linux mmap compatibility (-1=force disable 0=auto 1=force enable)")
static eventhandler_tag dsp_ehtag
static int dsp_stdclone(char *name, char *namep, char *sep, int use_sep, int *u, int *c)
void dsp_cdevinfo_flush(struct snddev_info *d)
static int getchns(struct cdev *dev, struct pcm_channel **rdch, struct pcm_channel **wrch, uint32_t prio)
static void relchns(struct cdev *dev, struct pcm_channel *rdch, struct pcm_channel *wrch, uint32_t prio)
static d_close_t dsp_close
static int dsp_oss_syncstart(int sg_id)
Launch a sync group into action.
SND_DECLARE_FILE("$FreeBSD$")
static void dsp_set_flags(struct cdev *dev, uint32_t flags)
static int dsp_ioctl_channel(struct cdev *dev, struct pcm_channel *volch, u_long cmd, caddr_t arg)
SYSUNINIT(dsp_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, dsp_sysuninit, NULL)
static d_mmap_single_t dsp_mmap_single
static int dsp_oss_policy(struct pcm_channel *wrch, struct pcm_channel *rdch, int policy)
Handler for SNDCTL_DSP_POLICY.
#define DSP_REGISTERED(x, y)
#define THE_REAL_SNDCTL_DSP_GETBLKSIZE
static int dsp_get_volume_channel(struct cdev *dev, struct pcm_channel **volch)
static d_ioctl_t dsp_ioctl
static __inline int dsp_io_ops(struct cdev *i_dev, struct uio *buf)
#define DSP_CDEVINFO_CACHESIZE
static int dsp_oss_setchnorder(struct pcm_channel *wrch, struct pcm_channel *rdch, unsigned long long *map)
Specify channel interleaving order.
static const struct @35 dsp_cdevs[]
char * dsp_unit2name(char *buf, size_t len, int unit)
static void dsp_cdevinfo_free(struct cdev *dev)
#define DSP_FIXUP_ERROR()
int dsp_oss_audioinfo(struct cdev *i_dev, oss_audioinfo *ai)
Handler for SNDCTL_AUDIOINFO.
static void dsp_sysinit(void *p)
struct pcmchan_matrix * feeder_matrix_default_channel_map(uint32_t)
int mixer_ioctl_cmd(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode, struct thread *td, int from)
u_int32_t mix_getdevs(struct snd_mixer *m)
int mixer_oss_mixerinfo(struct cdev *i_dev, oss_mixerinfo *mi)
Handler for SNDCTL_MIXERINFO.
#define RANGE(var, low, high)
void pcm_setflags(device_t dev, uint32_t val)
int sound_oss_card_info(oss_card_info *si)
uint32_t pcm_getflags(device_t dev)
struct unrhdr * pcmsg_unrhdr
Unit number allocator for syncgroup IDs.
void sound_oss_sysinfo(oss_sysinfo *si)
Handle OSSv4 SNDCTL_SYSINFO ioctl.
int pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction, pid_t pid, char *comm, int devunit)
int pcm_chnref(struct pcm_channel *c, int ref)
int pcm_chnrelease(struct pcm_channel *c)
#define PCM_GIANT_LEAVE(x)
#define SND_FORMAT(f, c, e)
#define PCM_RELEASE_QUICK(x)
#define PCM_LOCKASSERT(d)
#define SND_DEV_DSPHW_VREC
#define DSP_DEFAULT_SPEED
#define PCM_BUSYASSERT(x)
#define PCM_GIANT_EXIT(x)
#define SND_DEV_DSPHW_REC
#define SND_DEV_DSPHW_VPLAY
#define PCM_ACQUIRE_QUICK(x)
#define SND_DEV_DSPHW_PLAY
#define AFMT_EXTCHANNEL(v)
#define PCM_UNLOCKASSERT(d)
#define PCM_GIANT_ENTER(x)
#define PCM_REGISTERED(x)
struct pcm_channel * volch
struct pcm_channel * rdch
struct pcm_channel * wrch
struct pcmchan_syncmember * sm
struct pcm_channel::@28 channels
struct snd_dbuf * bufsoft
Specifies an audio device sync group.
Specifies a container for members of a sync group.
struct pcmchan_syncgroup * parent
struct snd_clone * clones
struct snddev_info::@49 channels