6211652 audioxxx_set_monitor_gain of audio drivers can use uninitialized stack data
authorcg149915
Tue, 14 Feb 2006 20:57:04 -0800
changeset 1439 93407330a3ba
parent 1438 e88c9869d700
child 1440 aebc0c016202
6211652 audioxxx_set_monitor_gain of audio drivers can use uninitialized stack data
usr/src/uts/common/io/audio/sada/drv/audio810/audio810.c
usr/src/uts/common/io/audio/sada/drv/audiots/audiots.c
usr/src/uts/sun/io/audio/sada/drv/audio1575/audio1575.c
--- 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;
 	}