mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-06 17:18:32 +00:00
sound: Retire unit.*
The unit.* code is largely obsolete and imposes limits that are no longer needed nowadays. - Capping the maximum allowed soundcards in a given machine. By default, the limit is 512 (snd_max_u() in unit.c), and the maximum possible is 2048 (SND_UNIT_UMAX in unit.h). It can also be tuned through the hw.snd.maxunit loader(8) tunable. Even though these limits are large enough that they should never cause problems, there is no need for this limit to exist in the first place. - Capping the available device/channel types. By default, this is 32 (snd_max_d() in unit.c). However, these types are pre-defined in pcm/sound.h (see SND_DEV_*), so the cap is unnecessary when we know that their number is constant. - Capping the number of channels per-device. By default, the limit 1024 (snd_max_c() in unit.c). This is probably the most problematic of the limits mentioned, because this limit can never be reached, as the maximum is hard-capped at either hw.snd.maxautovchans (16 by default), or SND_MAXHWCHAN and SND_MAXVCHANS. These limtits are encoded in masks (see SND_U_MASK, SND_D_MASK, SND_C_MASK in unit.h) and are used to construct a bitfield of the form [dsp_unit, type, channel_unit] in snd_mkunit() which is assigned to pcm_channel->unit. This patch gets rid of everything unit.*-related and makes a slightly different use of the "unit" field to only contain the channel unit number. The channel type is stored in a new pcm_channel->type field, and the DSP unit number need not be stored at all, since we can fetch it from device_get_unit(pcm_channel->dev). This change has the effect that we no longer need to impose caps on the number of soundcards, device/channel types and per-device channels. As a result the code is noticeably simplified and more readable. Apart from the fact that the hw.snd.maxunit loader(8) tunable is also retired as a side-effect of this patch, sound(4)'s behavior remains the same. Sponsored by: The FreeBSD Foundation MFC after: 1 week Reviewed by: dev_submerge.ch Differential Revision: https://reviews.freebsd.org/D44912
This commit is contained in:
parent
fa28452549
commit
25723d6636
3
RELNOTES
3
RELNOTES
|
@ -10,6 +10,9 @@ newline. Entries should be separated by a newline.
|
|||
|
||||
Changes to this file should not be MFCed.
|
||||
|
||||
8fef193e14e2:
|
||||
As a side-effect of retiring the unit.* code in sound(4), the
|
||||
hw.snd.maxunit loader(8) tunable is also retired.
|
||||
6d5ce2bb6344:
|
||||
The default value of the nfs_reserved_port_only rc.conf(5) setting has
|
||||
changed. The FreeBSD NFS server now requires the source port of
|
||||
|
|
|
@ -3072,7 +3072,6 @@ dev/smc/if_smc.c optional smc
|
|||
dev/smc/if_smc_acpi.c optional smc acpi
|
||||
dev/smc/if_smc_fdt.c optional smc fdt
|
||||
dev/snp/snp.c optional snp
|
||||
dev/sound/unit.c optional sound
|
||||
dev/sound/pci/als4000.c optional snd_als4000 pci
|
||||
dev/sound/pci/atiixp.c optional snd_atiixp pci
|
||||
dev/sound/pci/cmi.c optional snd_cmi pci
|
||||
|
|
|
@ -104,6 +104,7 @@ struct pcm_channel {
|
|||
void *devinfo;
|
||||
device_t dev;
|
||||
int unit;
|
||||
int type;
|
||||
char name[CHN_NAMELEN];
|
||||
char comm[MAXCOMLEN + 1];
|
||||
struct mtx *lock;
|
||||
|
@ -224,7 +225,7 @@ struct pcm_channel {
|
|||
#define CHN_INSERT_SORT(w, x, y, z) do { \
|
||||
struct pcm_channel *t, *a = NULL; \
|
||||
CHN_FOREACH(t, x, z) { \
|
||||
if ((y)->unit w t->unit) \
|
||||
if ((y)->type w t->type) \
|
||||
a = t; \
|
||||
else \
|
||||
break; \
|
||||
|
@ -235,13 +236,9 @@ struct pcm_channel {
|
|||
CHN_INSERT_HEAD(x, y, z); \
|
||||
} while (0)
|
||||
|
||||
#define CHN_INSERT_SORT_ASCEND(x, y, z) CHN_INSERT_SORT(>, x, y, z)
|
||||
#define CHN_INSERT_SORT_ASCEND(x, y, z) CHN_INSERT_SORT(>=, x, y, z)
|
||||
#define CHN_INSERT_SORT_DESCEND(x, y, z) CHN_INSERT_SORT(<, x, y, z)
|
||||
|
||||
#define CHN_UNIT(x) (snd_unit2u((x)->unit))
|
||||
#define CHN_DEV(x) (snd_unit2d((x)->unit))
|
||||
#define CHN_CHAN(x) (snd_unit2c((x)->unit))
|
||||
|
||||
#define CHN_BUF_PARENT(x, y) \
|
||||
(((x) != NULL && (x)->parentchannel != NULL && \
|
||||
(x)->parentchannel->bufhard != NULL) ? \
|
||||
|
|
|
@ -444,7 +444,7 @@ dsp_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
|
|||
if (DSP_F_READ(flags)) {
|
||||
/* open for read */
|
||||
rderror = pcm_chnalloc(d, &rdch, PCMDIR_REC,
|
||||
td->td_proc->p_pid, td->td_proc->p_comm, -1);
|
||||
td->td_proc->p_pid, td->td_proc->p_comm);
|
||||
|
||||
if (rderror == 0 && chn_reset(rdch, fmt, spd) != 0)
|
||||
rderror = ENXIO;
|
||||
|
@ -472,7 +472,7 @@ dsp_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
|
|||
if (DSP_F_WRITE(flags)) {
|
||||
/* open for write */
|
||||
wrerror = pcm_chnalloc(d, &wrch, PCMDIR_PLAY,
|
||||
td->td_proc->p_pid, td->td_proc->p_comm, -1);
|
||||
td->td_proc->p_pid, td->td_proc->p_comm);
|
||||
|
||||
if (wrerror == 0 && chn_reset(wrch, fmt, spd) != 0)
|
||||
wrerror = ENXIO;
|
||||
|
@ -629,69 +629,13 @@ dsp_write(struct cdev *i_dev, struct uio *buf, int flag)
|
|||
return (dsp_io_ops(priv, buf));
|
||||
}
|
||||
|
||||
static int
|
||||
dsp_get_volume_channel(struct dsp_cdevpriv *priv, struct pcm_channel **volch)
|
||||
{
|
||||
struct snddev_info *d;
|
||||
struct pcm_channel *c;
|
||||
int unit;
|
||||
|
||||
KASSERT(volch != NULL,
|
||||
("%s(): NULL query priv=%p volch=%p", __func__, priv, volch));
|
||||
|
||||
d = priv->sc;
|
||||
if (!PCM_REGISTERED(d)) {
|
||||
*volch = NULL;
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
PCM_UNLOCKASSERT(d);
|
||||
|
||||
*volch = NULL;
|
||||
|
||||
c = priv->volch;
|
||||
if (c != NULL) {
|
||||
if (!(c->feederflags & (1 << FEEDER_VOLUME)))
|
||||
return (-1);
|
||||
*volch = c;
|
||||
return (0);
|
||||
}
|
||||
|
||||
PCM_LOCK(d);
|
||||
PCM_WAIT(d);
|
||||
PCM_ACQUIRE(d);
|
||||
|
||||
unit = dev2unit(d->dsp_dev);
|
||||
|
||||
CHN_FOREACH(c, d, channels.pcm) {
|
||||
CHN_LOCK(c);
|
||||
if (c->unit != unit) {
|
||||
CHN_UNLOCK(c);
|
||||
continue;
|
||||
}
|
||||
*volch = c;
|
||||
pcm_chnref(c, 1);
|
||||
priv->volch = c;
|
||||
CHN_UNLOCK(c);
|
||||
PCM_RELEASE(d);
|
||||
PCM_UNLOCK(d);
|
||||
return ((c->feederflags & (1 << FEEDER_VOLUME)) ? 0 : -1);
|
||||
}
|
||||
|
||||
PCM_RELEASE(d);
|
||||
PCM_UNLOCK(d);
|
||||
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
static int
|
||||
dsp_ioctl_channel(struct dsp_cdevpriv *priv, struct pcm_channel *volch,
|
||||
u_long cmd, caddr_t arg)
|
||||
{
|
||||
struct snddev_info *d;
|
||||
struct pcm_channel *rdch, *wrch;
|
||||
int j, devtype, ret;
|
||||
int left, right, center, mute;
|
||||
int j, left, right, center, mute;
|
||||
|
||||
d = priv->sc;
|
||||
if (!PCM_REGISTERED(d) || !(pcm_getflags(d->dev) & SD_F_VPC))
|
||||
|
@ -716,19 +660,6 @@ dsp_ioctl_channel(struct dsp_cdevpriv *priv, struct pcm_channel *volch,
|
|||
volch = wrch;
|
||||
}
|
||||
|
||||
devtype = PCMDEV(d->dsp_dev);
|
||||
|
||||
/* Look super harder */
|
||||
if (volch == NULL &&
|
||||
(devtype == SND_DEV_DSPHW_PLAY || devtype == SND_DEV_DSPHW_VPLAY ||
|
||||
devtype == SND_DEV_DSPHW_REC || devtype == SND_DEV_DSPHW_VREC)) {
|
||||
ret = dsp_get_volume_channel(priv, &volch);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
if (volch == NULL)
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
/* Final validation */
|
||||
if (volch == NULL)
|
||||
return (EINVAL);
|
||||
|
@ -2105,8 +2036,6 @@ dsp_sysinit(void *p)
|
|||
{
|
||||
if (dsp_ehtag != NULL)
|
||||
return;
|
||||
/* initialize unit numbering */
|
||||
snd_unit_init();
|
||||
dsp_ehtag = EVENTHANDLER_REGISTER(dev_clone, dsp_clone, 0, 1000);
|
||||
}
|
||||
|
||||
|
@ -2123,20 +2052,19 @@ SYSINIT(dsp_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, dsp_sysinit, NULL);
|
|||
SYSUNINIT(dsp_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, dsp_sysuninit, NULL);
|
||||
|
||||
char *
|
||||
dsp_unit2name(char *buf, size_t len, int unit)
|
||||
dsp_unit2name(char *buf, size_t len, struct pcm_channel *ch)
|
||||
{
|
||||
int i, dtype;
|
||||
int i;
|
||||
|
||||
KASSERT(buf != NULL && len != 0,
|
||||
("bogus buf=%p len=%ju", buf, (uintmax_t)len));
|
||||
|
||||
dtype = snd_unit2d(unit);
|
||||
|
||||
for (i = 0; i < nitems(dsp_cdevs); i++) {
|
||||
if (dtype != dsp_cdevs[i].type || dsp_cdevs[i].alias != NULL)
|
||||
if (ch->type != dsp_cdevs[i].type || dsp_cdevs[i].alias != NULL)
|
||||
continue;
|
||||
snprintf(buf, len, "%s%d%s%d", dsp_cdevs[i].name,
|
||||
snd_unit2u(unit), dsp_cdevs[i].sep, snd_unit2c(unit));
|
||||
snprintf(buf, len, "%s%d%s%d",
|
||||
dsp_cdevs[i].name, device_get_unit(ch->dev),
|
||||
dsp_cdevs[i].sep, ch->unit);
|
||||
return (buf);
|
||||
}
|
||||
|
||||
|
@ -2224,12 +2152,10 @@ dsp_oss_audioinfo(struct cdev *i_dev, oss_audioinfo *ai)
|
|||
if (devfs_foreach_cdevpriv(i_dev,
|
||||
dsp_oss_audioinfo_cb, ch) != 0) {
|
||||
devname = dsp_unit2name(buf,
|
||||
sizeof(buf), ch->unit);
|
||||
sizeof(buf), ch);
|
||||
}
|
||||
} else if (ai->dev == nchan) {
|
||||
devname = dsp_unit2name(buf, sizeof(buf),
|
||||
ch->unit);
|
||||
}
|
||||
} else if (ai->dev == nchan)
|
||||
devname = dsp_unit2name(buf, sizeof(buf), ch);
|
||||
if (devname != NULL)
|
||||
break;
|
||||
CHN_UNLOCK(ch);
|
||||
|
|
|
@ -35,7 +35,7 @@ extern struct cdevsw dsp_cdevsw;
|
|||
|
||||
int dsp_make_dev(device_t);
|
||||
void dsp_destroy_dev(device_t);
|
||||
char *dsp_unit2name(char *, size_t, int);
|
||||
char *dsp_unit2name(char *, size_t, struct pcm_channel *);
|
||||
int dsp_oss_audioinfo(struct cdev *, oss_audioinfo *);
|
||||
|
||||
#endif /* !_PCMDSP_H_ */
|
||||
|
|
|
@ -82,9 +82,7 @@ feeder_register(void *p)
|
|||
if (snd_verbose < 0 || snd_verbose > 4)
|
||||
snd_verbose = 1;
|
||||
|
||||
/* initialize unit numbering */
|
||||
snd_unit_init();
|
||||
if (snd_unit < 0 || snd_unit > PCMMAXUNIT)
|
||||
if (snd_unit < 0)
|
||||
snd_unit = -1;
|
||||
|
||||
if (snd_maxautovchans < 0 ||
|
||||
|
|
|
@ -727,7 +727,7 @@ mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
|
|||
u_int16_t v;
|
||||
struct cdev *pdev;
|
||||
const char *name;
|
||||
int i, unit, devunit, val;
|
||||
int i, unit, val;
|
||||
|
||||
snddev = device_get_softc(dev);
|
||||
if (snddev == NULL)
|
||||
|
@ -764,8 +764,7 @@ mixer_init(device_t dev, kobj_class_t cls, void *devinfo)
|
|||
|
||||
mixer_setrecsrc(m, 0); /* Set default input. */
|
||||
|
||||
devunit = snd_mkunit(unit, SND_DEV_CTL, 0);
|
||||
pdev = make_dev(&mixer_cdevsw, devunit, UID_ROOT, GID_WHEEL, 0666,
|
||||
pdev = make_dev(&mixer_cdevsw, SND_DEV_CTL, UID_ROOT, GID_WHEEL, 0666,
|
||||
"mixer%d", unit);
|
||||
pdev->si_drv1 = m;
|
||||
snddev->mixer_dev = pdev;
|
||||
|
|
|
@ -244,98 +244,63 @@ pcm_setvchans(struct snddev_info *d, int direction, int newcnt, int num)
|
|||
/* return error status and a locked channel */
|
||||
int
|
||||
pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction,
|
||||
pid_t pid, char *comm, int devunit)
|
||||
pid_t pid, char *comm)
|
||||
{
|
||||
struct pcm_channel *c;
|
||||
int err, vchancount, vchan_num;
|
||||
bool retry;
|
||||
|
||||
KASSERT(d != NULL && ch != NULL && (devunit == -1 ||
|
||||
!(devunit & ~(SND_U_MASK | SND_D_MASK | SND_C_MASK))) &&
|
||||
KASSERT(d != NULL && ch != NULL &&
|
||||
(direction == PCMDIR_PLAY || direction == PCMDIR_REC),
|
||||
("%s(): invalid d=%p ch=%p direction=%d pid=%d devunit=%d",
|
||||
__func__, d, ch, direction, pid, devunit));
|
||||
("%s(): invalid d=%p ch=%p direction=%d pid=%d",
|
||||
__func__, d, ch, direction, pid));
|
||||
PCM_BUSYASSERT(d);
|
||||
|
||||
/* Double check again. */
|
||||
if (devunit != -1) {
|
||||
switch (snd_unit2d(devunit)) {
|
||||
case SND_DEV_DSPHW_PLAY:
|
||||
case SND_DEV_DSPHW_VPLAY:
|
||||
if (direction != PCMDIR_PLAY)
|
||||
return (ENOTSUP);
|
||||
break;
|
||||
case SND_DEV_DSPHW_REC:
|
||||
case SND_DEV_DSPHW_VREC:
|
||||
if (direction != PCMDIR_REC)
|
||||
return (ENOTSUP);
|
||||
break;
|
||||
default:
|
||||
if (!(direction == PCMDIR_PLAY ||
|
||||
direction == PCMDIR_REC))
|
||||
return (ENOTSUP);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*ch = NULL;
|
||||
vchan_num = 0;
|
||||
vchancount = (direction == PCMDIR_PLAY) ? d->pvchancount :
|
||||
d->rvchancount;
|
||||
|
||||
retry = false;
|
||||
retry_chnalloc:
|
||||
err = ENOTSUP;
|
||||
/* scan for a free channel */
|
||||
CHN_FOREACH(c, d, channels.pcm) {
|
||||
CHN_LOCK(c);
|
||||
if (devunit == -1 && c->direction == direction &&
|
||||
(c->flags & CHN_F_VIRTUAL)) {
|
||||
if (c->direction == direction && (c->flags & CHN_F_VIRTUAL)) {
|
||||
if (vchancount < snd_maxautovchans &&
|
||||
vchan_num < CHN_CHAN(c)) {
|
||||
vchan_num < c->unit) {
|
||||
CHN_UNLOCK(c);
|
||||
goto vchan_alloc;
|
||||
}
|
||||
vchan_num++;
|
||||
}
|
||||
if (c->direction == direction && !(c->flags & CHN_F_BUSY) &&
|
||||
(devunit == -1 || devunit == -2 || c->unit == devunit)) {
|
||||
if (c->direction == direction && !(c->flags & CHN_F_BUSY)) {
|
||||
c->flags |= CHN_F_BUSY;
|
||||
c->pid = pid;
|
||||
strlcpy(c->comm, (comm != NULL) ? comm :
|
||||
CHN_COMM_UNKNOWN, sizeof(c->comm));
|
||||
*ch = c;
|
||||
return (0);
|
||||
} else if (c->unit == devunit) {
|
||||
if (c->direction != direction)
|
||||
err = ENOTSUP;
|
||||
else if (c->flags & CHN_F_BUSY)
|
||||
err = EBUSY;
|
||||
else
|
||||
err = EINVAL;
|
||||
CHN_UNLOCK(c);
|
||||
return (err);
|
||||
} else if ((devunit == -1 || devunit == -2) &&
|
||||
c->direction == direction && (c->flags & CHN_F_BUSY))
|
||||
} else if (c->direction == direction && (c->flags & CHN_F_BUSY))
|
||||
err = EBUSY;
|
||||
CHN_UNLOCK(c);
|
||||
}
|
||||
|
||||
if (devunit == -2)
|
||||
/*
|
||||
* We came from retry_chnalloc and still didn't find a free channel.
|
||||
*/
|
||||
if (retry)
|
||||
return (err);
|
||||
|
||||
vchan_alloc:
|
||||
/* no channel available */
|
||||
if (devunit == -1 || snd_unit2d(devunit) == SND_DEV_DSPHW_VPLAY ||
|
||||
snd_unit2d(devunit) == SND_DEV_DSPHW_VREC) {
|
||||
if (!(vchancount > 0 && vchancount < snd_maxautovchans) &&
|
||||
(devunit == -1 || snd_unit2c(devunit) < snd_maxautovchans))
|
||||
return (err);
|
||||
err = pcm_setvchans(d, direction, vchancount + 1,
|
||||
(devunit == -1) ? -1 : snd_unit2c(devunit));
|
||||
if (err == 0) {
|
||||
if (devunit == -1)
|
||||
devunit = -2;
|
||||
goto retry_chnalloc;
|
||||
}
|
||||
if (!(vchancount > 0 && vchancount < snd_maxautovchans))
|
||||
return (err);
|
||||
err = pcm_setvchans(d, direction, vchancount + 1, -1);
|
||||
if (err == 0) {
|
||||
retry = true;
|
||||
goto retry_chnalloc;
|
||||
}
|
||||
|
||||
return (err);
|
||||
|
@ -445,7 +410,7 @@ pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t c
|
|||
{
|
||||
struct pcm_channel *ch;
|
||||
int direction, err, rpnum, *pnum, max;
|
||||
int udc, device, chan;
|
||||
int type, unit;
|
||||
char *dirs, *devname, buf[CHN_NAMELEN];
|
||||
|
||||
PCM_BUSYASSERT(d);
|
||||
|
@ -457,56 +422,54 @@ pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t c
|
|||
dirs = "play";
|
||||
direction = PCMDIR_PLAY;
|
||||
pnum = &d->playcount;
|
||||
device = SND_DEV_DSPHW_PLAY;
|
||||
type = SND_DEV_DSPHW_PLAY;
|
||||
max = SND_MAXHWCHAN;
|
||||
break;
|
||||
case PCMDIR_PLAY_VIRTUAL:
|
||||
dirs = "virtual_play";
|
||||
direction = PCMDIR_PLAY;
|
||||
pnum = &d->pvchancount;
|
||||
device = SND_DEV_DSPHW_VPLAY;
|
||||
type = SND_DEV_DSPHW_VPLAY;
|
||||
max = SND_MAXVCHANS;
|
||||
break;
|
||||
case PCMDIR_REC:
|
||||
dirs = "record";
|
||||
direction = PCMDIR_REC;
|
||||
pnum = &d->reccount;
|
||||
device = SND_DEV_DSPHW_REC;
|
||||
type = SND_DEV_DSPHW_REC;
|
||||
max = SND_MAXHWCHAN;
|
||||
break;
|
||||
case PCMDIR_REC_VIRTUAL:
|
||||
dirs = "virtual_record";
|
||||
direction = PCMDIR_REC;
|
||||
pnum = &d->rvchancount;
|
||||
device = SND_DEV_DSPHW_VREC;
|
||||
type = SND_DEV_DSPHW_VREC;
|
||||
max = SND_MAXVCHANS;
|
||||
break;
|
||||
default:
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
chan = (num == -1) ? 0 : num;
|
||||
unit = (num == -1) ? 0 : num;
|
||||
|
||||
if (*pnum >= max || chan >= max)
|
||||
if (*pnum >= max || unit >= max)
|
||||
return (NULL);
|
||||
|
||||
rpnum = 0;
|
||||
|
||||
CHN_FOREACH(ch, d, channels.pcm) {
|
||||
if (CHN_DEV(ch) != device)
|
||||
if (ch->type != type)
|
||||
continue;
|
||||
if (chan == CHN_CHAN(ch)) {
|
||||
if (num != -1) {
|
||||
device_printf(d->dev,
|
||||
"channel num=%d allocated!\n", chan);
|
||||
return (NULL);
|
||||
}
|
||||
chan++;
|
||||
if (chan >= max) {
|
||||
device_printf(d->dev,
|
||||
"chan=%d > %d\n", chan, max);
|
||||
return (NULL);
|
||||
}
|
||||
if (unit == ch->unit && num != -1) {
|
||||
device_printf(d->dev,
|
||||
"channel num=%d allocated!\n", unit);
|
||||
return (NULL);
|
||||
}
|
||||
unit++;
|
||||
if (unit >= max) {
|
||||
device_printf(d->dev,
|
||||
"chan=%d > %d\n", unit, max);
|
||||
return (NULL);
|
||||
}
|
||||
rpnum++;
|
||||
}
|
||||
|
@ -518,25 +481,24 @@ pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t c
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
udc = snd_mkunit(device_get_unit(d->dev), device, chan);
|
||||
devname = dsp_unit2name(buf, sizeof(buf), udc);
|
||||
|
||||
if (devname == NULL) {
|
||||
device_printf(d->dev,
|
||||
"Failed to query device name udc=0x%08x\n", udc);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
PCM_UNLOCK(d);
|
||||
ch = malloc(sizeof(*ch), M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
ch->methods = kobj_create(cls, M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
ch->unit = udc;
|
||||
ch->type = type;
|
||||
ch->unit = unit;
|
||||
ch->pid = -1;
|
||||
strlcpy(ch->comm, CHN_COMM_UNUSED, sizeof(ch->comm));
|
||||
ch->parentsnddev = d;
|
||||
ch->parentchannel = parent;
|
||||
ch->dev = d->dev;
|
||||
ch->trigger = PCMTRIG_STOP;
|
||||
devname = dsp_unit2name(buf, sizeof(buf), ch);
|
||||
if (devname == NULL) {
|
||||
device_printf(d->dev, "Failed to query device name");
|
||||
kobj_delete(ch->methods, M_DEVBUF);
|
||||
free(ch, M_DEVBUF);
|
||||
return (NULL);
|
||||
}
|
||||
snprintf(ch->name, sizeof(ch->name), "%s:%s:%s",
|
||||
device_get_nameunit(ch->dev), dirs, devname);
|
||||
|
||||
|
@ -585,7 +547,7 @@ pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch)
|
|||
|
||||
CHN_INSERT_SORT_ASCEND(d, ch, channels.pcm);
|
||||
|
||||
switch (CHN_DEV(ch)) {
|
||||
switch (ch->type) {
|
||||
case SND_DEV_DSPHW_PLAY:
|
||||
d->playcount++;
|
||||
break;
|
||||
|
@ -625,7 +587,7 @@ pcm_chn_remove(struct snddev_info *d, struct pcm_channel *ch)
|
|||
|
||||
CHN_REMOVE(d, ch, channels.pcm);
|
||||
|
||||
switch (CHN_DEV(ch)) {
|
||||
switch (ch->type) {
|
||||
case SND_DEV_DSPHW_PLAY:
|
||||
d->playcount--;
|
||||
break;
|
||||
|
@ -939,14 +901,6 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
|
|||
return EINVAL;
|
||||
}
|
||||
|
||||
if (device_get_unit(dev) > PCMMAXUNIT) {
|
||||
device_printf(dev, "PCMMAXUNIT reached : unit=%d > %d\n",
|
||||
device_get_unit(dev), PCMMAXUNIT);
|
||||
device_printf(dev,
|
||||
"Use 'hw.snd.maxunit' tunable to raise the limit.\n");
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
d = device_get_softc(dev);
|
||||
d->dev = dev;
|
||||
d->lock = snd_mtxcreate(device_get_nameunit(dev), "sound cdev");
|
||||
|
|
|
@ -88,7 +88,6 @@ struct snd_mixer;
|
|||
#include <dev/sound/pcm/feeder.h>
|
||||
#include <dev/sound/pcm/mixer.h>
|
||||
#include <dev/sound/pcm/dsp.h>
|
||||
#include <dev/sound/unit.h>
|
||||
|
||||
#define PCM_SOFTC_SIZE (sizeof(struct snddev_info))
|
||||
|
||||
|
@ -100,21 +99,6 @@ struct snd_mixer;
|
|||
#define SOUND_PREFVER SOUND_MODVER
|
||||
#define SOUND_MAXVER SOUND_MODVER
|
||||
|
||||
/*
|
||||
* We're abusing the fact that MAXMINOR still have enough room
|
||||
* for our bit twiddling and nobody ever need 512 unique soundcards,
|
||||
* 32 unique device types and 1024 unique cloneable devices for the
|
||||
* next 100 years...
|
||||
*/
|
||||
|
||||
#define PCMMAXUNIT (snd_max_u())
|
||||
#define PCMMAXDEV (snd_max_d())
|
||||
#define PCMMAXCHAN (snd_max_c())
|
||||
|
||||
#define PCMUNIT(x) (snd_unit2u(dev2unit(x)))
|
||||
#define PCMDEV(x) (snd_unit2d(dev2unit(x)))
|
||||
#define PCMCHAN(x) (snd_unit2c(dev2unit(x)))
|
||||
|
||||
/*
|
||||
* By design, limit possible channels for each direction.
|
||||
*/
|
||||
|
@ -311,7 +295,7 @@ SYSCTL_DECL(_hw_snd);
|
|||
|
||||
int pcm_setvchans(struct snddev_info *d, int direction, int newcnt, int num);
|
||||
int pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction,
|
||||
pid_t pid, char *comm, int devunit);
|
||||
pid_t pid, char *comm);
|
||||
int pcm_chnrelease(struct pcm_channel *c);
|
||||
int pcm_chnref(struct pcm_channel *c, int ref);
|
||||
|
||||
|
|
|
@ -923,7 +923,7 @@ vchan_sync(struct pcm_channel *c)
|
|||
if (snd_passthrough_verbose != 0) {
|
||||
char *devname, buf[CHN_NAMELEN];
|
||||
|
||||
devname = dsp_unit2name(buf, sizeof(buf), c->unit);
|
||||
devname = dsp_unit2name(buf, sizeof(buf), c);
|
||||
device_printf(c->dev,
|
||||
"%s(%s/%s) %s() -> re-sync err=%d\n",
|
||||
__func__, (devname != NULL) ? devname : "dspX", c->comm,
|
||||
|
|
|
@ -1,188 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2007 Ariff Abdullah <ariff@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#ifdef HAVE_KERNEL_OPTION_HEADERS
|
||||
#include "opt_snd.h"
|
||||
#endif
|
||||
|
||||
#include <dev/sound/unit.h>
|
||||
|
||||
/*
|
||||
* Unit magic allocator for sound driver.
|
||||
*
|
||||
* 'u' = Unit of attached soundcards
|
||||
* 'd' = Device type
|
||||
* 'c' = Channel number
|
||||
*
|
||||
* eg: dsp0.p1 - u=0, d=p, c=1
|
||||
* dsp1.vp0 - u=1, d=vp, c=0
|
||||
*
|
||||
* Maximum unit of soundcards can be tuned through "hw.snd.maxunit", which is
|
||||
* between SND_UNIT_UMIN (16) and SND_UNIT_UMAX (2048). By design, the maximum
|
||||
* allowable allocated channel is 256.
|
||||
*/
|
||||
|
||||
/* Default width */
|
||||
static int snd_u_shift = 9; /* 0 - 0x1ff : 512 distinct soundcards */
|
||||
static int snd_d_shift = 5; /* 0 - 0x1f : 32 distinct device types */
|
||||
static int snd_c_shift = 10; /* 0 - 0x3ff : 1024 distinct channels
|
||||
(256 limit "by design") */
|
||||
|
||||
static int snd_unit_initialized = 0;
|
||||
|
||||
#ifdef SND_DIAGNOSTIC
|
||||
#define SND_UNIT_ASSERT() do { \
|
||||
if (snd_unit_initialized == 0) \
|
||||
panic("%s(): Uninitialized sound unit!", __func__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define SND_UNIT_ASSERT() KASSERT(snd_unit_initialized != 0, \
|
||||
("%s(): Uninitialized sound unit!", \
|
||||
__func__))
|
||||
#endif
|
||||
|
||||
#define MKMASK(x) ((1 << snd_##x##_shift) - 1)
|
||||
|
||||
int
|
||||
snd_max_u(void)
|
||||
{
|
||||
SND_UNIT_ASSERT();
|
||||
|
||||
return (MKMASK(u));
|
||||
}
|
||||
|
||||
int
|
||||
snd_max_d(void)
|
||||
{
|
||||
SND_UNIT_ASSERT();
|
||||
|
||||
return (MKMASK(d));
|
||||
}
|
||||
|
||||
int
|
||||
snd_max_c(void)
|
||||
{
|
||||
SND_UNIT_ASSERT();
|
||||
|
||||
return (MKMASK(c));
|
||||
}
|
||||
|
||||
int
|
||||
snd_unit2u(int unit)
|
||||
{
|
||||
SND_UNIT_ASSERT();
|
||||
|
||||
return ((unit >> (snd_c_shift + snd_d_shift)) & MKMASK(u));
|
||||
}
|
||||
|
||||
int
|
||||
snd_unit2d(int unit)
|
||||
{
|
||||
SND_UNIT_ASSERT();
|
||||
|
||||
return ((unit >> snd_c_shift) & MKMASK(d));
|
||||
}
|
||||
|
||||
int
|
||||
snd_unit2c(int unit)
|
||||
{
|
||||
SND_UNIT_ASSERT();
|
||||
|
||||
return (unit & MKMASK(c));
|
||||
}
|
||||
|
||||
int
|
||||
snd_u2unit(int u)
|
||||
{
|
||||
SND_UNIT_ASSERT();
|
||||
|
||||
return ((u & MKMASK(u)) << (snd_c_shift + snd_d_shift));
|
||||
}
|
||||
|
||||
int
|
||||
snd_d2unit(int d)
|
||||
{
|
||||
SND_UNIT_ASSERT();
|
||||
|
||||
return ((d & MKMASK(d)) << snd_c_shift);
|
||||
}
|
||||
|
||||
int
|
||||
snd_c2unit(int c)
|
||||
{
|
||||
SND_UNIT_ASSERT();
|
||||
|
||||
return (c & MKMASK(c));
|
||||
}
|
||||
|
||||
int
|
||||
snd_mkunit(int u, int d, int c)
|
||||
{
|
||||
SND_UNIT_ASSERT();
|
||||
|
||||
return ((c & MKMASK(c)) | ((d & MKMASK(d)) << snd_c_shift) |
|
||||
((u & MKMASK(u)) << (snd_c_shift + snd_d_shift)));
|
||||
}
|
||||
|
||||
/*
|
||||
* This *must* be called first before any of the functions above!!!
|
||||
*/
|
||||
void
|
||||
snd_unit_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (snd_unit_initialized != 0)
|
||||
return;
|
||||
|
||||
snd_unit_initialized = 1;
|
||||
|
||||
if (getenv_int("hw.snd.maxunit", &i) != 0) {
|
||||
if (i < SND_UNIT_UMIN)
|
||||
i = SND_UNIT_UMIN;
|
||||
else if (i > SND_UNIT_UMAX)
|
||||
i = SND_UNIT_UMAX;
|
||||
else
|
||||
i = roundup2(i, 2);
|
||||
|
||||
for (snd_u_shift = 0; (i >> (snd_u_shift + 1)) != 0;
|
||||
snd_u_shift++)
|
||||
;
|
||||
|
||||
/* Make room for channels to fit within 24bit MAXMINOR limit. */
|
||||
snd_c_shift = 24 - snd_u_shift - snd_d_shift;
|
||||
}
|
||||
|
||||
if (bootverbose != 0)
|
||||
printf("%s() u=0x%08x [%d] d=0x%08x [%d] c=0x%08x [%d]\n",
|
||||
__func__, SND_U_MASK, snd_max_u() + 1,
|
||||
SND_D_MASK, snd_max_d() + 1, SND_C_MASK, snd_max_c() + 1);
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2007 Ariff Abdullah <ariff@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SND_UNIT_H_
|
||||
#define _SND_UNIT_H_
|
||||
|
||||
#define SND_UNIT_UMIN 16
|
||||
#define SND_UNIT_UMAX 2048
|
||||
|
||||
int snd_max_u(void);
|
||||
int snd_max_d(void);
|
||||
int snd_max_c(void);
|
||||
int snd_unit2u(int);
|
||||
int snd_unit2d(int);
|
||||
int snd_unit2c(int);
|
||||
int snd_u2unit(int);
|
||||
int snd_d2unit(int);
|
||||
int snd_c2unit(int);
|
||||
int snd_mkunit(int, int, int);
|
||||
|
||||
void snd_unit_init(void);
|
||||
|
||||
#define SND_U_MASK (snd_u2unit(snd_max_u()))
|
||||
#define SND_D_MASK (snd_d2unit(snd_max_d()))
|
||||
#define SND_C_MASK (snd_c2unit(snd_max_c()))
|
||||
|
||||
#endif /* !_SND_UNIT_H_ */
|
|
@ -17,7 +17,7 @@ SRCS+= feeder_eq_gen.h feeder_rate_gen.h snd_fxdiv_gen.h
|
|||
SRCS+= mpu_if.h mpufoi_if.h synth_if.h
|
||||
SRCS+= mpu_if.c mpufoi_if.c synth_if.c
|
||||
SRCS+= ac97.c ac97_patch.c buffer.c channel.c dsp.c
|
||||
SRCS+= mixer.c sndstat.c sound.c unit.c vchan.c
|
||||
SRCS+= mixer.c sndstat.c sound.c vchan.c
|
||||
SRCS+= midi.c mpu401.c sequencer.c
|
||||
|
||||
feeder_eq_gen.h: ${SYSDIR}/tools/sound/feeder_eq_mkfilter.awk
|
||||
|
|
Loading…
Reference in a new issue