diff options
author | cg <cg@FreeBSD.org> | 2002-01-26 22:13:24 +0000 |
---|---|---|
committer | cg <cg@FreeBSD.org> | 2002-01-26 22:13:24 +0000 |
commit | 7119c584879890efe6e984d27f939052ff2d0d0c (patch) | |
tree | 7f5235e1606d17de8b16949b2ddbfff99e3ba640 /sys/dev/sound | |
parent | 94fe6c387a335887a3fa8b9073ac110ac597f6d7 (diff) | |
download | FreeBSD-src-7119c584879890efe6e984d27f939052ff2d0d0c.zip FreeBSD-src-7119c584879890efe6e984d27f939052ff2d0d0c.tar.gz |
* improve error handling
* be more specific in verbose boot messages
* allow the feeder subsystem to veto pcm* attaching if there is an error
initialising the root feeder
* don't free/malloc a new tmpbuf when resizing a snd_dbuf to the same size as
it currently is
* store the feeder description in the feeder structure instead of mallocing
space for it
Diffstat (limited to 'sys/dev/sound')
-rw-r--r-- | sys/dev/sound/pcm/buffer.c | 9 | ||||
-rw-r--r-- | sys/dev/sound/pcm/buffer.h | 2 | ||||
-rw-r--r-- | sys/dev/sound/pcm/channel.c | 54 | ||||
-rw-r--r-- | sys/dev/sound/pcm/feeder.c | 58 | ||||
-rw-r--r-- | sys/dev/sound/pcm/feeder.h | 3 | ||||
-rw-r--r-- | sys/dev/sound/pcm/sound.c | 8 | ||||
-rw-r--r-- | sys/dev/sound/pcm/sound.h | 1 |
7 files changed, 93 insertions, 42 deletions
diff --git a/sys/dev/sound/pcm/buffer.c b/sys/dev/sound/pcm/buffer.c index 1081fdf..1604b9d 100644 --- a/sys/dev/sound/pcm/buffer.c +++ b/sys/dev/sound/pcm/buffer.c @@ -34,6 +34,7 @@ SND_DECLARE_FILE("$FreeBSD$"); #define SNDBUF_NAMELEN 48 struct snd_dbuf { + device_t dev; u_int8_t *buf, *tmpbuf; unsigned int bufsize, maxsize; volatile int dl; /* transfer size */ @@ -53,12 +54,14 @@ struct snd_dbuf { }; struct snd_dbuf * -sndbuf_create(char *drv, char *desc) +sndbuf_create(device_t dev, char *drv, char *desc) { struct snd_dbuf *b; b = malloc(sizeof(*b), M_DEVBUF, M_WAITOK | M_ZERO); snprintf(b->name, SNDBUF_NAMELEN, "%s:%s", drv, desc); + b->dev = dev; + return b; } @@ -74,7 +77,7 @@ sndbuf_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) struct snd_dbuf *b = (struct snd_dbuf *)arg; if (bootverbose) { - printf("pcm: setmap %lx, %lx; ", (unsigned long)segs->ds_addr, + device_printf(b->dev, "sndbuf_setmap %lx, %lx; ", (unsigned long)segs->ds_addr, (unsigned long)segs->ds_len); printf("%p -> %lx\n", b->buf, (unsigned long)vtophys(b->buf)); } @@ -133,6 +136,8 @@ sndbuf_resize(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz) blksz = b->blksz; if (blkcnt < 2 || blksz < 16 || (blkcnt * blksz > b->maxsize)) return EINVAL; + if (blkcnt == b->blkcnt && blksz == b->blksz) + return 0; b->blkcnt = blkcnt; b->blksz = blksz; b->bufsize = blkcnt * blksz; diff --git a/sys/dev/sound/pcm/buffer.h b/sys/dev/sound/pcm/buffer.h index 2a57b22..930d2e5 100644 --- a/sys/dev/sound/pcm/buffer.h +++ b/sys/dev/sound/pcm/buffer.h @@ -33,7 +33,7 @@ #define SNDBUF_F_XRUN 0x00000002 #define SNDBUF_F_RUNNING 0x00000004 -struct snd_dbuf *sndbuf_create(char *drv, char *desc); +struct snd_dbuf *sndbuf_create(device_t dev, char *drv, char *desc); void sndbuf_destroy(struct snd_dbuf *b); void sndbuf_dump(struct snd_dbuf *b, char *s, u_int32_t what); diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c index 5789a3d..9a5b6d3 100644 --- a/sys/dev/sound/pcm/channel.c +++ b/sys/dev/sound/pcm/channel.c @@ -686,10 +686,10 @@ chn_init(struct pcm_channel *c, void *devinfo, int dir) goto out; ret = ENOMEM; - b = sndbuf_create(c->name, "primary"); + b = sndbuf_create(c->dev, c->name, "primary"); if (b == NULL) goto out; - bs = sndbuf_create(c->name, "secondary"); + bs = sndbuf_create(c->dev, c->name, "secondary"); if (bs == NULL) goto out; sndbuf_setup(bs, NULL, 0); @@ -1032,6 +1032,7 @@ chn_buildfeeder(struct pcm_channel *c) struct feeder_class *fc; struct pcm_feederdesc desc; u_int32_t tmp[2], type, flags, hwfmt; + int err; CHN_LOCKASSERT(c); while (chn_removefeeder(c) == 0); @@ -1041,13 +1042,13 @@ chn_buildfeeder(struct pcm_channel *c) if (SLIST_EMPTY(&c->children)) { fc = feeder_getclass(NULL); - if (fc == NULL) { - DEB(printf("can't find root feeder\n")); - return EINVAL; - } - if (chn_addfeeder(c, fc, NULL)) { - DEB(printf("can't add root feeder\n")); - return EINVAL; + KASSERT(fc != NULL, ("can't find root feeder")); + + err = chn_addfeeder(c, fc, NULL); + if (err) { + DEB(printf("can't add root feeder, err %d\n", err)); + + return err; } c->feeder->desc->out = c->format; } else { @@ -1058,20 +1059,20 @@ chn_buildfeeder(struct pcm_channel *c) fc = feeder_getclass(&desc); if (fc == NULL) { DEB(printf("can't find vchan feeder\n")); - return EINVAL; + + return EOPNOTSUPP; } - if (chn_addfeeder(c, fc, &desc)) { - DEB(printf("can't add vchan feeder\n")); - return EINVAL; + + err = chn_addfeeder(c, fc, &desc); + if (err) { + DEB(printf("can't add vchan feeder, err %d\n", err)); + + return err; } } flags = c->feederflags; - if ((c->flags & CHN_F_MAPPED) && (flags != 0)) { - DEB(printf("can't build feeder chain on mapped channel\n")); - return EINVAL; - } - DEB(printf("not mapped, flags %x\n", flags)); + DEB(printf("not mapped, feederflags %x\n", flags)); for (type = FEEDER_RATE; type <= FEEDER_LAST; type++) { if (flags & (1 << type)) { @@ -1084,7 +1085,8 @@ chn_buildfeeder(struct pcm_channel *c) DEB(printf("got %p\n", fc)); if (fc == NULL) { DEB(printf("can't find required feeder type %d\n", type)); - return EINVAL; + + return EOPNOTSUPP; } if (c->feeder->desc->out != fc->desc->in) { @@ -1093,14 +1095,17 @@ chn_buildfeeder(struct pcm_channel *c) tmp[1] = 0; if (chn_fmtchain(c, tmp) == 0) { DEB(printf("failed\n")); - return EINVAL; + + return ENODEV; } DEB(printf("ok\n")); } - if (chn_addfeeder(c, fc, fc->desc)) { - DEB(printf("can't add feeder %p, output %x\n", fc, fc->desc->out)); - return EINVAL; + err = chn_addfeeder(c, fc, fc->desc); + if (err) { + DEB(printf("can't add feeder %p, output %x, err %d\n", fc, fc->desc->out, err)); + + return err; } DEB(printf("added feeder %p, output %x\n", fc, c->feeder->desc->out)); } @@ -1119,9 +1124,10 @@ chn_buildfeeder(struct pcm_channel *c) } if (hwfmt == 0) - return EINVAL; + return ENODEV; sndbuf_setfmt(c->bufhard, hwfmt); + return 0; } diff --git a/sys/dev/sound/pcm/feeder.c b/sys/dev/sound/pcm/feeder.c index 5f5da6b..db7c6ed 100644 --- a/sys/dev/sound/pcm/feeder.c +++ b/sys/dev/sound/pcm/feeder.c @@ -49,28 +49,46 @@ static SLIST_HEAD(, feedertab_entry) feedertab; void feeder_register(void *p) { + static int feedercnt = 0; + struct feeder_class *fc = p; struct feedertab_entry *fte; - static int feedercnt = 0; int i; if (feedercnt == 0) { - if (fc->desc) - panic("FIRST FEEDER NOT ROOT: %s\n", fc->name); + KASSERT(fc->desc == NULL, ("first feeder not root: %s", fc->name)); + SLIST_INIT(&feedertab); fte = malloc(sizeof(*fte), M_FEEDER, M_WAITOK | M_ZERO); + if (fte == NULL) { + printf("can't allocate memory for root feeder\n", fc->name); + + return; + } fte->feederclass = fc; fte->desc = NULL; fte->idx = feedercnt; SLIST_INSERT_HEAD(&feedertab, fte, link); feedercnt++; + + /* we've got our root feeder so don't veto pcm loading anymore */ + pcm_veto_load = 0; + return; } + KASSERT(fc->desc != NULL, ("feeder '%s' has no descriptor", fc->name)); + + /* beyond this point failure is non-fatal but may result in some translations being unavailable */ i = 0; while ((feedercnt < MAXFEEDERS) && (fc->desc[i].type > 0)) { /* printf("adding feeder %s, %x -> %x\n", fc->name, fc->desc[i].in, fc->desc[i].out); */ fte = malloc(sizeof(*fte), M_FEEDER, M_WAITOK | M_ZERO); + if (fte == NULL) { + printf("can't allocate memory for feeder '%s', %x -> %x\n", fc->name, fc->desc[i].in, fc->desc[i].out); + + return; + } fte->feederclass = fc; fte->desc = &fc->desc[i]; fte->idx = feedercnt; @@ -80,7 +98,7 @@ feeder_register(void *p) } feedercnt++; if (feedercnt >= MAXFEEDERS) - printf("MAXFEEDERS exceeded\n"); + printf("MAXFEEDERS (%d >= %d) exceeded\n", feedercnt, MAXFEEDERS); } static void @@ -109,7 +127,6 @@ static void feeder_destroy(struct pcm_feeder *f) { FEEDER_FREE(f); - free(f->desc, M_FEEDER); kobj_delete((kobj_t)f, M_FEEDER); } @@ -120,27 +137,35 @@ feeder_create(struct feeder_class *fc, struct pcm_feederdesc *desc) int err; f = (struct pcm_feeder *)kobj_create((kobj_class_t)fc, M_FEEDER, M_WAITOK | M_ZERO); + if (f == NULL) + return NULL; + f->align = fc->align; - f->desc = malloc(sizeof(*(f->desc)), M_FEEDER, M_WAITOK | M_ZERO); - if (desc) + f->data = fc->data; + f->source = NULL; + f->parent = NULL; + f->class = fc; + f->desc = &(f->desc_static); + + if (desc) { *(f->desc) = *desc; - else { + } else { f->desc->type = FEEDER_ROOT; f->desc->in = 0; f->desc->out = 0; f->desc->flags = 0; f->desc->idx = 0; } - f->data = fc->data; - f->source = NULL; - f->class = fc; + err = FEEDER_INIT(f); if (err) { printf("feeder_init(%p) on %s returned %d\n", f, fc->name, err); feeder_destroy(f); + return NULL; - } else - return f; + } + + return f; } struct feeder_class * @@ -164,7 +189,7 @@ chn_addfeeder(struct pcm_channel *c, struct feeder_class *fc, struct pcm_feederd nf = feeder_create(fc, desc); if (nf == NULL) - return -1; + return ENOSPC; nf->source = c->feeder; @@ -188,6 +213,7 @@ chn_removefeeder(struct pcm_channel *c) f = c->feeder; c->feeder = c->feeder->source; feeder_destroy(f); + return 0; } @@ -202,6 +228,7 @@ chn_findfeeder(struct pcm_channel *c, u_int32_t type) return f; f = f->source; } + return NULL; } @@ -225,6 +252,7 @@ chainok(struct pcm_feeder *test, struct pcm_feeder *stop) visited[idx] |= mask; test = test->source; } + return 1; } @@ -261,6 +289,7 @@ feeder_fmtchain(u_int32_t *to, struct pcm_feeder *source, struct pcm_feeder *sto no: } /* printf("giving up %s...\n", source->class->name); */ + return NULL; } @@ -339,6 +368,7 @@ chn_fmtchain(struct pcm_channel *c, u_int32_t *to) #ifdef FEEDER_DEBUG printf("%s [%d]\n", try->class->name, try->desc->idx); #endif + return (c->direction == PCMDIR_REC)? best : c->feeder->desc->out; } diff --git a/sys/dev/sound/pcm/feeder.h b/sys/dev/sound/pcm/feeder.h index f3374a1..9fb8ff7 100644 --- a/sys/dev/sound/pcm/feeder.h +++ b/sys/dev/sound/pcm/feeder.h @@ -43,10 +43,11 @@ struct feeder_class { struct pcm_feeder { KOBJ_FIELDS; int align; - struct pcm_feederdesc *desc; + struct pcm_feederdesc *desc, desc_static; void *data; struct feeder_class *class; struct pcm_feeder *source, *parent; + }; void feeder_register(void *p); diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c index cbd1bc1..535fe35 100644 --- a/sys/dev/sound/pcm/sound.c +++ b/sys/dev/sound/pcm/sound.c @@ -55,6 +55,8 @@ struct snddev_info { devclass_t pcm_devclass; +int pcm_veto_load = 1; + #ifdef USING_DEVFS int snd_unit = 0; TUNABLE_INT("hw.snd.unit", &snd_unit); @@ -599,6 +601,12 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec) { struct snddev_info *d = device_get_softc(dev); + if (pcm_veto_load) { + device_printf(dev, "disabled due to an error while initialising: %d\n", pcm_veto_load); + + return EINVAL; + } + d->lock = snd_mtxcreate(device_get_nameunit(dev)); snd_mtxlock(d->lock); diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h index 5c22ad3..a4418f4 100644 --- a/sys/dev/sound/pcm/sound.h +++ b/sys/dev/sound/pcm/sound.h @@ -198,6 +198,7 @@ int fkchan_kill(struct pcm_channel *c); #define ON 1 #define OFF 0 +extern int pcm_veto_load; extern int snd_unit; extern devclass_t pcm_devclass; |