Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-3]: src/sys/dev/pci Pull up revision 1.7 (requested by kent in ti...
details: https://anonhg.NetBSD.org/src/rev/601a8259c05b
branches: netbsd-3
changeset: 576414:601a8259c05b
user: tron <tron%NetBSD.org@localhost>
date: Sat Jul 02 16:41:49 2005 +0000
description:
Pull up revision 1.7 (requested by kent in ticket #494):
- free all of allocated resources when an error occurs
- code cleanup
diffstat:
sys/dev/pci/azalia.c | 487 +++++++++++++++++++++++++++++++++-----------------
1 files changed, 321 insertions(+), 166 deletions(-)
diffs (truncated from 951 to 300 lines):
diff -r ec61ed9b80a5 -r 601a8259c05b sys/dev/pci/azalia.c
--- a/sys/dev/pci/azalia.c Sat Jul 02 16:41:27 2005 +0000
+++ b/sys/dev/pci/azalia.c Sat Jul 02 16:41:49 2005 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: azalia.c,v 1.7.2.7 2005/07/02 16:41:27 tron Exp $ */
+/* $NetBSD: azalia.c,v 1.7.2.8 2005/07/02 16:41:49 tron Exp $ */
/*-
* Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -38,13 +38,13 @@
/*
* TO DO:
+ * - S/PDIF
* - Volume Knob widget
* - power hook
- * - detach
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.7.2.7 2005/07/02 16:41:27 tron Exp $");
+__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.7.2.8 2005/07/02 16:41:49 tron Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -598,9 +598,11 @@
struct device dev;
struct device *audiodev;
+ pci_chipset_tag_t pc;
void *ih;
bus_space_tag_t iot;
bus_space_handle_t ioh;
+ bus_size_t map_size;
bus_dma_tag_t dmat;
codec_t codecs[15];
@@ -630,12 +632,15 @@
/* prototypes */
static int azalia_pci_match(struct device *, struct cfdata *, void *);
static void azalia_pci_attach(struct device *, struct device *, void *);
+static int azalia_pci_activate(struct device *, enum devact);
static int azalia_pci_detach(struct device *, int);
static int azalia_intr(void *);
static int azalia_attach(azalia_t *);
static void azalia_attach_intr(struct device *);
static int azalia_init_corb(azalia_t *);
+static int azalia_delete_corb(azalia_t *);
static int azalia_init_rirb(azalia_t *);
+static int azalia_delete_rirb(azalia_t *);
static int azalia_set_command(const azalia_t *, nid_t, int, uint32_t,
uint32_t);
static int azalia_get_response(azalia_t *, uint32_t *);
@@ -643,7 +648,11 @@
static int azalia_free_dmamem(const azalia_t *, azalia_dma_t*);
static int azalia_codec_init(codec_t *);
+static int azalia_codec_delete(codec_t *);
+static int azalia_codec_init_dacgroup(codec_t *);
+static int azalia_codec_add_dacgroup(codec_t *, int, uint32_t);
static int azalia_codec_construct_format(codec_t *);
+static void azalia_codec_add_bits(codec_t *, int, uint32_t, int);
static void azalia_codec_add_format(codec_t *, int, int, int, uint32_t,
int32_t);
static int azalia_codec_find_pin(const codec_t *, int, int, uint32_t);
@@ -653,6 +662,7 @@
static int azalia_codec_connect_stream(codec_t *, int, uint16_t, int);
static int azalia_mixer_init(codec_t *);
+static int azalia_mixer_delete(codec_t *);
static int azalia_mixer_get(const codec_t *, mixer_ctrl_t *);
static int azalia_mixer_set(codec_t *, const mixer_ctrl_t *);
static int azalia_mixer_ensure_capacity(codec_t *, size_t);
@@ -671,6 +681,7 @@
static int azalia_widget_init_connection(widget_t *, const codec_t *);
static int azalia_stream_init(stream_t *, azalia_t *, int, int, int);
+static int azalia_stream_delete(stream_t *, azalia_t *);
static int azalia_stream_reset(stream_t *);
static int azalia_stream_start(stream_t *, void *, void *, int,
void (*)(void *), void *, uint16_t);
@@ -702,7 +713,7 @@
/* variables */
CFATTACH_DECL(azalia, sizeof(azalia_t),
- azalia_pci_match, azalia_pci_attach, azalia_pci_detach, NULL);
+ azalia_pci_match, azalia_pci_attach, azalia_pci_detach, azalia_pci_activate);
static const struct audio_hw_if azalia_hw_if = {
azalia_open,
@@ -768,7 +779,6 @@
{
azalia_t *sc;
struct pci_attach_args *pa;
- bus_size_t regsize;
pcireg_t v;
pci_intr_handle_t ih;
const char *intrrupt_str;
@@ -780,7 +790,7 @@
sc->dmat = pa->pa_dmat;
aprint_normal(": Generic High Definition Audio Controller\n");
if (pci_mapreg_map(pa, ICH_PCI_HDBARL, PCI_MAPREG_MEM_TYPE_64BIT, 0,
- &sc->iot, &sc->ioh, NULL, ®size)) {
+ &sc->iot, &sc->ioh, NULL, &sc->map_size)) {
aprint_error("%s: can't map device i/o space\n", XNAME(sc));
return;
}
@@ -795,6 +805,7 @@
aprint_error("%s: can't map interrupt\n", XNAME(sc));
return;
}
+ sc->pc = pa->pa_pc;
intrrupt_str = pci_intr_string(pa->pa_pc, ih);
sc->ih = pci_intr_establish(pa->pa_pc, ih, IPL_AUDIO, azalia_intr, sc);
if (sc->ih == NULL) {
@@ -818,18 +829,58 @@
if (azalia_attach(sc)) {
aprint_error("%s: initialization failure\n", XNAME(sc));
+ azalia_pci_detach(self, 0);
return;
}
config_interrupts(self, azalia_attach_intr);
}
static int
+azalia_pci_activate(struct device *self, enum devact act)
+{
+ azalia_t *sc;
+ int ret;
+
+ sc = (azalia_t*)self;
+ ret = 0;
+ switch (act) {
+ case DVACT_ACTIVATE:
+ return EOPNOTSUPP;
+ case DVACT_DEACTIVATE:
+ if (sc->audiodev != NULL)
+ ret = config_deactivate(sc->audiodev);
+ return ret;
+ }
+ return EOPNOTSUPP;
+}
+
+static int
azalia_pci_detach(struct device *self, int flags)
{
azalia_t *az;
+ int i;
az = (azalia_t*)self;
- azalia_free_dmamem(az, &az->corb_dma);
+ if (az->audiodev != NULL) {
+ config_detach(az->audiodev, flags);
+ az->audiodev = NULL;
+ }
+ azalia_stream_delete(&az->rstream, az);
+ azalia_stream_delete(&az->pstream, az);
+ for (i = 0; i < az->ncodecs; i++) {
+ azalia_codec_delete(&az->codecs[i]);
+ }
+ az->ncodecs = 0;
+ azalia_delete_corb(az);
+ azalia_delete_rirb(az);
+ if (az->ih != NULL) {
+ pci_intr_disestablish(az->pc, az->ih);
+ az->ih = NULL;
+ }
+ if (az->map_size != 0) {
+ bus_space_unmap(az->iot, az->ioh, az->map_size);
+ az->map_size = 0;
+ }
return 0;
}
@@ -958,18 +1009,20 @@
for (i = 0; i < az->ncodecs; i++) {
err = azalia_codec_init(&az->codecs[i]);
if (err)
- return;
+ goto err_exit;
}
if (azalia_stream_init(&az->pstream, az, az->nistreams + 0,
1, AUMODE_PLAY))
- return;
+ goto err_exit;
if (azalia_stream_init(&az->rstream, az, 0, 2, AUMODE_RECORD))
- return;
+ goto err_exit;
az->audiodev = audio_attach_mi(&azalia_hw_if, az, &az->dev);
return;
- /* XXX deallocation on errors */
+err_exit:
+ azalia_pci_detach(self, 0);
+ return;
}
static int
@@ -1064,6 +1117,27 @@
}
static int
+azalia_delete_corb(azalia_t *az)
+{
+ int i;
+ uint8_t corbctl;
+
+ if (az->corb_dma.addr == NULL)
+ return 0;
+ /* stop the CORB */
+ corbctl = AZ_READ_1(az, CORBCTL);
+ AZ_WRITE_1(az, CORBCTL, corbctl & ~HDA_CORBCTL_CORBRUN);
+ for (i = 5000; i >= 0; i--) {
+ DELAY(10);
+ corbctl = AZ_READ_1(az, CORBCTL);
+ if ((corbctl & HDA_CORBCTL_CORBRUN) == 0)
+ break;
+ }
+ azalia_free_dmamem(az, &az->corb_dma);
+ return 0;
+}
+
+static int
azalia_init_rirb(azalia_t *az)
{
int entries, err, i;
@@ -1137,6 +1211,27 @@
}
static int
+azalia_delete_rirb(azalia_t *az)
+{
+ int i;
+ uint8_t rirbctl;
+
+ if (az->rirb_dma.addr == NULL)
+ return 0;
+ /* stop the RIRB */
+ rirbctl = AZ_READ_1(az, RIRBCTL);
+ AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RIRBDMAEN);
+ for (i = 5000; i >= 0; i--) {
+ DELAY(10);
+ rirbctl = AZ_READ_1(az, RIRBCTL);
+ if ((rirbctl & HDA_RIRBCTL_RIRBDMAEN) == 0)
+ break;
+ }
+ azalia_free_dmamem(az, &az->rirb_dma);
+ return 0;
+}
+
+static int
azalia_set_command(const azalia_t *az, int caddr, nid_t nid, uint32_t control,
uint32_t param)
{
@@ -1242,16 +1337,20 @@
bus_dmamem_unmap(az->dmat, d->addr, size);
free:
bus_dmamem_free(az->dmat, d->segments, 1);
+ d->addr = NULL;
return err;
}
static int
azalia_free_dmamem(const azalia_t *az, azalia_dma_t* d)
{
+ if (d->addr == NULL)
+ return 0;
bus_dmamap_unload(az->dmat, d->map);
bus_dmamap_destroy(az->dmat, d->map);
bus_dmamem_unmap(az->dmat, d->addr, d->size);
bus_dmamem_free(az->dmat, d->segments, 1);
+ d->addr = NULL;
return 0;
}
@@ -1262,9 +1361,8 @@
static int
azalia_codec_init(codec_t *this)
{
- uint32_t rev, result, digital;
- int err, addr, n, i, j;
- int assoc, dac, seq, group;
+ uint32_t rev, result;
+ int err, addr, n, i;
this->comresp = azalia_codec_comresp;
@@ -1343,6 +1441,32 @@
return err;
}
+ azalia_codec_init_dacgroup(this);
+ err = azalia_codec_construct_format(this);
+ if (err)
+ return err;
+
+ return azalia_mixer_init(this);
+}
Home |
Main Index |
Thread Index |
Old Index