diff options
| author | kent <kent@NetBSD.org> | 2008-06-26 15:51:10 +0000 |
|---|---|---|
| committer | kent <kent@NetBSD.org> | 2008-06-26 15:51:10 +0000 |
| commit | fcc61272b463b5e09e28e10ea0fe0e43ac173b75 (patch) | |
| tree | 37658c035ee488aec8679cdb344136e2e6983025 /sys/dev | |
| parent | fe90ebb7ebf379feac67f9125eb2ad64a6425229 (diff) | |
* azalia_rirb_intr()
fix a problem that normal responses are skipped unintentionally.
* azalia_stream_start()
access HDA_INTCTL with AZ_READ_4()/AZ_WRITE_4().
access HDA_SD_CTL with STR_READ_1()/AZ_WRITE_1().
* azalia_modcmd()
enclose config_cfdata_attach() with splaudio().
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/pci/azalia.c | 38 |
1 files changed, 22 insertions, 16 deletions
diff --git a/sys/dev/pci/azalia.c b/sys/dev/pci/azalia.c index 049b09241c3..9b95ba97a7f 100644 --- a/sys/dev/pci/azalia.c +++ b/sys/dev/pci/azalia.c @@ -1,4 +1,4 @@ -/* $NetBSD: azalia.c,v 1.63 2008/06/08 08:47:05 cegger Exp $ */ +/* $NetBSD: azalia.c,v 1.64 2008/06/26 15:51:10 kent Exp $ */ /*- * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.63 2008/06/08 08:47:05 cegger Exp $"); +__KERNEL_RCSID(0, "$NetBSD: azalia.c,v 1.64 2008/06/26 15:51:10 kent Exp $"); #include <sys/param.h> #include <sys/device.h> @@ -951,19 +951,23 @@ static void azalia_rirb_intr(azalia_t *az) { const rirb_entry_t *rirb; - uint16_t wp; + uint16_t wp, newrp; wp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP; if (az->rirb_rp == wp) return; /* interrupted but no data in RIRB */ + /* Copy the first sequence of unsolicited reponses in the RIRB to + * unsolq. Don't consume non-unsolicited responses. */ rirb = (rirb_entry_t*)az->rirb_dma.addr; while (az->rirb_rp != wp) { - if (++az->rirb_rp >= az->rirb_size) - az->rirb_rp = 0; - if (rirb[az->rirb_rp].resp_ex & RIRB_RESP_UNSOL) { - az->unsolq[az->unsolq_wp].resp = rirb[az->rirb_rp].resp; - az->unsolq[az->unsolq_wp++].resp_ex = rirb[az->rirb_rp].resp_ex; + newrp = az->rirb_rp + 1; + if (newrp >= az->rirb_size) + newrp = 0; + if (rirb[newrp].resp_ex & RIRB_RESP_UNSOL) { + az->unsolq[az->unsolq_wp].resp = rirb[newrp].resp; + az->unsolq[az->unsolq_wp++].resp_ex = rirb[newrp].resp_ex; az->unsolq_wp %= UNSOLQ_SIZE; + az->rirb_rp = newrp; } else { break; } @@ -2003,8 +2007,8 @@ azalia_stream_start(stream_t *this, void *start, void *end, int blk, bdlist_entry_t *bdlist; bus_addr_t dmaaddr; int err, index; - uint16_t ctl; - uint8_t ctl2, intctl; + uint32_t intctl; + uint8_t ctl, ctl2; DPRINTF(("%s: start=%p end=%p\n", __func__, start, end)); if (this->bdlist.addr == NULL) @@ -2050,13 +2054,13 @@ azalia_stream_start(stream_t *this, void *start, void *end, int blk, if (err) return EINVAL; - intctl = AZ_READ_1(this->az, INTCTL); + intctl = AZ_READ_4(this->az, INTCTL); intctl |= this->intr_bit; - AZ_WRITE_1(this->az, INTCTL, intctl); + AZ_WRITE_4(this->az, INTCTL, intctl); - ctl = STR_READ_2(this, CTL); + ctl = STR_READ_1(this, CTL); ctl |= ctl | HDA_SD_CTL_DEIE | HDA_SD_CTL_FEIE | HDA_SD_CTL_IOCE | HDA_SD_CTL_RUN; - STR_WRITE_2(this, CTL, ctl); + STR_WRITE_1(this, CTL, ctl); return 0; } @@ -2070,7 +2074,7 @@ azalia_stream_halt(stream_t *this) ctl = STR_READ_2(this, CTL); ctl &= ~(HDA_SD_CTL_DEIE | HDA_SD_CTL_FEIE | HDA_SD_CTL_IOCE | HDA_SD_CTL_RUN); STR_WRITE_2(this, CTL, ctl); - AZ_WRITE_1(this->az, INTCTL, AZ_READ_1(this->az, INTCTL) & ~this->intr_bit); + AZ_WRITE_4(this->az, INTCTL, AZ_READ_4(this->az, INTCTL) & ~this->intr_bit); azalia_codec_disconnect_stream (&this->az->codecs[this->az->codecno], this->dir); return 0; @@ -2452,7 +2456,7 @@ static struct cfdata azalia_cfdata[] = { static int azalia_modcmd(modcmd_t cmd, void *arg) { - int err; + int err, s; switch (cmd) { case MODULE_CMD_INIT: @@ -2464,7 +2468,9 @@ azalia_modcmd(modcmd_t cmd, void *arg) config_cfdriver_detach(&azalia_cd); return err; } + s = splaudio(); err = config_cfdata_attach(azalia_cfdata, 1); + splx(s); if (err) { config_cfattach_detach("azalia", &azalia_ca); config_cfdriver_detach(&azalia_cd); |
