diff options
author | cg <cg@FreeBSD.org> | 2000-09-01 20:09:24 +0000 |
---|---|---|
committer | cg <cg@FreeBSD.org> | 2000-09-01 20:09:24 +0000 |
commit | a6b7de97e3e709e699c0638c9ff07e8fc3477772 (patch) | |
tree | ba5ec2ebf628be720fad52ae78db04a46cc46680 /sys/dev/sound/pcm | |
parent | e95936f6ddf2411361330abe8f44903c01b42fe5 (diff) | |
download | FreeBSD-src-a6b7de97e3e709e699c0638c9ff07e8fc3477772.zip FreeBSD-src-a6b7de97e3e709e699c0638c9ff07e8fc3477772.tar.gz |
change mixer api slightly
change channel interface - kobj implementation coming soonish
make pcm_makelinks not panic if modular
add pcm_unregister()
these changes support newpcm kld unloading, but this is only implemented
by ds1.c
Diffstat (limited to 'sys/dev/sound/pcm')
-rw-r--r-- | sys/dev/sound/pcm/ac97.c | 21 | ||||
-rw-r--r-- | sys/dev/sound/pcm/ac97.h | 1 | ||||
-rw-r--r-- | sys/dev/sound/pcm/channel.c | 26 | ||||
-rw-r--r-- | sys/dev/sound/pcm/channel.h | 2 | ||||
-rw-r--r-- | sys/dev/sound/pcm/datatypes.h | 16 | ||||
-rw-r--r-- | sys/dev/sound/pcm/mixer.c | 41 | ||||
-rw-r--r-- | sys/dev/sound/pcm/mixer.h | 11 | ||||
-rw-r--r-- | sys/dev/sound/pcm/sound.c | 245 | ||||
-rw-r--r-- | sys/dev/sound/pcm/sound.h | 1 |
9 files changed, 276 insertions, 88 deletions
diff --git a/sys/dev/sound/pcm/ac97.c b/sys/dev/sound/pcm/ac97.c index 8432769..296e800 100644 --- a/sys/dev/sound/pcm/ac97.c +++ b/sys/dev/sound/pcm/ac97.c @@ -386,6 +386,12 @@ ac97_create(device_t dev, void *devinfo, ac97_init *init, ac97_read *rd, ac97_wr return codec; } +void +ac97_destroy(struct ac97_info *codec) +{ + free(codec, M_DEVBUF); +} + static int ac97mix_init(snd_mixer *m) { @@ -400,6 +406,20 @@ ac97mix_init(snd_mixer *m) } static int +ac97mix_uninit(snd_mixer *m) +{ + struct ac97_info *codec = mix_getdevinfo(m); + if (codec == NULL) + return -1; + /* + if (ac97_uninitmixer(codec)) + return -1; + */ + ac97_destroy(codec); + return 0; +} + +static int ac97mix_set(snd_mixer *m, unsigned dev, unsigned left, unsigned right) { struct ac97_info *codec = mix_getdevinfo(m); @@ -424,6 +444,7 @@ ac97mix_setrecsrc(snd_mixer *m, u_int32_t src) snd_mixer ac97_mixer = { "AC97 mixer", ac97mix_init, + ac97mix_uninit, ac97mix_set, ac97mix_setrecsrc, }; diff --git a/sys/dev/sound/pcm/ac97.h b/sys/dev/sound/pcm/ac97.h index 11ff139..0697cea 100644 --- a/sys/dev/sound/pcm/ac97.h +++ b/sys/dev/sound/pcm/ac97.h @@ -72,6 +72,7 @@ struct ac97_info; struct ac97_info *ac97_create(device_t dev, void *devinfo, ac97_init *init, ac97_read *rd, ac97_write *wr); +void ac97_destroy(struct ac97_info *codec); int ac97_setrate(struct ac97_info *codec, int which, int rate); int ac97_setextmode(struct ac97_info *codec, u_int16_t mode); diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c index 2e292b7..af338628 100644 --- a/sys/dev/sound/pcm/channel.c +++ b/sys/dev/sound/pcm/channel.c @@ -850,13 +850,20 @@ chn_dma_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) int chn_allocbuf(snd_dbuf *b, bus_dma_tag_t parent_dmat) { - if (bus_dmamem_alloc(parent_dmat, (void **)&b->buf, + b->parent_dmat = parent_dmat; + if (bus_dmamem_alloc(b->parent_dmat, (void **)&b->buf, BUS_DMA_NOWAIT, &b->dmamap)) return -1; - if (bus_dmamap_load(parent_dmat, b->dmamap, b->buf, + if (bus_dmamap_load(b->parent_dmat, b->dmamap, b->buf, b->bufsize, chn_dma_setmap, b, 0)) return -1; return 0; } +void +chn_freebuf(snd_dbuf *b) +{ + bus_dmamem_free(b->parent_dmat, b->buf, b->dmamap); +} + static void buf_clear(snd_dbuf *b, u_int32_t fmt, int length) { @@ -1152,6 +1159,21 @@ chn_init(pcm_channel *c, void *devinfo, int dir) } int +chn_kill(pcm_channel *c) +{ + chn_trigger(c, PCMTRIG_ABORT); + while (chn_removefeeder(c) == 0); + free(c->feeder->desc, M_DEVBUF); + free(c->feeder, M_DEVBUF); + if (c->free) + c->free(c->devinfo); + else + chn_freebuf(&c->buffer); + c->flags |= CHN_F_DEAD; + return 0; +} + +int chn_setdir(pcm_channel *c, int dir) { int r; diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h index 3f6a359..26857a6 100644 --- a/sys/dev/sound/pcm/channel.h +++ b/sys/dev/sound/pcm/channel.h @@ -34,6 +34,7 @@ int chn_flush(pcm_channel *c); int chn_poll(pcm_channel *c, int ev, struct proc *p); int chn_init(pcm_channel *c, void *devinfo, int dir); +int chn_kill(pcm_channel *c); int chn_setdir(pcm_channel *c, int dir); int chn_reset(pcm_channel *c, u_int32_t fmt); int chn_setvolume(pcm_channel *c, int left, int right); @@ -46,6 +47,7 @@ pcmchan_caps *chn_getcaps(pcm_channel *c); u_int32_t chn_getformats(pcm_channel *c); int chn_allocbuf(snd_dbuf *b, bus_dma_tag_t parent_dmat); +void chn_freebuf(snd_dbuf *b); void chn_resetbuf(pcm_channel *c); void chn_intr(pcm_channel *c); void chn_checkunderflow(pcm_channel *c); diff --git a/sys/dev/sound/pcm/datatypes.h b/sys/dev/sound/pcm/datatypes.h index 6f831e5..c6343a5 100644 --- a/sys/dev/sound/pcm/datatypes.h +++ b/sys/dev/sound/pcm/datatypes.h @@ -36,14 +36,17 @@ typedef struct _pcm_channel pcm_channel; typedef int (mix_set_t)(snd_mixer *m, unsigned dev, unsigned left, unsigned right); typedef int (mix_recsrc_t)(snd_mixer *m, u_int32_t src); typedef int (mix_init_t)(snd_mixer *m); +typedef int (mix_uninit_t)(snd_mixer *m); struct _snd_mixer { char name[64]; mix_init_t *init; + mix_uninit_t *uninit; mix_set_t *set; mix_recsrc_t *setrecsrc; void *devinfo; + int busy; u_int32_t devs; u_int32_t recdevs; u_int32_t recsrc; @@ -70,6 +73,7 @@ struct _snd_dbuf { int fmt, blksz, blkcnt; int underflow, overrun; bus_dmamap_t dmamap; + bus_dma_tag_t parent_dmat; struct selinfo sel; }; @@ -116,6 +120,7 @@ typedef int (pcmchan_setspeed_t)(void *data, u_int32_t speed); typedef int (pcmchan_setblocksize_t)(void *data, u_int32_t blocksize); typedef int (pcmchan_trigger_t)(void *data, int go); typedef int (pcmchan_getptr_t)(void *data); +typedef int (pcmchan_free_t)(void *data); typedef pcmchan_caps *(pcmchan_getcaps_t)(void *data); struct _pcm_channel { @@ -127,6 +132,15 @@ struct _pcm_channel { pcmchan_trigger_t *trigger; pcmchan_getptr_t *getptr; pcmchan_getcaps_t *getcaps; + pcmchan_free_t *free; + void *nop1; + void *nop2; + void *nop3; + void *nop4; + void *nop5; + void *nop6; + void *nop7; + pcm_feeder *feeder; struct pcm_feederdesc *feederdesc; u_int32_t align; @@ -149,7 +163,7 @@ typedef void (pcm_swap_t)(void *data, int dir); struct _snddev_info { pcm_channel *play, *rec, **aplay, **arec, fakechan; int *ref; - unsigned playcount, reccount, chancount; + unsigned playcount, reccount, chancount, maxchans; snd_mixer mixer; u_long magic; unsigned flags; diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c index 68e45d9..77d3e66 100644 --- a/sys/dev/sound/pcm/mixer.c +++ b/sys/dev/sound/pcm/mixer.c @@ -45,8 +45,9 @@ static u_int16_t snd_mixerdefaults[SOUND_MIXER_NRDEVICES] = { }; int -mixer_init(snddev_info *d, snd_mixer *m, void *devinfo) +mixer_init(device_t dev, snd_mixer *m, void *devinfo) { + snddev_info *d = device_get_softc(dev); if (d == NULL) return -1; d->mixer = *m; d->mixer.devinfo = devinfo; @@ -63,9 +64,23 @@ mixer_init(snddev_info *d, snd_mixer *m, void *devinfo) } int -mixer_reinit(snddev_info *d) +mixer_uninit(device_t dev) { int i; + snddev_info *d = device_get_softc(dev); + if (d == NULL) return -1; + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) + mixer_set(d, i, 0); + mixer_setrecsrc(d, SOUND_MASK_MIC); + if (d->mixer.uninit != NULL) d->mixer.uninit(&d->mixer); + return 0; +} + +int +mixer_reinit(device_t dev) +{ + int i; + snddev_info *d = device_get_softc(dev); if (d == NULL) return -1; if (d->mixer.init != NULL && d->mixer.init(&d->mixer) == 0) { for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) @@ -75,7 +90,7 @@ mixer_reinit(snddev_info *d) } else return -1; } -int +static int mixer_set(snddev_info *d, unsigned dev, unsigned lev) { if (d == NULL || d->mixer.set == NULL) return -1; @@ -88,7 +103,7 @@ mixer_set(snddev_info *d, unsigned dev, unsigned lev) } else return -1; } -int +static int mixer_get(snddev_info *d, int dev) { if (d == NULL) return -1; @@ -97,7 +112,7 @@ mixer_get(snddev_info *d, int dev) else return -1; } -int +static int mixer_setrecsrc(snddev_info *d, u_int32_t src) { if (d == NULL || d->mixer.setrecsrc == NULL) return -1; @@ -107,7 +122,7 @@ mixer_setrecsrc(snddev_info *d, u_int32_t src) return 0; } -int +static int mixer_getrecsrc(snddev_info *d) { if (d == NULL) return -1; @@ -154,6 +169,20 @@ mixer_ioctl(snddev_info *d, u_long cmd, caddr_t arg) return ENXIO; } +int +mixer_busy(snddev_info *d, int busy) +{ + if (d == NULL) return -1; + d->mixer.busy = busy; +} + +int +mixer_isbusy(snddev_info *d) +{ + if (d == NULL) return -1; + return d->mixer.busy; +} + void mix_setdevs(snd_mixer *m, u_int32_t v) { diff --git a/sys/dev/sound/pcm/mixer.h b/sys/dev/sound/pcm/mixer.h index a0487d5..eb1946b 100644 --- a/sys/dev/sound/pcm/mixer.h +++ b/sys/dev/sound/pcm/mixer.h @@ -26,13 +26,12 @@ * $FreeBSD$ */ -extern int mixer_init(snddev_info *d, snd_mixer *m, void *devinfo); -extern int mixer_reinit(snddev_info *d); -extern int mixer_set(snddev_info *d, unsigned dev, unsigned lev); -extern int mixer_get(snddev_info *d, int dev); -extern int mixer_setrecsrc(snddev_info *d, u_int32_t src); -extern int mixer_getrecsrc(snddev_info *d); +extern int mixer_init(device_t dev, snd_mixer *m, void *devinfo); +extern int mixer_uninit(device_t dev); +extern int mixer_reinit(device_t dev); extern int mixer_ioctl(snddev_info *d, u_long cmd, caddr_t arg); +extern int mixer_busy(snddev_info *d, int busy); +extern int mixer_isbusy(snddev_info *d); extern void change_bits(mixer_tab *t, u_char *regval, int dev, int chn, int newval); diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c index b27e2d0..bd9434a 100644 --- a/sys/dev/sound/pcm/sound.c +++ b/sys/dev/sound/pcm/sound.c @@ -31,12 +31,11 @@ #include <sys/sysctl.h> #include "opt_devfs.h" +static dev_t status_dev = 0; static int status_isopen = 0; static int status_init(char *buf, int size); static int status_read(struct uio *buf); -MODULE_VERSION(snd_pcm, PCM_MODVER); - static d_open_t sndopen; static d_close_t sndclose; static d_ioctl_t sndioctl; @@ -94,42 +93,133 @@ int snd_unit; TUNABLE_INT_DECL("hw.sndunit", 0, snd_unit); #endif -static snddev_info * -gsd(int unit) +#ifdef DEVFS +static void +pcm_makelinks(void *dummy) { - return devclass_get_softc(pcm_devclass, unit); + int unit; + dev_t pdev; + static dev_t dsp = 0, dspW = 0, audio = 0, mixer = 0; + + if (pcm_devclass == NULL) + return; + if (dsp) { + destroy_dev(dsp); + dsp = 0; + } + if (dspW) { + destroy_dev(dspW); + dspW = 0; + } + if (audio) { + destroy_dev(audio); + audio = 0; + } + if (mixer) { + destroy_dev(mixer); + mixer = 0; + } + + unit = snd_unit; + if (unit < 0 || unit > devclass_get_maxunit(pcm_devclass)) + return; + if (devclass_get_softc(pcm_devclass, unit) == NULL) + return; + + pdev = makedev(CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_DSP, 0)); + dsp = make_dev_alias(pdev, "dsp"); + pdev = makedev(CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_DSP16, 0)); + dspW = make_dev_alias(pdev, "dspW"); + pdev = makedev(CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_AUDIO, 0)); + audio = make_dev_alias(pdev, "audio"); + pdev = makedev(CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_CTL, 0)); + mixer = make_dev_alias(pdev, "mixer"); } +static int +sysctl_hw_sndunit(SYSCTL_HANDLER_ARGS) +{ + int error, unit; + + unit = snd_unit; + error = sysctl_handle_int(oidp, &unit, sizeof(unit), req); + if (error == 0 && req->newptr != NULL) { + snd_unit = unit; + pcm_makelinks(NULL); + } + return (error); +} +SYSCTL_PROC(_hw, OID_AUTO, sndunit, CTLTYPE_INT | CTLFLAG_RW, + 0, sizeof(int), sysctl_hw_sndunit, "I", ""); +#endif + int pcm_addchan(device_t dev, int dir, pcm_channel *templ, void *devinfo) { - int unit = device_get_unit(dev); + int unit = device_get_unit(dev), idx; snddev_info *d = device_get_softc(dev); - pcm_channel *ch; + pcm_channel *chns, *ch; + char *dirs; + + dirs = ((dir == PCMDIR_PLAY)? "play" : "record"); + chns = ((dir == PCMDIR_PLAY)? d->play : d->rec); + idx = ((dir == PCMDIR_PLAY)? d->playcount++ : d->reccount++); - if (((dir == PCMDIR_PLAY)? d->play : d->rec) == NULL) { - device_printf(dev, "bad channel add (%s)\n", - (dir == PCMDIR_PLAY)? "play" : "record"); + if (chns == NULL) { + device_printf(dev, "bad channel add (%s:%d)\n", dirs, idx); return 1; } - ch = (dir == PCMDIR_PLAY)? &d->play[d->playcount] : &d->rec[d->reccount]; + ch = &chns[idx]; *ch = *templ; ch->parent = d; if (chn_init(ch, devinfo, dir)) { - device_printf(dev, "chn_init() for %s:%d failed\n", - (dir == PCMDIR_PLAY)? "play" : "record", - (dir == PCMDIR_PLAY)? d->playcount : d->reccount); + device_printf(dev, "chn_init() for (%s:%d) failed\n", dirs, idx); return 1; } - if (dir == PCMDIR_PLAY) d->playcount++; else d->reccount++; make_dev(&snd_cdevsw, PCMMKMINOR(unit, SND_DEV_DSP, d->chancount), UID_ROOT, GID_WHEEL, 0666, "dsp%d.%d", unit, d->chancount); - make_dev(&snd_cdevsw, PCMMKMINOR(unit, SND_DEV_AUDIO, d->chancount), - UID_ROOT, GID_WHEEL, 0666, "audio%d.%d", unit, d->chancount); make_dev(&snd_cdevsw, PCMMKMINOR(unit, SND_DEV_DSP16, d->chancount), UID_ROOT, GID_WHEEL, 0666, "dspW%d.%d", unit, d->chancount); + make_dev(&snd_cdevsw, PCMMKMINOR(unit, SND_DEV_AUDIO, d->chancount), + UID_ROOT, GID_WHEEL, 0666, "audio%d.%d", unit, d->chancount); /* XXX SND_DEV_NORESET? */ d->chancount++; +#ifdef DEVFS + if (d->chancount == d->maxchans) + pcm_makelinks(NULL); +#endif + return 0; +} + +static int +pcm_killchan(device_t dev, int dir) +{ + int unit = device_get_unit(dev), idx; + snddev_info *d = device_get_softc(dev); + pcm_channel *chns, *ch; + char *dirs; + dev_t pdev; + + dirs = ((dir == PCMDIR_PLAY)? "play" : "record"); + chns = ((dir == PCMDIR_PLAY)? d->play : d->rec); + idx = ((dir == PCMDIR_PLAY)? --d->playcount : --d->reccount); + + if (chns == NULL || idx < 0) { + device_printf(dev, "bad channel kill (%s:%d)\n", dirs, idx); + return 1; + } + ch = &chns[idx]; + if (chn_kill(ch)) { + device_printf(dev, "chn_kill() for (%s:%d) failed\n", dirs, idx); + return 1; + } + d->chancount--; + pdev = makedev(CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_DSP, d->chancount)); + destroy_dev(pdev); + pdev = makedev(CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_DSP16, d->chancount)); + destroy_dev(pdev); + pdev = makedev(CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_AUDIO, d->chancount)); + destroy_dev(pdev); return 0; } @@ -168,6 +258,7 @@ pcm_setswap(device_t dev, pcm_swap_t *swap) snddev_info *d = device_get_softc(dev); d->swap = swap; } + /* This is the generic init routine */ int pcm_register(device_t dev, void *devinfo, int numplay, int numrec) @@ -177,7 +268,7 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec) if (!pcm_devclass) { pcm_devclass = device_get_devclass(dev); - make_dev(&snd_cdevsw, PCMMKMINOR(0, SND_DEV_STATUS, 0), + status_dev = make_dev(&snd_cdevsw, PCMMKMINOR(0, SND_DEV_STATUS, 0), UID_ROOT, GID_WHEEL, 0444, "sndstat"); } make_dev(&snd_cdevsw, PCMMKMINOR(unit, SND_DEV_CTL, 0), @@ -185,6 +276,7 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec) d->dev = dev; d->devinfo = devinfo; d->chancount = d->playcount = d->reccount = 0; + d->maxchans = numplay + numrec; sz = (numplay + numrec) * sizeof(pcm_channel *); if (sz > 0) { @@ -232,67 +324,44 @@ no: if (d->play) free(d->play, M_DEVBUF); if (d->arec) free(d->arec, M_DEVBUF); if (d->rec) free(d->rec, M_DEVBUF); + if (d->ref) free(d->ref, M_DEVBUF); return ENXIO; } -#ifdef DEVFS -static void -pcm_makelinks(void *dummy) +int +pcm_unregister(device_t dev) { - int unit; + int r, i, unit = device_get_unit(dev); + snddev_info *d = device_get_softc(dev); dev_t pdev; - static dev_t dsp = 0, dspW = 0, audio = 0, mixer = 0; - unit = snd_unit; - if (unit > devclass_get_maxunit(pcm_devclass)) - unit = -1; + r = 0; + for (i = 0; i < d->chancount; i++) + if (d->ref[i]) r = EBUSY; + if (r) return r; + if (mixer_isbusy(d) || status_isopen) return EBUSY; - if (dsp) { - destroy_dev(dsp); - dsp = 0; - } - if (dspW) { - destroy_dev(dspW); - dspW = 0; - } - if (audio) { - destroy_dev(audio); - audio = 0; - } - if (mixer) { - destroy_dev(mixer); - mixer = 0; - } + pdev = makedev(CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_CTL, 0)); + destroy_dev(pdev); + mixer_uninit(dev); - if (unit >= 0) { - pdev = makedev(CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_DSP, 0)); - dsp = make_dev_alias(pdev, "dsp"); - pdev = makedev(CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_DSP16, 0)); - dspW = make_dev_alias(pdev, "dspW"); - pdev = makedev(CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_AUDIO, 0)); - audio = make_dev_alias(pdev, "audio"); - pdev = makedev(CDEV_MAJOR, PCMMKMINOR(unit, SND_DEV_CTL, 0)); - mixer = make_dev_alias(pdev, "mixer"); - } -} -SYSINIT(pcm_makelinks, SI_SUB_MOUNT_ROOT, SI_ORDER_ANY, pcm_makelinks, NULL); + while (d->playcount > 0) + pcm_killchan(dev, PCMDIR_PLAY); + while (d->reccount > 0) + pcm_killchan(dev, PCMDIR_REC); + d->magic = 0; -static int -sysctl_hw_sndunit(SYSCTL_HANDLER_ARGS) -{ - int error, unit; + if (d->aplay) free(d->aplay, M_DEVBUF); + if (d->play) free(d->play, M_DEVBUF); + if (d->arec) free(d->arec, M_DEVBUF); + if (d->rec) free(d->rec, M_DEVBUF); + if (d->ref) free(d->ref, M_DEVBUF); - unit = snd_unit; - error = sysctl_handle_int(oidp, &unit, sizeof(unit), req); - if (error == 0 && req->newptr != NULL) { - snd_unit = unit; - pcm_makelinks(NULL); - } - return (error); -} -SYSCTL_PROC(_hw, OID_AUTO, sndunit, CTLTYPE_INT | CTLFLAG_RW, - 0, sizeof(int), sysctl_hw_sndunit, "I", ""); +#ifdef DEVFS + pcm_makelinks(NULL); #endif + return 0; +} /* * a small utility function which, given a device number, returns @@ -302,6 +371,7 @@ SYSCTL_PROC(_hw, OID_AUTO, sndunit, CTLTYPE_INT | CTLFLAG_RW, static snddev_info * get_snddev_info(dev_t i_dev, int *unit, int *dev, int *chan) { + snddev_info *sc; int u, d, c; u = PCMUNIT(i_dev); @@ -313,13 +383,16 @@ get_snddev_info(dev_t i_dev, int *unit, int *dev, int *chan) if (chan) *chan = c; if (u < 0) return NULL; - switch(d) { + sc = devclass_get_softc(pcm_devclass, u); + if (sc == NULL || sc->magic == 0) return NULL; + + switch(d) { case SND_DEV_CTL: /* /dev/mixer handled by pcm */ case SND_DEV_STATUS: /* /dev/sndstat handled by pcm */ case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: - return gsd(u); + return sc; case SND_DEV_SEQ: /* XXX when enabled... */ case SND_DEV_SEQ2: @@ -347,7 +420,7 @@ sndopen(dev_t i_dev, int flags, int mode, struct proc *p) return 0; case SND_DEV_CTL: - return d? 0 : ENXIO; + return d? mixer_busy(d, 1) : ENXIO; case SND_DEV_AUDIO: case SND_DEV_DSP: @@ -375,7 +448,7 @@ sndclose(dev_t i_dev, int flags, int mode, struct proc *p) return 0; case SND_DEV_CTL: - return d? 0 : ENXIO; + return d? mixer_busy(d, 0) : ENXIO; case SND_DEV_AUDIO: case SND_DEV_DSP: @@ -521,7 +594,7 @@ status_init(char *buf, int size) "Installed devices:\n", __DATE__, __TIME__); for (i = 0; i <= devclass_get_maxunit(pcm_devclass); i++) { - d = gsd(i); + d = devclass_get_softc(pcm_devclass, i); if (!d) continue; dev = devclass_get_device(pcm_devclass, i); if (1) { @@ -558,3 +631,29 @@ status_read(struct uio *buf) bufptr += l; return (l > 0)? uiomove(status_buf + bufptr - l, l, buf) : 0; } + +static int +sndpcm_modevent(module_t mod, int type, void *data) +{ + + switch (type) { + case MOD_LOAD: + break; + case MOD_UNLOAD: + if (status_dev) + destroy_dev(status_dev); + status_dev = 0; + break; + default: + break; + } + return 0; +} + +static moduledata_t sndpcm_mod = { + "snd_pcm", + sndpcm_modevent, + NULL +}; +DECLARE_MODULE(snd_pcm, sndpcm_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); +MODULE_VERSION(snd_pcm, PCM_MODVER); diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h index 0e50926..4bc388e 100644 --- a/sys/dev/sound/pcm/sound.h +++ b/sys/dev/sound/pcm/sound.h @@ -165,6 +165,7 @@ int fkchan_setup(pcm_channel *c); int pcm_addchan(device_t dev, int dir, pcm_channel *templ, void *devinfo); int pcm_register(device_t dev, void *devinfo, int numplay, int numrec); +int pcm_unregister(device_t dev); int pcm_setstatus(device_t dev, char *str); u_int32_t pcm_getflags(device_t dev); void pcm_setflags(device_t dev, u_int32_t val); |