summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/pcm
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2001-08-29 02:49:54 +0000
committercg <cg@FreeBSD.org>2001-08-29 02:49:54 +0000
commitbf28cfba58b1a7895383d4ec68d72573fb5cd2a6 (patch)
tree407b331880ea4820591f73bd9fe09c4c0ea093fe /sys/dev/sound/pcm
parentbe67da33283716a7b1e17c3e7adfee3da9ea77d4 (diff)
downloadFreeBSD-src-bf28cfba58b1a7895383d4ec68d72573fb5cd2a6.zip
FreeBSD-src-bf28cfba58b1a7895383d4ec68d72573fb5cd2a6.tar.gz
add some extra diagnostic info to sndstat output.
Diffstat (limited to 'sys/dev/sound/pcm')
-rw-r--r--sys/dev/sound/pcm/channel.c30
-rw-r--r--sys/dev/sound/pcm/channel.h1
-rw-r--r--sys/dev/sound/pcm/sound.c28
3 files changed, 41 insertions, 18 deletions
diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c
index 93d4593..59f5660f 100644
--- a/sys/dev/sound/pcm/channel.c
+++ b/sys/dev/sound/pcm/channel.c
@@ -188,6 +188,8 @@ chn_wrfeed(struct pcm_channel *c)
})
amt = sndbuf_getfree(b);
+ if (sndbuf_getready(bs) < amt)
+ c->xruns++;
ret = (amt > 0)? sndbuf_feed(bs, b, c, c->feeder, amt) : ENOSPC;
if (ret == 0 && sndbuf_getfree(b) < amt)
chn_wakeup(c);
@@ -216,7 +218,7 @@ chn_wrintr(struct pcm_channel *c)
}
/*
- * user write routine - uiomove data into secondary bufhard, trigger if necessary
+ * user write routine - uiomove data into secondary buffer, trigger if necessary
* if blocking, sleep, rinse and repeat.
*
* called externally, so must handle locking
@@ -293,7 +295,7 @@ chn_rddump(struct pcm_channel *c, unsigned int cnt)
}
/*
- * Feed new data from the read bufhard. Can be called in the bottom half.
+ * Feed new data from the read buffer. Can be called in the bottom half.
* Hence must be called at spltty.
*/
int
@@ -301,7 +303,7 @@ chn_rdfeed(struct pcm_channel *c)
{
struct snd_dbuf *b = c->bufhard;
struct snd_dbuf *bs = c->bufsoft;
- int ret;
+ unsigned int ret, amt;
CHN_LOCKASSERT(c);
DEB(
@@ -310,10 +312,16 @@ chn_rdfeed(struct pcm_channel *c)
sndbuf_dump(bs, "bs", 0x02);
})
- ret = sndbuf_feed(b, bs, c, c->feeder, sndbuf_getblksz(b));
+ amt = sndbuf_getready(b);
+ if (sndbuf_getfree(bs) < amt)
+ c->xruns++;
+ ret = (amt > 0)? sndbuf_feed(b, bs, c, c->feeder, amt) : 0;
- if (ret == 0)
- chn_wakeup(c);
+ amt -= sndbuf_getready(b);
+ if (amt > 0)
+ chn_rddump(c, amt);
+
+ chn_wakeup(c);
return ret;
}
@@ -340,18 +348,15 @@ chn_rdupdate(struct pcm_channel *c)
static void
chn_rdintr(struct pcm_channel *c)
{
- struct snd_dbuf *b = c->bufhard;
int ret;
CHN_LOCKASSERT(c);
- /* tell the driver to update the primary bufhard if non-dma */
+ /* tell the driver to update the primary buffer if non-dma */
chn_trigger(c, PCMTRIG_EMLDMARD);
/* update pointers in primary bufhard */
chn_dmaupdate(c);
/* ...and feed from primary to secondary */
ret = chn_rdfeed(c);
- if (ret)
- chn_rddump(c, sndbuf_getblksz(b));
}
/*
@@ -406,6 +411,7 @@ void
chn_intr(struct pcm_channel *c)
{
CHN_LOCK(c);
+ c->interrupts++;
if (c->direction == PCMDIR_PLAY)
chn_wrintr(c);
else
@@ -603,6 +609,8 @@ chn_reset(struct pcm_channel *c, u_int32_t fmt)
CHN_LOCKASSERT(c);
c->flags &= CHN_F_RESET;
+ c->interrupts = 0;
+ c->xruns = 0;
CHANNEL_RESET(c->methods, c->devinfo);
if (fmt) {
hwspd = DSP_DEFAULT_SPEED;
@@ -633,7 +641,7 @@ chn_init(struct pcm_channel *c, void *devinfo, int dir)
chn_lockinit(c);
CHN_LOCK(c);
- /* Initialize the hardware and DMA bufhard first. */
+
c->feeder = NULL;
fc = feeder_getclass(NULL);
if (fc == NULL)
diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h
index 9095c1b..8e2454f 100644
--- a/sys/dev/sound/pcm/channel.h
+++ b/sys/dev/sound/pcm/channel.h
@@ -54,6 +54,7 @@ struct pcm_channel {
u_int32_t blocks;
int direction;
+ unsigned int interrupts, xruns;
struct snd_dbuf *bufhard, *bufsoft;
struct snddev_info *parentsnddev;
struct pcm_channel *parentchannel;
diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c
index 08da0a4..4ea2b58 100644
--- a/sys/dev/sound/pcm/sound.c
+++ b/sys/dev/sound/pcm/sound.c
@@ -633,6 +633,7 @@ sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose)
struct snddev_channel *sce;
struct pcm_channel *c;
struct pcm_feeder *f;
+ char *fsep;
int pc, rc, vc;
if (verbose < 1)
@@ -667,25 +668,38 @@ sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose)
goto skipverbose;
SLIST_FOREACH(sce, &d->channels, link) {
c = sce->channel;
- sbuf_printf(s, "\n\t%s[%s]: speed %d, format %08x, flags %08x",
- c->parentchannel? c->parentchannel->name : "",
- c->name, c->speed, c->format, c->flags);
+ sbuf_printf(s, "\n\t");
+
+ sbuf_printf(s, "%s[%s]: ", c->parentchannel? c->parentchannel->name : "", c->name);
+ sbuf_printf(s, "speed %d, format %08x, flags %08x", c->speed, c->format, c->flags);
if (c->pid != -1)
sbuf_printf(s, ", pid %d", c->pid);
sbuf_printf(s, "\n\t");
+ if (c->pid != -1 && c->bufhard != NULL && c->bufsoft != NULL) {
+ sbuf_printf(s, "interrupts %d, ", c->interrupts);
+ if (c->direction == PCMDIR_REC)
+ sbuf_printf(s, "overruns %d, hfree %d, sfree %d",
+ c->xruns, sndbuf_getfree(c->bufhard), sndbuf_getfree(c->bufsoft));
+ else
+ sbuf_printf(s, "underruns %d, hready %d, sready %d",
+ c->xruns, sndbuf_getready(c->bufhard), sndbuf_getready(c->bufsoft));
+ sbuf_printf(s, "\n\t");
+ }
+ fsep = (c->direction == PCMDIR_REC)? " -> " : " <- ";
+ sbuf_printf(s, "[hardware]%s", fsep);
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);
+ sbuf_printf(s, "(%08x%s%08x)", f->desc->out, fsep, f->desc->in);
if (f->desc->type == FEEDER_RATE)
- sbuf_printf(s, "(%d <- %d)", FEEDER_GET(f, FEEDRATE_DST), FEEDER_GET(f, FEEDRATE_SRC));
+ sbuf_printf(s, "(%d%s%d)", FEEDER_GET(f, FEEDRATE_DST), fsep, 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, " <- ");
+ sbuf_printf(s, "%s", fsep);
f = f->source;
}
+ sbuf_printf(s, "[userland]");
}
skipverbose:
} else
OpenPOWER on IntegriCloud