summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/pci/csapcm.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/sound/pci/csapcm.c')
-rw-r--r--sys/dev/sound/pci/csapcm.c38
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 },
};
OpenPOWER on IntegriCloud