Subject: kern/7427: ess driver can't detect ES18[67][89].
To: None <gnats-bugs@gnats.netbsd.org>
From: None <AW9K-NNK@asahi-net.or.jp>
List: netbsd-bugs
Date: 04/20/1999 09:06:22
>Number:         7427
>Category:       kern
>Synopsis:       ess driver can't detect ES18[67][89]
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Tue Apr 20 09:05:00 1999
>Last-Modified:
>Originator:     Nonaka Kimihiro
>Organization:
>Release:        NetBSD-current 19990419
>Environment:
System: NetBSD koharu 1.4_ALPHA NetBSD 1.4_ALPHA (KOHARU) #236: Sun Apr 18 01:37:11 JST 1999 nonaka@koharu:/usr/src/sys/arch/i386/compile/KOHARU i386


>Description:
	ess driver can't detect ES18[67][89].
	ES18[67]8 is detected ES1788.
	ES18[67]9 is detected ES1887.

>How-To-Repeat:
	attach ess driver with ES18[67][89].

>Fix:
	Apply the following patch.
	ES18[67][89] treat as ES1788. (use audio1 interface for playing.)

diff -uNr sys.orig/dev/isa/ess.c sys/dev/isa/ess.c
--- sys.orig/dev/isa/ess.c	Mon Mar 22 21:14:50 1999
+++ sys/dev/isa/ess.c	Tue Apr 20 23:50:18 1999
@@ -170,7 +170,7 @@
 u_int	ess_srtofc __P((u_int));
 u_char	ess_get_dsp_status __P((struct ess_softc *));
 u_char	ess_dsp_read_ready __P((struct ess_softc *));
-u_char	ess_dsp_write_ready __P((struct ess_softc *sc));
+u_char	ess_dsp_write_ready __P((struct ess_softc *));
 int	ess_rdsp __P((struct ess_softc *));
 int	ess_wdsp __P((struct ess_softc *, u_char));
 u_char	ess_read_x_reg __P((struct ess_softc *, u_char));
@@ -181,13 +181,18 @@
 void	ess_write_mix_reg __P((struct ess_softc *, u_char, u_char));
 void	ess_clear_mreg_bits __P((struct ess_softc *, u_char, u_char));
 void	ess_set_mreg_bits __P((struct ess_softc *, u_char, u_char));
+void	ess_read_multi_mix_reg __P((struct ess_softc *, u_char, u_int8_t *, bus_size_t));
 
 static char *essmodel[] = {
 	"unsupported",
 	"1888",
 	"1887",
 	"888",
-	"1788"
+	"1788",
+	"1869",
+	"1879",
+	"1868",
+	"1878",
 };
 
 struct audio_device ess_device = {
@@ -276,7 +281,7 @@
 	       sc->sc_audio1.drq, sc->sc_audio1.irq, sc->sc_audio1.nintr,
 	       sc->sc_audio1.intr, sc->sc_audio1.arg);
 
-	if (sc->sc_model != ESS_1788) {
+	if (!ESS_USE_AUDIO1(sc->sc_model)) {
 		printf("audio2: dmachan %d irq %d nintr %lu intr %p arg %p\n",
 		       sc->sc_audio2.drq, sc->sc_audio2.irq, sc->sc_audio2.nintr,
 		       sc->sc_audio2.intr, sc->sc_audio2.arg);
@@ -508,7 +513,7 @@
 	}
 	ess_write_x_reg(sc, ESS_XCMD_IRQ_CTRL, v);
 
-	if (sc->sc_model == ESS_1788)
+	if (ESS_USE_AUDIO1(sc->sc_model))
 		return;
 
 	if (sc->sc_audio2.polled) {
@@ -553,7 +558,7 @@
 	/* Set DRQ1 */
 	ess_write_x_reg(sc, ESS_XCMD_DRQ_CTRL, v);
 
-	if (sc->sc_model == ESS_1788)
+	if (ESS_USE_AUDIO1(sc->sc_model))
 		return;
 
 	/* Configure DRQ2 */
@@ -613,10 +618,12 @@
 	u_char reg1;
 	u_char reg2;
 	u_char reg3;
+	u_int8_t ident[4];
 
 	sc->sc_model = ESS_UNSUPPORTED;
 	sc->sc_version = 0;
 
+	memset(ident, 0, sizeof(ident));
 
 	/*
 	 * 1. Check legacy ID bytes.  These should be 0x68 0x8n, where
@@ -677,6 +684,21 @@
 	if (ess_read_mix_reg(sc, ESS_MREG_SAMPLE_RATE) != reg2) {
 		/* If we got this far before failing, it's a 1788. */
 		sc->sc_model = ESS_1788;
+
+		/*
+		 * Identify ESS model for ES18[67]8.
+		 */
+		ess_read_multi_mix_reg(sc, 0x40, ident, sizeof(ident));
+		if(ident[0] == 0x18) {
+			switch(ident[1]) {
+			case 0x68:
+				sc->sc_model = ESS_1868;
+				break;
+			case 0x78:
+				sc->sc_model = ESS_1878;
+				break;
+			}
+		}
 	} else {
 		/*
 		 * 4. Determine if we can change bit 5 in mixer register 0x64.
@@ -697,6 +719,21 @@
 			 * Restore the original value of mixer register 0x64.
 			 */
 			ess_write_mix_reg(sc, ESS_MREG_VOLUME_CTRL, reg1);
+
+			/*
+			 * Identify ESS model for ES18[67]9.
+			 */
+			ess_read_multi_mix_reg(sc, 0x40, ident, sizeof(ident));
+			if(ident[0] == 0x18) {
+				switch(ident[1]) {
+				case 0x69:
+					sc->sc_model = ESS_1869;
+					break;
+				case 0x79:
+					sc->sc_model = ESS_1879;
+					break;
+				}
+			}
 		} else {
 			/*
 			 * 5. Determine if we can change the value of mixer
@@ -785,7 +822,7 @@
 	}
 	if (!isa_drq_isfree(sc->sc_ic, sc->sc_audio1.drq))
 		return (0);
-	if (sc->sc_model != ESS_1788) {
+	if (!ESS_USE_AUDIO1(sc->sc_model)) {
 		if (!ESS_DRQ2_VALID(sc->sc_audio2.drq)) {
 			printf("ess: play drq %d invalid\n", sc->sc_audio2.drq);
 			return (0);
@@ -815,7 +852,7 @@
 		printf("ess: record irq %d invalid\n", sc->sc_audio1.irq);
 		return (0);
 	}
-	if (sc->sc_model != ESS_1788) {
+	if (!ESS_USE_AUDIO1(sc->sc_model)) {
 		if (sc->sc_audio2.irq != -1 &&
 		    !ESS_IRQ2_VALID(sc->sc_audio2.irq)) {
 			printf("ess: play irq %d invalid\n", sc->sc_audio2.irq);
@@ -856,9 +893,6 @@
 
 	printf(": ESS Technology ES%s [version 0x%04x]\n", 
 	       essmodel[sc->sc_model], sc->sc_version);
-	
-	sc->sc_audio1.irq = -1;
-	sc->sc_audio2.irq = -1;
 
 	sc->sc_audio1.polled = sc->sc_audio1.irq == -1;
 	if (!sc->sc_audio1.polled) {
@@ -876,7 +910,7 @@
 		return;
 	}
 
-	if (sc->sc_model != ESS_1788) {
+	if (!ESS_USE_AUDIO1(sc->sc_model)) {
 		sc->sc_audio2.polled = sc->sc_audio2.irq == -1;
 		if (!sc->sc_audio2.polled) {
 			sc->sc_audio2.ih = isa_intr_establish(sc->sc_ic,
@@ -909,11 +943,11 @@
 	 * Set volume of Audio 1 to zero and disable Audio 1 DAC input
 	 * to playback mixer, since playback is always through Audio 2.
 	 */
-	if (sc->sc_model != ESS_1788)
+	if (!ESS_USE_AUDIO1(sc->sc_model))
 		ess_write_mix_reg(sc, ESS_MREG_VOLUME_VOICE, 0);
 	ess_wdsp(sc, ESS_ACMD_DISABLE_SPKR);
 
-	if (sc->sc_model == ESS_1788) {
+	if (ESS_USE_AUDIO1(sc->sc_model)) {
 		ess_write_mix_reg(sc, ESS_MREG_ADC_SOURCE, ESS_SOURCE_MIC);
 		sc->in_port = ESS_SOURCE_MIC;
 		sc->ndevs = ESS_1788_NDEVS;
@@ -966,7 +1000,7 @@
 	sprintf(ess_device.name, "ES%s", essmodel[sc->sc_model]);
 	sprintf(ess_device.version, "0x%04x", sc->sc_version);
 
-	if (sc->sc_model == ESS_1788)
+	if (ESS_USE_AUDIO1(sc->sc_model))
 		audio_attach_mi(&ess_1788_hw_if, sc, &sc->sc_dev);
 	else
 		audio_attach_mi(&ess_1888_hw_if, sc, &sc->sc_dev);
@@ -1227,7 +1261,7 @@
 	ess_write_x_reg(sc, ESS_XCMD_SAMPLE_RATE, ess_srtotc(rate));
 	ess_write_x_reg(sc, ESS_XCMD_FILTER_CLOCK, ess_srtofc(rate));
 
-	if (sc->sc_model != ESS_1788) {
+	if (!ESS_USE_AUDIO1(sc->sc_model)) {
 		ess_write_mix_reg(sc, ESS_MREG_SAMPLE_RATE, ess_srtotc(rate));
 		ess_write_mix_reg(sc, ESS_MREG_FILTER_CLOCK, ess_srtofc(rate));
 	}
@@ -1682,7 +1716,7 @@
 		return (0);
 
 	case ESS_RECORD_SOURCE:
-		if (sc->sc_model == ESS_1788) {
+		if (ESS_USE_AUDIO1(sc->sc_model)) {
 			if (cp->type == AUDIO_MIXER_ENUM)
 				return (ess_set_in_port(sc, cp->un.ord));
 			else
@@ -1710,7 +1744,7 @@
 		return (0);
 	}
 
-	if (sc->sc_model == ESS_1788)
+	if (ESS_USE_AUDIO1(sc->sc_model))
 		return (EINVAL);
 
 	switch (cp->dev) {
@@ -1804,7 +1838,7 @@
 		return (0);
 
 	case ESS_RECORD_SOURCE:
-		if (sc->sc_model == ESS_1788)
+		if (ESS_USE_AUDIO1(sc->sc_model))
 			cp->un.ord = sc->in_port;
 		else
 			cp->un.mask = sc->in_mask;
@@ -1816,7 +1850,7 @@
 		return (0);
 	}
 
-	if (sc->sc_model == ESS_1788)
+	if (ESS_USE_AUDIO1(sc->sc_model))
 		return (EINVAL);
 
 	switch (cp->dev) {
@@ -1883,7 +1917,7 @@
 	case ESS_MIC_PLAY_VOL:
 		dip->mixer_class = ESS_INPUT_CLASS;
 		dip->prev = AUDIO_MIXER_LAST;
-		if (sc->sc_model == ESS_1788)
+		if (ESS_USE_AUDIO1(sc->sc_model))
 			dip->next = AUDIO_MIXER_LAST;
 		else
 			dip->next = ESS_MIC_PREAMP;
@@ -1974,7 +2008,7 @@
 		dip->mixer_class = ESS_RECORD_CLASS;
 		dip->next = dip->prev = AUDIO_MIXER_LAST;
 		strcpy(dip->label.name, AudioNsource);
-		if (sc->sc_model == ESS_1788) {
+		if (ESS_USE_AUDIO1(sc->sc_model)) {
 			/*
 			 * The 1788 doesn't use the input mixer control that
 			 * the 1888 uses, because it's a pain when you only
@@ -2039,7 +2073,7 @@
 		return (0);
 	}
 
-	if (sc->sc_model == ESS_1788)
+	if (ESS_USE_AUDIO1(sc->sc_model))
 		return (ENXIO);
 
 	switch (dip->index) {
@@ -2124,7 +2158,7 @@
 	struct ess_softc *sc = addr;
 	int drq;
 
-	if (sc->sc_model != ESS_1788 && direction == AUMODE_PLAY)
+	if ((!ESS_USE_AUDIO1(sc->sc_model)) && direction == AUMODE_PLAY)
 		drq = sc->sc_audio2.drq;
 	else
 		drq = sc->sc_audio1.drq;
@@ -2232,7 +2266,7 @@
 		src = ESS_MREG_VOLUME_MASTER;
 		break;
 	case ESS_DAC_PLAY_VOL:
-		if (sc->sc_model == ESS_1788)
+		if (ESS_USE_AUDIO1(sc->sc_model))
 			src = ESS_MREG_VOLUME_VOICE;
 		else
 			src = 0x7C;
@@ -2283,7 +2317,7 @@
 	}
 
 	/* 1788 doesn't have a separate recording mixer */
-	if (sc->sc_model == ESS_1788 && mix && src > 0x62)
+	if (ESS_USE_AUDIO1(sc->sc_model) && mix && src > 0x62)
 		return;
 
 	if (on) {
@@ -2637,4 +2671,21 @@
 	u_char mask;
 {
 	ess_write_mix_reg(sc, reg, ess_read_mix_reg(sc, reg) | mask);
+}
+
+void
+ess_read_multi_mix_reg(sc, reg, datap, count)
+	struct ess_softc *sc;
+	u_char reg;
+	u_int8_t *datap;
+	bus_size_t count;
+{
+	bus_space_tag_t iot = sc->sc_iot;
+	bus_space_handle_t ioh = sc->sc_ioh;
+	int s;
+
+	s = splaudio();
+	EWRITE1(iot, ioh, ESS_MIX_REG_SELECT, reg);
+	bus_space_read_multi_1(iot, ioh, ESS_MIX_REG_DATA, datap, count);
+	splx(s);
 }
diff -uNr sys.orig/dev/isa/ess_isa.c sys/dev/isa/ess_isa.c
--- sys.orig/dev/isa/ess_isa.c	Fri Mar 19 21:11:21 1999
+++ sys/dev/isa/ess_isa.c	Sun Apr 18 19:04:36 1999
@@ -97,7 +97,7 @@
 		DPRINTF(("ess_isa_probe succeeded (score %d)\n", ret));
 		ia->ia_iosize = ESS_NPORT;
 	} else
-		DPRINTF(("ess_isa_probe failed]n"));
+		DPRINTF(("ess_isa_probe failed\n"));
 		
 	return ret;
 }
diff -uNr sys.orig/dev/isa/essreg.h sys/dev/isa/essreg.h
--- sys.orig/dev/isa/essreg.h	Mon Mar 22 21:14:50 1999
+++ sys/dev/isa/essreg.h	Sun Apr 18 19:07:20 1999
@@ -164,6 +164,7 @@
  * Macros to detect valid hardware configuration data.
  */
 #define ESS_BASE_VALID(base) ((base) == 0x220 || (base) == 0x230 || (base) == 0x240 || (base) == 0x250)
+
 #define ESS_IRQ1_VALID(irq)  ((irq) == 5 || (irq) == 7 || (irq) == 9 || (irq) == 10)
 
 #define ESS_IRQ2_VALID(irq)  ((irq) == 15)
@@ -174,7 +175,7 @@
 
 #define ESS_DRQ2_VALID(chan) ((chan) == 0 || (chan) == 1 || (chan) == 3 || (chan) == 5)
 
-#define ESS_BASE_VALID(base) ((base) == 0x220 || (base) == 0x230 || (base) == 0x240 || (base) == 0x250)
+#define ESS_USE_AUDIO1(model) (((model) == ESS_1788) || ((model) == ESS_1868) || ((model) == ESS_1878) || ((model) == ESS_1869) || ((model) == ESS_1879))
 
 /*
  * Macros to manipulate gain values
diff -uNr sys.orig/dev/isa/essvar.h sys/dev/isa/essvar.h
--- sys.orig/dev/isa/essvar.h	Thu Mar 18 21:14:14 1999
+++ sys/dev/isa/essvar.h	Mon Mar 29 21:24:48 1999
@@ -148,6 +148,10 @@
 #define ESS_1887	2
 #define ESS_888		3
 #define ESS_1788	4
+#define ESS_1869	5
+#define ESS_1879	6
+#define ESS_1868	7
+#define ESS_1878	8
 
 	u_int	sc_version;		/* Legacy ES688/ES1688 ID */
 };
diff -uNr sys.orig/dev/isapnp/ess_isapnp.c sys/dev/isapnp/ess_isapnp.c
--- sys.orig/dev/isapnp/ess_isapnp.c	Mon Mar 22 21:14:52 1999
+++ sys/dev/isapnp/ess_isapnp.c	Tue Apr 20 23:33:02 1999
@@ -71,7 +71,7 @@
  */
 
 /*
- * Probe for the soundblaster hardware.
+ * Probe for the ess hardware.
  */
 int
 ess_isapnp_match(parent, match, aux)
>Audit-Trail:
>Unformatted: