summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcg <cg@FreeBSD.org>2000-09-09 19:21:04 +0000
committercg <cg@FreeBSD.org>2000-09-09 19:21:04 +0000
commita081b436a34dc6b7c3f1418e1429edbd7a31c3ff (patch)
tree916a90fe682463a47c2285b9f4bc874b6720fce7
parentf80149566df17edb15598b2d33d559f831c5edb5 (diff)
downloadFreeBSD-src-a081b436a34dc6b7c3f1418e1429edbd7a31c3ff.zip
FreeBSD-src-a081b436a34dc6b7c3f1418e1429edbd7a31c3ff.tar.gz
detach support
remove un-needed setdir functions add bus_teardown_intr calls where necessary destroy our dma tags where necessary destroy ac97 before releasing resources
-rw-r--r--sys/dev/sound/isa/ad1816.c28
-rw-r--r--sys/dev/sound/isa/ess.c49
-rw-r--r--sys/dev/sound/isa/mss.c35
-rw-r--r--sys/dev/sound/isa/sb.c31
-rw-r--r--sys/dev/sound/isa/sb16.c31
-rw-r--r--sys/dev/sound/isa/sb8.c31
-rw-r--r--sys/dev/sound/isa/sbc.c28
-rw-r--r--sys/dev/sound/pci/csapcm.c38
-rw-r--r--sys/dev/sound/pci/ds1.c32
-rw-r--r--sys/dev/sound/pci/emu10k1.c5
-rw-r--r--sys/dev/sound/pci/es137x.c77
-rw-r--r--sys/dev/sound/pci/fm801.c75
-rw-r--r--sys/dev/sound/pci/maestro.c4
-rw-r--r--sys/dev/sound/pci/neomagic.c31
-rw-r--r--sys/dev/sound/pci/solo.c39
-rw-r--r--sys/dev/sound/pci/t4dwave.c23
-rw-r--r--sys/dev/sound/pci/via82c686.c65
-rw-r--r--sys/dev/sound/pcm/channel.c3
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, &regid,
+ 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, &regid,
+ 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, &regid,
+ 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);
OpenPOWER on IntegriCloud