diff options
Diffstat (limited to 'sys/dev/sound/pci/csapcm.c')
-rw-r--r-- | sys/dev/sound/pci/csapcm.c | 38 |
1 files changed, 36 insertions, 2 deletions
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 }, }; |