summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/pcm/sndstat.c
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2001-08-23 11:30:52 +0000
committercg <cg@FreeBSD.org>2001-08-23 11:30:52 +0000
commit2cfb90cc8dc9d8f8ae1f12afed63cf0409ed6dd2 (patch)
tree069cd9e58d47e13e77afc32cbb02b958a6dbc95e /sys/dev/sound/pcm/sndstat.c
parent1a36f4817c302232acb54087dddcd1d1f4c6a36f (diff)
downloadFreeBSD-src-2cfb90cc8dc9d8f8ae1f12afed63cf0409ed6dd2.zip
FreeBSD-src-2cfb90cc8dc9d8f8ae1f12afed63cf0409ed6dd2.tar.gz
many changes:
* add new channels to the end of the list so channels used in order of addition * de-globalise definition of struct snddev_info and provide accessor functions where necessary. * move the $FreeBSD$ tag in each .c file into a macro and allow the /dev/sndstat handler to display these when set to maximum verbosity to aid debugging. * allow each device to register its own sndstat handler to reduce the amount of groping sndstat must do in foreign structs.
Diffstat (limited to 'sys/dev/sound/pcm/sndstat.c')
-rw-r--r--sys/dev/sound/pcm/sndstat.c279
1 files changed, 200 insertions, 79 deletions
diff --git a/sys/dev/sound/pcm/sndstat.c b/sys/dev/sound/pcm/sndstat.c
index 6792700..dd786e9 100644
--- a/sys/dev/sound/pcm/sndstat.c
+++ b/sys/dev/sound/pcm/sndstat.c
@@ -22,15 +22,19 @@
* 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.
- *
- * $FreeBSD$
*/
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/vchan.h>
-#include <sys/sbuf.h>
-#include "feeder_if.h"
+SND_DECLARE_FILE("$FreeBSD$");
+
+#define SS_TYPE_MODULE 0
+#define SS_TYPE_FIRST 1
+#define SS_TYPE_PCM 1
+#define SS_TYPE_MIDI 2
+#define SS_TYPE_SEQUENCER 3
+#define SS_TYPE_LAST 3
static d_open_t sndstat_open;
static d_close_t sndstat_close;
@@ -52,16 +56,31 @@ static struct cdevsw sndstat_cdevsw = {
/* flags */ 0,
};
+struct sndstat_entry {
+ SLIST_ENTRY(sndstat_entry) link;
+ device_t dev;
+ char *str;
+ sndstat_handler handler;
+ int type, unit;
+};
+
+#ifdef USING_MUTEX
+static struct mtx sndstat_lock;
+#endif
static struct sbuf sndstat_sbuf;
static dev_t sndstat_dev = 0;
static int sndstat_isopen = 0;
static int sndstat_bufptr;
+static int sndstat_maxunit = -1;
+static int sndstat_files = 0;
-static int sndstat_verbose = 0;
+static SLIST_HEAD(, sndstat_entry) sndstat_devlist = SLIST_HEAD_INITIALIZER(none);
+
+static int sndstat_verbose = 1;
#ifdef USING_MUTEX
TUNABLE_INT("hw.snd.verbose", &sndstat_verbose);
#else
-TUNABLE_INT_DECL("hw.snd.verbose", 0, sndstat_verbose);
+TUNABLE_INT_DECL("hw.snd.verbose", 1, sndstat_verbose);
#endif
static int sndstat_prepare(struct sbuf *s);
@@ -69,15 +88,20 @@ static int sndstat_prepare(struct sbuf *s);
static int
sysctl_hw_sndverbose(SYSCTL_HANDLER_ARGS)
{
+ intrmask_t s;
int error, verbose;
verbose = sndstat_verbose;
error = sysctl_handle_int(oidp, &verbose, sizeof(verbose), req);
if (error == 0 && req->newptr != NULL) {
- if (verbose == 0 || verbose == 1)
- sndstat_verbose = verbose;
- else
+ s = spltty();
+ mtx_lock(&sndstat_lock);
+ if (verbose < 0 || verbose > 3)
error = EINVAL;
+ else
+ sndstat_verbose = verbose;
+ mtx_unlock(&sndstat_lock);
+ splx(s);
}
return error;
}
@@ -91,11 +115,14 @@ sndstat_open(dev_t i_dev, int flags, int mode, struct proc *p)
int err;
s = spltty();
+ mtx_lock(&sndstat_lock);
if (sndstat_isopen) {
+ mtx_unlock(&sndstat_lock);
splx(s);
return EBUSY;
}
if (sbuf_new(&sndstat_sbuf, NULL, 4096, 0) == NULL) {
+ mtx_unlock(&sndstat_lock);
splx(s);
return ENXIO;
}
@@ -104,6 +131,7 @@ sndstat_open(dev_t i_dev, int flags, int mode, struct proc *p)
if (!err)
sndstat_isopen = 1;
+ mtx_unlock(&sndstat_lock);
splx(s);
return err;
}
@@ -114,13 +142,16 @@ sndstat_close(dev_t i_dev, int flags, int mode, struct proc *p)
intrmask_t s;
s = spltty();
+ mtx_lock(&sndstat_lock);
if (!sndstat_isopen) {
+ mtx_unlock(&sndstat_lock);
splx(s);
return EBADF;
}
sbuf_delete(&sndstat_sbuf);
sndstat_isopen = 0;
+ mtx_unlock(&sndstat_lock);
splx(s);
return 0;
}
@@ -132,7 +163,9 @@ sndstat_read(dev_t i_dev, struct uio *buf, int flag)
int l, err;
s = spltty();
+ mtx_lock(&sndstat_lock);
if (!sndstat_isopen) {
+ mtx_unlock(&sndstat_lock);
splx(s);
return EBADF;
}
@@ -140,85 +173,169 @@ sndstat_read(dev_t i_dev, struct uio *buf, int flag)
err = (l > 0)? uiomove(sbuf_data(&sndstat_sbuf) + sndstat_bufptr, l, buf) : 0;
sndstat_bufptr += l;
+ mtx_unlock(&sndstat_lock);
splx(s);
return err;
}
+/************************************************************************/
+
+static struct sndstat_entry *
+sndstat_find(int type, int unit)
+{
+ struct sndstat_entry *ent;
+
+ SLIST_FOREACH(ent, &sndstat_devlist, link) {
+ if (ent->type == type && ent->unit == unit)
+ return ent;
+ }
+
+ return NULL;
+}
+
+int
+sndstat_register(device_t dev, char *str, sndstat_handler handler)
+{
+ intrmask_t s;
+ struct sndstat_entry *ent;
+ const char *devtype;
+ int type, unit;
+
+ if (dev) {
+ unit = device_get_unit(dev);
+ devtype = device_get_name(dev);
+ if (!strcmp(devtype, "pcm"))
+ type = SS_TYPE_PCM;
+ else if (!strcmp(devtype, "midi"))
+ type = SS_TYPE_MIDI;
+ else if (!strcmp(devtype, "sequencer"))
+ type = SS_TYPE_SEQUENCER;
+ else
+ return EINVAL;
+ } else {
+ type = SS_TYPE_MODULE;
+ unit = -1;
+ }
+
+ ent = malloc(sizeof *ent, M_DEVBUF, M_ZERO | M_WAITOK);
+ if (!ent)
+ return ENOSPC;
+
+ ent->dev = dev;
+ ent->str = str;
+ ent->type = type;
+ ent->unit = unit;
+ ent->handler = handler;
+
+ s = spltty();
+ mtx_lock(&sndstat_lock);
+ SLIST_INSERT_HEAD(&sndstat_devlist, ent, link);
+ if (type == SS_TYPE_MODULE)
+ sndstat_files++;
+ sndstat_maxunit = (unit > sndstat_maxunit)? unit : sndstat_maxunit;
+ mtx_unlock(&sndstat_lock);
+ splx(s);
+
+ return 0;
+}
+
+int
+sndstat_registerfile(char *str)
+{
+ return sndstat_register(NULL, str, NULL);
+}
+
+int
+sndstat_unregister(device_t dev)
+{
+ intrmask_t s;
+ struct sndstat_entry *ent;
+
+ s = spltty();
+ mtx_lock(&sndstat_lock);
+ SLIST_FOREACH(ent, &sndstat_devlist, link) {
+ if (ent->dev == dev) {
+ SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
+ free(ent, M_DEVBUF);
+ mtx_unlock(&sndstat_lock);
+ splx(s);
+
+ return 0;
+ }
+ }
+ mtx_unlock(&sndstat_lock);
+ splx(s);
+
+ return ENXIO;
+}
+
+int
+sndstat_unregisterfile(char *str)
+{
+ intrmask_t s;
+ struct sndstat_entry *ent;
+
+ s = spltty();
+ mtx_lock(&sndstat_lock);
+ SLIST_FOREACH(ent, &sndstat_devlist, link) {
+ if (ent->dev == NULL && ent->str == str) {
+ SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
+ free(ent, M_DEVBUF);
+ sndstat_files--;
+ mtx_unlock(&sndstat_lock);
+ splx(s);
+
+ return 0;
+ }
+ }
+ mtx_unlock(&sndstat_lock);
+ splx(s);
+
+ return ENXIO;
+}
+
+/************************************************************************/
+
static int
sndstat_prepare(struct sbuf *s)
{
- int i, pc, rc, vc;
- device_t dev;
- struct snddev_info *d;
- struct snddev_channel *sce;
- struct pcm_channel *c;
- struct pcm_feeder *f;
-
- sbuf_printf(s, "FreeBSD Audio Driver (newpcm) %s %s\n", __DATE__, __TIME__);
- if (!pcm_devclass || devclass_get_maxunit(pcm_devclass) == 0) {
+ struct sndstat_entry *ent;
+ int i, j;
+
+ sbuf_printf(s, "FreeBSD Audio Driver (newpcm)\n");
+ if (SLIST_EMPTY(&sndstat_devlist)) {
sbuf_printf(s, "No devices installed.\n");
sbuf_finish(s);
return sbuf_len(s);
- } else
- sbuf_printf(s, "Installed devices:\n");
-
- for (i = 0; i < devclass_get_maxunit(pcm_devclass); i++) {
- d = devclass_get_softc(pcm_devclass, i);
- if (!d)
- continue;
- snd_mtxlock(d->lock);
- dev = devclass_get_device(pcm_devclass, i);
- sbuf_printf(s, "pcm%d: <%s> %s", i, device_get_desc(dev), d->status);
- if (!SLIST_EMPTY(&d->channels)) {
- pc = rc = vc = 0;
- SLIST_FOREACH(sce, &d->channels, link) {
- c = sce->channel;
- if (c->direction == PCMDIR_PLAY) {
- if (c->flags & CHN_F_VIRTUAL)
- vc++;
- else
- pc++;
- } else
- rc++;
- }
- sbuf_printf(s, " (%dp/%dr/%dv channels%s%s)\n", pc, rc, vc,
- (d->flags & SD_F_SIMPLEX)? "" : " duplex",
-#ifdef USING_DEVFS
- (i == snd_unit)? " default" : ""
-#else
- ""
-#endif
- );
- if (!sndstat_verbose)
- goto skipverbose;
- SLIST_FOREACH(sce, &d->channels, link) {
- c = sce->channel;
- sbuf_printf(s, "\t%s[%s]: speed %d, format %08x, flags %08x",
- c->parentchannel? c->parentchannel->name : "",
- c->name, c->speed, c->format, c->flags);
- if (c->pid != -1)
- sbuf_printf(s, ", pid %d", c->pid);
- sbuf_printf(s, "\n\t");
- f = c->feeder;
- while (f) {
- sbuf_printf(s, "%s", f->class->name);
- if (f->desc->type == FEEDER_FMT)
- sbuf_printf(s, "(%08x <- %08x)", f->desc->out, f->desc->in);
- if (f->desc->type == FEEDER_RATE)
- sbuf_printf(s, "(%d <- %d)", FEEDER_GET(f, FEEDRATE_DST), FEEDER_GET(f, FEEDRATE_SRC));
- if (f->desc->type == FEEDER_ROOT || f->desc->type == FEEDER_MIXER)
- sbuf_printf(s, "(%08x)", f->desc->out);
- if (f->source)
- sbuf_printf(s, " <- ");
- f = f->source;
- }
- sbuf_printf(s, "\n");
- }
-skipverbose:
- } else
- sbuf_printf(s, " (mixer only)\n");
- snd_mtxunlock(d->lock);
+ }
+
+ sbuf_printf(s, "Installed devices:\n");
+
+ for (i = 0; i <= sndstat_maxunit; i++) {
+ for (j = SS_TYPE_FIRST; j <= SS_TYPE_LAST; j++) {
+ ent = sndstat_find(j, i);
+ if (!ent)
+ continue;
+ sbuf_printf(s, "%s:", device_get_nameunit(ent->dev));
+ sbuf_printf(s, " <%s>", device_get_desc(ent->dev));
+ sbuf_printf(s, " %s", ent->str);
+ if (ent->handler)
+ ent->handler(s, ent->dev, sndstat_verbose);
+ else
+ sbuf_printf(s, " [no handler]");
+ sbuf_printf(s, "\n");
+ }
}
+
+ if (sndstat_verbose >= 3 && sndstat_files > 0) {
+ sbuf_printf(s, "\nFile Versions:\n");
+
+ SLIST_FOREACH(ent, &sndstat_devlist, link) {
+ if (ent->dev == NULL && ent->str != NULL)
+ sbuf_printf(s, "%s\n", ent->str);
+ }
+ }
+
sbuf_finish(s);
return sbuf_len(s);
}
@@ -226,6 +343,7 @@ skipverbose:
static int
sndstat_init(void)
{
+ mtx_init(&sndstat_lock, "sndstat", 0);
sndstat_dev = make_dev(&sndstat_cdevsw, SND_DEV_STATUS, UID_ROOT, GID_WHEEL, 0444, "sndstat");
return (sndstat_dev != 0)? 0 : ENXIO;
@@ -237,7 +355,9 @@ sndstat_uninit(void)
intrmask_t s;
s = spltty();
+ mtx_lock(&sndstat_lock);
if (sndstat_isopen) {
+ mtx_unlock(&sndstat_lock);
splx(s);
return EBUSY;
}
@@ -247,6 +367,7 @@ sndstat_uninit(void)
sndstat_dev = 0;
splx(s);
+ mtx_destroy(&sndstat_lock);
return 0;
}
@@ -262,7 +383,7 @@ sndstat_sysuninit(void *p)
sndstat_uninit();
}
-SYSINIT(sndstat_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sndstat_sysinit, NULL);
-SYSUNINIT(sndstat_sysuninit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, sndstat_sysuninit, NULL);
+SYSINIT(sndstat_sysinit, SI_SUB_DRIVERS, SI_ORDER_FIRST, sndstat_sysinit, NULL);
+SYSUNINIT(sndstat_sysuninit, SI_SUB_DRIVERS, SI_ORDER_FIRST, sndstat_sysuninit, NULL);
OpenPOWER on IntegriCloud