aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/sound/pcm/sound.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/sound/pcm/sound.c')
-rw-r--r--sys/dev/sound/pcm/sound.c336
1 files changed, 16 insertions, 320 deletions
diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c
index 9d5eaf3f5ad7..e66462af2a71 100644
--- a/sys/dev/sound/pcm/sound.c
+++ b/sys/dev/sound/pcm/sound.c
@@ -41,7 +41,6 @@
#include <dev/sound/pcm/ac97.h>
#include <dev/sound/pcm/vchan.h>
#include <dev/sound/pcm/dsp.h>
-#include <dev/sound/version.h>
#include <sys/limits.h>
#include <sys/sysctl.h>
@@ -57,22 +56,11 @@ static int snd_unit_auto = -1;
SYSCTL_INT(_hw_snd, OID_AUTO, default_auto, CTLFLAG_RWTUN,
&snd_unit_auto, 0, "assign default unit to a newly attached device");
-int snd_maxautovchans = 16;
-
SYSCTL_NODE(_hw, OID_AUTO, snd, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
"Sound driver");
static void pcm_sysinit(device_t);
-/*
- * XXX I've had enough with people not telling proper version/arch
- * while reporting problems, not after 387397913213th questions/requests.
- */
-static char snd_driver_version[] =
- __XSTRING(SND_DRV_VERSION)"/"MACHINE_ARCH;
-SYSCTL_STRING(_hw_snd, OID_AUTO, version, CTLFLAG_RD, &snd_driver_version,
- 0, "driver version/arch");
-
/**
* @brief Unit number allocator for syncgroup IDs
*/
@@ -121,126 +109,6 @@ snd_setup_intr(device_t dev, struct resource *res, int flags, driver_intr_t hand
return bus_setup_intr(dev, res, flags, NULL, hand, param, cookiep);
}
-int
-pcm_setvchans(struct snddev_info *d, int direction, int newcnt, int num)
-{
- struct pcm_channel *c, *ch, *nch;
- struct pcmchan_caps *caps;
- int i, err, vcnt;
-
- PCM_BUSYASSERT(d);
-
- if ((direction == PCMDIR_PLAY && d->playcount < 1) ||
- (direction == PCMDIR_REC && d->reccount < 1))
- return (ENODEV);
-
- if (!(d->flags & SD_F_AUTOVCHAN))
- return (EINVAL);
-
- if (newcnt < 0 || newcnt > SND_MAXVCHANS)
- return (E2BIG);
-
- if (direction == PCMDIR_PLAY)
- vcnt = d->pvchancount;
- else if (direction == PCMDIR_REC)
- vcnt = d->rvchancount;
- else
- return (EINVAL);
-
- if (newcnt > vcnt) {
- KASSERT(num == -1 ||
- (num >= 0 && num < SND_MAXVCHANS && (newcnt - 1) == vcnt),
- ("bogus vchan_create() request num=%d newcnt=%d vcnt=%d",
- num, newcnt, vcnt));
- /* add new vchans - find a parent channel first */
- ch = NULL;
- CHN_FOREACH(c, d, channels.pcm) {
- CHN_LOCK(c);
- if (c->direction == direction &&
- ((c->flags & CHN_F_HAS_VCHAN) || (vcnt == 0 &&
- c->refcount < 1 &&
- !(c->flags & (CHN_F_BUSY | CHN_F_VIRTUAL))))) {
- /*
- * Reuse hw channel with vchans already
- * created.
- */
- if (c->flags & CHN_F_HAS_VCHAN) {
- ch = c;
- break;
- }
- /*
- * No vchans ever created, look for
- * channels with supported formats.
- */
- caps = chn_getcaps(c);
- if (caps == NULL) {
- CHN_UNLOCK(c);
- continue;
- }
- for (i = 0; caps->fmtlist[i] != 0; i++) {
- if (caps->fmtlist[i] & AFMT_CONVERTIBLE)
- break;
- }
- if (caps->fmtlist[i] != 0) {
- ch = c;
- break;
- }
- }
- CHN_UNLOCK(c);
- }
- if (ch == NULL)
- return (EBUSY);
- ch->flags |= CHN_F_BUSY;
- err = 0;
- while (err == 0 && newcnt > vcnt) {
- err = vchan_create(ch, num);
- if (err == 0)
- vcnt++;
- else if (err == E2BIG && newcnt > vcnt)
- device_printf(d->dev,
- "%s: err=%d Maximum channel reached.\n",
- __func__, err);
- }
- if (vcnt == 0)
- ch->flags &= ~CHN_F_BUSY;
- CHN_UNLOCK(ch);
- if (err != 0)
- return (err);
- } else if (newcnt < vcnt) {
- KASSERT(num == -1,
- ("bogus vchan_destroy() request num=%d", num));
- CHN_FOREACH(c, d, channels.pcm) {
- CHN_LOCK(c);
- if (c->direction != direction ||
- CHN_EMPTY(c, children) ||
- !(c->flags & CHN_F_HAS_VCHAN)) {
- CHN_UNLOCK(c);
- continue;
- }
- CHN_FOREACH_SAFE(ch, c, nch, children) {
- CHN_LOCK(ch);
- if (vcnt == 1 && c->refcount > 0) {
- CHN_UNLOCK(ch);
- break;
- }
- if (!(ch->flags & CHN_F_BUSY) &&
- ch->refcount < 1) {
- err = vchan_destroy(ch);
- if (err == 0)
- vcnt--;
- } else
- CHN_UNLOCK(ch);
- if (vcnt == newcnt)
- break;
- }
- CHN_UNLOCK(c);
- break;
- }
- }
-
- return (0);
-}
-
/* return error status and a locked channel */
int
pcm_chnalloc(struct snddev_info *d, struct pcm_channel **ch, int direction,
@@ -297,7 +165,7 @@ vchan_alloc:
/* no channel available */
if (!(vchancount > 0 && vchancount < snd_maxautovchans))
return (err);
- err = pcm_setvchans(d, direction, vchancount + 1, -1);
+ err = vchan_setnew(d, direction, vchancount + 1);
if (err == 0) {
retry = true;
goto retry_chnalloc;
@@ -306,25 +174,6 @@ vchan_alloc:
return (err);
}
-static void
-pcm_setmaxautovchans(struct snddev_info *d, int num)
-{
- PCM_BUSYASSERT(d);
-
- if (num < 0)
- return;
-
- if (num >= 0 && d->pvchancount > num)
- (void)pcm_setvchans(d, PCMDIR_PLAY, num, -1);
- else if (num > 0 && d->pvchancount == 0)
- (void)pcm_setvchans(d, PCMDIR_PLAY, 1, -1);
-
- if (num >= 0 && d->rvchancount > num)
- (void)pcm_setvchans(d, PCMDIR_REC, num, -1);
- else if (num > 0 && d->rvchancount == 0)
- (void)pcm_setvchans(d, PCMDIR_REC, 1, -1);
-}
-
static int
sysctl_hw_snd_default_unit(SYSCTL_HANDLER_ARGS)
{
@@ -348,148 +197,7 @@ SYSCTL_PROC(_hw_snd, OID_AUTO, default_unit,
sizeof(int), sysctl_hw_snd_default_unit, "I",
"default sound device");
-static int
-sysctl_hw_snd_maxautovchans(SYSCTL_HANDLER_ARGS)
-{
- struct snddev_info *d;
- int i, v, error;
-
- v = snd_maxautovchans;
- error = sysctl_handle_int(oidp, &v, 0, req);
- if (error == 0 && req->newptr != NULL) {
- if (v < 0)
- v = 0;
- if (v > SND_MAXVCHANS)
- v = SND_MAXVCHANS;
- snd_maxautovchans = v;
- for (i = 0; pcm_devclass != NULL &&
- i < devclass_get_maxunit(pcm_devclass); i++) {
- d = devclass_get_softc(pcm_devclass, i);
- if (!PCM_REGISTERED(d))
- continue;
- PCM_ACQUIRE_QUICK(d);
- pcm_setmaxautovchans(d, v);
- PCM_RELEASE_QUICK(d);
- }
- }
- return (error);
-}
-SYSCTL_PROC(_hw_snd, OID_AUTO, maxautovchans,
- CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0, sizeof(int),
- sysctl_hw_snd_maxautovchans, "I",
- "maximum virtual channel");
-
-struct pcm_channel *
-pcm_chn_create(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, int num, void *devinfo)
-{
- struct pcm_channel *ch;
- int direction, err, rpnum, *pnum, max;
- int type, unit;
- char *dirs, *devname, buf[CHN_NAMELEN];
-
- PCM_BUSYASSERT(d);
- PCM_LOCKASSERT(d);
- KASSERT(num >= -1, ("invalid num=%d", num));
-
- switch (dir) {
- case PCMDIR_PLAY:
- dirs = "play";
- direction = PCMDIR_PLAY;
- pnum = &d->playcount;
- type = SND_DEV_DSPHW_PLAY;
- max = SND_MAXHWCHAN;
- break;
- case PCMDIR_PLAY_VIRTUAL:
- dirs = "virtual_play";
- direction = PCMDIR_PLAY;
- pnum = &d->pvchancount;
- type = SND_DEV_DSPHW_VPLAY;
- max = SND_MAXVCHANS;
- break;
- case PCMDIR_REC:
- dirs = "record";
- direction = PCMDIR_REC;
- pnum = &d->reccount;
- type = SND_DEV_DSPHW_REC;
- max = SND_MAXHWCHAN;
- break;
- case PCMDIR_REC_VIRTUAL:
- dirs = "virtual_record";
- direction = PCMDIR_REC;
- pnum = &d->rvchancount;
- type = SND_DEV_DSPHW_VREC;
- max = SND_MAXVCHANS;
- break;
- default:
- return (NULL);
- }
-
- unit = (num == -1) ? 0 : num;
-
- if (*pnum >= max || unit >= max)
- return (NULL);
-
- rpnum = 0;
-
- CHN_FOREACH(ch, d, channels.pcm) {
- if (ch->type != type)
- continue;
- 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++;
- }
-
- if (*pnum != rpnum) {
- device_printf(d->dev,
- "%s(): WARNING: pnum screwed : dirs=%s pnum=%d rpnum=%d\n",
- __func__, dirs, *pnum, rpnum);
- 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->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);
-
- err = chn_init(ch, devinfo, dir, direction);
- PCM_LOCK(d);
- if (err) {
- device_printf(d->dev, "chn_init(%s) failed: err = %d\n",
- ch->name, err);
- kobj_delete(ch->methods, M_DEVBUF);
- free(ch, M_DEVBUF);
- return (NULL);
- }
-
- return (ch);
-}
-
-int
+void
pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch)
{
PCM_BUSYASSERT(d);
@@ -513,10 +221,8 @@ pcm_chn_add(struct snddev_info *d, struct pcm_channel *ch)
d->rvchancount++;
break;
default:
- break;
+ __assert_unreachable();
}
-
- return (0);
}
int
@@ -553,7 +259,7 @@ pcm_chn_remove(struct snddev_info *d, struct pcm_channel *ch)
d->rvchancount--;
break;
default:
- break;
+ __assert_unreachable();
}
return (0);
@@ -564,28 +270,22 @@ 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;
PCM_BUSYASSERT(d);
PCM_LOCK(d);
- ch = pcm_chn_create(d, NULL, cls, dir, -1, devinfo);
+ ch = chn_init(d, NULL, cls, dir, devinfo);
if (!ch) {
- device_printf(d->dev, "pcm_chn_create(%s, %d, %p) failed\n",
+ device_printf(d->dev, "chn_init(%s, %d, %p) failed\n",
cls->name, dir, devinfo);
PCM_UNLOCK(d);
return (ENODEV);
}
- err = pcm_chn_add(d, ch);
+ pcm_chn_add(d, ch);
PCM_UNLOCK(d);
- if (err) {
- device_printf(d->dev, "pcm_chn_add(%s) failed, err=%d\n",
- ch->name, err);
- chn_kill(ch);
- }
- return (err);
+ return (0);
}
static void
@@ -677,7 +377,7 @@ pcm_setstatus(device_t dev, char *str)
if (d->playcount > 0 || d->reccount > 0)
d->flags |= SD_F_AUTOVCHAN;
- pcm_setmaxautovchans(d, snd_maxautovchans);
+ vchan_setmaxauto(d, snd_maxautovchans);
strlcpy(d->status, str, SND_STATUSLEN);
@@ -1008,9 +708,8 @@ sound_oss_sysinfo(oss_sysinfo *si)
struct snddev_info *d;
struct pcm_channel *c;
- int i, j, ncards;
-
- ncards = 0;
+ int j;
+ size_t i;
strlcpy(si->product, si_product, sizeof(si->product));
strlcpy(si->version, si_version, sizeof(si->version));
@@ -1019,7 +718,7 @@ sound_oss_sysinfo(oss_sysinfo *si)
/*
* Iterate over PCM devices and their channels, gathering up data
- * for the numaudios, ncards, and openedaudio fields.
+ * for the numaudios and openedaudio fields.
*/
si->numaudios = 0;
bzero((void *)&si->openedaudio, sizeof(si->openedaudio));
@@ -1039,7 +738,6 @@ sound_oss_sysinfo(oss_sysinfo *si)
PCM_LOCK(d);
si->numaudios += PCM_CHANCOUNT(d);
- ++ncards;
CHN_FOREACH(c, d, channels.pcm) {
CHN_UNLOCKASSERT(c);
@@ -1070,7 +768,7 @@ sound_oss_sysinfo(oss_sysinfo *si)
si->nummidis = 0;
si->numtimers = 0;
si->nummixers = mixer_count;
- si->numcards = ncards;
+ si->numcards = devclass_get_maxunit(pcm_devclass);
/* OSSv4 docs: Intended only for test apps; API doesn't
really have much of a concept of cards. Shouldn't be
used by applications. */
@@ -1086,7 +784,7 @@ sound_oss_sysinfo(oss_sysinfo *si)
* Si->filler is a reserved array, but according to docs each
* element should be set to -1.
*/
- for (i = 0; i < sizeof(si->filler)/sizeof(si->filler[0]); i++)
+ for (i = 0; i < nitems(si->filler); i++)
si->filler[i] = -1;
}
@@ -1094,9 +792,7 @@ int
sound_oss_card_info(oss_card_info *si)
{
struct snddev_info *d;
- int i, ncards;
-
- ncards = 0;
+ int i;
for (i = 0; pcm_devclass != NULL &&
i < devclass_get_maxunit(pcm_devclass); i++) {
@@ -1104,7 +800,7 @@ sound_oss_card_info(oss_card_info *si)
if (!PCM_REGISTERED(d))
continue;
- if (ncards++ != si->card)
+ if (i != si->card)
continue;
PCM_UNLOCKASSERT(d);