diff options
author | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2009-09-08 23:30:18 +0000 |
---|---|---|
committer | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2009-09-08 23:30:18 +0000 |
commit | 6aa31a6cfc8d5e5d83670a1418b2c1f7834ce938 (patch) | |
tree | d20c44ecad6ba31186caecd8afdd8dca32442a52 /sys/dev | |
parent | 2148386d169a34091eceb12ef3219197881e425b (diff) |
cleanup/fix RIRB processing:
* move the code for azalia_comresp() to be nearer the functions it
uses (azalia_set_command() and azalia_get_response()) for easier
comprehension.
* don't turn off RIRB interrupts in azalia_set_command(), then reenable
them in azalia_get_response(). it's ugly, problematic, and the code
is already at SPL_AUDIO.
* in azalia_get_response(), wait for a solicited response (the response
from azalia_set_command()) instead of "waiting" for just any response
as there may already be an unsolicited response in the RIRB.
* no need to run the unsolicited response handler in azalia_get_response().
since RIRB interrupts aren't being disables, the unsolicited response
handler will be run by the RIRB interrupt handler.
* in azalia_rirb_intr(), when a solicited response is found in the RIRB,
instead of stopping and losing the response, print a debug message
and keep going. there should never be a solicited response in the
RIRB at this point.
* remove some now useless #if 0'd debug cruft.
* minor KNF while here.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/pci/azalia.c | 102 |
1 files changed, 40 insertions, 62 deletions
diff --git a/sys/dev/pci/azalia.c b/sys/dev/pci/azalia.c index 3f753bd3c2e..946fbc68cb4 100644 --- a/sys/dev/pci/azalia.c +++ b/sys/dev/pci/azalia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: azalia.c,v 1.143 2009/08/13 23:59:15 jakemsr Exp $ */ +/* $OpenBSD: azalia.c,v 1.144 2009/09/08 23:30:17 jakemsr Exp $ */ /* $NetBSD: azalia.c,v 1.20 2006/05/07 08:31:44 kent Exp $ */ /*- @@ -191,8 +191,7 @@ int azalia_delete_corb(azalia_t *); int azalia_halt_rirb(azalia_t *); int azalia_init_rirb(azalia_t *); int azalia_delete_rirb(azalia_t *); -int azalia_set_command(azalia_t *, nid_t, int, uint32_t, - uint32_t); +int azalia_set_command(azalia_t *, nid_t, int, uint32_t, uint32_t); int azalia_get_response(azalia_t *, uint32_t *); void azalia_rirb_kick_unsol_events(azalia_t *); void azalia_rirb_intr(azalia_t *); @@ -997,19 +996,36 @@ azalia_delete_rirb(azalia_t *az) } int +azalia_comresp(const codec_t *codec, nid_t nid, uint32_t control, + uint32_t param, uint32_t* result) +{ + int err, s; + + s = splaudio(); + err = azalia_set_command(codec->az, codec->address, nid, control, + param); + if (err) + goto exit; + err = azalia_get_response(codec->az, result); +exit: + splx(s); + + return(err); +} + +int azalia_set_command(azalia_t *az, int caddr, nid_t nid, uint32_t control, - uint32_t param) + uint32_t param) { corb_entry_t *corb; int wp; uint32_t verb; uint16_t corbwp; - uint8_t rirbctl; #ifdef DIAGNOSTIC if ((AZ_READ_1(az, CORBCTL) & HDA_CORBCTL_CORBRUN) == 0) { printf("%s: CORB is not running.\n", XNAME(az)); - return -1; + return(-1); } #endif verb = (caddr << 28) | (nid << 20) | (control << 8) | param; @@ -1020,19 +1036,9 @@ azalia_set_command(azalia_t *az, int caddr, nid_t nid, uint32_t control, wp = 0; corb[wp] = verb; - /* disable RIRB interrupts */ - rirbctl = AZ_READ_1(az, RIRBCTL); - if (rirbctl & HDA_RIRBCTL_RINTCTL) { - AZ_WRITE_1(az, RIRBCTL, rirbctl & ~HDA_RIRBCTL_RINTCTL); - azalia_rirb_intr(az); - } - AZ_WRITE_2(az, CORBWP, (corbwp & ~HDA_CORBWP_CORBWP) | wp); -#if 0 - DPRINTF(("%s: caddr=%d nid=%d control=0x%x param=0x%x verb=0x%8.8x wp=%d\n", - __func__, caddr, nid, control, param, verb, wp)); -#endif - return 0; + + return(0); } int @@ -1041,26 +1047,28 @@ azalia_get_response(azalia_t *az, uint32_t *result) const rirb_entry_t *rirb; int i; uint16_t wp; - uint8_t rirbctl; #ifdef DIAGNOSTIC if ((AZ_READ_1(az, RIRBCTL) & HDA_RIRBCTL_RIRBDMAEN) == 0) { printf("%s: RIRB is not running.\n", XNAME(az)); - return -1; + return(-1); } #endif - for (i = 5000; i >= 0; i--) { - wp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP; - if (az->rirb_rp != wp) - break; - DELAY(10); - } - if (i <= 0) { - printf("%s: RIRB time out\n", XNAME(az)); - return ETIMEDOUT; - } + rirb = (rirb_entry_t*)az->rirb_dma.addr; + i = 5000; for (;;) { + while (i > 0) { + wp = AZ_READ_2(az, RIRBWP) & HDA_RIRBWP_RIRBWP; + if (az->rirb_rp != wp) + break; + DELAY(10); + i--; + } + if (i <= 0) { + printf("%s: RIRB time out\n", XNAME(az)); + return(ETIMEDOUT); + } if (++az->rirb_rp >= az->rirb_size) az->rirb_rp = 0; if (rirb[az->rirb_rp].resp_ex & RIRB_RESP_UNSOL) { @@ -1073,20 +1081,7 @@ azalia_get_response(azalia_t *az, uint32_t *result) if (result != NULL) *result = rirb[az->rirb_rp].resp; - azalia_rirb_kick_unsol_events(az); -#if 0 - for (i = 0; i < 16 /*az->rirb_size*/; i++) { - DPRINTF(("rirb[%d] 0x%8.8x:0x%8.8x ", i, rirb[i].resp, rirb[i].resp_ex)); - if ((i % 2) == 1) - DPRINTF(("\n")); - } -#endif - - /* re-enable RIRB interrupts */ - rirbctl = AZ_READ_1(az, RIRBCTL); - AZ_WRITE_1(az, RIRBCTL, rirbctl | HDA_RIRBCTL_RINTCTL); - - return 0; + return(0); } void @@ -1129,10 +1124,9 @@ azalia_rirb_intr(azalia_t *az) az->unsolq[az->unsolq_wp++].resp_ex = rirb[az->rirb_rp].resp_ex; az->unsolq_wp %= UNSOLQ_SIZE; } else { - break; + DPRINTF(("%s: dropped solicited response\n", __func__)); } } - azalia_rirb_kick_unsol_events(az); AZ_WRITE_1(az, RIRBSTS, @@ -2423,22 +2417,6 @@ azalia_codec_add_format(codec_t *this, int chan, int prec, uint32_t rates, } int -azalia_comresp(const codec_t *codec, nid_t nid, uint32_t control, - uint32_t param, uint32_t* result) -{ - int err, s; - - s = splaudio(); - err = azalia_set_command(codec->az, codec->address, nid, control, param); - if (err) - goto exit; - err = azalia_get_response(codec->az, result); -exit: - splx(s); - return err; -} - -int azalia_codec_connect_stream(codec_t *this, int dir, uint16_t fmt, int number) { const convgroup_t *group; |