32#ifdef HAVE_KERNEL_OPTION_HEADERS
42#include <sys/limits.h>
43#include <sys/sysctl.h>
56SYSCTL_INT(_hw_snd, OID_AUTO, default_auto, CTLFLAG_RWTUN,
57 &
snd_unit_auto, 0,
"assign default unit to a newly attached device");
61SYSCTL_NODE(_hw, OID_AUTO, snd, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
73 0,
"driver version/arch");
92 m = malloc(
sizeof(*
m), M_DEVBUF, M_WAITOK | M_ZERO);
112 mtx_assert(mtx, MA_OWNED);
117snd_setup_intr(device_t
dev,
struct resource *res,
int flags, driver_intr_t hand,
void *param,
void **cookiep)
121 flags &= INTR_MPSAFE;
122 flags |= INTR_TYPE_AV;
123 d = device_get_softc(
dev);
124 if (d != NULL && (
flags & INTR_MPSAFE))
127 return bus_setup_intr(
dev, res,
flags, NULL, hand,
param, cookiep);
177 (
"bogus vchan_create() request num=%d newcnt=%d vcnt=%d",
204 for (i = 0;
caps->fmtlist[i] != 0; i++) {
208 if (
caps->fmtlist[i] != 0) {
219 while (err == 0 && newcnt > vcnt) {
223 else if (err == E2BIG && newcnt > vcnt)
224 device_printf(d->
dev,
225 "%s: err=%d Maximum channel reached.\n",
229 ch->
flags &= ~CHN_F_BUSY;
235 }
else if (newcnt < vcnt) {
237 (
"bogus vchan_destroy() request num=%d", num));
274 pid_t pid,
char *comm,
int devunit)
277 int err, vchancount, vchan_num;
279 KASSERT(d != NULL && ch != NULL && (devunit == -1 ||
282 (
"%s(): invalid d=%p ch=%p direction=%d pid=%d devunit=%d",
327 (devunit == -1 || devunit == -2 ||
c->
unit == devunit)) {
334 }
else if (
c->
unit == devunit) {
343 }
else if ((devunit == -1 || devunit == -2) &&
435 error = sysctl_handle_int(oidp, &unit, 0,
req);
436 if (
error == 0 &&
req->newptr != NULL) {
447 CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_ANYBODY | CTLFLAG_NEEDGIANT, 0,
449 "default sound device");
458 error = sysctl_handle_int(oidp, &v, 0,
req);
459 if (
error == 0 &&
req->newptr != NULL) {
478 CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0,
sizeof(
int),
480 "maximum virtual channel");
487 int udc, device,
chan;
492 KASSERT(num >= -1, (
"invalid num=%d", num));
527 chan = (num == -1) ? 0 : num;
539 device_printf(d->
dev,
540 "channel num=%d allocated!\n",
chan);
545 device_printf(d->
dev,
553 if (*pnum != rpnum) {
554 device_printf(d->
dev,
555 "%s(): WARNING: pnum screwed : dirs=%s pnum=%d rpnum=%d\n",
556 __func__, dirs, *pnum, rpnum);
563 if (devname == NULL) {
564 device_printf(d->
dev,
565 "Failed to query device name udc=0x%08x\n", udc);
570 ch = malloc(
sizeof(*ch), M_DEVBUF, M_WAITOK | M_ZERO);
571 ch->
methods = kobj_create(cls, M_DEVBUF, M_WAITOK | M_ZERO);
579 snprintf(ch->
name,
sizeof(ch->
name),
"%s:%s:%s",
580 device_get_nameunit(ch->
dev), dirs, devname);
585 device_printf(d->
dev,
"chn_init(%s) failed: err = %d\n",
587 kobj_delete(ch->
methods, M_DEVBUF);
606 device_printf(ch->
dev,
"chn_kill(%s) failed, err = %d\n",
611 kobj_delete(ch->
methods, M_DEVBUF);
703 device_printf(d->
dev,
"pcm_chn_create(%s, %d, %p) failed\n",
712 device_printf(d->
dev,
"pcm_chn_add(%s) failed, err=%d\n",
743 int i, best, bestprio, prio;
757 if (prio > bestprio || (prio == bestprio && i == old)) {
807 if (snd_unit < 0 || snd_unit_auto > 1)
846 if (resource_int_value(device_get_name(
dev), device_get_unit(
dev),
"buffersize", &sz) == 0) {
848 RANGE(sz, minbufsz, maxbufsz);
850 device_printf(
dev,
"'buffersize=%d' hint is out of range (%d-%d), using %d\n", x, minbufsz, maxbufsz, sz);
857 device_printf(
dev,
"'buffersize=%d' hint is not a power of 2, using %d\n", sz, x);
885 err = sysctl_handle_int(oidp, &
val, 0,
req);
887 if (err == 0 &&
req->newptr != NULL) {
888 if (!(
val == 0 ||
val == 1)) {
895 d->
flags &= ~SD_F_BITPERFECT;
908sysctl_dev_pcm_clone_flags(SYSCTL_HANDLER_ARGS)
921 err = sysctl_handle_int(oidp, &
flags, 0, req);
923 if (err == 0 &&
req->newptr != NULL) {
936sysctl_dev_pcm_clone_deadline(SYSCTL_HANDLER_ARGS)
948 err = sysctl_handle_int(oidp, &deadline, 0, req);
950 if (err == 0 &&
req->newptr != NULL) {
963sysctl_dev_pcm_clone_gc(SYSCTL_HANDLER_ARGS)
973 err = sysctl_handle_int(oidp, &val, 0, req);
975 if (err == 0 &&
req->newptr != NULL && val != 0) {
980 device_printf(d->
dev,
"clone gc: pruned=%d\n", val);
987sysctl_hw_snd_clone_gc(SYSCTL_HANDLER_ARGS)
993 err = sysctl_handle_int(oidp, &val, 0, req);
995 if (err == 0 &&
req->newptr != NULL && val != 0) {
1005 device_printf(d->
dev,
"clone gc: pruned=%d\n",
1013 CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0,
sizeof(
int),
1014 sysctl_hw_snd_clone_gc,
"I",
1015 "global clone garbage collector");
1043 SYSCTL_ADD_UINT(device_get_sysctl_ctx(
dev),
1044 SYSCTL_CHILDREN(device_get_sysctl_tree(
dev)),
1045 OID_AUTO,
"buffersize", CTLFLAG_RD, &d->
bufsz, 0,
"allocated buffer size");
1046 SYSCTL_ADD_PROC(device_get_sysctl_ctx(
dev),
1047 SYSCTL_CHILDREN(device_get_sysctl_tree(
dev)), OID_AUTO,
1048 "bitperfect", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, d,
1050 "bit-perfect playback/recording (0=disable, 1=enable)");
1051 SYSCTL_ADD_UINT(device_get_sysctl_ctx(
dev),
1052 SYSCTL_CHILDREN(device_get_sysctl_tree(
dev)),
1053 OID_AUTO,
"mode", CTLFLAG_RD, NULL, mode,
1054 "mode (1=mixer, 2=play, 4=rec. The values are OR'ed if more than one"
1055 "mode is supported)");
1057 SYSCTL_ADD_PROC(device_get_sysctl_ctx(
dev),
1058 SYSCTL_CHILDREN(device_get_sysctl_tree(
dev)), OID_AUTO,
1059 "clone_flags", CTLTYPE_UINT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1060 d,
sizeof(d), sysctl_dev_pcm_clone_flags,
"IU",
1062 SYSCTL_ADD_PROC(device_get_sysctl_ctx(
dev),
1063 SYSCTL_CHILDREN(device_get_sysctl_tree(
dev)), OID_AUTO,
1064 "clone_deadline", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
1065 d,
sizeof(d), sysctl_dev_pcm_clone_deadline,
"I",
1066 "clone expiration deadline (ms)");
1067 SYSCTL_ADD_PROC(device_get_sysctl_ctx(
dev),
1068 SYSCTL_CHILDREN(device_get_sysctl_tree(
dev)), OID_AUTO,
1070 CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, d,
sizeof(d),
1071 sysctl_dev_pcm_clone_gc,
"I",
"clone garbage collector");
1086 device_printf(
dev,
"disabled due to an error while initialising: %d\n",
pcm_veto_load);
1092 device_printf(
dev,
"PCMMAXUNIT reached : unit=%d > %d\n",
1095 "Use 'hw.snd.maxunit' tunable to raise the limit.\n");
1099 d = device_get_softc(
dev);
1102 cv_init(&d->
cv, device_get_nameunit(
dev));
1114 if (resource_int_value(device_get_name(
dev), device_get_unit(
dev),
1115 "vpc", &i) != 0 || i != 0)
1118 if (resource_int_value(device_get_name(
dev), device_get_unit(
dev),
1119 "bitperfect", &i) == 0 && i != 0)
1149 if ((numplay == 0 || numrec == 0) && numplay != numrec)
1152 sysctl_ctx_init(&d->play_sysctl_ctx);
1154 SYSCTL_CHILDREN(device_get_sysctl_tree(
dev)), OID_AUTO,
"play",
1155 CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
"playback channels node");
1158 SYSCTL_CHILDREN(device_get_sysctl_tree(
dev)), OID_AUTO,
"rec",
1159 CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
"recording channels node");
1161 if (numplay > 0 || numrec > 0)
1175 d = device_get_softc(
dev);
1178 device_printf(
dev,
"unregister: device not configured\n");
1188 device_printf(
dev,
"unregister: operation in progress\n");
1200 "unregister: channel %s busy (pid %d)\n",
1211 device_printf(
dev,
"unregister: clone busy\n");
1222 device_printf(
dev,
"unregister: mixer busy\n");
1236 d->
flags &= ~SD_F_REGISTERED;
1249 sysctl_ctx_free(&d->play_sysctl_ctx);
1298 static char si_product[] =
"FreeBSD native OSS ABI";
1299 static char si_version[] = __XSTRING(__FreeBSD_version);
1300 static char si_license[] =
"BSD";
1301 static int intnbits =
sizeof(int) * 8;
1310 strlcpy(si->product, si_product,
sizeof(si->product));
1311 strlcpy(si->version, si_version,
sizeof(si->version));
1312 si->versionnum = SOUND_VERSION;
1313 strlcpy(si->license, si_license,
sizeof(si->license));
1320 bzero((
void *)&si->openedaudio,
sizeof(si->openedaudio));
1343 si->openedaudio[j / intnbits] |=
1344 (1 << (j % intnbits));
1351 si->numaudioengines = si->numaudios;
1368 si->numcards = ncards;
1378 bzero((
void *)&si->openedmidi,
sizeof(si->openedmidi));
1384 for (i = 0; i <
sizeof(si->filler)/
sizeof(si->filler[0]); i++)
1402 if (ncards++ != si->card)
1408 strlcpy(si->shortname, device_get_nameunit(d->
dev),
1409 sizeof(si->shortname));
1410 strlcpy(si->longname, device_get_desc(d->
dev),
1411 sizeof(si->longname));
1412 strlcpy(si->hw_info, d->
status,
sizeof(si->hw_info));
1413 si->intr_count = si->ack_count = 0;
int chn_kill(struct pcm_channel *c)
struct pcmchan_caps * chn_getcaps(struct pcm_channel *c)
int chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction)
#define CHN_UNLOCKASSERT(c)
#define PCMDIR_PLAY_VIRTUAL
#define CHN_FOREACH_SAFE(w, x, y, z)
#define CHN_INSERT_SORT_ASCEND(x, y, z)
#define CHN_FOREACH(x, y, z)
#define CHN_LOCKASSERT(c)
#define PCMDIR_REC_VIRTUAL
#define CHN_REMOVE(x, y, z)
struct pcmchan_matrix * m
int snd_clone_busy(struct snd_clone *c)
struct snd_clone * snd_clone_create(int typemask, int maxunit, int deadline, uint32_t flags)
uint32_t snd_clone_setflags(struct snd_clone *c, uint32_t flags)
int snd_clone_setmaxunit(struct snd_clone *c, int maxunit)
int snd_clone_disable(struct snd_clone *c)
uint32_t snd_clone_getflags(struct snd_clone *c)
int snd_clone_setdeadline(struct snd_clone *c, int deadline)
int snd_clone_enable(struct snd_clone *c)
int snd_clone_getdeadline(struct snd_clone *c)
int snd_clone_gc(struct snd_clone *c)
void snd_clone_destroy(struct snd_clone *c)
#define SND_CLONE_DEADLINE_DEFAULT
#define SND_CLONE_GC_UNREF
#define SND_CLONE_GC_ENABLE
#define SND_CLONE_GC_LASTREF
#define SND_CLONE_GC_EXPIRED
void dsp_cdevinfo_init(struct snddev_info *d)
void dsp_cdevinfo_flush(struct snddev_info *d)
char * dsp_unit2name(char *buf, size_t len, int unit)
void feeder_eq_initsys(device_t)
static int midi_modevent(module_t mod, int type, void *data)
int mixer_uninit(device_t dev)
#define RANGE(var, low, high)
int sndstat_unregister(device_t dev)
int sndstat_register(device_t dev, char *str, sndstat_handler handler)
#define SNDSTAT_PREPARE_PCM_BEGIN()
#define SNDSTAT_PREPARE_PCM_ARGS
#define SNDSTAT_PREPARE_PCM_END()
void snd_mtxassert(void *m)
void * snd_mtxcreate(const char *desc, const char *type)
static int pcm_killchan(device_t dev)
void pcm_setflags(device_t dev, uint32_t val)
static int sysctl_dev_pcm_bitperfect(SYSCTL_HANDLER_ARGS)
SYSCTL_NODE(_hw, OID_AUTO, snd, CTLFLAG_RD|CTLFLAG_MPSAFE, 0, "Sound driver")
void * pcm_getdevinfo(device_t dev)
int sound_oss_card_info(oss_card_info *si)
uint32_t pcm_getflags(device_t dev)
SYSCTL_PROC(_hw_snd, OID_AUTO, default_unit, CTLTYPE_INT|CTLFLAG_RWTUN|CTLFLAG_ANYBODY|CTLFLAG_NEEDGIANT, 0, sizeof(int), sysctl_hw_snd_default_unit, "I", "default sound device")
struct unrhdr * pcmsg_unrhdr
Unit number allocator for syncgroup IDs.
int pcm_setvchans(struct snddev_info *d, int direction, int newcnt, int num)
struct pcm_channel * pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, int num, void *devinfo)
static void pcm_setmaxautovchans(struct snddev_info *d, int num)
static u_int8_t pcm_mode_init(struct snddev_info *d)
int pcm_setstatus(device_t dev, char *str)
void snd_mtxfree(void *m)
static char snd_driver_version[]
void sound_oss_sysinfo(oss_sysinfo *si)
Handle OSSv4 SNDCTL_SYSINFO ioctl.
SND_DECLARE_FILE("$FreeBSD$")
int pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo)
int pcm_chn_destroy(struct pcm_channel *ch)
static void pcm_clonereset(struct snddev_info *d)
static int sndstat_prepare_pcm(SNDSTAT_PREPARE_PCM_ARGS)
static int sysctl_hw_snd_maxautovchans(SYSCTL_HANDLER_ARGS)
int pcm_unregister(device_t dev)
int pcm_inprog(struct snddev_info *d, int delta)
static int pcm_best_unit(int old)
int pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
int pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction, pid_t pid, char *comm, int devunit)
int snd_setup_intr(device_t dev, struct resource *res, int flags, driver_intr_t hand, void *param, void **cookiep)
int pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch)
unsigned int pcm_getbuffersize(device_t dev, unsigned int minbufsz, unsigned int deflt, unsigned int maxbufsz)
SYSCTL_INT(_hw_snd, OID_AUTO, default_auto, CTLFLAG_RWTUN, &snd_unit_auto, 0, "assign default unit to a newly attached device")
SYSCTL_STRING(_hw_snd, OID_AUTO, version, CTLFLAG_RD, &snd_driver_version, 0, "driver version/arch")
DEV_MODULE(sound, sound_modevent, NULL)
static int sysctl_hw_snd_default_unit(SYSCTL_HANDLER_ARGS)
MODULE_VERSION(sound, SOUND_MODVER)
int pcm_chnref(struct pcm_channel *c, int ref)
static void pcm_sysinit(device_t)
int pcm_chnrelease(struct pcm_channel *c)
int pcm_chn_remove(struct snddev_info *d, struct pcm_channel *ch)
static int sound_modevent(module_t mod, int type, void *data)
#define PCM_RELEASE_QUICK(x)
#define PCM_LOCKASSERT(d)
#define SND_DEV_DSPHW_VREC
#define PCM_BUSYASSERT(x)
#define SND_DEV_DSPHW_REC
#define SND_DEV_DSPHW_VPLAY
#define PCM_ACQUIRE_QUICK(x)
#define SND_DEV_DSPHW_PLAY
#define PCM_UNLOCKASSERT(d)
#define PCM_REGISTERED(x)
struct pcm_channel::@28 channels
struct pcm_channel * parentchannel
struct snddev_info * parentsnddev
char status[SND_STATUSLEN]
struct snd_clone * clones
struct snddev_info::@49::@50 pcm
struct sysctl_oid * play_sysctl_tree
struct snddev_info::@49 channels
struct sysctl_ctx_list play_sysctl_ctx rec_sysctl_ctx
struct sysctl_oid * rec_sysctl_tree
int snd_mkunit(int u, int d, int c)
int vchan_destroy(struct pcm_channel *c)
int vchan_create(struct pcm_channel *parent, int num)
void vchan_initsys(device_t dev)