patch-2.4.0-test7 linux/drivers/sound/emu10k1/main.c

Next file: linux/drivers/sound/emu10k1/midi.c
Previous file: linux/drivers/sound/emu10k1/irqmgr.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test6/linux/drivers/sound/emu10k1/main.c linux/drivers/sound/emu10k1/main.c
@@ -1,4 +1,3 @@
-
 /*
  **********************************************************************
  *     main.c - Creative EMU10K1 audio driver
@@ -42,24 +41,35 @@
  *      0.4 Added rear-channel, SPDIF support.
  *	0.5 Source cleanup, SMP fixes, multiopen support, 64 bit arch fixes,
  *	    moved bh's to tasklets, moved to the new PCI driver initialization style.
+ *	0.6 Make use of pci_alloc_consistent, improve compatibility layer for 2.2 kernels,
+ *	    code reorganization and cleanup.
+ *      0.7 Support for the Emu-APS. Bug fixes for voice cache setup, mmaped sound + poll().
+ *	    Support for setting external TRAM size.
+ *	
  **********************************************************************
  */
 
 /* These are only included once per module */
+#include <linux/version.h>
 #include <linux/module.h>
+#include <linux/malloc.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 
 #include "hwaccess.h"
+#include "8010.h"
 #include "efxmgr.h"
 #include "cardwo.h"
 #include "cardwi.h"
 #include "cardmo.h"
 #include "cardmi.h"
 #include "recmgr.h"
+#include "ecard.h"
 
-#define DRIVER_VERSION "0.5"
+#define DRIVER_VERSION "0.7"
 
 /* FIXME: is this right? */
+/* does the card support 32 bit bus master?*/
 #define EMU10K1_DMA_MASK                0xffffffff	/* DMA buffer mask for pci_alloc_consist */
 
 #ifndef PCI_VENDOR_ID_CREATIVE
@@ -70,8 +80,8 @@
 #define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002
 #endif
 
-#define EMU10K1_EXTENT	0x20	/* 32 byte I/O space */
-
+#define EMU_APS_SUBID	0x40011102
+ 
 enum {
 	EMU10K1 = 0,
 };
@@ -80,7 +90,7 @@
 	"EMU10K1",
 };
 
-static struct pci_device_id emu10k1_pci_tbl[] __devinitdata = {
+static struct pci_device_id emu10k1_pci_tbl[] = {
 	{PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_EMU10K1,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, EMU10K1},
 	{0,}
@@ -99,32 +109,38 @@
 extern void emu10k1_interrupt(int, void *, struct pt_regs *s);
 extern int emu10k1_mixer_wrch(struct emu10k1_card *, unsigned int, int);
 
-static int __devinit audio_init(struct emu10k1_card *card)
+static void __devinit audio_init(struct emu10k1_card *card)
 {
-	if ((card->waveout = kmalloc(sizeof(struct emu10k1_waveout), GFP_KERNEL)) == NULL) {
-		printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_waveout: out of memory\n");
-		return CTSTATUS_ERROR;
-	}
-	memset(card->waveout, 0, sizeof(struct emu10k1_waveout));
-
-	/* Assign default global volume, reverb, chorus */
-	card->waveout->globalvol = 0xffffffff;
-	card->waveout->left = 0xffff;
-	card->waveout->right = 0xffff;
-	card->waveout->mute = 0;
-	card->waveout->globalreverb = 0xffffffff;
-	card->waveout->globalchorus = 0xffffffff;
+	/* Assign default playback voice parameters */
+	/* mono voice */
+	card->waveout.send_a[0] = 0x00;
+	card->waveout.send_b[0] = 0xff;
+	card->waveout.send_c[0] = 0xff;
+	card->waveout.send_d[0] = 0x00;
+	card->waveout.send_routing[0] = 0xd01c;
+
+	/* stereo voice */
+	card->waveout.send_a[1] = 0x00;
+        card->waveout.send_b[1] = 0xff;
+        card->waveout.send_c[1] = 0x00;
+        card->waveout.send_d[1] = 0x00;
+        card->waveout.send_routing[1] = 0xd01c;
+
+	card->waveout.send_a[2] = 0x00;
+        card->waveout.send_b[2] = 0x00;
+        card->waveout.send_c[2] = 0xff;
+        card->waveout.send_d[2] = 0x00;
+        card->waveout.send_routing[2] = 0xd01c;
+
+	/* Assign default recording parameters */
+	if(card->isaps)
+		card->wavein.recsrc = WAVERECORD_FX;
+	else
+		card->wavein.recsrc = WAVERECORD_AC97;
 
-	if ((card->wavein = kmalloc(sizeof(struct emu10k1_wavein), GFP_KERNEL))
-	    == NULL) {
-		printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_wavein: out of memory\n");
-		return CTSTATUS_ERROR;
-	}
-	memset(card->wavein, 0, sizeof(struct emu10k1_wavein));
+	card->wavein.fxwc = 0x0003;
 
-	card->wavein->recsrc = WAVERECORD_AC97;
-
-	return CTSTATUS_SUCCESS;
+	return;
 }
 
 static void __devinit mixer_init(struct emu10k1_card *card)
@@ -141,61 +157,64 @@
 		SOUND_MIXER_PHONEIN, 0x3232}, {
 		SOUND_MIXER_MIC, 0x0000}, {
 		SOUND_MIXER_LINE, 0x0000}, {
-		SOUND_MIXER_CD, 0x3232}, {
-		SOUND_MIXER_LINE1, 0x3232}, {
+		SOUND_MIXER_CD, 0x4b4b}, {
+		SOUND_MIXER_LINE1, 0x4b4b}, {
 		SOUND_MIXER_LINE3, 0x3232}, {
 		SOUND_MIXER_DIGITAL1, 0x6464}, {
 		SOUND_MIXER_DIGITAL2, 0x6464}, {
 		SOUND_MIXER_PCM, 0x6464}, {
-		SOUND_MIXER_RECLEV, 0x3232}, {
+		SOUND_MIXER_RECLEV, 0x0404}, {
 		SOUND_MIXER_TREBLE, 0x3232}, {
 		SOUND_MIXER_BASS, 0x3232}, {
-	SOUND_MIXER_LINE2, 0x4b4b}};
+		SOUND_MIXER_LINE2, 0x4b4b}};
 
-	int initdig[] = { 0, 1, 2, 3, 6, 7, 16, 17, 18, 19, 22, 23, 64, 65, 66, 67, 70, 71,
-		84, 85
+	int initdig[] = { 0, 1, 2, 3, 6, 7, 18, 19, 20, 21, 24, 25, 72, 73, 74, 75, 78, 79,
+		94, 95
 	};
 
-	/* Reset */
-	sblive_writeac97(card, AC97_RESET, 0);
-
-#if 0
-	/* Check status word */
-	{
-		u16 reg;
-
-		sblive_readac97(card, AC97_RESET, &reg);
-		DPD(2, "RESET 0x%x\n", reg);
-		sblive_readac97(card, AC97_MASTERTONE, &reg);
-		DPD(2, "MASTER_TONE 0x%x\n", reg);
+	for (count = 0; count < sizeof(card->digmix) / sizeof(card->digmix[0]); count++) {
+		card->digmix[count] = 0x80000000;
+		sblive_writeptr(card, FXGPREGBASE + 0x10 + count, 0, 0);
 	}
-#endif
 
-	/* Set default recording source to mic in */
-	sblive_writeac97(card, AC97_RECORDSELECT, 0);
+	card->modcnt = 0;       // Should this be here or in open() ?
 
-	/* Set default AC97 "PCM" volume to acceptable max */
-	//sblive_writeac97(card, AC97_PCMOUTVOLUME, 0);
-	//sblive_writeac97(card, AC97_LINE2, 0);
+	if (!card->isaps) {
 
-	/* Set default volumes for all mixer channels */
+		for (count = 0; count < sizeof(initdig) / sizeof(initdig[0]); count++) {
+			card->digmix[initdig[count]] = 0x7fffffff;
+			sblive_writeptr(card, FXGPREGBASE + 0x10 + initdig[count], 0, 0x7fffffff);
+		}
 
-	for (count = 0; count < sizeof(card->digmix) / sizeof(card->digmix[0]); count++) {
-		card->digmix[count] = 0x80000000;
-		sblive_writeptr(card, FXGPREGBASE + 0x10 + count, 0, 0);
-	}
+		/* Reset */
+		sblive_writeac97(card, AC97_RESET, 0);
 
-	for (count = 0; count < sizeof(initdig) / sizeof(initdig[0]); count++) {
-		card->digmix[initdig[count]] = 0x7fffffff;
-		sblive_writeptr(card, FXGPREGBASE + 0x10 + initdig[count], 0, 0x7fffffff);
+#if 0
+		/* Check status word */
+		{
+			u16 reg;
+
+			sblive_readac97(card, AC97_RESET, &reg);
+			DPD(2, "RESET 0x%x\n", reg);
+			sblive_readac97(card, AC97_MASTERTONE, &reg);
+			DPD(2, "MASTER_TONE 0x%x\n", reg);
+		}
+#endif
+
+		/* Set default recording source to mic in */
+		sblive_writeac97(card, AC97_RECORDSELECT, 0);
+
+		/* Set default AC97 "PCM" volume to acceptable max */
+		//sblive_writeac97(card, AC97_PCMOUTVOLUME, 0);
+		//sblive_writeac97(card, AC97_LINE2, 0);
 	}
 
+	/* Set default volumes for all mixer channels */
+
 	for (count = 0; count < sizeof(initvol) / sizeof(initvol[0]); count++) {
 		emu10k1_mixer_wrch(card, initvol[count].mixch, initvol[count].vol);
 	}
 
-	card->modcnt = 0;	// Should this be here or in open() ?
-
 	return;
 }
 
@@ -204,7 +223,7 @@
 	if ((card->mpuout = kmalloc(sizeof(struct emu10k1_mpuout), GFP_KERNEL))
 	    == NULL) {
 		printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuout: out of memory\n");
-		return CTSTATUS_ERROR;
+		return -1;
 	}
 
 	memset(card->mpuout, 0, sizeof(struct emu10k1_mpuout));
@@ -220,7 +239,7 @@
 	if ((card->mpuin = kmalloc(sizeof(struct emu10k1_mpuin), GFP_KERNEL)) == NULL) {
 		kfree(card->mpuout);
 		printk(KERN_WARNING "emu10k1: Unable to allocate emu10k1_mpuin: out of memory\n");
-		return CTSTATUS_ERROR;
+		return -1;
 	}
 
 	memset(card->mpuin, 0, sizeof(struct emu10k1_mpuin));
@@ -232,31 +251,20 @@
 	spin_lock_init(&card->mpuin->lock);
 
 	/* Reset the MPU port */
-	if (emu10k1_mpu_reset(card) != CTSTATUS_SUCCESS) {
+	if (emu10k1_mpu_reset(card) < 0) {
 		ERROR();
-		return CTSTATUS_ERROR;
+		return -1;
 	}
 
-	return CTSTATUS_SUCCESS;
+	return 0;
 }
 
 static void __devinit voice_init(struct emu10k1_card *card)
 {
-	struct voice_manager *voicemgr = &card->voicemgr;
-	struct emu_voice *voice;
 	int i;
 
-	voicemgr->card = card;
-	voicemgr->lock = SPIN_LOCK_UNLOCKED;
-
-	voice = voicemgr->voice;
-	for (i = 0; i < NUM_G; i++) {
-		voice->card = card;
-		voice->usage = VOICEMGR_USAGE_FREE;
-		voice->num = i;
-		voice->linked_voice = NULL;
-		voice++;
-	}
+	for (i = 0; i < NUM_G; i++)
+		card->voicetable[i] = VOICE_USAGE_FREE;
 
 	return;
 }
@@ -280,21 +288,27 @@
 	/* Mark first page as used */
 	/* This page is reserved by the driver */
 	card->emupagetable[0] = 0x8001;
-	card->emupagetable[1] = MAXPAGES - RESERVED - 1;
+	card->emupagetable[1] = MAXPAGES - 1;
 
 	return;
 }
 
 static void __devinit fx_init(struct emu10k1_card *card)
 {
-	int i, j, k, l;
+	int i, j, k;
+#ifdef TONE_CONTROL
+	int l;
+#endif	
 	u32 pc = 0;
 
 	for (i = 0; i < 512; i++)
 		OP(6, 0x40, 0x40, 0x40, 0x40);
 
 	for (i = 0; i < 256; i++)
-		sblive_writeptr(card, FXGPREGBASE + i, 0, 0);
+		sblive_writeptr_tag(card, 0,
+				    FXGPREGBASE + i, 0,
+				    TANKMEMADDRREGBASE + i, 0,
+				    TAGLIST_END);
 
 	pc = 0;
 
@@ -304,7 +318,7 @@
 		OP(4, 0x101, 0x40, j + 2, 0x44);
 
 		for (i = 0; i < 6; i++) {
-			k = i * 16 + j;
+			k = i * 18 + j;
 			OP(0, 0x102, 0x40, 0x110 + k, 0x100);
 			OP(0, 0x102, 0x102, 0x112 + k, 0x101);
 			OP(0, 0x102, 0x102, 0x114 + k, 0x10 + j);
@@ -313,25 +327,32 @@
 			OP(0, 0x102, 0x102, 0x11a + k, 0x16 + j);
 			OP(0, 0x102, 0x102, 0x11c + k, 0x18 + j);
 			OP(0, 0x102, 0x102, 0x11e + k, 0x1a + j);
+#ifdef TONE_CONTROL
+			OP(0, 0x102, 0x102, 0x120 + k, 0x1c + j);
 
-			k = 0x190 + i * 8 + j * 4;
-			OP(0, 0x40, 0x40, 0x102, 0x170 + j);
-			OP(7, k + 1, k, k + 1, 0x174 + j);
-			OP(7, k, 0x102, k, 0x172 + j);
-			OP(7, k + 3, k + 2, k + 3, 0x178 + j);
-			OP(0, k + 2, 0x56, k + 2, 0x176 + j);
+			k = 0x1a0 + i * 8 + j * 4;
+			OP(0, 0x40, 0x40, 0x102, 0x180 + j);
+			OP(7, k + 1, k, k + 1, 0x184 + j);
+			OP(7, k, 0x102, k, 0x182 + j);
+			OP(7, k + 3, k + 2, k + 3, 0x188 + j);
+			OP(0, k + 2, 0x56, k + 2, 0x186 + j);
 			OP(6, k + 2, k + 2, k + 2, 0x40);
 
-			l = 0x1c0 + i * 8 + j * 4;
-			OP(0, 0x40, 0x40, k + 2, 0x180 + j);
-			OP(7, l + 1, l, l + 1, 0x184 + j);
-			OP(7, l, k + 2, l, 0x182 + j);
-			OP(7, l + 3, l + 2, l + 3, 0x188 + j);
-			OP(0, l + 2, 0x56, l + 2, 0x186 + j);
+			l = 0x1d0 + i * 8 + j * 4;
+			OP(0, 0x40, 0x40, k + 2, 0x190 + j);
+			OP(7, l + 1, l, l + 1, 0x194 + j);
+			OP(7, l, k + 2, l, 0x192 + j);
+			OP(7, l + 3, l + 2, l + 3, 0x198 + j);
+			OP(0, l + 2, 0x56, l + 2, 0x196 + j);
 			OP(4, l + 2, 0x40, l + 2, 0x46);
 
-			OP(6, 0x20 + (i * 2) + j, l + 2, 0x40, 0x40);
-
+			if ((i == 0) && !card->isaps)
+				OP(4, 0x20 + (i * 2) + j, 0x40, l + 2, 0x50);	/* FIXME: Is this really needed? */
+			else
+				OP(6, 0x20 + (i * 2) + j, l + 2, 0x40, 0x40);
+#else
+			OP(0, 0x20 + (i * 2) + j, 0x102, 0x120 + k, 0x1c + j);
+#endif
 		}
 	}
 	sblive_writeptr(card, DBG, 0, 0);
@@ -342,63 +363,64 @@
 static int __devinit hw_init(struct emu10k1_card *card)
 {
 	int nCh;
-
-#ifdef TANKMEM
-	u32 size = 0;
-#endif
-	u32 sizeIdx = 0;
-	u32 pagecount, tmp;
+	u32 pagecount; /* tmp */
 
 	/* Disable audio and lock cache */
-	sblive_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE | HCFG_MUTEBUTTONENABLE);
+	emu10k1_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE);
 
 	/* Reset recording buffers */
-	sblive_writeptr(card, MICBS, 0, ADCBS_BUFSIZE_NONE);
-	sblive_writeptr(card, MICBA, 0, 0);
-	sblive_writeptr(card, FXBS, 0, ADCBS_BUFSIZE_NONE);
-	sblive_writeptr(card, FXBA, 0, 0);
-	sblive_writeptr(card, ADCBS, 0, ADCBS_BUFSIZE_NONE);
-	sblive_writeptr(card, ADCBA, 0, 0);
+	sblive_writeptr_tag(card, 0,
+			    MICBS, ADCBS_BUFSIZE_NONE,
+			    MICBA, 0,
+			    FXBS, ADCBS_BUFSIZE_NONE,
+			    FXBA, 0,
+			    ADCBS, ADCBS_BUFSIZE_NONE,
+			    ADCBA, 0,
+			    TAGLIST_END);
 
 	/* Disable channel interrupt */
-	sblive_writefn0(card, INTE, DISABLE);
-	sblive_writeptr(card, CLIEL, 0, 0);
-	sblive_writeptr(card, CLIEH, 0, 0);
-	sblive_writeptr(card, SOLEL, 0, 0);
-	sblive_writeptr(card, SOLEH, 0, 0);
+	emu10k1_writefn0(card, INTE, 0);
+	sblive_writeptr_tag(card, 0,
+			    CLIEL, 0,
+			    CLIEH, 0,
+			    SOLEL, 0,
+			    SOLEH, 0,
+			    TAGLIST_END);
 
 	/* Init envelope engine */
 	for (nCh = 0; nCh < NUM_G; nCh++) {
-		sblive_writeptr(card, DCYSUSV, nCh, ENV_OFF);
-		sblive_writeptr(card, IP, nCh, 0);
-		sblive_writeptr(card, VTFT, nCh, 0xffff);
-		sblive_writeptr(card, CVCF, nCh, 0xffff);
-		sblive_writeptr(card, PTRX, nCh, 0);
-		sblive_writeptr(card, CPF, nCh, 0);
-		sblive_writeptr(card, CCR, nCh, 0);
-
-		sblive_writeptr(card, PSST, nCh, 0);
-		sblive_writeptr(card, DSL, nCh, 0x10);
-		sblive_writeptr(card, CCCA, nCh, 0);
-		sblive_writeptr(card, Z1, nCh, 0);
-		sblive_writeptr(card, Z2, nCh, 0);
-		sblive_writeptr(card, FXRT, nCh, 0xd01c0000);
-
-		sblive_writeptr(card, ATKHLDM, nCh, 0);
-		sblive_writeptr(card, DCYSUSM, nCh, 0);
-		sblive_writeptr(card, IFATN, nCh, 0xffff);
-		sblive_writeptr(card, PEFE, nCh, 0);
-		sblive_writeptr(card, FMMOD, nCh, 0);
-		sblive_writeptr(card, TREMFRQ, nCh, 24);	/* 1 Hz */
-		sblive_writeptr(card, FM2FRQ2, nCh, 24);	/* 1 Hz */
-		sblive_writeptr(card, TEMPENV, nCh, 0);
-
-		/*** These are last so OFF prevents writing ***/
-		sblive_writeptr(card, LFOVAL2, nCh, 0);
-		sblive_writeptr(card, LFOVAL1, nCh, 0);
-		sblive_writeptr(card, ATKHLDV, nCh, 0);
-		sblive_writeptr(card, ENVVOL, nCh, 0);
-		sblive_writeptr(card, ENVVAL, nCh, 0);
+		sblive_writeptr_tag(card, nCh,
+				    DCYSUSV, 0,
+				    IP, 0,
+				    VTFT, 0xffff,
+				    CVCF, 0xffff,
+				    PTRX, 0,
+				    CPF, 0,
+				    CCR, 0,
+
+				    PSST, 0,
+				    DSL, 0x10,
+				    CCCA, 0,
+				    Z1, 0,
+				    Z2, 0,
+				    FXRT, 0xd01c0000,
+
+				    ATKHLDM, 0,
+				    DCYSUSM, 0,
+				    IFATN, 0xffff,
+				    PEFE, 0,
+				    FMMOD, 0,
+				    TREMFRQ, 24,	/* 1 Hz */
+				    FM2FRQ2, 24,	/* 1 Hz */
+				    TEMPENV, 0,
+
+				    /*** These are last so OFF prevents writing ***/
+				    LFOVAL2, 0,
+				    LFOVAL1, 0,
+				    ATKHLDV, 0,
+				    ENVVOL, 0,
+				    ENVVAL, 0,
+                                    TAGLIST_END);
 	}
 
 	/*
@@ -416,73 +438,57 @@
 	 ** P                 = 0     (Consumer)
 	 */
 
-	/* SPDIF0 */
-	sblive_writeptr(card, SPCS0, 0, SPCS_CLKACCY_1000PPM | 0x002000000 |
-			SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
-
-	/* SPDIF1 */
-	sblive_writeptr(card, SPCS1, 0, SPCS_CLKACCY_1000PPM | 0x002000000 |
-			SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
-
-	/* SPDIF2 & SPDIF3 */
-	sblive_writeptr(card, SPCS2, 0, SPCS_CLKACCY_1000PPM | 0x002000000 |
-			SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
+	sblive_writeptr_tag(card, 0,
 
-	fx_init(card);		/* initialize effects engine */
+			    /* SPDIF0 */
+			    SPCS0, (SPCS_CLKACCY_1000PPM | 0x002000000 |
+				    SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),
 
-	card->tankmem = NULL;
+			    /* SPDIF1 */
+			    SPCS1, (SPCS_CLKACCY_1000PPM | 0x002000000 |
+				    SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),
 
-#ifdef TANKMEM
-	size = TMEMSIZE;
-	sizeIdx = TMEMSIZEREG;
-	while (size > 16384) {
-		if ((card->tankmem = emu10k1_alloc_memphysical(size)) != NULL)
-			break;
+			    /* SPDIF2 & SPDIF3 */
+			    SPCS2, (SPCS_CLKACCY_1000PPM | 0x002000000 |
+				    SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | SPCS_GENERATIONSTATUS | 0x00001200 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT),
 
-		size /= 2;
-		sizeIdx -= 1;
-	}
+			    TAGLIST_END);
 
-	if (card->tankmem == NULL) {
-		card->tmemsize = 0;
-		return CTSTATUS_ERROR;
-	}
+	fx_init(card);		/* initialize effects engine */
+
+	card->tankmem.size = 0;
 
-	card->tmemsize = size;
-#else				/* !TANKMEM */
-	card->tmemsize = 0;
-#endif				/* TANKMEM */
+	card->virtualpagetable.size = MAXPAGES * sizeof(u32);
 
-	if ((card->virtualpagetable = emu10k1_alloc_memphysical((MAXPAGES - RESERVED) * sizeof(u32))) == NULL) {
+	if ((card->virtualpagetable.addr = pci_alloc_consistent(card->pci_dev, card->virtualpagetable.size, &card->virtualpagetable.dma_handle)) ==
+	    NULL) {
 		ERROR();
-		emu10k1_free_memphysical(card->tankmem);
-		return CTSTATUS_ERROR;
+		return -1;
 	}
 
-	if ((card->silentpage = emu10k1_alloc_memphysical(EMUPAGESIZE)) == NULL) {
-		ERROR();
-		emu10k1_free_memphysical(card->tankmem);
-		emu10k1_free_memphysical(card->virtualpagetable);
-		return CTSTATUS_ERROR;
-	} else
-		memset(card->silentpage->virtaddx, 0, EMUPAGESIZE);
+	card->silentpage.size = EMUPAGESIZE;
 
-	for (pagecount = 0; pagecount < (MAXPAGES - RESERVED); pagecount++)
+	if ((card->silentpage.addr = pci_alloc_consistent(card->pci_dev, card->silentpage.size, &card->silentpage.dma_handle)) == NULL) {
+		ERROR();
+		pci_free_consistent(card->pci_dev, card->virtualpagetable.size, card->virtualpagetable.addr, card->virtualpagetable.dma_handle);
+		return -1;
+	}
 
-		((u32 *) card->virtualpagetable->virtaddx)[pagecount] = (card->silentpage->busaddx * 2) | pagecount;
+	for (pagecount = 0; pagecount < MAXPAGES; pagecount++)
+		((u32 *) card->virtualpagetable.addr)[pagecount] = (card->silentpage.dma_handle * 2) | pagecount;
 
 	/* Init page table & tank memory base register */
-	sblive_writeptr(card, PTB, 0, card->virtualpagetable->busaddx);
-#ifdef TANKMEM
-	sblive_writeptr(card, TCB, 0, card->tankmem->busaddx);
-#else
-	sblive_writeptr(card, TCB, 0, 0);
-#endif
-	sblive_writeptr(card, TCBS, 0, sizeIdx);
+	sblive_writeptr_tag(card, 0,
+			    PTB, card->virtualpagetable.dma_handle,
+			    TCB, 0,
+			    TCBS, 0,
+			    TAGLIST_END);
 
 	for (nCh = 0; nCh < NUM_G; nCh++) {
-		sblive_writeptr(card, MAPA, nCh, MAP_PTI_MASK | (card->silentpage->busaddx * 2));
-		sblive_writeptr(card, MAPB, nCh, MAP_PTI_MASK | (card->silentpage->busaddx * 2));
+		sblive_writeptr_tag(card, nCh,
+				    MAPA, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
+				    MAPB, MAP_PTI_MASK | (card->silentpage.dma_handle * 2),
+				    TAGLIST_END);
 	}
 
 	/* Hokay, now enable the AUD bit */
@@ -497,12 +503,16 @@
 	sblive_writeac97(card, AC97_MASTERVOLUME, 0);
 	sblive_writeac97(card, AC97_PCMOUTVOLUME, 0);
 
-	sblive_writefn0(card, HCFG, HCFG_AUDIOENABLE | HCFG_LOCKTANKCACHE | HCFG_AUTOMUTE | HCFG_JOYENABLE);
+	if(card->model == 0x20 || card->model == 0xc400 ||
+	  (card->model == 0x21 && card->chiprev < 6))
+	        emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE);
+	else
+		emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE  | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE);
 
-	/* TOSLink detection */
+	/* FIXME: TOSLink detection */
 	card->has_toslink = 0;
 
-	tmp = sblive_readfn0(card, HCFG);
+/*	tmp = sblive_readfn0(card, HCFG);
 	if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) {
 		sblive_writefn0(card, HCFG, tmp | 0x800);
 
@@ -513,30 +523,23 @@
 			sblive_writefn0(card, HCFG, tmp);
 		}
 	}
-
-	return CTSTATUS_SUCCESS;
+*/
+	return 0;
 }
 
 static int __devinit emu10k1_init(struct emu10k1_card *card)
 {
 	/* Init Card */
-	if (hw_init(card) != CTSTATUS_SUCCESS)
-		return CTSTATUS_ERROR;
+	if (hw_init(card) < 0)
+		return -1;
 
 	voice_init(card);
 	timer_init(card);
 	addxmgr_init(card);
 
-	DPD(2, "  hw control register -> %x\n", sblive_readfn0(card, HCFG));
-
-	return CTSTATUS_SUCCESS;
-}
+	DPD(2, "  hw control register -> 0x%x\n", emu10k1_readfn0(card, HCFG));
 
-static void __devexit audio_exit(struct emu10k1_card *card)
-{
-	kfree(card->waveout);
-	kfree(card->wavein);
-	return;
+	return 0;
 }
 
 static void __devexit midi_exit(struct emu10k1_card *card)
@@ -550,50 +553,57 @@
 	return;
 }
 
-static void __devexit emu10k1_exit(struct emu10k1_card *card)
+static void __devinit emu10k1_exit(struct emu10k1_card *card)
 {
 	int ch;
 
-	sblive_writefn0(card, INTE, DISABLE);
+	emu10k1_writefn0(card, INTE, 0);
 
 	/** Shutdown the chip **/
 	for (ch = 0; ch < NUM_G; ch++)
-		sblive_writeptr(card, DCYSUSV, ch, ENV_OFF);
+		sblive_writeptr(card, DCYSUSV, ch, 0);
 
 	for (ch = 0; ch < NUM_G; ch++) {
-		sblive_writeptr(card, VTFT, ch, 0);
-		sblive_writeptr(card, CVCF, ch, 0);
-		sblive_writeptr(card, PTRX, ch, 0);
-		sblive_writeptr(card, CPF, ch, 0);
+		sblive_writeptr_tag(card, ch,
+				    VTFT, 0,
+				    CVCF, 0,
+				    PTRX, 0,
+				    CPF, 0,
+				    TAGLIST_END);
 	}
 
-	/* Reset recording buffers */
-	sblive_writeptr(card, MICBS, 0, ADCBS_BUFSIZE_NONE);
-	sblive_writeptr(card, MICBA, 0, 0);
-	sblive_writeptr(card, FXBS, 0, ADCBS_BUFSIZE_NONE);
-	sblive_writeptr(card, FXBA, 0, 0);
-	sblive_writeptr(card, FXWC, 0, 0);
-	sblive_writeptr(card, ADCBS, 0, ADCBS_BUFSIZE_NONE);
-	sblive_writeptr(card, ADCBA, 0, 0);
-	sblive_writeptr(card, TCBS, 0, TCBS_BUFFSIZE_16K);
-	sblive_writeptr(card, TCB, 0, 0);
-	sblive_writeptr(card, DBG, 0, 0x8000);
+	/* Disable audio and lock cache */
+	emu10k1_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE);
 
-	/* Disable channel interrupt */
-	sblive_writeptr(card, CLIEL, 0, 0);
-	sblive_writeptr(card, CLIEH, 0, 0);
-	sblive_writeptr(card, SOLEL, 0, 0);
-	sblive_writeptr(card, SOLEH, 0, 0);
+	sblive_writeptr_tag(card, 0,
+                            PTB, 0,
 
-	/* Disable audio and lock cache */
-	sblive_writefn0(card, HCFG, HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE | HCFG_MUTEBUTTONENABLE);
-	sblive_writeptr(card, PTB, 0, 0);
+			    /* Reset recording buffers */
+			    MICBS, ADCBS_BUFSIZE_NONE,
+			    MICBA, 0,
+			    FXBS, ADCBS_BUFSIZE_NONE,
+			    FXBA, 0,
+			    FXWC, 0,
+			    ADCBS, ADCBS_BUFSIZE_NONE,
+			    ADCBA, 0,
+			    TCBS, 0,
+			    TCB, 0,
+			    DBG, 0x8000,
+
+			    /* Disable channel interrupt */
+			    CLIEL, 0,
+			    CLIEH, 0,
+			    SOLEL, 0,
+			    SOLEH, 0,
+			    TAGLIST_END);
+
+
+	pci_free_consistent(card->pci_dev, card->virtualpagetable.size, card->virtualpagetable.addr, card->virtualpagetable.dma_handle);
+	pci_free_consistent(card->pci_dev, card->silentpage.size, card->silentpage.addr, card->silentpage.dma_handle);
+	
+	if(card->tankmem.size != 0)
+		pci_free_consistent(card->pci_dev, card->tankmem.size, card->tankmem.addr, card->tankmem.dma_handle);
 
-	emu10k1_free_memphysical(card->silentpage);
-	emu10k1_free_memphysical(card->virtualpagetable);
-#ifdef TANKMEM
-	emu10k1_free_memphysical(card->tankmem);
-#endif
 	return;
 }
 
@@ -601,6 +611,7 @@
 static int __devinit emu10k1_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
 {
 	struct emu10k1_card *card;
+	u32 subsysvid;
 
 	if ((card = kmalloc(sizeof(struct emu10k1_card), GFP_KERNEL)) == NULL) {
 		printk(KERN_ERR "emu10k1: out of memory\n");
@@ -608,7 +619,6 @@
 	}
 	memset(card, 0, sizeof(struct emu10k1_card));
 
-#if LINUX_VERSION_CODE > 0x020320
 	if (!pci_dma_supported(pci_dev, EMU10K1_DMA_MASK)) {
 		printk(KERN_ERR "emu10k1: architecture does not support 32bit PCI busmaster DMA\n");
 		kfree(card);
@@ -623,27 +633,17 @@
 	pci_set_master(pci_dev);
 
 	card->iobase = pci_resource_start(pci_dev, 0);
+	card->length = pci_resource_len(pci_dev, 0); 
 
-	if (request_region(card->iobase, EMU10K1_EXTENT, card_names[pci_id->driver_data]) == NULL) {
+	if (request_region(card->iobase, card->length, card_names[pci_id->driver_data]) == NULL) {
 		printk(KERN_ERR "emu10k1: IO space in use\n");
 		kfree(card);
 		return -ENODEV;
 	}
-	pci_dev->driver_data = card;
-	pci_dev->dma_mask = EMU10K1_DMA_MASK;
-#else
-	pci_set_master(pci_dev);
-
-	card->iobase = pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
 
-	if (check_region(card->iobase, EMU10K1_EXTENT)) {
-		printk(KERN_ERR "emu10k1: IO space in use\n");
-		kfree(card);
-		return -ENODEV;
-	}
+	PCI_SET_DRIVER_DATA(pci_dev, card);
+	PCI_SET_DMA_MASK(pci_dev, EMU10K1_DMA_MASK);
 
-	request_region(card->iobase, EMU10K1_EXTENT, card_names[pci_id->driver_data]);
-#endif
 	card->irq = pci_dev->irq;
 	card->pci_dev = pci_dev;
 
@@ -654,22 +654,27 @@
 	}
 
 	pci_read_config_byte(pci_dev, PCI_REVISION_ID, &card->chiprev);
+	pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &card->model);
+
+	printk(KERN_INFO "emu10k1: %s rev %d model 0x%x found, IO at 0x%04lx-0x%04lx, IRQ %d\n",
+		card_names[pci_id->driver_data], card->chiprev, card->model, card->iobase,
+		card->iobase + card->length - 1, card->irq);
 
-	printk(KERN_INFO "emu10k1: %s rev %d found at IO 0x%04lx, IRQ %d\n", card_names[pci_id->driver_data], card->chiprev, card->iobase, card->irq);
+	pci_read_config_dword(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &subsysvid);
+	card->isaps = (subsysvid == EMU_APS_SUBID);
 
 	spin_lock_init(&card->lock);
-	card->mixeraddx = card->iobase + AC97DATA;
 	init_MUTEX(&card->open_sem);
 	card->open_mode = 0;
 	init_waitqueue_head(&card->open_wait);
 
 	/* Register devices */
-	if ((card->audio1_num = register_sound_dsp(&emu10k1_audio_fops, -1)) < 0) {
+	if ((card->audio_num = register_sound_dsp(&emu10k1_audio_fops, -1)) < 0) {
 		printk(KERN_ERR "emu10k1: cannot register first audio device!\n");
 		goto err_dev0;
 	}
 
-	if ((card->audio2_num = register_sound_dsp(&emu10k1_audio_fops, -1)) < 0) {
+	if ((card->audio1_num = register_sound_dsp(&emu10k1_audio_fops, -1)) < 0) {
 		printk(KERN_ERR "emu10k1: cannot register second audio device!\n");
 		goto err_dev1;
 	}
@@ -684,33 +689,27 @@
 		goto err_dev3;
 	}
 
-	if (emu10k1_init(card) != CTSTATUS_SUCCESS) {
+	if (emu10k1_init(card) < 0) {
 		printk(KERN_ERR "emu10k1: cannot initialize device!\n");
 		goto err_emu10k1_init;
 	}
 
-	if (audio_init(card) != CTSTATUS_SUCCESS) {
-		printk(KERN_ERR "emu10k1: cannot initialize audio!\n");
-		goto err_audio_init;
-	}
-
-	if (midi_init(card) != CTSTATUS_SUCCESS) {
+	if (midi_init(card) < 0) {
 		printk(KERN_ERR "emu10k1: cannot initialize midi!\n");
 		goto err_midi_init;
 	}
 
+	audio_init(card);
 	mixer_init(card);
 
-	DPD(2, "Hardware initialized. TRAM allocated: %u bytes\n", (unsigned int) card->tmemsize);
+	if (card->isaps)
+		emu10k1_ecard_init(card);
 
 	list_add(&card->list, &emu10k1_devs);
 
 	return 0;
 
       err_midi_init:
-	audio_exit(card);
-
-      err_audio_init:
 	emu10k1_exit(card);
 
       err_emu10k1_init:
@@ -720,16 +719,16 @@
 	unregister_sound_mixer(card->mixer_num);
 
       err_dev2:
-	unregister_sound_dsp(card->audio2_num);
+	unregister_sound_dsp(card->audio1_num);
 
       err_dev1:
-	unregister_sound_dsp(card->audio1_num);
+	unregister_sound_dsp(card->audio_num);
 
       err_dev0:
 	free_irq(card->irq, card);
 
       err_irq:
-	release_region(card->iobase, EMU10K1_EXTENT);
+	release_region(card->iobase, card->length);
 	kfree(card);
 
 	return -ENODEV;
@@ -737,26 +736,25 @@
 
 static void __devexit emu10k1_remove(struct pci_dev *pci_dev)
 {
-#if LINUX_VERSION_CODE > 0x020320
-	struct emu10k1_card *card = pci_dev->driver_data;
-#else
-	struct emu10k1_card *card = list_entry(emu10k1_devs.next, struct emu10k1_card, list);
-#endif
+	struct emu10k1_card *card = PCI_GET_DRIVER_DATA(pci_dev);
+
 	midi_exit(card);
-	audio_exit(card);
 	emu10k1_exit(card);
 
 	unregister_sound_midi(card->midi_num);
+	
 	unregister_sound_mixer(card->mixer_num);
-	unregister_sound_dsp(card->audio2_num);
+
 	unregister_sound_dsp(card->audio1_num);
+	unregister_sound_dsp(card->audio_num);
 
 	free_irq(card->irq, card);
-	release_region(card->iobase, EMU10K1_EXTENT);
+	release_region(card->iobase, card->length);
 
 	list_del(&card->list);
 
 	kfree(card);
+
 	return;
 }
 
@@ -770,7 +768,6 @@
 	remove:emu10k1_remove,
 };
 
-#if LINUX_VERSION_CODE > 0x020320
 static int __init emu10k1_init_module(void)
 {
 	printk(KERN_INFO "Creative EMU10K1 PCI Audio Driver, version " DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
@@ -781,44 +778,9 @@
 static void __exit emu10k1_cleanup_module(void)
 {
 	pci_unregister_driver(&emu10k1_pci_driver);
-	return;
-}
-
-#else
-
-static int __init emu10k1_init_module(void)
-{
-	struct pci_dev *dev = NULL;
-	const struct pci_device_id *pci_id = emu10k1_pci_driver.id_table;
-
-	printk(KERN_INFO "Creative EMU10K1 PCI Audio Driver, version " DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
-
-	if (!pci_present())
-		return -ENODEV;
-
-	while (pci_id->vendor) {
-		while ((dev = pci_find_device(pci_id->vendor, pci_id->device, dev)))
-			emu10k1_probe(dev, pci_id);
-
-		pci_id++;
-	}
-	return 0;
-}
-
-static void __exit emu10k1_cleanup_module(void)
-{
-	struct emu10k1_card *card;
-
-	while (!list_empty(&emu10k1_devs)) {
-		card = list_entry(emu10k1_devs.next, struct emu10k1_card, list);
-
-		emu10k1_remove(card->pci_dev);
-	}
 
 	return;
 }
-
-#endif
 
 module_init(emu10k1_init_module);
 module_exit(emu10k1_cleanup_module);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)