add a tunable/sysctl, hw.snd.autovchans. if this is set to a value n where

n > 0, n vchans will be assigned to any devices that subsequently register
with a single playback channel.
This commit is contained in:
Cameron Grant 2001-06-26 21:54:55 +00:00
parent a30e186209
commit cd9766c5f8
3 changed files with 53 additions and 4 deletions

View file

@ -37,6 +37,8 @@ devclass_t pcm_devclass;
int snd_unit = 0;
TUNABLE_INT("hw.snd.unit", &snd_unit);
#endif
int snd_autovchans = 0;
TUNABLE_INT("hw.snd.autovchans", &snd_autovchans);
SYSCTL_NODE(_hw, OID_AUTO, snd, CTLFLAG_RD, 0, "Sound driver");
@ -157,7 +159,7 @@ pcm_chnref(struct pcm_channel *c, int ref)
#ifdef USING_DEVFS
static int
sysctl_hw_sndunit(SYSCTL_HANDLER_ARGS)
sysctl_hw_snd_unit(SYSCTL_HANDLER_ARGS)
{
struct snddev_info *d;
int error, unit;
@ -175,9 +177,26 @@ sysctl_hw_sndunit(SYSCTL_HANDLER_ARGS)
return (error);
}
SYSCTL_PROC(_hw_snd, OID_AUTO, unit, CTLTYPE_INT | CTLFLAG_RW,
0, sizeof(int), sysctl_hw_sndunit, "I", "");
0, sizeof(int), sysctl_hw_snd_unit, "I", "");
#endif
static int
sysctl_hw_snd_autovchans(SYSCTL_HANDLER_ARGS)
{
int v, error;
v = snd_autovchans;
error = sysctl_handle_int(oidp, &v, sizeof(v), req);
if (error == 0 && req->newptr != NULL) {
if (v < 0 || v >= SND_MAXVCHANS)
return EINVAL;
snd_autovchans = v;
}
return (error);
}
SYSCTL_PROC(_hw_snd, OID_AUTO, autovchans, CTLTYPE_INT | CTLFLAG_RW,
0, sizeof(int), sysctl_hw_snd_autovchans, "I", "");
struct pcm_channel *
pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, void *devinfo)
{
@ -296,18 +315,36 @@ int
pcm_addchan(device_t dev, int dir, kobj_class_t cls, void *devinfo)
{
struct snddev_info *d = device_get_softc(dev);
struct pcm_channel *ch;
int err;
struct pcm_channel *ch, *child;
struct pcmchan_children *pce;
int i, err;
ch = pcm_chn_create(d, NULL, cls, dir, devinfo);
if (!ch) {
device_printf(d->dev, "pcm_chn_create(%s, %d, %p) failed\n", cls->name, dir, devinfo);
return ENODEV;
}
err = pcm_chn_add(d, ch);
if (err) {
device_printf(d->dev, "pcm_chn_add(%s) failed, err=%d\n", ch->name, err);
pcm_chn_destroy(ch);
return err;
}
if ((dir == PCMDIR_PLAY) && (d->flags & SD_F_AUTOVCHAN)) {
ch->flags |= CHN_F_BUSY;
for (i = 0; err == 0 && i < snd_autovchans; i++)
err = vchan_create(ch);
if (err) {
device_printf(d->dev, "vchan_create(%d) failed, err=%d\n", i - 1, err);
SLIST_FOREACH(pce, &ch->children, link) {
child = pce->channel;
vchan_destroy(child);
}
return err;
}
}
return err;
@ -370,6 +407,7 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
d->lock = snd_mtxcreate(device_get_nameunit(dev));
snd_mtxlock(d->lock);
d->flags = 0;
d->dev = dev;
d->devinfo = devinfo;
d->chancount = 0;
@ -393,6 +431,9 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
#endif
if (numplay > 0)
vchan_initsys(d);
if (numplay == 1)
d->flags |= SD_F_AUTOVCHAN;
snd_mtxunlock(d->lock);
return 0;
no:

View file

@ -164,6 +164,7 @@ nomenclature:
#define PCMMKMINOR(u, d, c) ((((c) & 0xff) << 16) | (((u) & 0x0f) << 4) | ((d) & 0x0f))
#define SD_F_SIMPLEX 0x00000001
#define SD_F_AUTOVCHAN 0x00000002
#define SD_F_PRIO_RD 0x10000000
#define SD_F_PRIO_WR 0x20000000
#define SD_F_PRIO_SET (SD_F_PRIO_RD | SD_F_PRIO_WR)
@ -190,6 +191,8 @@ int fkchan_kill(struct pcm_channel *c);
*/
#define SND_CDEV_MAJOR 30
#define SND_MAXVCHANS 255
/*
* Minor numbers for the sound driver.
*

View file

@ -348,6 +348,11 @@ sysctl_hw_snd_vchans(SYSCTL_HANDLER_ARGS)
err = sysctl_handle_int(oidp, &newcnt, sizeof(newcnt), req);
if (err == 0 && req->newptr != NULL) {
if (newcnt < 0 || newcnt > SND_MAXVCHANS) {
snd_mtxunlock(d->lock);
return EINVAL;
}
if (newcnt > cnt) {
/* add new vchans - find a parent channel first */
SLIST_FOREACH(sce, &d->channels, link) {