6211652 audioxxx_set_monitor_gain of audio drivers can use uninitialized stack data
--- a/usr/src/uts/common/io/audio/sada/drv/audio810/audio810.c Tue Feb 14 16:44:40 2006 -0800
+++ b/usr/src/uts/common/io/audio/sada/drv/audio810/audio810.c Tue Feb 14 20:57:04 2006 -0800
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -2706,7 +2706,6 @@
static int
audio810_set_monitor_gain(audio810_state_t *statep, int gain)
{
- uint32_t tmp_word;
uint16_t tmp_short;
int rc = AUDIO_SUCCESS;
@@ -2716,20 +2715,45 @@
gain = AUDIO_MAX_GAIN;
}
+ if (gain == 0) {
+ /* disable loopbacks when gain == 0 */
+ tmp_short = MVR_MUTE;
+ } else {
+ /* Adjust the value of gain to the requirement of AC'97 */
+ tmp_short = AUDIO_MAX_GAIN - gain;
+ tmp_short = ((tmp_short << statep->vol_bits_mask) - tmp_short) /
+ AUDIO_MAX_GAIN;
+ tmp_short |= (((tmp_short << statep->vol_bits_mask) -
+ tmp_short) / AUDIO_MAX_GAIN) << 8;
+ }
+
switch (statep->i810_input_port) {
case AUDIO_NONE:
+ /*
+ * It is possible to set the value of gain before any input
+ * is selected. So, we just save the gain and then return
+ * SUCCESS.
+ */
break;
case AUDIO_MICROPHONE:
- tmp_word = AC97_MIC_VOLUME_REGISTER;
+ /*
+ * MIC input has 20dB boost, we just preserve it
+ */
+ tmp_short |= statep->codec_shadow[I810_CODEC_REG(
+ AC97_MIC_VOLUME_REGISTER)] & MICVR_20dB_BOOST;
+ (void) audio810_write_ac97(statep,
+ AC97_MIC_VOLUME_REGISTER, tmp_short);
break;
case AUDIO_LINE_IN:
- tmp_word = AC97_LINE_IN_VOLUME_REGISTER;
+ (void) audio810_write_ac97(statep,
+ AC97_LINE_IN_VOLUME_REGISTER, tmp_short);
break;
case AUDIO_CD:
- tmp_word = AC97_CD_VOLUME_REGISTER;
+ (void) audio810_write_ac97(statep,
+ AC97_CD_VOLUME_REGISTER, tmp_short);
break;
case AUDIO_CODEC_LOOPB_IN:
@@ -2745,20 +2769,8 @@
}
if (gain == 0) {
- /* disable loopbacks when gain == 0 */
- (void) audio810_or_ac97(statep, tmp_word, MVR_MUTE);
statep->i810_monitor_gain = 0;
} else {
- /* enable loopbacks and set gain */
- tmp_short = AUDIO_MAX_GAIN - gain;
- tmp_short = ((tmp_short << statep->vol_bits_mask) - tmp_short) /
- AUDIO_MAX_GAIN;
- tmp_short |= (((tmp_short << statep->vol_bits_mask) -
- tmp_short) / AUDIO_MAX_GAIN) << 8;
- tmp_short |=
- statep->codec_shadow[I810_CODEC_REG(tmp_word)] &
- MICVR_20dB_BOOST;
- (void) audio810_write_ac97(statep, tmp_word, tmp_short);
statep->i810_monitor_gain = tmp_short;
}
--- a/usr/src/uts/common/io/audio/sada/drv/audiots/audiots.c Tue Feb 14 16:44:40 2006 -0800
+++ b/usr/src/uts/common/io/audio/sada/drv/audiots/audiots.c Tue Feb 14 20:57:04 2006 -0800
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -3515,7 +3515,6 @@
static int
audiots_set_monitor_gain(audiots_state_t *state, int gain)
{
- uint32_t tmp_word;
uint16_t tmp_short;
int rc = AUDIO_SUCCESS;
@@ -3527,19 +3526,43 @@
gain = AUDIO_MAX_GAIN;
}
+ if (gain == 0) {
+ /* disable loopbacks when gain == 0 */
+ tmp_short = MVR_MUTE;
+ } else {
+ /* Adjust the value of gain to meet the requirement of AC'97 */
+ tmp_short = (((AUDIO_MAX_GAIN - gain) >> TS_GAIN_SHIFT3) <<
+ TS_BYTE_SHIFT) & PCMOVR_LEFT_GAIN_MASK;
+ tmp_short |= ((AUDIO_MAX_GAIN - gain) >> TS_GAIN_SHIFT3) &
+ PCMOVR_RIGHT_GAIN_MASK;
+ }
+
mutex_enter(&state->ts_lock);
switch (state->ts_input_port) {
case AUDIO_NONE:
+ /*
+ * It is possible to set the value of gain before any input
+ * is selected. So, we just save the gain and then return
+ * SUCCESS.
+ */
break;
case AUDIO_MICROPHONE:
- tmp_word = AC97_MIC_VOLUME_REGISTER;
+ /*
+ * MIC input has 20dB boost, we just preserve it
+ */
+ tmp_short |= state->ts_shadow[TS_CODEC_REG(
+ AC97_MIC_VOLUME_REGISTER)] & MICVR_20dB_BOOST;
+ audiots_set_ac97(state,
+ AC97_MIC_VOLUME_REGISTER, tmp_short);
break;
case AUDIO_LINE_IN:
- tmp_word = AC97_LINE_IN_VOLUME_REGISTER;
+ audiots_set_ac97(state,
+ AC97_LINE_IN_VOLUME_REGISTER, tmp_short);
break;
case AUDIO_CD:
- tmp_word = AC97_CD_VOLUME_REGISTER;
+ audiots_set_ac97(state,
+ AC97_CD_VOLUME_REGISTER, tmp_short);
break;
case AUDIO_CODEC_LOOPB_IN:
/* we already are getting the loopback, so done */
@@ -3556,18 +3579,8 @@
}
if (gain == 0) {
- /* disable loopbacks when gain == 0 */
- audiots_or_ac97(state, tmp_word, MVR_MUTE);
state->ts_monitor_gain = 0;
} else {
- /* enable loopbacks and set gain */
- tmp_short =
- state->ts_shadow[TS_CODEC_REG(tmp_word)] & MICVR_20dB_BOOST;
- tmp_short = (((AUDIO_MAX_GAIN - gain) >> TS_GAIN_SHIFT3) <<
- TS_BYTE_SHIFT) & PCMOVR_LEFT_GAIN_MASK;
- tmp_short |= ((AUDIO_MAX_GAIN - gain) >> TS_GAIN_SHIFT3) &
- PCMOVR_RIGHT_GAIN_MASK;
- audiots_set_ac97(state, tmp_word, tmp_short);
state->ts_monitor_gain = tmp_short;
}
mutex_exit(&state->ts_lock);
--- a/usr/src/uts/sun/io/audio/sada/drv/audio1575/audio1575.c Tue Feb 14 16:44:40 2006 -0800
+++ b/usr/src/uts/sun/io/audio/sada/drv/audio1575/audio1575.c Tue Feb 14 20:57:04 2006 -0800
@@ -3262,7 +3262,6 @@
static int
audio1575_set_monitor_gain(audio1575_state_t *statep, int gain)
{
- uint32_t tmp_word;
uint16_t tmp_short;
int rc = AUDIO_SUCCESS;
@@ -3273,20 +3272,41 @@
gain = AUDIO_MAX_GAIN;
}
+ if (gain == 0) {
+ /* disable loopbacks when gain == 0 */
+ tmp_short = MVR_MUTE;
+ } else {
+ /* Adjust the value of gain to the requirement of AC'97 */
+ tmp_short = (((AUDIO_MAX_GAIN - gain) >> M1575_GAIN_SHIFT3) <<
+ M1575_BYTE_SHIFT) & PCMOVR_LEFT_GAIN_MASK;
+ tmp_short |= ((AUDIO_MAX_GAIN - gain) >> M1575_GAIN_SHIFT3) &
+ PCMOVR_RIGHT_GAIN_MASK;
+ }
+
switch (statep->m1575_input_port) {
case AUDIO_NONE:
+ /*
+ * It is possible to set the value of gain before any input
+ * is selected. So, we just save the gain and then return
+ * SUCCESS.
+ */
break;
case AUDIO_MICROPHONE:
- tmp_word = AC97_MIC_VOLUME_REGISTER;
+ tmp_short |= statep->m1575_codec_shadow[M1575_CODEC_REG(
+ AC97_MIC_VOLUME_REGISTER)] & MICVR_20dB_BOOST;
+ (void) audio1575_write_ac97(statep,
+ AC97_MIC_VOLUME_REGISTER, tmp_short);
break;
case AUDIO_LINE_IN:
- tmp_word = AC97_LINE_IN_VOLUME_REGISTER;
+ (void) audio1575_write_ac97(statep,
+ AC97_LINE_IN_VOLUME_REGISTER, tmp_short);
break;
case AUDIO_CD:
- tmp_word = AC97_CD_VOLUME_REGISTER;
+ (void) audio1575_write_ac97(statep,
+ AC97_CD_VOLUME_REGISTER, tmp_short);
break;
case AUDIO_CODEC_LOOPB_IN:
@@ -3302,19 +3322,8 @@
}
if (gain == 0) {
- /* disable loopbacks when gain == 0 */
- (void) audio1575_or_ac97(statep, tmp_word, MVR_MUTE);
statep->m1575_monitor_gain = 0;
} else {
- /* enable loopbacks and set gain */
- tmp_short = (((AUDIO_MAX_GAIN - gain) >> M1575_GAIN_SHIFT3) <<
- M1575_BYTE_SHIFT) & PCMOVR_LEFT_GAIN_MASK;
- tmp_short |= ((AUDIO_MAX_GAIN - gain) >> M1575_GAIN_SHIFT3) &
- PCMOVR_RIGHT_GAIN_MASK;
- tmp_short |=
- statep->m1575_codec_shadow[M1575_CODEC_REG(tmp_word)] &
- MICVR_20dB_BOOST;
- (void) audio1575_write_ac97(statep, tmp_word, tmp_short);
statep->m1575_monitor_gain = tmp_short;
}