summaryrefslogtreecommitdiffstats
path: root/sys/dev/sound/pci/es137x.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/sound/pci/es137x.c')
-rw-r--r--sys/dev/sound/pci/es137x.c77
1 files changed, 49 insertions, 28 deletions
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 }
};
OpenPOWER on IntegriCloud