diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/sound/isa/ad1816.c | 28 | ||||
-rw-r--r-- | sys/dev/sound/isa/ess.c | 49 | ||||
-rw-r--r-- | sys/dev/sound/isa/mss.c | 35 | ||||
-rw-r--r-- | sys/dev/sound/isa/sb.c | 31 | ||||
-rw-r--r-- | sys/dev/sound/isa/sb16.c | 31 | ||||
-rw-r--r-- | sys/dev/sound/isa/sb8.c | 31 | ||||
-rw-r--r-- | sys/dev/sound/isa/sbc.c | 28 | ||||
-rw-r--r-- | sys/dev/sound/pci/csapcm.c | 38 | ||||
-rw-r--r-- | sys/dev/sound/pci/ds1.c | 32 | ||||
-rw-r--r-- | sys/dev/sound/pci/emu10k1.c | 5 | ||||
-rw-r--r-- | sys/dev/sound/pci/es137x.c | 77 | ||||
-rw-r--r-- | sys/dev/sound/pci/fm801.c | 75 | ||||
-rw-r--r-- | sys/dev/sound/pci/maestro.c | 4 | ||||
-rw-r--r-- | sys/dev/sound/pci/neomagic.c | 31 | ||||
-rw-r--r-- | sys/dev/sound/pci/solo.c | 39 | ||||
-rw-r--r-- | sys/dev/sound/pci/t4dwave.c | 23 | ||||
-rw-r--r-- | sys/dev/sound/pci/via82c686.c | 65 | ||||
-rw-r--r-- | sys/dev/sound/pcm/channel.c | 3 |
18 files changed, 436 insertions, 189 deletions
diff --git a/sys/dev/sound/isa/ad1816.c b/sys/dev/sound/isa/ad1816.c index 3cebbe3..d25931e 100644 --- a/sys/dev/sound/isa/ad1816.c +++ b/sys/dev/sound/isa/ad1816.c @@ -49,6 +49,7 @@ struct ad1816_info { int drq1_rid; struct resource *drq2; /* rec */ int drq2_rid; + void *ih; bus_dma_tag_t parent_dmat; struct ad1816_chinfo pch, rch; @@ -480,6 +481,8 @@ static void ad1816_release_resources(struct ad1816_info *ad1816, device_t dev) { if (ad1816->irq) { + if (ad1816->ih) + bus_teardown_intr(dev, ad1816->irq, ad1816->ih); bus_release_resource(dev, SYS_RES_IRQ, ad1816->irq_rid, ad1816->irq); ad1816->irq = 0; @@ -499,7 +502,11 @@ ad1816_release_resources(struct ad1816_info *ad1816, device_t dev) ad1816->io_base); ad1816->io_base = 0; } - free(ad1816, M_DEVBUF); + if (ad1816->parent_dmat) { + bus_dma_tag_destroy(ad1816->parent_dmat); + ad1816->parent_dmat = 0; + } + free(ad1816, M_DEVBUF); } static int @@ -575,7 +582,6 @@ static int ad1816_attach(device_t dev) { struct ad1816_info *ad1816; - void *ih; char status[SND_STATUSLEN]; ad1816 = (struct ad1816_info *)malloc(sizeof *ad1816, M_DEVBUF, M_NOWAIT); @@ -590,7 +596,7 @@ ad1816_attach(device_t dev) if (!ad1816_alloc_resources(ad1816, dev)) goto no; ad1816_init(ad1816, dev); mixer_init(dev, &ad1816_mixer, ad1816); - bus_setup_intr(dev, ad1816->irq, INTR_TYPE_TTY, ad1816_intr, ad1816, &ih); + bus_setup_intr(dev, ad1816->irq, INTR_TYPE_TTY, ad1816_intr, ad1816, &ad1816->ih); if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/2, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, /*highaddr*/BUS_SPACE_MAXADDR, @@ -621,10 +627,26 @@ no: } +static int +ad1816_detach(device_t dev) +{ + int r; + struct ad1816_info *ad1816; + + r = pcm_unregister(dev); + if (r) + return r; + + ad1816 = pcm_getdevinfo(dev); + ad1816_release_resources(ad1816, dev); + return 0; +} + static device_method_t ad1816_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ad1816_probe), DEVMETHOD(device_attach, ad1816_attach), + DEVMETHOD(device_detach, ad1816_detach), { 0, 0 } }; diff --git a/sys/dev/sound/isa/ess.c b/sys/dev/sound/isa/ess.c index abef688..7b1bddf 100644 --- a/sys/dev/sound/isa/ess.c +++ b/sys/dev/sound/isa/ess.c @@ -47,7 +47,6 @@ /* channel interface for ESS */ static void *esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); -static int esschan_setdir(void *data, int dir); static int esschan_setformat(void *data, u_int32_t format); static int esschan_setspeed(void *data, u_int32_t speed); static int esschan_setblocksize(void *data, u_int32_t blocksize); @@ -85,7 +84,7 @@ static pcmchan_caps ess_reccaps = {5000, 49000, ess_rfmt, 0}; static pcm_channel ess_chantemplate = { esschan_init, - esschan_setdir, + NULL, /* setdir */ esschan_setformat, esschan_setspeed, esschan_setblocksize, @@ -117,6 +116,7 @@ struct ess_info { struct resource *irq; struct resource *drq1; struct resource *drq2; + void *ih; bus_dma_tag_t parent_dmat; int type, duplex:1, newspeed:1; @@ -312,8 +312,9 @@ ess_reset_dsp(struct ess_info *sc) static void ess_release_resources(struct ess_info *sc, device_t dev) { - /* should we bus_teardown_intr here? */ if (sc->irq) { + if (sc->ih) + bus_teardown_intr(dev, sc->irq, sc->ih); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); sc->irq = 0; } @@ -329,7 +330,11 @@ ess_release_resources(struct ess_info *sc, device_t dev) bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->io_base); sc->io_base = 0; } - free(sc, M_DEVBUF); + if (sc->parent_dmat) { + bus_dma_tag_destroy(sc->parent_dmat); + sc->parent_dmat = 0; + } + free(sc, M_DEVBUF); } static int @@ -374,7 +379,6 @@ ess_alloc_resources(struct ess_info *sc, device_t dev) static int ess_doattach(device_t dev, struct ess_info *sc) { - void *ih; char status[SND_STATUSLEN], buf[64]; int ver; @@ -410,7 +414,7 @@ ess_doattach(device_t dev, struct ess_info *sc) if (sc->newspeed) ess_setmixer(sc, 0x71, 0x22); - bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, ess_intr, sc, &ih); + bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, ess_intr, sc, &sc->ih); if (!sc->duplex) pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); @@ -445,6 +449,21 @@ no: return ENXIO; } +static int +ess_detach(device_t dev) +{ + int r; + struct ess_info *sc; + + r = pcm_unregister(dev); + if (r) + return r; + + sc = pcm_getdevinfo(dev); + ess_release_resources(sc, dev); + return 0; +} + static void ess_intr(void *arg) { @@ -650,6 +669,7 @@ esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) ch->buffer->bufsize = ESS_BUFFSIZE; if (chn_allocbuf(ch->buffer, sc->parent_dmat) == -1) return NULL; + ch->dir = dir; ch->hwch = 1; if ((dir == PCMDIR_PLAY) && (sc->duplex)) ch->hwch = 2; @@ -658,15 +678,6 @@ esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) } static int -esschan_setdir(void *data, int dir) -{ - struct ess_chinfo *ch = data; - - ch->dir = dir; - return 0; -} - -static int esschan_setformat(void *data, u_int32_t format) { struct ess_chinfo *ch = data; @@ -881,6 +892,7 @@ static device_method_t ess_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ess_probe), DEVMETHOD(device_attach, ess_attach), + DEVMETHOD(device_detach, ess_detach), { 0, 0 } }; @@ -935,10 +947,17 @@ esscontrol_attach(device_t dev) return 0; } +static int +esscontrol_detach(device_t dev) +{ + return 0; +} + static device_method_t esscontrol_methods[] = { /* Device interface */ DEVMETHOD(device_probe, esscontrol_probe), DEVMETHOD(device_attach, esscontrol_attach), + DEVMETHOD(device_detach, esscontrol_detach), { 0, 0 } }; diff --git a/sys/dev/sound/isa/mss.c b/sys/dev/sound/isa/mss.c index 93347c5..a59d9b9 100644 --- a/sys/dev/sound/isa/mss.c +++ b/sys/dev/sound/isa/mss.c @@ -60,6 +60,7 @@ struct mss_info { int drq1_rid; struct resource *drq2; /* rec */ int drq2_rid; + void *ih; bus_dma_tag_t parent_dmat; char mss_indexed_regs[MSS_INDEXED_REGS]; @@ -284,7 +285,9 @@ static void mss_release_resources(struct mss_info *mss, device_t dev) { if (mss->irq) { - bus_release_resource(dev, SYS_RES_IRQ, mss->irq_rid, + if (mss->ih) + bus_teardown_intr(dev, mss->irq, mss->ih); + bus_release_resource(dev, SYS_RES_IRQ, mss->irq_rid, mss->irq); mss->irq = 0; } @@ -310,7 +313,11 @@ mss_release_resources(struct mss_info *mss, device_t dev) mss->conf_base); mss->conf_base = 0; } - free(mss, M_DEVBUF); + if (mss->parent_dmat) { + bus_dma_tag_destroy(mss->parent_dmat); + mss->parent_dmat = 0; + } + free(mss, M_DEVBUF); } static int @@ -872,7 +879,6 @@ ymf_test(device_t dev, struct mss_info *mss) static int mss_doattach(device_t dev, struct mss_info *mss) { - void *ih; int flags = device_get_flags(dev); char status[SND_STATUSLEN]; @@ -914,10 +920,10 @@ mss_doattach(device_t dev, struct mss_info *mss) mixer_init(dev, (mss->bd_id == MD_YM0020)? &yamaha_mixer : &mss_mixer, mss); switch (mss->bd_id) { case MD_OPTI931: - bus_setup_intr(dev, mss->irq, INTR_TYPE_TTY, opti931_intr, mss, &ih); + bus_setup_intr(dev, mss->irq, INTR_TYPE_TTY, opti931_intr, mss, &mss->ih); break; default: - bus_setup_intr(dev, mss->irq, INTR_TYPE_TTY, mss_intr, mss, &ih); + bus_setup_intr(dev, mss->irq, INTR_TYPE_TTY, mss_intr, mss, &mss->ih); } if (mss->pdma == mss->rdma) pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); @@ -948,6 +954,22 @@ no: } static int +mss_detach(device_t dev) +{ + int r; + struct mss_info *mss; + + r = pcm_unregister(dev); + if (r) + return r; + + mss = pcm_getdevinfo(dev); + mss_release_resources(mss, dev); + + return 0; +} + +static int mss_attach(device_t dev) { struct mss_info *mss; @@ -1043,6 +1065,7 @@ static device_method_t mss_methods[] = { /* Device interface */ DEVMETHOD(device_probe, mss_probe), DEVMETHOD(device_attach, mss_attach), + DEVMETHOD(device_detach, mss_detach), DEVMETHOD(device_suspend, mss_suspend), DEVMETHOD(device_resume, mss_resume), @@ -1540,6 +1563,7 @@ static device_method_t pnpmss_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pnpmss_probe), DEVMETHOD(device_attach, pnpmss_attach), + DEVMETHOD(device_detach, mss_detach), DEVMETHOD(device_suspend, mss_suspend), DEVMETHOD(device_resume, mss_resume), @@ -1684,6 +1708,7 @@ skip_setup: static device_method_t guspcm_methods[] = { DEVMETHOD(device_probe, guspcm_probe), DEVMETHOD(device_attach, guspcm_attach), + DEVMETHOD(device_detach, mss_detach), { 0, 0 } }; diff --git a/sys/dev/sound/isa/sb.c b/sys/dev/sound/isa/sb.c index 21c3e6f..6d9154a 100644 --- a/sys/dev/sound/isa/sb.c +++ b/sys/dev/sound/isa/sb.c @@ -132,6 +132,7 @@ struct sb_info { struct resource *irq; struct resource *drq1; struct resource *drq2; + void *ih; bus_dma_tag_t parent_dmat; int bd_id; @@ -329,9 +330,10 @@ sb_reset_dsp(struct sb_info *sb) static void sb_release_resources(struct sb_info *sb, device_t dev) { - /* should we bus_teardown_intr here? */ if (sb->irq) { - bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq); + if (sb->ih) + bus_teardown_intr(dev, sb->irq, sb->ih); + bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq); sb->irq = 0; } if (sb->drq1) { @@ -346,7 +348,11 @@ sb_release_resources(struct sb_info *sb, device_t dev) bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base); sb->io_base = 0; } - free(sb, M_DEVBUF); + if (sb->parent_dmat) { + bus_dma_tag_destroy(sb->parent_dmat); + sb->parent_dmat = 0; + } + free(sb, M_DEVBUF); } static int @@ -421,7 +427,6 @@ sb16_swap(void *v, int dir) static int sb_doattach(device_t dev, struct sb_info *sb) { - void *ih; char status[SND_STATUSLEN]; int bs = DSP_BUFFSIZE; @@ -431,7 +436,7 @@ sb_doattach(device_t dev, struct sb_info *sb) goto no; mixer_init(dev, &sb_mixer, sb); - bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &ih); + bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &sb->ih); if ((sb->bd_flags & BD_F_SB16) && !(sb->bd_flags & BD_F_SB16X)) pcm_setswap(dev, sb16_swap); if (!sb->drq2) @@ -468,6 +473,21 @@ no: return ENXIO; } +static int +sb_detach(device_t dev) +{ + int r; + struct sb_info *sb; + + r = pcm_unregister(dev); + if (r) + return r; + + sb = pcm_getdevinfo(dev); + sb_release_resources(sb, dev); + return 0; +} + static void sb_intr(void *arg) { @@ -897,6 +917,7 @@ static device_method_t sbsbc_methods[] = { /* Device interface */ DEVMETHOD(device_probe, sbsbc_probe), DEVMETHOD(device_attach, sbsbc_attach), + DEVMETHOD(device_detach, sb_detach), { 0, 0 } }; diff --git a/sys/dev/sound/isa/sb16.c b/sys/dev/sound/isa/sb16.c index 21c3e6f..6d9154a 100644 --- a/sys/dev/sound/isa/sb16.c +++ b/sys/dev/sound/isa/sb16.c @@ -132,6 +132,7 @@ struct sb_info { struct resource *irq; struct resource *drq1; struct resource *drq2; + void *ih; bus_dma_tag_t parent_dmat; int bd_id; @@ -329,9 +330,10 @@ sb_reset_dsp(struct sb_info *sb) static void sb_release_resources(struct sb_info *sb, device_t dev) { - /* should we bus_teardown_intr here? */ if (sb->irq) { - bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq); + if (sb->ih) + bus_teardown_intr(dev, sb->irq, sb->ih); + bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq); sb->irq = 0; } if (sb->drq1) { @@ -346,7 +348,11 @@ sb_release_resources(struct sb_info *sb, device_t dev) bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base); sb->io_base = 0; } - free(sb, M_DEVBUF); + if (sb->parent_dmat) { + bus_dma_tag_destroy(sb->parent_dmat); + sb->parent_dmat = 0; + } + free(sb, M_DEVBUF); } static int @@ -421,7 +427,6 @@ sb16_swap(void *v, int dir) static int sb_doattach(device_t dev, struct sb_info *sb) { - void *ih; char status[SND_STATUSLEN]; int bs = DSP_BUFFSIZE; @@ -431,7 +436,7 @@ sb_doattach(device_t dev, struct sb_info *sb) goto no; mixer_init(dev, &sb_mixer, sb); - bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &ih); + bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &sb->ih); if ((sb->bd_flags & BD_F_SB16) && !(sb->bd_flags & BD_F_SB16X)) pcm_setswap(dev, sb16_swap); if (!sb->drq2) @@ -468,6 +473,21 @@ no: return ENXIO; } +static int +sb_detach(device_t dev) +{ + int r; + struct sb_info *sb; + + r = pcm_unregister(dev); + if (r) + return r; + + sb = pcm_getdevinfo(dev); + sb_release_resources(sb, dev); + return 0; +} + static void sb_intr(void *arg) { @@ -897,6 +917,7 @@ static device_method_t sbsbc_methods[] = { /* Device interface */ DEVMETHOD(device_probe, sbsbc_probe), DEVMETHOD(device_attach, sbsbc_attach), + DEVMETHOD(device_detach, sb_detach), { 0, 0 } }; diff --git a/sys/dev/sound/isa/sb8.c b/sys/dev/sound/isa/sb8.c index 21c3e6f..6d9154a 100644 --- a/sys/dev/sound/isa/sb8.c +++ b/sys/dev/sound/isa/sb8.c @@ -132,6 +132,7 @@ struct sb_info { struct resource *irq; struct resource *drq1; struct resource *drq2; + void *ih; bus_dma_tag_t parent_dmat; int bd_id; @@ -329,9 +330,10 @@ sb_reset_dsp(struct sb_info *sb) static void sb_release_resources(struct sb_info *sb, device_t dev) { - /* should we bus_teardown_intr here? */ if (sb->irq) { - bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq); + if (sb->ih) + bus_teardown_intr(dev, sb->irq, sb->ih); + bus_release_resource(dev, SYS_RES_IRQ, 0, sb->irq); sb->irq = 0; } if (sb->drq1) { @@ -346,7 +348,11 @@ sb_release_resources(struct sb_info *sb, device_t dev) bus_release_resource(dev, SYS_RES_IOPORT, 0, sb->io_base); sb->io_base = 0; } - free(sb, M_DEVBUF); + if (sb->parent_dmat) { + bus_dma_tag_destroy(sb->parent_dmat); + sb->parent_dmat = 0; + } + free(sb, M_DEVBUF); } static int @@ -421,7 +427,6 @@ sb16_swap(void *v, int dir) static int sb_doattach(device_t dev, struct sb_info *sb) { - void *ih; char status[SND_STATUSLEN]; int bs = DSP_BUFFSIZE; @@ -431,7 +436,7 @@ sb_doattach(device_t dev, struct sb_info *sb) goto no; mixer_init(dev, &sb_mixer, sb); - bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &ih); + bus_setup_intr(dev, sb->irq, INTR_TYPE_TTY, sb_intr, sb, &sb->ih); if ((sb->bd_flags & BD_F_SB16) && !(sb->bd_flags & BD_F_SB16X)) pcm_setswap(dev, sb16_swap); if (!sb->drq2) @@ -468,6 +473,21 @@ no: return ENXIO; } +static int +sb_detach(device_t dev) +{ + int r; + struct sb_info *sb; + + r = pcm_unregister(dev); + if (r) + return r; + + sb = pcm_getdevinfo(dev); + sb_release_resources(sb, dev); + return 0; +} + static void sb_intr(void *arg) { @@ -897,6 +917,7 @@ static device_method_t sbsbc_methods[] = { /* Device interface */ DEVMETHOD(device_probe, sbsbc_probe), DEVMETHOD(device_attach, sbsbc_attach), + DEVMETHOD(device_detach, sb_detach), { 0, 0 } }; diff --git a/sys/dev/sound/isa/sbc.c b/sys/dev/sound/isa/sbc.c index dcb85ee..6bce41a 100644 --- a/sys/dev/sound/isa/sbc.c +++ b/sys/dev/sound/isa/sbc.c @@ -58,7 +58,7 @@ struct sbc_softc { struct sbc_ihl ihl[IRQ_MAX]; - void *ih; + void *ih[IRQ_MAX]; u_int32_t bd_ver; }; @@ -372,9 +372,11 @@ sbc_attach(device_t dev) else sb_setmixer(scp->io[0], IRQ_NR, x); sb_setmixer(scp->io[0], DMA_NR, (1 << dh) | (1 << dl)); #endif - device_printf(dev, "setting card to irq %d, drq %d", irq, dl); - if (dl != dh) printf(", %d", dh); - printf("\n"); + if (bootverbose) { + device_printf(dev, "setting card to irq %d, drq %d", irq, dl); + if (dl != dh) printf(", %d", dh); + printf("\n"); + } break; } @@ -389,7 +391,7 @@ sbc_attach(device_t dev) err = "setup_intr"; for (i = 0; i < IRQ_MAX; i++) { - if (bus_setup_intr(dev, scp->irq[i], INTR_TYPE_TTY, sbc_intr, &scp->ihl[i], &scp->ih)) + if (bus_setup_intr(dev, scp->irq[i], INTR_TYPE_TTY, sbc_intr, &scp->ihl[i], &scp->ih[i])) goto bad; } @@ -427,6 +429,15 @@ bad: if (err) device_printf(dev, "%s\n", err); return (ENXIO); } +static int +sbc_detach(device_t dev) +{ + struct sbc_softc *scp = device_get_softc(dev); + + release_resource(scp); + return bus_generic_detach(dev); +} + static void sbc_intr(void *p) { @@ -648,7 +659,7 @@ alloc_resource(struct sbc_softc *scp) } } for (i = 0 ; i < IRQ_MAX ; i++) { - if (scp->irq[i] == NULL) { + if (scp->irq[i] == NULL) { scp->irq_rid[i] = i; scp->irq[i] = bus_alloc_resource(scp->dev, SYS_RES_IRQ, &scp->irq_rid[i], 0, ~0, 1, RF_ACTIVE); @@ -679,6 +690,9 @@ release_resource(struct sbc_softc *scp) } for (i = 0 ; i < IRQ_MAX ; i++) { if (scp->irq[i] != NULL) { + if (scp->ih[i] != NULL) + bus_teardown_intr(scp->dev, scp->irq[i], scp->ih[i]); + scp->ih[i] = NULL; bus_release_resource(scp->dev, SYS_RES_IRQ, scp->irq_rid[i], scp->irq[i]); scp->irq[i] = NULL; } @@ -690,7 +704,7 @@ static device_method_t sbc_methods[] = { /* Device interface */ DEVMETHOD(device_probe, sbc_probe), DEVMETHOD(device_attach, sbc_attach), - DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_detach, sbc_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), diff --git a/sys/dev/sound/pci/csapcm.c b/sys/dev/sound/pci/csapcm.c index 2c9e5ca..1a5f807 100644 --- a/sys/dev/sound/pci/csapcm.c +++ b/sys/dev/sound/pci/csapcm.c @@ -751,6 +751,8 @@ csa_releaseres(struct csa_info *csa, device_t dev) resp = &csa->res; if (resp->irq != NULL) { + if (csa->ih) + bus_teardown_intr(dev, resp->irq, csa->ih); bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq); resp->irq = NULL; } @@ -762,6 +764,14 @@ csa_releaseres(struct csa_info *csa, device_t dev) bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem); resp->mem = NULL; } + if (csa->parent_dmat != NULL) { + bus_dma_tag_destroy(csa->parent_dmat); + csa->parent_dmat = NULL; + } + if (csa != NULL) { + free(csa, M_DEVBUF); + csa = NULL; + } } static int pcmcsa_probe(device_t dev); @@ -824,15 +834,21 @@ pcmcsa_attach(device_t dev) return (ENXIO); } codec = ac97_create(dev, csa, NULL, csa_rdcd, csa_wrcd); - if (codec == NULL) + if (codec == NULL) { + csa_releaseres(csa, dev); return (ENXIO); - if (mixer_init(dev, &ac97_mixer, codec) == -1) + } + if (mixer_init(dev, &ac97_mixer, codec) == -1) { + ac97_destroy(codec); + csa_releaseres(csa, dev); return (ENXIO); + } snprintf(status, SND_STATUSLEN, "at irq %ld", rman_get_start(resp->irq)); /* Enable interrupt. */ if (bus_setup_intr(dev, resp->irq, INTR_TYPE_TTY, csa_intr, csa, &csa->ih)) { + ac97_destroy(codec); csa_releaseres(csa, dev); return (ENXIO); } @@ -840,6 +856,7 @@ pcmcsa_attach(device_t dev) csa_writemem(resp, BA1_CIE, (csa_readmem(resp, BA1_CIE) & ~0x0000003f) | 0x00000001); if (pcm_register(dev, csa, 1, 1)) { + ac97_destroy(codec); csa_releaseres(csa, dev); return (ENXIO); } @@ -850,6 +867,22 @@ pcmcsa_attach(device_t dev) return (0); } +static int +pcmcsa_detach(device_t dev) +{ + int r; + struct csa_info *csa; + + r = pcm_unregister(dev); + if (r) + return r; + + csa = pcm_getdevinfo(dev); + csa_releaseres(csa, dev); + + return 0; +} + /* ac97 codec */ static u_int32_t @@ -876,6 +909,7 @@ static device_method_t pcmcsa_methods[] = { /* Device interface */ DEVMETHOD(device_probe , pcmcsa_probe ), DEVMETHOD(device_attach, pcmcsa_attach), + DEVMETHOD(device_detach, pcmcsa_detach), { 0, 0 }, }; diff --git a/sys/dev/sound/pci/ds1.c b/sys/dev/sound/pci/ds1.c index 143b5b4..3195c8b 100644 --- a/sys/dev/sound/pci/ds1.c +++ b/sys/dev/sound/pci/ds1.c @@ -210,7 +210,7 @@ static pcmchan_caps ds_playcaps = {4000, 96000, ds_playfmt, 0}; static pcm_channel ds_pchantemplate = { ds1pchan_init, - ds1pchan_setdir, + NULL, /* setdir */ ds1pchan_setformat, ds1pchan_setspeed, ds1pchan_setblocksize, @@ -229,7 +229,7 @@ static pcm_channel ds_pchantemplate = { static pcm_channel ds_rchantemplate = { ds1rchan_init, - ds1rchan_setdir, + NULL, /* setdir */ ds1rchan_setformat, ds1rchan_setspeed, ds1rchan_setblocksize, @@ -550,12 +550,6 @@ ds1pchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) } static int -ds1pchan_setdir(void *data, int dir) -{ - return 0; -} - -static int ds1pchan_setformat(void *data, u_int32_t format) { struct sc_pchinfo *ch = data; @@ -661,12 +655,6 @@ ds1rchan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) } static int -ds1rchan_setdir(void *data, int dir) -{ - return 0; -} - -static int ds1rchan_setformat(void *data, u_int32_t format) { struct sc_rchinfo *ch = data; @@ -938,7 +926,7 @@ ds_pci_attach(device_t dev) u_int32_t data; u_int32_t subdev, i; struct sc_info *sc; - struct ac97_info *codec; + struct ac97_info *codec = NULL; char status[SND_STATUSLEN]; if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) { @@ -1012,12 +1000,16 @@ ds_pci_attach(device_t dev) return 0; bad: + if (codec) + ac97_destroy(codec); if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih); if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); + if (sc->parent_dmat) + bus_dma_tag_destroy(sc->parent_dmat); free(sc, M_DEVBUF); return ENXIO; } @@ -1052,12 +1044,10 @@ ds_pci_detach(device_t dev) sc = pcm_getdevinfo(dev); ds_uninit(sc); - if (sc->reg) - bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); - if (sc->ih) - bus_teardown_intr(dev, sc->irq, sc->ih); - if (sc->irq) - bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); + bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); + bus_teardown_intr(dev, sc->irq, sc->ih); + bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); + bus_dma_tag_destroy(sc->parent_dmat); free(sc, M_DEVBUF); return 0; } diff --git a/sys/dev/sound/pci/emu10k1.c b/sys/dev/sound/pci/emu10k1.c index d0f73d2..98d55c7 100644 --- a/sys/dev/sound/pci/emu10k1.c +++ b/sys/dev/sound/pci/emu10k1.c @@ -1410,7 +1410,7 @@ emu_pci_attach(device_t dev) { u_int32_t data; struct sc_info *sc; - struct ac97_info *codec; + struct ac97_info *codec = NULL; int i, mapped; char status[SND_STATUSLEN]; @@ -1496,9 +1496,11 @@ emu_pci_attach(device_t dev) return 0; bad: + if (codec) ac97_destroy(codec); if (sc->reg) bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih); if (sc->irq) bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); + if (sc->parent_dmat) bus_dma_tag_destroy(sc->parent_dmat); free(sc, M_DEVBUF); return ENXIO; } @@ -1520,6 +1522,7 @@ emu_pci_detach(device_t dev) bus_release_resource(dev, sc->regtype, sc->regid, sc->reg); bus_teardown_intr(dev, sc->irq, sc->ih); bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); + bus_dma_tag_destroy(sc->parent_dmat); free(sc, M_DEVBUF); return 0; diff --git a/sys/dev/sound/pci/es137x.c b/sys/dev/sound/pci/es137x.c index 544ad83..3764e15 100644 --- a/sys/dev/sound/pci/es137x.c +++ b/sys/dev/sound/pci/es137x.c @@ -88,6 +88,10 @@ struct es_info { bus_space_handle_t sh; bus_dma_tag_t parent_dmat; + struct resource *reg, *irq; + int regtype, regid, irqid; + void *ih; + device_t dev; int num; /* Contents of board's registers */ @@ -761,15 +765,9 @@ es_pci_attach(device_t dev) { u_int32_t data; struct es_info *es = 0; - int type = 0; - int regid; - struct resource *reg = 0; int mapped; - int irqid; - struct resource *irq = 0; - void *ih = 0; char status[SND_STATUSLEN]; - struct ac97_info *codec; + struct ac97_info *codec = 0; pcm_channel *ct = NULL; if ((es = malloc(sizeof *es, M_DEVBUF, M_NOWAIT)) == NULL) { @@ -785,24 +783,24 @@ es_pci_attach(device_t dev) pci_write_config(dev, PCIR_COMMAND, data, 2); data = pci_read_config(dev, PCIR_COMMAND, 2); if (mapped == 0 && (data & PCIM_CMD_MEMEN)) { - regid = MEM_MAP_REG; - type = SYS_RES_MEMORY; - reg = bus_alloc_resource(dev, type, ®id, + es->regid = MEM_MAP_REG; + es->regtype = SYS_RES_MEMORY; + es->reg = bus_alloc_resource(dev, es->regtype, &es->regid, 0, ~0, 1, RF_ACTIVE); - if (reg) { - es->st = rman_get_bustag(reg); - es->sh = rman_get_bushandle(reg); + if (es->reg) { + es->st = rman_get_bustag(es->reg); + es->sh = rman_get_bushandle(es->reg); mapped++; } } if (mapped == 0 && (data & PCIM_CMD_PORTEN)) { - regid = PCIR_MAPS; - type = SYS_RES_IOPORT; - reg = bus_alloc_resource(dev, type, ®id, + es->regid = PCIR_MAPS; + es->regtype = SYS_RES_IOPORT; + es->reg = bus_alloc_resource(dev, es->regtype, &es->regid, 0, ~0, 1, RF_ACTIVE); - if (reg) { - es->st = rman_get_bustag(reg); - es->sh = rman_get_bushandle(reg); + if (es->reg) { + es->st = rman_get_bustag(es->reg); + es->sh = rman_get_bushandle(es->reg); mapped++; } } @@ -834,11 +832,11 @@ es_pci_attach(device_t dev) ct = &es1370_chantemplate; } else goto bad; - irqid = 0; - irq = bus_alloc_resource(dev, SYS_RES_IRQ, &irqid, + es->irqid = 0; + es->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &es->irqid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); - if (!irq - || bus_setup_intr(dev, irq, INTR_TYPE_TTY, es_intr, es, &ih)) { + if (!es->irq + || bus_setup_intr(dev, es->irq, INTR_TYPE_TTY, es_intr, es, &es->ih)) { device_printf(dev, "unable to map interrupt\n"); goto bad; } @@ -854,8 +852,8 @@ es_pci_attach(device_t dev) } snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld", - (type == SYS_RES_IOPORT)? "io" : "memory", - rman_get_start(reg), rman_get_start(irq)); + (es->regtype == SYS_RES_IOPORT)? "io" : "memory", + rman_get_start(es->reg), rman_get_start(es->irq)); if (pcm_register(dev, es, 1, 1)) goto bad; pcm_addchan(dev, PCMDIR_REC, ct, es); @@ -865,17 +863,40 @@ es_pci_attach(device_t dev) return 0; bad: + if (codec) ac97_destroy(codec); + if (es->reg) bus_release_resource(dev, es->regtype, es->regid, es->reg); + if (es->ih) bus_teardown_intr(dev, es->irq, es->ih); + if (es->irq) bus_release_resource(dev, SYS_RES_IRQ, es->irqid, es->irq); + if (es->parent_dmat) bus_dma_tag_destroy(es->parent_dmat); if (es) free(es, M_DEVBUF); - if (reg) bus_release_resource(dev, type, regid, reg); - if (ih) bus_teardown_intr(dev, irq, ih); - if (irq) bus_release_resource(dev, SYS_RES_IRQ, irqid, irq); return ENXIO; } +static int +es_pci_detach(device_t dev) +{ + int r; + struct es_info *es; + + r = pcm_unregister(dev); + if (r) + return r; + + es = pcm_getdevinfo(dev); + bus_release_resource(dev, es->regtype, es->regid, es->reg); + bus_teardown_intr(dev, es->irq, es->ih); + bus_release_resource(dev, SYS_RES_IRQ, es->irqid, es->irq); + bus_dma_tag_destroy(es->parent_dmat); + free(es, M_DEVBUF); + + return 0; +} + static device_method_t es_methods[] = { /* Device interface */ DEVMETHOD(device_probe, es_pci_probe), DEVMETHOD(device_attach, es_pci_attach), + DEVMETHOD(device_detach, es_pci_detach), { 0, 0 } }; diff --git a/sys/dev/sound/pci/fm801.c b/sys/dev/sound/pci/fm801.c index 8188a1d..2173c0a 100644 --- a/sys/dev/sound/pci/fm801.c +++ b/sys/dev/sound/pci/fm801.c @@ -104,7 +104,6 @@ /* channel interface */ static void *fm801ch_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir); -static int fm801ch_setdir(void *data, int dir); static int fm801ch_setformat(void *data, u_int32_t format); static int fm801ch_setspeed(void *data, u_int32_t speed); static int fm801ch_setblocksize(void *data, u_int32_t blocksize); @@ -119,9 +118,7 @@ static u_int32_t fmts[] = { AFMT_U8, AFMT_STEREO | AFMT_U8, AFMT_S16_LE, - AFMT_STEREO | AFMT_S16_LE, /* - AFMT_STEREO | (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE), - (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE), */ + AFMT_STEREO | AFMT_S16_LE, 0 }; @@ -132,7 +129,7 @@ static pcmchan_caps fm801ch_caps = { static pcm_channel fm801_chantemplate = { fm801ch_init, - fm801ch_setdir, + NULL, /* setdir */ fm801ch_setformat, fm801ch_setspeed, fm801ch_setblocksize, @@ -192,23 +189,6 @@ struct fm801_info { struct fm801_chinfo pch, rch; }; - -/* several procedures to release the thing properly if compiled as module */ -static struct fm801_info *save801; -struct fm801_info *fm801_get __P((void )); - -static void -fm801_save(struct fm801_info *fm801) -{ - save801 = fm801; -} - -struct fm801_info * -fm801_get(void ) -{ - return save801; -} - /* Bus Read / Write routines */ static u_int32_t fm801_rd(struct fm801_info *fm801, int regno, int size) @@ -395,7 +375,7 @@ static int fm801_pci_attach(device_t dev) { u_int32_t data; - struct ac97_info *codec; + struct ac97_info *codec = 0; struct fm801_info *fm801; int i; int mapped = 0; @@ -475,19 +455,40 @@ fm801_pci_attach(device_t dev) pcm_addchan(dev, PCMDIR_REC, &fm801_chantemplate, fm801); pcm_setstatus(dev, status); - fm801_save(fm801); return 0; oops: - printf("Forte Media FM801 initialization failed\n"); + if (codec) ac97_destroy(codec); if (fm801->reg) bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg); if (fm801->ih) bus_teardown_intr(dev, fm801->irq, fm801->ih); if (fm801->irq) bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq); + if (fm801->parent_dmat) bus_dma_tag_destroy(fm801->parent_dmat); free(fm801, M_DEVBUF); return ENXIO; } static int +fm801_pci_detach(device_t dev) +{ + int r; + struct fm801_info *fm801; + + DPRINT("Forte Media FM801 detach\n"); + + r = pcm_unregister(dev); + if (r) + return r; + + fm801 = pcm_getdevinfo(dev); + bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg); + bus_teardown_intr(dev, fm801->irq, fm801->ih); + bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq); + bus_dma_tag_destroy(fm801->parent_dmat); + free(fm801, M_DEVBUF); + return 0; +} + +static int fm801_pci_probe( device_t dev ) { int id; @@ -524,14 +525,6 @@ fm801ch_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) } static int -fm801ch_setdir(void *data, int dir) -{ - struct fm801_chinfo *ch = data; - ch->dir = dir; - return 0; -} - -static int fm801ch_setformat(void *data, u_int32_t format) { struct fm801_chinfo *ch = data; @@ -716,20 +709,6 @@ fm801ch_getcaps(void *data) return &fm801ch_caps; } -static int -fm801_pci_detach(device_t dev) -{ - struct fm801_info *fm801 = fm801_get(); - - DPRINT("Forte Media FM801 detach\n"); - - if (fm801->reg) bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg); - if (fm801->ih) bus_teardown_intr(dev, fm801->irq, fm801->ih); - if (fm801->irq) bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq); - free(fm801, M_DEVBUF); - return 0; -} - static device_method_t fm801_methods[] = { /* Device interface */ DEVMETHOD(device_probe, fm801_pci_probe), @@ -746,4 +725,4 @@ static driver_t fm801_driver = { static devclass_t pcm_devclass; -DRIVER_MODULE(fm801, pci, fm801_driver, pcm_devclass,0, 0); +DRIVER_MODULE(fm801, pci, fm801_driver, pcm_devclass, 0, 0); diff --git a/sys/dev/sound/pci/maestro.c b/sys/dev/sound/pci/maestro.c index c9926c4..a465d5c 100644 --- a/sys/dev/sound/pci/maestro.c +++ b/sys/dev/sound/pci/maestro.c @@ -1041,12 +1041,12 @@ agg_attach(device_t dev) return 0; bad: + if (codec != NULL) + ac97_destroy(codec); if (ih != NULL) bus_teardown_intr(dev, irq, ih); if (irq != NULL) bus_release_resource(dev, SYS_RES_IRQ, irqid, irq); - if (codec != NULL) - free(codec, M_DEVBUF); if (reg != NULL) bus_release_resource(dev, SYS_RES_IOPORT, regid, reg); if (ess != NULL) { diff --git a/sys/dev/sound/pci/neomagic.c b/sys/dev/sound/pci/neomagic.c index 72ae8b8..7cfe838 100644 --- a/sys/dev/sound/pci/neomagic.c +++ b/sys/dev/sound/pci/neomagic.c @@ -137,7 +137,7 @@ static pcmchan_caps nm_caps = {4000, 48000, nm_fmt, 0}; static pcm_channel nm_chantemplate = { nmchan_init, - nmchan_setdir, + NULL, /* setdir */ nmchan_setformat, nmchan_setspeed, nmchan_setblocksize, @@ -379,12 +379,6 @@ nmchan_free(void *data) } static int -nmchan_setdir(void *data, int dir) -{ - return 0; -} - -static int nmchan_setformat(void *data, u_int32_t format) { struct sc_chinfo *ch = data; @@ -599,7 +593,7 @@ nm_pci_attach(device_t dev) { u_int32_t data; struct sc_info *sc; - struct ac97_info *codec; + struct ac97_info *codec = 0; char status[SND_STATUSLEN]; if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) { @@ -658,6 +652,7 @@ nm_pci_attach(device_t dev) return 0; bad: + if (codec) ac97_destroy(codec); if (sc->buf) bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf); if (sc->reg) bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); if (sc->ih) bus_teardown_intr(dev, sc->irq, sc->ih); @@ -667,6 +662,26 @@ bad: } static int +nm_pci_detach(device_t dev) +{ + int r; + struct sc_info *sc; + + r = pcm_unregister(dev); + if (r) + return r; + + sc = pcm_getdevinfo(dev); + bus_release_resource(dev, SYS_RES_MEMORY, sc->bufid, sc->buf); + bus_release_resource(dev, SYS_RES_MEMORY, sc->regid, sc->reg); + bus_teardown_intr(dev, sc->irq, sc->ih); + bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq); + free(sc, M_DEVBUF); + + return 0; +} + +static int nm_pci_resume(device_t dev) { struct sc_info *sc; diff --git a/sys/dev/sound/pci/solo.c b/sys/dev/sound/pci/solo.c index 58161db..315262d 100644 --- a/sys/dev/sound/pci/solo.c +++ b/sys/dev/sound/pci/solo.c @@ -83,7 +83,7 @@ static pcmchan_caps ess_reccaps = {5000, 49000, ess_recfmt, 0}; static pcm_channel ess_chantemplate = { esschan_init, - esschan_setdir, + NULL, /* setdir */ esschan_setformat, esschan_setspeed, esschan_setblocksize, @@ -113,6 +113,7 @@ struct ess_chinfo { struct ess_info { struct resource *io, *sb, *vc, *mpu, *gp; /* I/O address for the board */ struct resource *irq; + void *ih; bus_dma_tag_t parent_dmat; int simplex_dir, type, duplex:1, newspeed:1, dmasz[2]; @@ -557,6 +558,7 @@ esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) ch->channel = c; ch->buffer = b; ch->buffer->bufsize = ESS_BUFFSIZE; + ch->dir = dir; if (chn_allocbuf(ch->buffer, sc->parent_dmat) == -1) return NULL; ch->hwch = 1; @@ -566,15 +568,6 @@ esschan_init(void *devinfo, snd_dbuf *b, pcm_channel *c, int dir) } static int -esschan_setdir(void *data, int dir) -{ - struct ess_chinfo *ch = data; - - ch->dir = dir; - return 0; -} - -static int esschan_setformat(void *data, u_int32_t format) { struct ess_chinfo *ch = data; @@ -830,6 +823,8 @@ ess_release_resources(struct ess_info *sc, device_t dev) { /* should we bus_teardown_intr here? */ if (sc->irq) { + if (sc->ih) + bus_teardown_intr(dev, sc->irq, sc->ih); bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); sc->irq = 0; } @@ -858,6 +853,11 @@ ess_release_resources(struct ess_info *sc, device_t dev) sc->gp = 0; } + if (sc->parent_dmat) { + bus_dma_tag_destroy(sc->parent_dmat); + sc->parent_dmat = 0; + } + free(sc, M_DEVBUF); } @@ -918,7 +918,6 @@ static int ess_attach(device_t dev) { struct ess_info *sc; - void *ih; char status[SND_STATUSLEN]; u_int16_t ddma; u_int32_t data; @@ -960,7 +959,7 @@ ess_attach(device_t dev) if (sc->newspeed) ess_setmixer(sc, 0x71, 0x2a); - bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, ess_intr, sc, &ih); + bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, ess_intr, sc, &sc->ih); if (!sc->duplex) pcm_setflags(dev, pcm_getflags(dev) | SD_F_SIMPLEX); @@ -992,10 +991,26 @@ no: return ENXIO; } +static int +ess_detach(device_t dev) +{ + int r; + struct sc_info *sc; + + r = pcm_unregister(dev); + if (r) + return r; + + sc = pcm_getdevinfo(dev); + ess_release_resources(sc, dev); + return 0; +} + static device_method_t ess_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ess_probe), DEVMETHOD(device_attach, ess_attach), + DEVMETHOD(device_detach, ess_detach), { 0, 0 } }; diff --git a/sys/dev/sound/pci/t4dwave.c b/sys/dev/sound/pci/t4dwave.c index f65bdb4..f411338 100644 --- a/sys/dev/sound/pci/t4dwave.c +++ b/sys/dev/sound/pci/t4dwave.c @@ -695,17 +695,40 @@ tr_pci_attach(device_t dev) return 0; bad: + if (codec) ac97_destroy(codec); if (tr->reg) bus_release_resource(dev, tr->regtype, tr->regid, tr->reg); if (tr->ih) bus_teardown_intr(dev, tr->irq, tr->ih); if (tr->irq) bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq); + if (tr->parent_dmat) bus_dma_tag_destroy(tr->parent_dmat); free(tr, M_DEVBUF); return ENXIO; } +static int +tr_pci_detach(device_t dev) +{ + int r; + struct tr_info *tr; + + r = pcm_unregister(dev); + if (r) + return r; + + tr = pcm_getdevinfo(dev); + bus_release_resource(dev, tr->regtype, tr->regid, tr->reg); + bus_teardown_intr(dev, tr->irq, tr->ih); + bus_release_resource(dev, SYS_RES_IRQ, tr->irqid, tr->irq); + bus_dma_tag_destroy(tr->parent_dmat); + free(tr, M_DEVBUF); + + return 0; +} + static device_method_t tr_methods[] = { /* Device interface */ DEVMETHOD(device_probe, tr_pci_probe), DEVMETHOD(device_attach, tr_pci_attach), + DEVMETHOD(device_detach, tr_pci_detach), { 0, 0 } }; diff --git a/sys/dev/sound/pci/via82c686.c b/sys/dev/sound/pci/via82c686.c index 14fe9bf..df72136 100644 --- a/sys/dev/sound/pci/via82c686.c +++ b/sys/dev/sound/pci/via82c686.c @@ -58,6 +58,10 @@ struct via_info { bus_dma_tag_t parent_dmat; bus_dma_tag_t sgd_dmat; + struct resource *reg, *irq; + int regid, irqid; + void *ih; + struct via_chinfo pch, rch; struct via_dma_op *sgd_table; u_int16_t codec_caps; @@ -146,15 +150,10 @@ static int via_attach(device_t dev) { struct via_info *via = 0; - struct ac97_info *codec; + struct ac97_info *codec = 0; char status[SND_STATUSLEN]; u_int32_t data; - struct resource *reg = 0; - int regid; - struct resource *irq = 0; - void *ih = 0; - int irqid; u_int16_t v; bus_dmamap_t sgd_dma_map; @@ -175,21 +174,21 @@ via_attach(device_t dev) VIA_PCICONF_ACLINKENAB | VIA_PCICONF_ACSGD | VIA_PCICONF_ACNOTRST | VIA_PCICONF_ACVSR, 1); - regid = PCIR_MAPS; - reg = bus_alloc_resource(dev, SYS_RES_IOPORT, ®id, + via->regid = PCIR_MAPS; + via->reg = bus_alloc_resource(dev, SYS_RES_IOPORT, &via->regid, 0, ~0, 1, RF_ACTIVE); - if (!reg) { + if (!via->reg) { device_printf(dev, "via: Cannot allocate bus resource."); goto bad; } - via->st = rman_get_bustag(reg); - via->sh = rman_get_bushandle(reg); + via->st = rman_get_bustag(via->reg); + via->sh = rman_get_bushandle(via->reg); - irqid = 0; - irq = bus_alloc_resource(dev, SYS_RES_IRQ, &irqid, + via->irqid = 0; + via->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &via->irqid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE); - if (!irq - || bus_setup_intr(dev, irq, INTR_TYPE_TTY, via_intr, via, &ih)){ + if (!via->irq + || bus_setup_intr(dev, via->irq, INTR_TYPE_TTY, via_intr, via, &via->ih)){ device_printf(dev, "unable to map interrupt\n"); goto bad; } @@ -216,8 +215,8 @@ via_attach(device_t dev) via_write_codec(via, AC97_REG_EXT_AUDIO_STAT, v); via->codec_caps = v; { - v = via_read_codec(via, AC97_REG_EXT_AUDIO_STAT); - DEB(printf("init: codec stat: %d\n", v)); + v = via_read_codec(via, AC97_REG_EXT_AUDIO_STAT); + DEB(printf("init: codec stat: %d\n", v)); } if (!(v & AC97_CODEC_DOES_VRA)) { @@ -259,7 +258,7 @@ via_attach(device_t dev) NSEGS * sizeof(struct via_dma_op), dma_cb, 0, 0)) goto bad; snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld", - rman_get_start(reg), rman_get_start(irq)); + rman_get_start(via->reg), rman_get_start(via->irq)); /* Register */ if (pcm_register(dev, via, 1, 1)) goto bad; @@ -268,17 +267,41 @@ via_attach(device_t dev) pcm_setstatus(dev, status); return 0; bad: + if (codec) ac97_destroy(codec); + if (via->reg) bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); + if (via->ih) bus_teardown_intr(dev, via->irq, via->ih); + if (via->irq) bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); + if (via->parent_dmat) bus_dma_tag_destroy(via->parent_dmat); + if (via->sgd_dmat) bus_dma_tag_destroy(via->sgd_dmat); if (via) free(via, M_DEVBUF); - bus_release_resource(dev, SYS_RES_IOPORT, regid, reg); - if (ih) bus_teardown_intr(dev, irq, ih); - if (irq) bus_release_resource(dev, SYS_RES_IRQ, irqid, irq); return ENXIO; } +static int +via_detach(device_t dev) +{ + int r; + struct via_info *via = 0; + + r = pcm_unregister(dev); + if (r) + return r; + + via = pcm_getdevinfo(dev); + bus_release_resource(dev, SYS_RES_IOPORT, via->regid, via->reg); + bus_teardown_intr(dev, via->irq, via->ih); + bus_release_resource(dev, SYS_RES_IRQ, via->irqid, via->irq); + bus_dma_tag_destroy(via->parent_dmat); + bus_dma_tag_destroy(via->sgd_dmat); + free(via, M_DEVBUF); + return 0; +} + static device_method_t via_methods[] = { DEVMETHOD(device_probe, via_probe), DEVMETHOD(device_attach, via_attach), + DEVMETHOD(device_detach, via_detach), { 0, 0} }; diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c index 74ce10f..9fd4e4a 100644 --- a/sys/dev/sound/pcm/channel.c +++ b/sys/dev/sound/pcm/channel.c @@ -1161,7 +1161,8 @@ chn_init(pcm_channel *c, void *devinfo, int dir) int chn_kill(pcm_channel *c) { - chn_trigger(c, PCMTRIG_ABORT); + if (c->flags & CHN_F_TRIGGERED) + chn_trigger(c, PCMTRIG_ABORT); while (chn_removefeeder(c) == 0); free(c->feeder->desc, M_DEVBUF); free(c->feeder, M_DEVBUF); |