diff -ru alsa-v009-test/alsa-kernel/include/emu10k1.h alsa-old/alsa-kernel/include/emu10k1.h
--- alsa-v009-test/alsa-kernel/include/emu10k1.h	2005-02-11 15:21:16.000000000 -0500
+++ alsa-old/alsa-kernel/include/emu10k1.h	2005-02-11 15:37:25.000000000 -0500
@@ -47,8 +47,6 @@
  *       them to IFACE_PCM.  Free all voices in pcm_channel_alloc error path.
  * v0.08 Connect external inputs to the EFX recording channels, rather than 
  *       the FX buses.  This was the original intent.
- * v0.09 Fix bug in voice allocator reported by Mikael Magnusson.
- * v0.10 Really fix bug in voice allocator reported by Mikael Magnusson.
  */
 
 #ifdef __KERNEL__
@@ -796,9 +794,6 @@
 #define A_SPDIF_44100		0x00000040
 #define A_SPDIF_96000		0x00000080
 
-/* 0x77,0x78,0x79 "something i2s-related" - default to 0x01080000 on my audigy 2 ZS --rlrevell	*/
-/* 0x7a, 0x7b - lookup tables */
-
 #define A_FXRT2			0x7c
 #define A_FXRT_CHANNELE		0x0000003f	/* Effects send bus number for channel's effects send E	*/
 #define A_FXRT_CHANNELF		0x00003f00	/* Effects send bus number for channel's effects send F	*/
@@ -877,7 +872,7 @@
 struct _snd_emu10k1_voice {
 	emu10k1_t *emu;
 	int number;
-	int use: 1,
+	unsigned int use: 1,
 	    pcm: 1,
 	    efx: 1,
 	    synth: 1,
@@ -1101,6 +1096,7 @@
 	emu10k1_midi_t midi2; /* for audigy */
 
 	unsigned int efx_voices_mask[2];
+	unsigned int input_monitor[1];
 	unsigned int next_free_voice;
 };
 
diff -ru alsa-v009-test/alsa-kernel/pci/emu10k1/emufx.c alsa-old/alsa-kernel/pci/emu10k1/emufx.c
--- alsa-v009-test/alsa-kernel/pci/emu10k1/emufx.c	2005-02-02 06:52:46.000000000 -0500
+++ alsa-old/alsa-kernel/pci/emu10k1/emufx.c	2005-02-11 15:38:09.000000000 -0500
@@ -323,6 +323,8 @@
 	return 0;
 }
 
+/* GPR mixer controls */
+
 static int snd_emu10k1_gpr_ctl_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
diff -ru alsa-v009-test/alsa-kernel/pci/emu10k1/emupcm.c alsa-old/alsa-kernel/pci/emu10k1/emupcm.c
--- alsa-v009-test/alsa-kernel/pci/emu10k1/emupcm.c	2005-02-10 16:55:56.000000000 -0500
+++ alsa-old/alsa-kernel/pci/emu10k1/emupcm.c	2005-02-10 22:48:39.000000000 -0500
@@ -235,6 +235,7 @@
 
 static unsigned int emu10k1_select_interprom(unsigned int pitch_target)
 {
+	
 	if (pitch_target == PITCH_48000)
 		return CCCA_INTERPROM_0;
 	else if (pitch_target < PITCH_48000)
@@ -677,7 +678,7 @@
 {
 	snd_pcm_substream_t *substream;
 	snd_pcm_runtime_t *runtime;
-	unsigned int voice, pitch, pitch_target, tmp;
+	unsigned int voice, pitch, pitch_target;
 
 	if (evoice == NULL)	/* skip second voice for mono */
 		return;
@@ -1459,6 +1460,66 @@
 	.put = snd_emu10k1_pcm_efx_voices_mask_put
 };
 
+/*
+ * control for direct monitoring with multichannel PCM.  JACK needs this  
+ * for hardware monitoring.  Although you can do it in the DSP it's nice to 
+ * have ASIO styly zero latency monitoring controlled by the JACK, rather than 
+ * having to manually connect a route in the DSP. 
+ * For now all selected EXTINs will be mixed together to the analog 
+ * capture port.  We will need more flexible send routing control eventually.
+ */
+
+static int snd_emu10k1_pcm_input_monitor_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = NUM_EFX_PLAYBACK;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_emu10k1_pcm_input_monitor_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	int idx;
+	
+	spin_lock_irq(&emu->reg_lock);
+	for (idx = 0; idx < NUM_EFX_PLAYBACK; idx++)
+		ucontrol->value.integer.value[idx] = (emu->input_monitor[idx / 32] & ( 1 << (idx % 32))) ? 1 : 0;
+	spin_unlock_irq(&emu->reg_lock);
+	return 0;
+}
+
+static int snd_emu10k1_pcm_input_monitor_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	unsigned int nval[1];
+	int change, idx;
+	
+	nval[0] = 0;
+	for (idx = 0; idx < NUM_EFX_PLAYBACK; idx++) {
+		if (ucontrol->value.integer.value[idx]) {
+			printk("channel %d set\n", idx);
+			nval[idx / 32] |= 1 << ( idx % 32);
+		}
+	}
+		
+	spin_lock_irq(&emu->reg_lock);
+	change = (nval[0] != emu->input_monitor[0]);
+	emu->input_monitor[0] = nval[0];
+	printk("input monitoring activated: %x\n", nval[0]);
+	spin_unlock_irq(&emu->reg_lock);
+	return change;
+}
+
+static snd_kcontrol_new_t snd_emu10k1_pcm_input_monitor = {
+	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
+	.name = "Multi Track Input Monitor",
+	.info = snd_emu10k1_pcm_input_monitor_info,
+	.get = snd_emu10k1_pcm_input_monitor_get,
+	.put = snd_emu10k1_pcm_input_monitor_put
+};
+
 static snd_pcm_ops_t snd_emu10k1_capture_efx_ops = {
 	.open =			snd_emu10k1_capture_efx_open,
 	.close =		snd_emu10k1_capture_efx_close,
@@ -1743,6 +1804,9 @@
 	}
 	snd_ctl_add(emu->card, snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu));
 
+	/* don't monitor the inputs by default */
+	snd_ctl_add(emu->card, snd_ctl_new1(&snd_emu10k1_pcm_input_monitor, emu));
+	
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
 
 	return 0;
Only in alsa-old/alsa-kernel/pci/emu10k1: emupcm.c~
diff -ru alsa-v009-test/alsa-kernel/pci/emu10k1/emuproc.c alsa-old/alsa-kernel/pci/emu10k1/emuproc.c
--- alsa-v009-test/alsa-kernel/pci/emu10k1/emuproc.c	2005-02-10 16:55:56.000000000 -0500
+++ alsa-old/alsa-kernel/pci/emu10k1/emuproc.c	2005-02-05 23:26:59.000000000 -0500
@@ -140,38 +140,38 @@
 		/* 29 */ "???",
 		/* 30 */ "???",
 		/* 31 */ "???",
-		/* 32 */ "???",
-		/* 33 */ "???",
-		/* 34 */ "???",
-		/* 35 */ "???",
-		/* 36 */ "???",
-		/* 37 */ "???",
-		/* 38 */ "???",
-		/* 39 */ "???",
-		/* 40 */ "???",
-		/* 41 */ "???",
-		/* 42 */ "???",
-		/* 43 */ "???",
-		/* 44 */ "???",
-		/* 45 */ "???",
-		/* 46 */ "???",
-		/* 47 */ "???",
-		/* 48 */ "???",
-		/* 49 */ "???",
-		/* 50 */ "???",
-		/* 51 */ "???",
-		/* 52 */ "???",
-		/* 53 */ "???",
-		/* 54 */ "???",
-		/* 55 */ "???",
-		/* 56 */ "???",
-		/* 57 */ "???",
-		/* 58 */ "???",
-		/* 59 */ "???",
-		/* 60 */ "???",
-		/* 61 */ "???",
-		/* 62 */ "???",
-		/* 33 */ "???"
+		/* 32 */ "FXBUS2_0",
+		/* 33 */ "FXBUS2_1",
+		/* 34 */ "FXBUS2_2",
+		/* 35 */ "FXBUS2_3",
+		/* 36 */ "FXBUS2_4",
+		/* 37 */ "FXBUS2_5",
+		/* 38 */ "FXBUS2_6",
+		/* 39 */ "FXBUS2_7",
+		/* 40 */ "FXBUS2_8",
+		/* 41 */ "FXBUS2_9",
+		/* 42 */ "FXBUS2_10",
+		/* 43 */ "FXBUS2_11",
+		/* 44 */ "FXBUS2_12",
+		/* 45 */ "FXBUS2_13",
+		/* 46 */ "FXBUS2_14",
+		/* 47 */ "FXBUS2_15",
+		/* 48 */ "FXBUS2_16",
+		/* 49 */ "FXBUS2_17",
+		/* 50 */ "FXBUS2_18",
+		/* 51 */ "FXBUS2_19",
+		/* 52 */ "FXBUS2_20",
+		/* 53 */ "FXBUS2_21",
+		/* 54 */ "FXBUS2_22",
+		/* 55 */ "FXBUS2_23",
+		/* 56 */ "FXBUS2_24",
+		/* 57 */ "FXBUS2_25",
+		/* 58 */ "FXBUS2_26",
+		/* 59 */ "FXBUS2_27",
+		/* 60 */ "FXBUS2_28",
+		/* 61 */ "FXBUS2_29",
+		/* 62 */ "FXBUS2_30",
+		/* 63 */ "FXBUS2_31"
 	};
 
 	emu10k1_t *emu = entry->private_data;
@@ -221,7 +221,7 @@
 			snd_iprintf(buffer, "  Output %02i [%s]\n", idx, outputs[idx]);
 	}
 	snd_iprintf(buffer, "\nAll FX Outputs        :\n");
-	for (idx = 0; idx < 32; idx++)
+	for (idx = 0; idx < (emu->audigy ? 64 : 32); idx++)
 		snd_iprintf(buffer, "  Output %02i [%s]\n", idx, outputs[idx]);
 	snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 0", SPCS0, -1);
 	snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 1", SPCS1, -1);
@@ -322,6 +322,26 @@
 	return 0;
 }
 
+static void snd_emu10k1_proc_voices_read(snd_info_entry_t *entry, 
+				  snd_info_buffer_t * buffer)
+{
+	emu10k1_t *emu = entry->private_data;
+	emu10k1_voice_t *voice;
+	int idx;
+	
+	snd_iprintf(buffer, "ch\tuse\tpcm\tefx\tsynth\tmidi\n");
+	for (idx = 0; idx < NUM_G; idx++) {
+		voice = &emu->voices[idx];
+		snd_iprintf(buffer, "%i\t%i\t%i\t%i\t%i\t%i\n",
+			idx,
+			voice->use,
+			voice->pcm,
+			voice->efx,
+			voice->synth,
+			voice->midi);
+	}
+}
+
 #ifdef CONFIG_SND_DEBUG
 static void snd_emu_proc_io_reg_read(snd_info_entry_t *entry,
 				     snd_info_buffer_t * buffer)
@@ -506,6 +526,9 @@
 	if (! snd_card_proc_new(emu->card, "emu10k1", &entry))
 		snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_read);
 
+	if (! snd_card_proc_new(emu->card, "voices", &entry))
+		snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read);
+
 	if (! snd_card_proc_new(emu->card, "fx8010_gpr", &entry)) {
 		entry->content = SNDRV_INFO_CONTENT_DATA;
 		entry->private_data = emu;

